Skip to content

sdcorejs/angular-material-datetime

Repository files navigation

@sdcorejs/angular-material-datetime

SDCoreJS

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 version npm downloads build status license types included stars

npm · GitHub · Live Demo · API Reference


✨ Features

  • <sd-datetime-picker> — calendar + time spinner inside a CDK Overlay
  • [sdDatetimePicker] input directive — full ControlValueAccessor support ([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

📦 Installation

npm install @sdcorejs/angular-material-datetime @angular/material @angular/cdk

Then register the date adapter in your app.config.ts:

import { provideSdNativeDateAdapter } from '@sdcorejs/angular-material-datetime';

export const appConfig: ApplicationConfig = {
  providers: [
    provideSdNativeDateAdapter(),
  ],
};

🚀 Quick Examples

Minimal datetime picker

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.


Customizing actions

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.


With seconds + step minute

<sd-datetime-picker #picker [showSeconds]="true" [stepMinute]="5"></sd-datetime-picker>

Min / max constraints

<sd-datetime-picker
  #picker
  [minDate]="today"
  [maxDate]="endOfMonth">
</sd-datetime-picker>

Reactive form validation

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.


🧩 Packages

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.


🎨 Theming — Material 2 and Material 3

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.


🏗 Build

npm install --legacy-peer-deps
npm run build:all

Outputs dist/datetime/, dist/moment-adapter/, dist/date-fns-adapter/ (FESM2022 + .d.ts).


🧪 Testing

npm test
npm run test:coverage

Powered by Jest + jest-preset-angular. Coverage thresholds: 80% global, 95% native adapter directory.


🚀 Publishing

This repo uses Changesets + a GitHub Actions workflow. Day-to-day flow:

  1. Make changes on a feature branch.
  2. Add a changeset describing what changed:
    npx changeset
  3. Commit the generated .changeset/*.md alongside your code change.
  4. 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_TOKEN repository secret (already configured)
  • Member of the @sdcorejs npm org with publish access

📐 Compatibility

Angular @sdcorejs/angular-material-datetime
19.x 1.x
20.x 1.x
21.x 1.x

Material 19+, CDK 19+, rxjs 7+.


🎯 Philosophy

@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

🌐 Ecosystem


📄 License

MIT — Copyright (c) 2026 Trần Thuận Nghĩa and contributors

About

Datetime components and utilities built for Angular Material.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors