Skip to content

About

Datetime components and utilities built for Angular Material.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

@sdcorejs/angular-material-datetime

SDCoreJS

Datetime and time picker for Angular Material — with an adapter-pluggable core.

Standalone components · Signal-driven · Material 3 only · 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 — use the included native adapter or implement your own SdDateAdapter<D>
  • ✅ Standalone-only components — no NgModule
  • ✅ Signal-driven (Angular 19+ input(), model(), output(), signal(), computed())
  • ✅ Material 3 theming with system-token support and dark-mode compatibility
  • ✅ Tree-shakable — only what you import is bundled
  • ✅ Tested — unit and integration coverage includes custom non-native date objects

📦 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>

stepMinute uses strict validation: valid minutes must be divisible by the configured step. Invalid step configuration (<= 0, fractional, non-finite, or > 60) is normalized to 1.


Min / max constraints

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

minDate and maxDate are inclusive full datetime boundaries. The input directive exposes sdDatetimeParse, sdDatetimeMin, sdDatetimeMax, and sdDatetimeMinuteStep validation errors.

Global defaults and touch UI

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

providers: [{
  provide: SD_DATETIME_DEFAULT_OPTIONS,
  useValue: { showSeconds: true, stepMinute: 15, touchUi: true },
}]

Explicit picker inputs override injected defaults. touchUi uses a centered, viewport-constrained overlay.

Internationalization

import { Injectable } from '@angular/core';
import { SdDatetimeIntl } from '@sdcorejs/angular-material-datetime';

@Injectable()
export class VietnameseDatetimeIntl extends SdDatetimeIntl {
  override dialogLabel = 'Chọn ngày và giờ';
  override nowLabel = 'Hiện tại';
  override cancelLabel = 'Hủy';
  override applyLabel = 'Áp dụng';
  override hourLabel = 'Giờ';
  override minuteLabel = 'Phút';
  override secondLabel = 'Giây';
}

providers: [{ provide: SdDatetimeIntl, useClass: VietnameseDatetimeIntl }]

After changing labels at runtime, call intl.changes.next() so open pickers refresh.


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

The Moment and date-fns packages are placeholders with empty public APIs. They are excluded from the release workflow until runtime implementations exist; use the native adapter today.


🎨 Theming — Material 3

The library requires an Angular Material 3 theme. Define your application theme with mat.theme(...) so the picker can read system variables such as --mat-sys-surface-container, --mat-sys-primary, and --mat-sys-outline-variant. These variables keep the picker aligned with your palette and dark mode.

@use '@angular/material' as mat;

html {
  @include mat.theme((
    color: mat.$violet-palette,
    typography: Roboto,
    density: 0,
  ));
}

Migrating an existing theme

If your application uses an earlier Angular Material theming API, migrate the application theme to mat.theme(...) before adopting this package version. The datetime picker expects Material 3 system variables and does not provide a compatibility styling layer for older theme definitions.


🏗 Build

npm ci
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 → builds with ng-packagr, packs once, verifies that exact Angular Package Format tarball, and publishes those same bytes.

The source workspace under projects/datetime and the built dist/datetime directory are never direct publish targets. A manually approved release must retain the verified absolute tarball path and SHA-256 produced by the release preflight:

export SD_DATETIME_RELEASE_TARBALL=/absolute/path/to/sdcorejs-angular-material-datetime-1.0.4.tgz
export SD_DATETIME_RELEASE_SHA256=<verified-sha256>
npm run release

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
22.x 1.x

Angular, Angular Material, CDK, and Angular Forms 19–22 with RxJS 7 are verified by clean strict-template consumer builds from one packed release artifact.


🎯 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

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages