Datetime, timepicker, and date-range picker for Angular Material — with the date adapter you pick.
Standalone components · Signal-driven · Material 3 ready · Adapter-pluggable
npm · GitHub · Live Demo · API Reference
- ✅
<sd-datetime-picker>— calendar + time spinner inside a CDK Overlay - ✅
[sdDatetimePicker]input directive — fullControlValueAccessorsupport ([formControl],formControlName,[(ngModel)]) - ✅ Default actions render automatically (Now / Cancel / Apply) — projection-based override available
- ✅ Adapter-pluggable — pick native, Moment, date-fns, or your own
- ✅ Standalone-only components — no NgModule
- ✅ Signal-driven (Angular 19+
input(),model(),output(),signal(),computed()) - ✅ Material 3 themed surface tokens with Material 2 fallback
- ✅ Tree-shakable — only what you import is bundled
- ✅ Tested — 84 unit tests, 95%+ coverage on adapter contracts
npm install @sdcorejs/angular-material-datetime @angular/material @angular/cdkThen register the date adapter in your app.config.ts:
import { provideSdNativeDateAdapter } from '@sdcorejs/angular-material-datetime';
export const appConfig: ApplicationConfig = {
providers: [
provideSdNativeDateAdapter(),
],
};import {
SdDatetimePicker, SdDatetimePickerInput, SdDatetimePickerToggle,
} from '@sdcorejs/angular-material-datetime';
@Component({
imports: [
ReactiveFormsModule, MatInputModule, MatFormFieldModule, MatButtonModule,
SdDatetimePicker, SdDatetimePickerInput, SdDatetimePickerToggle,
],
template: `
<mat-form-field>
<mat-label>Pick a datetime</mat-label>
<input matInput [sdDatetimePicker]="picker" [formControl]="ctrl">
<button matSuffix [sdDatetimePickerToggle]="picker">Open</button>
<sd-datetime-picker #picker></sd-datetime-picker>
</mat-form-field>
`,
})
export class MyComponent {
ctrl = new FormControl<Date | null>(null);
}The default actions (Now / Cancel / Apply) render automatically. Nothing else needed.
Project your own <sd-datetime-picker-actions> block to fully replace the defaults — for example, Vietnamese labels:
<sd-datetime-picker #picker>
<sd-datetime-picker-actions>
<button mat-button sdDatetimePickerNow>Bây giờ</button>
<button mat-button sdDatetimePickerCancel>Hủy</button>
<button mat-flat-button sdDatetimePickerApply>Xác nhận</button>
</sd-datetime-picker-actions>
</sd-datetime-picker>Add SdDatetimePickerActions, SdDatetimePickerNow, SdDatetimePickerCancel, SdDatetimePickerApply to your component imports only when projecting custom actions.
<sd-datetime-picker #picker [showSeconds]="true" [stepMinute]="5"></sd-datetime-picker><sd-datetime-picker
#picker
[minDate]="today"
[maxDate]="endOfMonth">
</sd-datetime-picker>ctrl = new FormControl<Date | null>(null, Validators.required);<mat-form-field>
<input matInput [sdDatetimePicker]="picker" [formControl]="ctrl">
<button matSuffix [sdDatetimePickerToggle]="picker">Open</button>
<sd-datetime-picker #picker></sd-datetime-picker>
@if (ctrl.invalid && ctrl.touched) {
<mat-error>Required</mat-error>
}
</mat-form-field>See the live demo for 9 working examples plus copy-pastable source.
| Package | Purpose | Status |
|---|---|---|
@sdcorejs/angular-material-datetime |
Core components + directives + native date adapter | v1 ✅ |
@sdcorejs/angular-material-datetime-moment |
Moment.js date adapter | v1.x planned |
@sdcorejs/angular-material-datetime-date-fns |
date-fns date adapter | v1.x planned |
All packages publish lockstep with the same version. The Moment and date-fns adapters ship as version-aligned placeholders at v1.0 — their implementations land in subsequent minor releases.
The library works out-of-the-box with both Material 2 and Material 3 themes.
| Theme | Behaviour |
|---|---|
Material 3 (mat.theme(...)) — recommended |
Picker chrome reads --mat-sys-surface-container, --mat-sys-primary, --mat-sys-outline-variant — colors track your app theme (including dark mode) |
Material 2 (mat.core() + mat.all-component-themes($theme)) |
M3 tokens not defined → picker falls back to neutral defaults (#fff surface, #1976d2 focus). All Material primitives inside the picker are still themed by Material itself |
| Hybrid M2 + M3 | Both layers coexist; the picker prefers M3 tokens when present |
For best visual harmony use Material 3. Material 2 is fully supported but the picker surface and divider won't pick up your M2 palette without a custom override.
npm install --legacy-peer-deps
npm run build:allOutputs dist/datetime/, dist/moment-adapter/, dist/date-fns-adapter/ (FESM2022 + .d.ts).
npm test
npm run test:coveragePowered by Jest + jest-preset-angular. Coverage thresholds: 80% global, 95% native adapter directory.
This repo uses Changesets + a GitHub Actions workflow. Day-to-day flow:
- Make changes on a feature branch.
- Add a changeset describing what changed:
npx changeset
- Commit the generated
.changeset/*.mdalongside your code change. - Open a PR into
main.
When the PR merges, the Release workflow:
- If unreleased changesets exist → opens a "Version Packages" PR that bumps versions + updates CHANGELOG.
- When that PR is merged → publishes the affected packages to npm and creates the matching git tags.
Requirements:
NPM_TOKENrepository secret (already configured)- Member of the
@sdcorejsnpm org with publish access
| Angular | @sdcorejs/angular-material-datetime |
|---|---|
| 19.x | 1.x |
| 20.x | 1.x |
| 21.x | 1.x |
Material 19+, CDK 19+, rxjs 7+.
@sdcorejs/angular-material-datetime is designed around:
- Material-idiomatic API (extends, not replaces, the Material datepicker family)
- Standalone-only — zero NgModule, zero migration friction
- Signal-driven internals — predictable change detection, no Zone.js coupling
- Adapter-pluggable — your date library, your choice
- Sensible defaults — works out of the box, customizable when you need it
- AI-friendly contracts — semantic naming, explicit types, copy-pastable examples
@sdcorejs/utils— TypeScript utilities@sdcorejs/angular-material-datetime— this package
MIT — Copyright (c) 2026 Trần Thuận Nghĩa and contributors
