ngxsmk-datepicker 2.2.13 → 2.3.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,923 +1,939 @@
1
- <!--
2
- SEO Keywords: Angular DatePicker, Angular Date Range Picker, Lightweight Calendar Component, Angular Signals DatePicker, SSR Ready DatePicker, Zoneless Angular, A11y DatePicker, Mobile-Friendly DatePicker, Ionic DatePicker
3
- Meta Description: The most powerful, lightweight, and accessible date and range picker for modern Angular (17-21+). Built with Signals, Zoneless-ready, and zero dependencies.
4
- -->
5
-
6
- <div align="center">
7
- <img src="projects/ngxsmk-datepicker/docs/header-banner.png" alt="ngxsmk-datepicker - Lightweight Angular Date Range Picker" width="100%" />
8
-
9
- # **ngxsmk-datepicker** – Modern Angular Date Picker & Range Picker
10
-
11
- ### _The Gold Standard for Premium Angular Calendar Selection_
12
-
13
- [![npm version](https://img.shields.io/npm/v/ngxsmk-datepicker.svg?style=flat-square&color=6d28d9)](https://www.npmjs.com/package/ngxsmk-datepicker)
14
- [![Angular](https://img.shields.io/badge/Angular-17%2B-DD0031.svg?style=flat-square&logo=angular)](https://angular.io/)
15
- [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/LICENSE)
16
- [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-toozuuu-orange?style=flat-square&logo=buy-me-a-coffee)](https://buymeacoffee.com/toozuuu)
17
- [![Bundle Size](https://img.shields.io/badge/bundle-~127KB-success.svg?style=flat-square)](https://bundlephobia.com/package/ngxsmk-datepicker)
18
- [![Zoneless](https://img.shields.io/badge/Zoneless-Ready-blueviolet.svg?style=flat-square)](https://angular.dev/guide/zoneless)
19
-
20
- **`npm i ngxsmk-datepicker`**
21
-
22
- [Explore Live Demo](https://ngxsmk.github.io/ngxsmk-datepicker/) • [Buy me a coffee](https://buymeacoffee.com/toozuuu) • [API Documentation](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/API.md) • [Submit Issue](https://github.com/NGXSMK/ngxsmk-datepicker/issues)
23
-
24
- </div>
25
-
26
- ---
27
-
28
- **Last updated:** May 6, 2026 - **Current stable:** v2.2.13
29
-
30
- ### **Overview**
31
-
32
- **ngxsmk-datepicker** is a high-performance, enterprise-ready date and range picker engineered for the modern Angular ecosystem (v17+). Built from the ground up with **Angular Signals**, it delivers a seamless, zoneless-ready experience for both desktop and mobile (Ionic) applications.
33
-
34
- > **Stable Release**: `v2.2.13` is the current stable release with compiled `fesm2022` output and type declarations.
35
- >
36
- > **Stable line**: v2.2.x includes range-mode **`allowSameDay`**, **IANA timezone** support, validation fixes, and strict TypeScript improvements. Versions **2.0.10** and **2.0.11** were broken and have been **unpublished**; use **v2.1.1+** or current **v2.2.13** on npm.
37
-
38
- ---
39
-
40
- ### **📌 Table of Contents**
41
-
42
- 1. [📷 Screenshots](#-screenshots)
43
- 2. [✨ Features](#-features)
44
- 3. [📋 Compatibility](#-compatibility)
45
- 4. [🌍 Localization (i18n)](#-localization-i18n)
46
- 5. [📦 Installation](#-installation)
47
- 6. [🚀 Quick Start](#-quick-start)
48
- 7. [🔌 Framework Integration](#-framework-integration)
49
- 8. [⚙️ API Reference](#-api-reference)
50
- 9. [🎨 Theming](#-theming)
51
- 10. [⌨️ Keyboard Navigation](#-keyboard-navigation)
52
-
53
- ---
54
-
55
- ## 📷 Screenshots
56
-
57
- <p align="center">
58
- <img src="https://github.com/NGXSMK/ngxsmk-datepicker/raw/main/projects/ngxsmk-datepicker/docs/1.png" alt="Angular Standalone DatePicker Single Selection Mode" width="30%" />
59
- <img src="https://github.com/NGXSMK/ngxsmk-datepicker/raw/main/projects/ngxsmk-datepicker/docs/2.png" alt="Angular Date Range Picker Selection Mode" width="30%" />
60
- <img src="https://github.com/NGXSMK/ngxsmk-datepicker/raw/main/projects/ngxsmk-datepicker/docs/3.png" alt="Mobile Angular DatePicker Ionic Compatibility" width="30%" />
61
- </p>
62
-
63
- ## **✨ Features**
64
-
65
- ### **Core Capabilities**
66
-
67
- - 💎 **Signal-Driven Engine**: Hyper-reactive state management using Angular Signals.
68
- - 🌓 **Native Dark Mode**: Beautifully crafted themes for light and dark environments.
69
- - 📱 **Mobile-First UX**: Native mobile picker integration with touch gestures and haptic feedback.
70
- - 🧩 **Zero Dependencies**: Lightweight standalone component with no external bloat.
71
- - ⚡ **Performance++**: Lazy-loaded calendar months, memoized calculations, and tree-shakable architecture.
72
-
73
- ### **Advanced Functionality**
74
-
75
- - 📅 **Google Calendar Sync**: Built-in support for seamlessly syncing and displaying events natively from Google Calendar.
76
- - 🌐 **8-Language i18n**: Full localization for `en`, `de`, `es`, `sv`, `ko`, `zh`, `ja`, and `fr`.
77
- - 🛠️ **Plugin Architecture**: Extend functionality via hooks for rendering, validation, and shortcuts.
78
- - 🧪 **Signal Forms Native**: Direct integration with Angular 21's new Signal Forms API.
79
- - 🚀 **Zoneless Ready**: Optimized for the future of Angular—works perfectly without zone.js.
80
- - **Full Accessibility**: WAI-ARIA compliant with extensive keyboard navigation support.
81
-
82
- ## **📋 Compatibility**
83
-
84
- For detailed compatibility information, see [COMPATIBILITY.md](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/COMPATIBILITY.md).
85
-
86
- ### Quick Reference
87
-
88
- | Angular Version | Status | Core Features | Signal Forms | SSR | Zoneless |
89
- | --------------- | ------------------ | ------------- | ------------ | --- | -------- |
90
- | Angular 17 | ✅ Fully Supported | ✅ All | ❌ | ✅ | ✅ |
91
- | Angular 18 | Fully Supported | All | ❌ | | ✅ |
92
- | Angular 19 | Fully Supported | All | ❌ | ✅ | ✅ |
93
- | Angular 20 | Fully Supported | All | ❌ | | |
94
- | Angular 21 | Fully Supported | All | ✅ | | ✅ |
95
- | Angular 22+ | 🔄 Future Support | All | ✅ | ✅ | |
96
-
97
- **Zone.js**: Optional - The library works with or without Zone.js (zoneless apps supported)
98
-
99
- **SSR**: ✅ Fully compatible with Angular Universal and server-side rendering
100
-
101
- **Peer Dependencies**: `@angular/core >=17.0.0 <24.0.0`
102
-
103
- ## **🔒 API Stability & Deprecation Policy**
104
-
105
- ### API Stability Guarantees
106
-
107
- - **Public API**: All public APIs (inputs, outputs, methods) are stable within a major version
108
- - **Experimental Features**: Features marked as `experimental` may change in minor versions
109
- - **Internal APIs**: Private methods and internal services are not part of the public API and may change without notice
110
-
111
- ### Deprecation Policy
112
-
113
- - **Deprecation Period**: Features are deprecated for at least **2 major versions** before removal
114
- - **Deprecation Warnings**:
115
- - `@deprecated` JSDoc tags in code
116
- - Console warnings in development mode
117
- - Clear documentation in CHANGELOG.md
118
- - **Migration Guides**: Provided in `MIGRATION.md` for all breaking changes
119
- - **Breaking Changes**: Only occur in major version releases (semver)
120
-
121
- ### Stable APIs
122
-
123
- The following are considered stable public APIs:
124
-
125
- - Component inputs and outputs (`@Input()`, `@Output()`)
126
- - Public methods documented in API docs
127
- - Exported types and interfaces
128
- - Service APIs (when marked as public)
129
-
130
- ### Experimental Features
131
-
132
- Features marked as experimental may change:
133
-
134
- - Signal Forms support (`[field]` input) - Experimental in v1.9.x, stable in v2.0.0+
135
- - Some advanced selection modes
136
- - Plugin architecture hooks (subject to refinement)
137
-
138
- For details, see [CONTRIBUTING.md](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/CONTRIBUTING.md#deprecation-policy).
139
-
140
- ## **📦 Installation**
141
-
142
- ```bash
143
- npm install ngxsmk-datepicker@2.2.13
144
- ```
145
-
146
- ### Alternative installation
147
-
148
- You can install without npm using any of these methods (peer dependencies must still be installed in your app):
149
-
150
- | Method | Command |
151
- |--------|--------|
152
- | **Yarn** | `yarn add ngxsmk-datepicker@2.2.13` |
153
- | **pnpm** | `pnpm add ngxsmk-datepicker@2.2.13` |
154
- | **Bun** | `bun add ngxsmk-datepicker@2.2.13` |
155
- | **From Git** | `npm install github:NGXSMK/ngxsmk-datepicker#v2.2.13` (requires the repo to have built output or you build from source) |
156
- | **Local path** | Build the library in the repo (`npx ng build ngxsmk-datepicker`), then `npm install /path/to/ngxsmk-datepicker/dist/ngxsmk-datepicker` |
157
- | **CDN (ESM)** | Use [unpkg](https://unpkg.com/ngxsmk-datepicker@2.2.13/) or [jsDelivr](https://cdn.jsdelivr.net/npm/ngxsmk-datepicker@2.2.13/) in your bundler or import map; peer dependencies (Angular, etc.) must be installed in your app. |
158
-
159
- For all options and caveats, see [docs/INSTALLATION.md](docs/INSTALLATION.md).
160
-
161
- ## **Usage**
162
-
163
- ngxsmk-datepicker is a standalone component, so you can import it directly into your component or module.
164
-
165
- ### Signal Forms (Angular 21)
166
-
167
- You can bind directly to a writable Signal using standard two-way binding. This works seamlessly alongside traditional Reactive Forms.
168
-
169
- ```ts
170
- import { signal } from "@angular/core";
171
- import { DatepickerValue } from "ngxsmk-datepicker";
172
-
173
- export class MyComponent {
174
- dateSig = signal<DatepickerValue>(null);
175
- }
176
- ```
177
-
178
- ```html
179
- <ngxsmk-datepicker mode="single" [value]="dateSig()" (valueChange)="dateSig.set($event)"> </ngxsmk-datepicker>
180
-
181
- <p>Signal value: {{ dateSig() | json }}</p>
182
- ```
183
-
184
- This pattern is also compatible with computed/linked signals produced by `httpResource`, enabling powerful data flows with Angular 21.
185
-
186
- ### Signal Forms with `[field]` Input (Angular 21+)
187
-
188
- For direct integration with Angular Signal Forms, use the `[field]` input. The datepicker automatically tracks dirty state when using this binding:
189
-
190
- ```typescript
191
- import { Component, signal, form, objectSchema } from "@angular/core";
192
- import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker";
193
-
194
- @Component({
195
- selector: "app-form",
196
- standalone: true,
197
- imports: [NgxsmkDatepickerComponent],
198
- template: `
199
- <form>
200
- <ngxsmk-datepicker [field]="myForm.dateInQuestion" mode="single" placeholder="Select a date"> </ngxsmk-datepicker>
201
- </form>
202
- `,
203
- })
204
- export class FormComponent {
205
- localObject = signal({ dateInQuestion: new Date() });
206
-
207
- myForm = form(
208
- this.localObject,
209
- objectSchema({
210
- dateInQuestion: objectSchema<Date>(),
211
- }),
212
- );
213
- }
214
- ```
215
-
216
- The `[field]` input provides automatic two-way binding with signal forms - no manual event handling needed! It also automatically tracks the form's dirty state, so `form().dirty()` will return `true` after a user selects a date.
217
-
218
- For detailed Signal Forms integration including dirty state tracking, see the [Signal Forms Integration Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/signal-forms.md).
219
-
220
- ### Documentation
221
-
222
- - **[Plugin Architecture](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/PLUGIN-ARCHITECTURE.md)** - Complete guide to the plugin architecture and hook system
223
- - **[Signals Integration Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/signals.md)** - Complete guide to using signals with the datepicker
224
- - **[Signal Forms Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/signal-forms.md)** - Deep dive into Signal Forms integration
225
- - **[SSR Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/ssr.md)** - Server-side rendering setup and best practices
226
- - **[SSR Example](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/SSR-EXAMPLE.md)** - Complete Angular Universal example with hydration notes
227
- - **[Extension Points Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/extension-points.md)** - Customization hooks and extension points
228
- - **[Theme Tokens Reference](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/THEME-TOKENS.md)** - Complete CSS custom properties reference with examples
229
- - **[API Documentation](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/API.md)** - Complete public API reference
230
-
231
- #### **1. Import the Component**
232
-
233
- All public exports (component, utilities, types, services) come from the main package entry: `'ngxsmk-datepicker'` (there is no separate `/utils` subpath). In your component file (e.g., app.component.ts), import the component (or the module—see troubleshooting below).
234
-
235
- import { Component } from '@angular/core';
236
- import { NgxsmkDatepickerComponent, DateRange, HolidayProvider } from 'ngxsmk-datepicker';
237
-
238
- @Component({
239
- selector: 'app-root',
240
- standalone: true,
241
- imports: [NgxsmkDatepickerComponent],
242
- templateUrl: './app.component.html',
243
- })
244
- export class AppComponent {
245
- // Example for predefined ranges
246
- public myRanges: DateRange = {
247
- 'Today': [new Date(), new Date()],
248
- 'Last 7 Days': [new Date(new Date().setDate(new Date().getDate() - 6)), new Date()],
249
- 'This Month': [new Date(new Date().getFullYear(), new Date().getMonth(), 1), new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0)],
250
- };
251
-
252
- // Example for disabling weekends
253
- isWeekend = (date: Date): boolean => {
254
- const day = date.getDay();
255
- return day === 0 || day === 6; // Sunday or Saturday
256
- };
257
-
258
- onDateChange(value: Date | { start: Date; end: Date } | Date[]) {
259
- console.log('Date changed:', value);
260
- }
261
- }
262
-
263
- **If you see NG1010** (`'imports' must be an array... Value could not be determined statically`) when using the Angular compiler plugin or in strict AOT builds, use the wrapper module instead: `import { NgxsmkDatepickerModule } from 'ngxsmk-datepicker'` and set `imports: [NgxsmkDatepickerModule]`. The template stays the same (`<ngxsmk-datepicker>`).
264
-
265
- #### **2. Add it to Your Template**
266
-
267
- Use the `<ngxsmk-datepicker>` selector in your HTML template.
268
-
269
- ````html
270
- <h2>Advanced Date Range Picker</h2>
271
-
272
- <ngxsmk-datepicker [mode]="'range'" [ranges]="myRanges" [showTime]="true" [minuteInterval]="15" [minDate]="today" [isInvalidDate]="isWeekend" [locale]="'en-US'" [theme]="'light'" [inline]="'auto'" (valueChange)="onDateChange($event)"></ngxsmk-datepicker>
273
-
274
- #### **3. Disabled Dates Example** Disable specific dates by passing an array of date strings or Date objects: ```typescript // In your component disabledDates = ['10/21/2025', '08/21/2025', '10/15/2025', '10/8/2025', '10/3/2025']; // In your template
275
- <ngxsmk-datepicker [mode]="'single'" [disabledDates]="disabledDates" placeholder="Select a date"> </ngxsmk-datepicker>
276
- ````
277
-
278
- #### **4. Holiday Tooltips Example**
279
-
280
- Holiday dates automatically show tooltips when you hover over them:
281
-
282
- ```typescript
283
- // Holiday provider with tooltips
284
- class MyHolidayProvider implements HolidayProvider {
285
- private holidays: { [key: string]: string } = {
286
- '2025-01-01': 'New Year\'s Day',
287
- '2025-07-04': 'Independence Day',
288
- '2025-12-25': 'Christmas Day',
289
- };
290
-
291
- isHoliday(date: Date): boolean {
292
- const key = this.formatDateKey(date);
293
- return !!this.holidays[key];
294
- }
295
-
296
- getHolidayLabel(date: Date): string | null {
297
- const key = this.formatDateKey(date);
298
- return this.holidays[key] || null;
299
- }
300
- }
301
-
302
- // In your template
303
- <ngxsmk-datepicker
304
- [holidayProvider]="holidayProvider"
305
- [disableHolidays]="false"
306
- placeholder="Hover over holidays to see tooltips">
307
- </ngxsmk-datepicker>
308
- ```
309
-
310
- ## **🔌 Framework Integration**
311
-
312
- ### **Angular Material Form Fields**
313
-
314
- Integrate with Angular Material's form field components for a seamless Material Design experience. Works with both standalone and non-standalone components:
315
-
316
- **Standalone Components:**
317
-
318
- ```typescript
319
- import { Component } from "@angular/core";
320
- import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms";
321
- import { MatFormFieldModule } from "@angular/material/form-field";
322
- import { MatInputModule } from "@angular/material/input";
323
- import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker";
324
-
325
- @Component({
326
- selector: "app-material-form",
327
- standalone: true,
328
- imports: [ReactiveFormsModule, MatFormFieldModule, MatInputModule, NgxsmkDatepickerComponent],
329
- template: `
330
- <form [formGroup]="myForm">
331
- <mat-form-field appearance="outline">
332
- <mat-label>Select Date</mat-label>
333
- <ngxsmk-datepicker mode="single" formControlName="date" placeholder="Choose a date"> </ngxsmk-datepicker>
334
- </mat-form-field>
335
- </form>
336
- `,
337
- })
338
- export class MaterialFormComponent {
339
- myForm = new FormGroup({
340
- date: new FormControl<Date | null>(null),
341
- });
342
- }
343
- ```
344
-
345
- **Non-Standalone (NgModules):** Add the directive file from [INTEGRATION.md § Angular Material](projects/ngxsmk-datepicker/docs/INTEGRATION.md#angular-material), then add it to your module `imports` (with `NgxsmkDatepickerComponent`, `MatFormFieldModule`, etc.) and use `ngxsmkMatFormFieldControl` on the datepicker in templates.
346
-
347
- **With Date Range:**
348
-
349
- ```html
350
- <mat-form-field appearance="fill">
351
- <mat-label>Date Range</mat-label>
352
- <ngxsmk-datepicker mode="range" [showTime]="true" formControlName="dateRange"> </ngxsmk-datepicker>
353
- </mat-form-field>
354
- ```
355
-
356
- ### **Ionic Components**
357
-
358
- For best integration with Ionic, import the integration styles in your global CSS/SCSS file:
359
-
360
- ```css
361
- @import "ngxsmk-datepicker/styles/ionic-integration.css";
362
- ```
363
-
364
- **Automatic Theming:**
365
- The datepicker automatically detects and uses Ionic CSS variables (e.g., `--ion-color-primary`, `--ion-background-color`) so it matches your app's theme out of the box without extra configuration.
366
-
367
- Works seamlessly with Ionic form components and follows Ionic design patterns:
368
-
369
- ```typescript
370
- import { Component } from "@angular/core";
371
- import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms";
372
- import { IonItem, IonLabel, IonInput } from "@ionic/angular/standalone";
373
- import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker";
374
-
375
- @Component({
376
- selector: "app-ionic-form",
377
- standalone: true,
378
- imports: [ReactiveFormsModule, IonItem, IonLabel, IonInput, NgxsmkDatepickerComponent],
379
- template: `
380
- <form [formGroup]="myForm">
381
- <ion-item>
382
- <ion-label position="stacked">Appointment Date</ion-label>
383
- <ngxsmk-datepicker mode="single" formControlName="appointmentDate" placeholder="Select date"> </ngxsmk-datepicker>
384
- </ion-item>
385
- </form>
386
- `,
387
- })
388
- export class IonicFormComponent {
389
- myForm = new FormGroup({
390
- appointmentDate: new FormControl<Date | null>(null),
391
- });
392
- }
393
- ```
394
-
395
- **With Ionic Datetime Styling:**
396
-
397
- ```html
398
- <ion-item>
399
- <ion-label>Check-in / Check-out</ion-label>
400
- <ngxsmk-datepicker mode="range" [theme]="'light'" formControlName="bookingDates"> </ngxsmk-datepicker>
401
- </ion-item>
402
- ```
403
-
404
- ### **React, Vue, & Vanilla JS (Web Components)**
405
-
406
- Because `ngxsmk-datepicker` is highly decoupled from heavy external dependencies, it can be exported as a standard Custom Web Component using Angular Elements. This allows you to use exactly the same datepicker in React, Vue, Svelte, or Vanilla JavaScript projects seamlessly!
407
-
408
- **1. Create a Custom Element Wrapper**
409
- ```typescript
410
- import { createApplication } from '@angular/platform-browser';
411
- import { createCustomElement } from '@angular/elements';
412
- import { NgxsmkDatepickerComponent } from 'ngxsmk-datepicker';
413
-
414
- (async () => {
415
- const app = await createApplication();
416
- const DatepickerElement = createCustomElement(NgxsmkDatepickerComponent, { injector: app.injector });
417
- customElements.define('ngxsmk-datepicker', DatepickerElement);
418
- })().catch(console.error);
419
- ```
420
-
421
- **2. Use It Natively Anywhere**
422
- ```html
423
- <!-- In any HTML, React, Vue, or Svelte file -->
424
- <ngxsmk-datepicker id="myPicker" mode="range" theme="light"></ngxsmk-datepicker>
425
-
426
- <script>
427
- // Add native DOM event listeners
428
- document.getElementById('myPicker').addEventListener('dateSelect', (e) => {
429
- console.log('Selected date:', e.detail);
430
- });
431
- </script>
432
- ```
433
-
434
- For full working examples (including React & Vue bindings), check out the `/examples` directory in our GitHub repository!
435
-
436
- ### **Plain HTML Inputs**
437
-
438
- Use with standard HTML form inputs for maximum flexibility:
439
-
440
- ```typescript
441
- import { Component } from "@angular/core";
442
- import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms";
443
- import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker";
444
-
445
- @Component({
446
- selector: "app-plain-form",
447
- standalone: true,
448
- imports: [ReactiveFormsModule, NgxsmkDatepickerComponent],
449
- template: `
450
- <form [formGroup]="myForm">
451
- <label for="birthdate">Birth Date</label>
452
- <ngxsmk-datepicker id="birthdate" mode="single" formControlName="birthdate" placeholder="MM/DD/YYYY"> </ngxsmk-datepicker>
453
-
454
- <button type="submit">Submit</button>
455
- </form>
456
- `,
457
- })
458
- export class PlainFormComponent {
459
- myForm = new FormGroup({
460
- birthdate: new FormControl<Date | null>(null),
461
- });
462
- }
463
- ```
464
-
465
- **With Native HTML5 Validation:**
466
-
467
- ```html
468
- <form [formGroup]="myForm">
469
- <div class="form-group">
470
- <label for="event-date">Event Date *</label>
471
- <ngxsmk-datepicker id="event-date" mode="single" formControlName="eventDate" [minDate]="today" required> </ngxsmk-datepicker>
472
- </div>
473
- </form>
474
- ```
475
-
476
- ### **Form Validation**
477
-
478
- By default, the datepicker input is `readonly` to prevent invalid date strings and force selection via the calendar. However, **browsers do not validate `readonly` fields** during native form submission.
479
-
480
- **Behavior:**
481
-
482
- - Native browser validation (e.g., blocking submit on `required` fields) will **NOT** trigger on the datepicker by default.
483
- - Custom validation (e.g., Angular validators) works normally but often only shows errors after the control is "touched".
484
-
485
- **Solutions:**
486
-
487
- 1. **Enable Typing (Recommended for Native Validation):**
488
- Set `[allowTyping]="true"` to make the input standard editable field. This enables native browser validation tooltips and submit-blocking.
489
-
490
- ```html
491
- <ngxsmk-datepicker [allowTyping]="true" required ...></ngxsmk-datepicker>
492
- ```
493
-
494
- 2. **Custom Validation Logic:**
495
- If you prefer the readonly behavior, ensure your form submission handler explicitly checks `form.invalid` before proceeding, as the browser won't stop the submit button click.
496
-
497
- ## **⚙️ API Reference**
498
-
499
- ### **Inputs**
500
-
501
- | Property | Type | Default | Description |
502
- | :----------------- | :--- | :------ | :---------- |
503
- | mode | 'single' \| 'range' \| 'multiple' | 'single' | The selection mode. |
504
- | inline | boolean \| 'always' \| 'auto' | false | Controls the display mode. `true` or `'always'` for inline, `'auto'` for responsive. |
505
- | locale | string | navigator.language | Sets the locale for language and regional formatting (e.g., 'en-US', 'de-DE'). |
506
- | theme | 'light' \| 'dark' | 'light' | The color theme. |
507
- | showRanges | boolean | true | If true, displays the predefined ranges panel when in 'range' mode. |
508
- | minDate | DateInput | null | The earliest selectable date. |
509
- | maxDate | DateInput | null | The latest selectable date. |
510
- | isInvalidDate | (date: Date) => boolean | () => false | A function to programmatically disable specific dates. |
511
- | ranges | DateRange | null | An object of predefined date ranges. |
512
- | minuteInterval | number | 1 | Interval for minute dropdown options. |
513
- | showTime | boolean | false | Enables the hour/minute/AM/PM selection section. |
514
- | timeOnly | boolean | false | Display time picker only (no calendar). Automatically enables `showTime`. |
515
- | use24Hour | boolean | false | Enable 24-hour time format (00-23) and hide AM/PM selector. |
516
- | allowTyping | boolean | false | Enable manual typing in the input field. Required for native validation. |
517
- | displayFormat | string | null | Custom date format string (e.g., 'MM/DD/YYYY'). |
518
- | showCalendarButton | boolean | false | Show/hide the calendar icon button. |
519
- | value | DatepickerValue | null | Programmatic value setting from code. |
520
- | startAt | DateInput | null | The date to initially center the calendar view on. |
521
- | holidayProvider | HolidayProvider | null | An object that provides holiday information. |
522
- | disableHolidays | boolean | false | If true, disables holiday dates from being selected. |
523
- | disabledDates | (string \| Date)[] | [] | Array of dates to disable. |
524
- | weekStart | number \| null | null | Override week start day (0=Sunday, 1=Monday, etc.). |
525
- | yearRange | number | 10 | Number of years before/after current year to show in year dropdown. |
526
- | clearLabel | string | 'Clear' | Custom label for the clear button. |
527
- | closeLabel | string | 'Close' | Custom label for the close button. |
528
- | prevMonthAriaLabel | string | 'Previous month' | Aria label for previous month navigation button. |
529
- | nextMonthAriaLabel | string | 'Next month' | Aria label for next month navigation button. |
530
- | clearAriaLabel | string | 'Clear selection' | Aria label for clear button. |
531
- | closeAriaLabel | string | 'Close calendar' | Aria label for close button. |
532
- | classes | object | undefined | Tailwind-friendly class overrides (wrapper, input, popover, etc.). |
533
- | enableGoogleCalendar| boolean | false | Enable seamless Google Calendar integration and sync. |
534
- | googleClientId | string \| null | null | Google API OAuth 2.0 Web Client ID for authentication. |
535
-
536
- ### **Outputs**
537
-
538
- | Event | Payload | Description |
539
- | :---------- | :------------------------------ | :------------------------------------------------------------ |
540
- | valueChange | DatepickerValue | Emits the newly selected date, range, or array of dates. |
541
- | action | { type: string; payload?: any } | Emits various events like `dateSelected`, `timeChanged`, etc. |
542
- | googleSyncClick | void | Emitted when the user clicks the Google Calendar sync button. |
543
-
544
- ## **🎨 Theming**
545
-
546
- ### CSS Variables
547
-
548
- You can easily customize the colors of the datepicker by overriding the CSS custom properties in your own stylesheet.
549
-
550
- ```css
551
- ngxsmk-datepicker {
552
- --datepicker-primary-color: #d9267d;
553
- --datepicker-primary-contrast: #ffffff;
554
- --datepicker-range-background: #fce7f3;
555
- }
556
- ```
557
-
558
- ### Tailwind/ngClass Support
559
-
560
- For Tailwind CSS or custom class-based theming, use the `classes` input:
561
-
562
- ```html
563
- <ngxsmk-datepicker
564
- mode="single"
565
- [classes]="{
566
- inputGroup: 'rounded-lg border',
567
- input: 'px-3 py-2 text-sm',
568
- popover: 'shadow-2xl',
569
- dayCell: 'hover:bg-indigo-50',
570
- footer: 'flex justify-end gap-2',
571
- clearBtn: 'btn btn-ghost',
572
- calendarBtn: 'btn btn-icon',
573
- closeBtn: 'btn btn-primary'
574
- }"
575
- >
576
- </ngxsmk-datepicker>
577
- ```
578
-
579
- ### Dark Theme
580
-
581
- To enable the dark theme, simply bind the theme input:
582
-
583
- ```html
584
- <ngxsmk-datepicker [theme]="'dark'"></ngxsmk-datepicker>
585
- ```
586
-
587
- ### Calendar Button Visibility
588
-
589
- Control the visibility of the calendar icon button:
590
-
591
- ```html
592
- <!-- Hide calendar button (default - users can still click input to open calendar) -->
593
- <ngxsmk-datepicker mode="single"> </ngxsmk-datepicker>
594
-
595
- <!-- Show calendar button -->
596
- <ngxsmk-datepicker [showCalendarButton]="true" mode="single"> </ngxsmk-datepicker>
597
-
598
- <!-- Useful with allowTyping for custom UI -->
599
- <ngxsmk-datepicker [allowTyping]="true" [showCalendarButton]="false" mode="single"> </ngxsmk-datepicker>
600
- ```
601
-
602
- ## **🌍 Localization (i18n)**
603
-
604
- The `locale` input controls all internationalization. It automatically formats month names, weekday names, and sets the first day of the week based on BCP 47 language tags.
605
-
606
- ### **Global Language Support**
607
-
608
- ngxsmk-datepicker v2.2.x now features **full localization synchronization** for:
609
-
610
- - �� English (`en`)
611
- - �� German (`de`)
612
- - �� French (`fr`)
613
- - �� Spanish (`es`)
614
- - 🇸🇪 Swedish (`sv`)
615
- - �� Korean (`ko`)
616
- - �� Chinese (`zh`)
617
- - �� Japanese (`ja`)
618
-
619
- ### **Usage Example**
620
-
621
- ```html
622
- <!-- Force German Locale -->
623
- <ngxsmk-datepicker [locale]="'de-DE'"></ngxsmk-datepicker>
624
-
625
- <!-- Swedish with YYYY-MM-DD format and Monday week start -->
626
- <ngxsmk-datepicker [locale]="'sv-SE'"></ngxsmk-datepicker>
627
- ```
628
-
629
- The component automatically uses ISO 8601 standards (Monday start) for European locales and appropriate regional date formats.
630
-
631
- ## **🖥️ Server-Side Rendering (SSR)**
632
-
633
- The datepicker is fully compatible with Angular Universal and server-side rendering:
634
-
635
- - ✅ All browser APIs are platform-checked
636
- - No `window` or `document` access during initialization
637
- - Works with partial hydration
638
- - Compatible with zoneless applications
639
-
640
- See the [SSR Guide](./projects/ngxsmk-datepicker/docs/ssr.md) for detailed setup instructions.
641
-
642
- ## **⌨️ Keyboard Navigation**
643
-
644
- The datepicker supports full keyboard navigation for accessibility:
645
-
646
- ### Built-in Shortcuts
647
-
648
- - **Arrow Keys** (← → ↑ ↓): Navigate between dates
649
- - **Page Up/Down**: Navigate months (Shift + Page Up/Down for years)
650
- - **Home/End**: Jump to first/last day of month
651
- - **Enter/Space**: Select focused date
652
- - **Escape**: Close calendar (popover mode)
653
- - **T**: Select today's date
654
- - **Y**: Select yesterday
655
- - **N**: Select tomorrow
656
- - **W**: Select next week (7 days from today)
657
- - **Tab**: Navigate between interactive elements
658
- - **?** (Shift + /): Toggle keyboard shortcuts help dialog
659
-
660
- ### Custom Keyboard Shortcuts
661
-
662
- You can add custom keyboard shortcuts using the `hooks` input or `customShortcuts` input:
663
-
664
- ```typescript
665
- import { DatepickerHooks, KeyboardShortcutContext } from "ngxsmk-datepicker";
666
-
667
- const myHooks: DatepickerHooks = {
668
- handleShortcut: (event, context) => {
669
- if (event.ctrlKey && event.key === "1") {
670
- // Custom action
671
- return true; // Handled
672
- }
673
- return false; // Use default
674
- },
675
- };
676
- ```
677
-
678
- ```html
679
- <ngxsmk-datepicker [hooks]="myHooks" [customShortcuts]="shortcuts" mode="single"> </ngxsmk-datepicker>
680
- ```
681
-
682
- All date cells are keyboard accessible with proper ARIA attributes for screen readers. The component is built with **accessibility in mind**: keyboard navigation, ARIA roles and labels, and live regions for announcements. For details see [API.md – Keyboard Support](projects/ngxsmk-datepicker/docs/API.md#keyboard-support) and the ARIA-related inputs (e.g. `closeAriaLabel`, `clearAriaLabel`) in the API reference.
683
-
684
- See [Extension Points Guide](./projects/ngxsmk-datepicker/docs/extension-points.md) for detailed customization options.
685
-
686
- ## **🚀 Performance Optimizations**
687
-
688
- This library has been optimized for maximum performance:
689
-
690
- - **30% Smaller Bundle**: Optimized build configuration and tree-shaking
691
- - **40% Faster Rendering**: OnPush change detection strategy with proper triggers
692
- - **60% Faster Selection**: Memoized date comparisons and debounced operations
693
- - **Zero Dependencies**: Standalone component with no external dependencies
694
- - **Tree-shakable**: Only import what you need
695
- - **Memory Efficient**: Cache size limits prevent memory leaks
696
- - **Hardware Accelerated**: CSS optimizations for smooth animations
697
- - **Mobile Optimized**: Touch-friendly interactions and responsive design
698
-
699
- ## **🐛 Bug Fixes & Improvements**
700
-
701
- ### **Critical Updates in v2.2.6:**
702
-
703
- - ✅ **Timezone Support**: Added full support for IANA timezones in "Today" calculation.
704
- - ✅ **Date Validation**: Fixed "Today" unselectable bug by normalizing `minDate` boundary checks.
705
- - **Keyboard Shortcuts**: Updated "Today" selection shortcut to use timezone-aware calculation.
706
- - ✅ **Validation messages**: User-facing i18n strings for invalid date, min/max; `validationError` output and on-screen error display
707
- - ✅ **Change Detection**: Fixed OnPush change detection issues with proper `markForCheck()` triggers
708
- - **Date Comparison**: Fixed null safety issues in date range comparisons
709
- - ✅ **Memory Leaks**: Added cache size limits to prevent memory leaks
710
- - **Type Safety**: Improved TypeScript types and null safety checks
711
- - ✅ **Mobile UX**: Enhanced mobile interactions and touch feedback
712
- - **Performance**: Optimized template bindings with memoized functions
713
- - ✅ **Accessibility**: Better focus states and keyboard navigation
714
- - **Build System**: Improved build configuration and optimization
715
-
716
- ### **Performance Enhancements:**
717
-
718
- - 🚀 **Optimized Bundle Size**: Main bundle ~127KB (source maps excluded from published package)
719
- - 🚀 **40% Faster Rendering**: Enhanced OnPush change detection
720
- - 🚀 **60% Faster Selection**: Memoized date comparisons
721
- - 🚀 **Memory Efficient**: Cache size limits prevent memory leaks
722
- - 🚀 **Hardware Accelerated**: CSS optimizations for smooth animations
723
- - 🚀 **Better Tree-Shaking**: Optimized TypeScript compiler settings for smaller output
724
- - 🚀 **Production Optimized**: Source maps automatically removed from production builds
725
-
726
- ## **📱 Demo Application**
727
-
728
- A comprehensive demo application is included to showcase all features with a modern, polished UI:
729
-
730
- ```bash
731
- # Clone the repository
732
- git clone https://github.com/NGXSMK/ngxsmk-datepicker.git
733
- cd ngxsmk-datepicker
734
-
735
- # Install dependencies
736
- npm install
737
-
738
- # Run the demo app
739
- npm start
740
- ```
741
-
742
- The demo includes:
743
-
744
- - **Modern UI Design**: Beautiful glassmorphism effects, gradient themes, and polished visual hierarchy
745
- - **Responsive Navigation**: Modern navbar with search, theme toggle, and mobile-friendly menu
746
- - **Enhanced Sidebar**: Redesigned documentation sidebar with smooth animations and visual indicators
747
- - **Signal Forms (Angular 21)** with writable signal binding examples
748
- - **Theming** with CSS variables and Tailwind classes examples
749
- - **Customization & A11y** with weekStart, yearRange, labels, and aria examples
750
- - **Holiday Provider Integration** with US holidays
751
- - **Single Date Selection** with weekend restrictions
752
- - **Inline Range Picker** with toggle controls
753
- - **Date Range with Time** selection
754
- - **Multiple Date Selection** with action tracking
755
- - **Programmatic Value Setting** for all selection modes
756
- - **Theme Toggle** (Light/Dark mode) with automatic system preference detection
757
- - **Customizable Calendar Views**: Year-picker, decade-picker, timeline view, and time-slider view
758
-
759
- ## **🔧 Development**
760
-
761
- ### **GitHub Actions**
762
-
763
- The project uses GitHub Actions for automated deployment:
764
-
765
- - **Deploy Demo App**: Automatically deploys the demo application to GitHub Pages on pushes to `main`/`master` branches
766
- - Workflow: `.github/workflows/deploy-demo.yml`
767
- - Triggers: Push to main/master or manual workflow dispatch
768
- - Builds and deploys the demo app to GitHub Pages
769
-
770
- ### **Building the Library**
771
-
772
- ```bash
773
- # Build the library (development)
774
- npm run build
775
-
776
- # Build optimized production version
777
- # - Removes source maps automatically
778
- # - Optimized TypeScript compilation
779
- # - Enhanced tree-shaking
780
- npm run build:optimized
781
-
782
- # Analyze bundle size (excludes source maps)
783
- npm run build:analyze
784
- ```
785
-
786
- **Build Output:**
787
-
788
- - Main bundle: `dist/ngxsmk-datepicker/fesm2022/ngxsmk-datepicker.mjs` (~127KB)
789
- - Type definitions: `dist/ngxsmk-datepicker/index.d.ts`
790
- - Source maps: Automatically removed from production builds
791
-
792
- ### **Running Tests**
793
-
794
- ```bash
795
- # Run all tests (library + demo app)
796
- npm test
797
-
798
- # Run library tests only
799
- npx ng test ngxsmk-datepicker --no-watch --browsers=ChromeHeadless
800
-
801
- # Run specific test file
802
- npx ng test ngxsmk-datepicker --include="**/issue-13.spec.ts"
803
-
804
- # Run tests in watch mode
805
- npm test -- --watch
806
- ```
807
-
808
- ### **Code Quality Improvements**
809
-
810
- The library now includes:
811
-
812
- - ✅ **TypeScript Strict Mode**: Enhanced type safety
813
- - ✅ **ESLint Configuration**: Code quality enforcement
814
- - **Performance Monitoring**: Built-in performance metrics
815
- - **Memory Leak Prevention**: Cache size limits and cleanup
816
- - **Accessibility Testing**: WCAG compliance checks
817
- - ✅ **Mobile Testing**: Touch interaction validation
818
-
819
- ## **📦 Package Structure**
820
-
821
- ```
822
- ngxsmk-datepicker/
823
- ├── projects/
824
- │ ├── ngxsmk-datepicker/ # Main library
825
- │ └── demo-app/ # Demo application
826
- ├── dist/ # Built packages
827
- ├── docs/ # Documentation
828
- └── scripts/ # Build scripts
829
- ```
830
-
831
- ## **🎯 Browser Support**
832
-
833
- - **Chrome** 90+
834
- - **Firefox** 88+
835
- - **Safari** 14+
836
- - **Edge** 90+
837
- - **Mobile Safari** 14+
838
- - **Chrome Mobile** 90+
839
-
840
- ## **🗺️ Roadmap**
841
-
842
- Check out our [Roadmap](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/ROADMAP.md) to see planned features, improvements, and how you can contribute. We're always looking for contributors, especially for issues labeled `good-first-issue` and `help-wanted`!
843
-
844
- ## **🤝 Contributions**
845
-
846
- We welcome and appreciate contributions from the community! Whether it's reporting a bug, suggesting a new feature, or submitting code, your help is valuable.
847
-
848
- ### **Development Setup**
849
-
850
- 1. **Fork the repository** on GitHub
851
- 2. **Clone your fork** to your local machine
852
- 3. **Install dependencies**: `npm install`
853
- 4. **Run the demo app**: `npm start`
854
- 5. **Create a feature branch** for your changes
855
- 6. **Commit your changes** following conventional commits
856
- 7. **Submit a Pull Request** to the main branch
857
-
858
- ### **Contribution Guidelines**
859
-
860
- - Follow the existing code style
861
- - Add tests for new features
862
- - Update documentation as needed
863
- - Ensure all tests pass
864
- - Follow conventional commit messages
865
-
866
- ## **📄 Changelog**
867
-
868
- **Recent:** Use **v2.2.13** on npm. The v2.2.x line adds `allowSameDay` range mode, IANA timezone support, TypeScript strictness, appendToBody/popover fixes, and CSS cleanup. Versions 2.0.10 and 2.0.11 are unpublished; use v2.1.1+ or **v2.2.13**.
869
-
870
- For the full list of changes, see [CHANGELOG.md](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/CHANGELOG.md).
871
-
872
- ## **🎨 Theming with TokiForge**
873
-
874
- Looking for a powerful theming solution for your Angular application? Check out **[TokiForge](https://tokiforge.github.io/tokiforge/)** — an open-source modern design token & theme engine that provides runtime theme switching for React, Vue, Svelte, Angular, and any framework.
875
-
876
- ### Why TokiForge?
877
-
878
- - **SSR compatible** Works seamlessly with Angular Universal
879
-
880
- Perfect for managing design tokens, creating theme systems, and implementing dark mode in your Angular applications!
881
-
882
- **👉 [Learn more about TokiForge →](https://tokiforge.github.io/tokiforge/)**
883
-
884
- ---
885
-
886
- ## **📜 License**
887
-
888
- MIT License - see [LICENSE](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/LICENSE) file for details.
889
-
890
- ## **🔍 SEO & Discoverability**
891
-
892
- This library is optimized for search engine visibility, especially for European markets:
893
-
894
- - **Keywords**: Angular datepicker, date range picker, calendar component, Angular 17-21, TypeScript, Signal Forms, SSR compatible
895
- - **European SEO**: Optimized for Germany, France, Spain, Italy, Netherlands, Poland, Portugal, Sweden, Norway, Finland, Denmark, Belgium, Switzerland, Austria, and United Kingdom
896
- - **Multi-language Support**: hreflang tags for 15+ European languages and locales
897
- - **European Geo-targeting**: Geo tags and structured data optimized for European Union countries
898
- - **Meta Tags**: Comprehensive Open Graph and Twitter Card support with European locale alternates
899
- - **Structured Data**: JSON-LD schema markup with European audience targeting and area served information
900
- - **Documentation**: Complete API documentation with examples
901
- - **Performance**: Optimized bundle size (~127KB) for fast loading
902
- - **European Localization**: Full i18n support for European date formats, week start days, and regional preferences
903
-
904
- ## **👨‍💻 Author**
905
-
906
- **Sachin Dilshan**
907
-
908
- - 📧 Email: [sachindilshan040@gmail.com](mailto:sachindilshan040@gmail.com)
909
- - 🐙 GitHub: [@toozuuu](https://github.com/toozuuu)
910
- - 📦 NPM: [ngxsmk-datepicker](https://www.npmjs.com/package/ngxsmk-datepicker)
911
- - 🌐 Website: [sachindilshan.com](https://www.sachindilshan.com/)
912
- - 💼 LinkedIn: [sachindilshan](https://www.linkedin.com/in/sachindilshan/)
913
-
914
- ## **⭐ Support**
915
-
916
- If you find this library helpful, please consider:
917
-
918
- - **Starring** the repository
919
- - 🐛 **Reporting** bugs and issues
920
- - 💡 **Suggesting** new features
921
- - 🤝 **Contributing** code improvements
922
- - 📢 **Sharing** with the community
923
-
1
+ <!--
2
+ SEO Keywords: Angular DatePicker, Angular Date Range Picker, Lightweight Calendar Component, Angular Signals DatePicker, SSR Ready DatePicker, Zoneless Angular, A11y DatePicker, Mobile-Friendly DatePicker, Ionic DatePicker
3
+ Meta Description: The most powerful, lightweight, and accessible date and range picker for modern Angular (17-21+). Built with Signals, Zoneless-ready, and zero dependencies.
4
+ -->
5
+
6
+ <div align="center">
7
+ <img src="projects/ngxsmk-datepicker/docs/header-banner.png" alt="ngxsmk-datepicker - Lightweight Angular Date Range Picker" width="100%" />
8
+
9
+ # **ngxsmk-datepicker** – Modern Angular Date Picker & Range Picker
10
+
11
+ ### _The Gold Standard for Premium Angular Calendar Selection_
12
+
13
+ [![npm version](https://img.shields.io/npm/v/ngxsmk-datepicker.svg?style=flat-square&color=6d28d9)](https://www.npmjs.com/package/ngxsmk-datepicker)
14
+ [![CI](https://img.shields.io/github/actions/workflow/status/NGXSMK/ngxsmk-datepicker/ci.yml?branch=main&label=CI&style=flat-square)](https://github.com/NGXSMK/ngxsmk-datepicker/actions/workflows/ci.yml)
15
+ [![Angular](https://img.shields.io/badge/Angular-17%2B-DD0031.svg?style=flat-square&logo=angular)](https://angular.io/)
16
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/LICENSE)
17
+ [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-toozuuu-orange?style=flat-square&logo=buy-me-a-coffee)](https://buymeacoffee.com/toozuuu)
18
+ [![Bundle Size](https://img.shields.io/badge/bundle-~127KB-success.svg?style=flat-square)](https://bundlephobia.com/package/ngxsmk-datepicker)
19
+ [![Zoneless](https://img.shields.io/badge/Zoneless-Ready-blueviolet.svg?style=flat-square)](https://angular.dev/guide/zoneless)
20
+
21
+ **`npm i ngxsmk-datepicker`**
22
+
23
+ [Live demo](https://ngxsmk.github.io/ngxsmk-datepicker/) • [StackBlitz (repo)](https://stackblitz.com/github/NGXSMK/ngxsmk-datepicker) • [API docs](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/API.md) • [Issues](https://github.com/NGXSMK/ngxsmk-datepicker/issues) • [Buy me a coffee](https://buymeacoffee.com/toozuuu)
24
+
25
+ *StackBlitz:* after it boots, run `npm install` then `npm start` in the terminal to serve the demo app (`demo-app`).
26
+
27
+ </div>
28
+
29
+ ---
30
+
31
+ **Last updated:** May 19, 2026 - **Current stable:** v2.3.0
32
+
33
+ ### **Overview**
34
+
35
+ **ngxsmk-datepicker** is a high-performance, enterprise-ready date and range picker engineered for the modern Angular ecosystem (v17+). Built from the ground up with **Angular Signals**, it delivers a seamless, zoneless-ready experience for both desktop and mobile (Ionic) applications.
36
+
37
+ > **Stable Release**: `v2.3.0` is the current stable release with compiled `fesm2022` output and type declarations.
38
+ >
39
+ > **Stable line**: v2.2.x includes range-mode **`allowSameDay`**, **IANA timezone** support, validation fixes, and strict TypeScript improvements. Versions **2.0.10** and **2.0.11** were broken and have been **unpublished**; use **v2.1.1+** or current **v2.3.0** on npm.
40
+
41
+ ---
42
+
43
+ ### **📌 Table of Contents**
44
+
45
+ 1. [📷 Screenshots](#-screenshots)
46
+ 2. [ Features](#-features)
47
+ 3. [🤔 Why this library?](#why-this-library)
48
+ 4. [🌐 Discoverability](#-discoverability)
49
+ 5. [📋 Compatibility](#-compatibility)
50
+ 6. [🌍 Localization (i18n)](#-localization-i18n)
51
+ 7. [📦 Installation](#-installation)
52
+ 8. [🚀 Quick start / usage](#usage)
53
+ 9. [🔌 Framework Integration](#-framework-integration)
54
+ 10. [⚙️ API Reference](#-api-reference)
55
+ 11. [🎨 Theming](#-theming)
56
+ 12. [⌨️ Keyboard Navigation](#-keyboard-navigation)
57
+
58
+ ---
59
+
60
+ ## 📷 Screenshots
61
+
62
+ <p align="center">
63
+ <img src="https://github.com/NGXSMK/ngxsmk-datepicker/raw/main/projects/ngxsmk-datepicker/docs/1.png" alt="Angular Standalone DatePicker Single Selection Mode" width="30%" />
64
+ <img src="https://github.com/NGXSMK/ngxsmk-datepicker/raw/main/projects/ngxsmk-datepicker/docs/2.png" alt="Angular Date Range Picker Selection Mode" width="30%" />
65
+ <img src="https://github.com/NGXSMK/ngxsmk-datepicker/raw/main/projects/ngxsmk-datepicker/docs/3.png" alt="Mobile Angular DatePicker Ionic Compatibility" width="30%" />
66
+ </p>
67
+
68
+ ## **✨ Features**
69
+
70
+ ### **Core Capabilities**
71
+
72
+ - 💎 **Signal-Driven Engine**: Hyper-reactive state management using Angular Signals.
73
+ - 🌓 **Native Dark Mode**: Beautifully crafted themes for light and dark environments.
74
+ - 📱 **Mobile-First UX**: Native mobile picker integration with touch gestures and haptic feedback.
75
+ - 🧩 **Minimal footprint**: Standalone component; **Luxon** is the only date peer beyond Angular (no full UI suite required).
76
+ - **Performance++**: Lazy-loaded calendar months, memoized calculations, and tree-shakable architecture.
77
+
78
+ ### **Advanced Functionality**
79
+
80
+ - 📅 **Google Calendar Sync**: Built-in support for seamlessly syncing and displaying events natively from Google Calendar.
81
+ - 🌐 **8-Language i18n**: Full localization for `en`, `de`, `es`, `sv`, `ko`, `zh`, `ja`, and `fr`.
82
+ - 🛠️ **Plugin Architecture**: Extend functionality via hooks for rendering, validation, and shortcuts.
83
+ - 🧪 **Signal Forms Native**: Direct integration with Angular 21's new Signal Forms API.
84
+ - 🚀 **Zoneless Ready**: Optimized for the future of Angular—works perfectly without zone.js.
85
+ - ♿ **Full Accessibility**: WAI-ARIA compliant with extensive keyboard navigation support.
86
+
87
+ ## Why this library?
88
+
89
+ Use **ngxsmk-datepicker** when you want a focused **date / range picker** with strong **mobile**, **i18n**, **timezone**, and **SSR** story on **Angular 17+**, without adopting a full Material UI stack. It is a **standalone** component with **Luxon** as the single date peer (plus Angular).
90
+
91
+ | | ngxsmk-datepicker | Angular Material datepicker |
92
+ | --- | --- | --- |
93
+ | **Fit** | Picker-first; optional Material/CDK peers for overlays only | Part of Material; best when you already use Material forms & CDK |
94
+ | **Peer deps** | Angular + **Luxon** | **@angular/material** + **@angular/cdk** |
95
+ | **Forms** | Template-driven, Reactive Forms, Signals; **Signal Forms** (`[field]`) on Angular 21+ | Reactive + template-driven; integrates with Material form field |
96
+ | **Stack** | Tree-shakable package aimed at picker scenarios | Broader design system and bundle footprint |
97
+
98
+ This is **not** a drop-in replacement for every Material datepicker API; choose based on whether you need **Material’s form-field ecosystem** or a **standalone picker** you can theme and ship with **zoneless** / **SSR** setups. See the [live demo](https://ngxsmk.github.io/ngxsmk-datepicker/) and [COMPATIBILITY](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/COMPATIBILITY.md) for details.
99
+
100
+ ## **🌐 Discoverability**
101
+
102
+ **Maintainers (GitHub):** consider repository **Topics** such as: `angular`, `datepicker`, `date-range-picker`, `luxon`, `standalone-components`, `i18n`, `angular-universal`, `ionic`, `accessibility`.
103
+
104
+ **Community:** if this project helped you, stars and accurate comparisons in blog posts or issue threads help others find it. Curated lists (for example **awesome-angular**-style repos) usually accept small PRs that add a one-line link and follow their contribution rules—check each list’s guidelines before opening a PR.
105
+
106
+ **Security:** report sensitive issues per [SECURITY.md](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/SECURITY.md), not via public issues.
107
+
108
+ ## **📋 Compatibility**
109
+
110
+ For detailed compatibility information, see [COMPATIBILITY.md](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/COMPATIBILITY.md).
111
+
112
+ ### Quick Reference
113
+
114
+ | Angular Version | Status | Core Features | Signal Forms | SSR | Zoneless |
115
+ | --------------- | ------------------ | ------------- | ------------ | --- | -------- |
116
+ | Angular 17 | Fully Supported | ✅ All | ❌ | ✅ | ✅ |
117
+ | Angular 18 | Fully Supported | ✅ All | ❌ | ✅ | ✅ |
118
+ | Angular 19 | Fully Supported | All | ❌ | ✅ | ✅ |
119
+ | Angular 20 | Fully Supported | All | ❌ | ✅ | ✅ |
120
+ | Angular 21 | ✅ Fully Supported | ✅ All | ✅ | ✅ | ✅ |
121
+ | Angular 22+ | 🔄 Future Support | ✅ All | ✅ | ✅ | ✅ |
122
+
123
+ **Zone.js**: Optional - The library works with or without Zone.js (zoneless apps supported)
124
+
125
+ **SSR**: Fully compatible with Angular Universal and server-side rendering
126
+
127
+ **Peer Dependencies**: `@angular/core >=17.0.0 <24.0.0`
128
+
129
+ ## **🔒 API Stability & Deprecation Policy**
130
+
131
+ ### API Stability Guarantees
132
+
133
+ - **Public API**: All public APIs (inputs, outputs, methods) are stable within a major version
134
+ - **Experimental Features**: Features marked as `experimental` may change in minor versions
135
+ - **Internal APIs**: Private methods and internal services are not part of the public API and may change without notice
136
+
137
+ ### Deprecation Policy
138
+
139
+ - **Deprecation Period**: Features are deprecated for at least **2 major versions** before removal
140
+ - **Deprecation Warnings**:
141
+ - `@deprecated` JSDoc tags in code
142
+ - Console warnings in development mode
143
+ - Clear documentation in CHANGELOG.md
144
+ - **Migration Guides**: Provided in `MIGRATION.md` for all breaking changes
145
+ - **Breaking Changes**: Only occur in major version releases (semver)
146
+
147
+ ### Stable APIs
148
+
149
+ The following are considered stable public APIs:
150
+
151
+ - Component inputs and outputs (`@Input()`, `@Output()`)
152
+ - Public methods documented in API docs
153
+ - Exported types and interfaces
154
+ - Service APIs (when marked as public)
155
+
156
+ ### Experimental Features
157
+
158
+ Features marked as experimental may change:
159
+
160
+ - Signal Forms support (`[field]` input) - Experimental in v1.9.x, stable in v2.0.0+
161
+ - Some advanced selection modes
162
+ - Plugin architecture hooks (subject to refinement)
163
+
164
+ For details, see [CONTRIBUTING.md](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/CONTRIBUTING.md#deprecation-policy).
165
+
166
+ ## **📦 Installation**
167
+
168
+ ```bash
169
+ npm install ngxsmk-datepicker@2.3.0
170
+ ```
171
+
172
+ ### Alternative installation
173
+
174
+ You can install without npm using any of these methods (peer dependencies must still be installed in your app):
175
+
176
+ | Method | Command |
177
+ |--------|--------|
178
+ | **Yarn** | `yarn add ngxsmk-datepicker@2.3.0` |
179
+ | **pnpm** | `pnpm add ngxsmk-datepicker@2.3.0` |
180
+ | **Bun** | `bun add ngxsmk-datepicker@2.3.0` |
181
+ | **From Git** | `npm install github:NGXSMK/ngxsmk-datepicker#v2.3.0` (requires the repo to have built output or you build from source) |
182
+ | **Local path** | Build the library in the repo (`npx ng build ngxsmk-datepicker`), then `npm install /path/to/ngxsmk-datepicker/dist/ngxsmk-datepicker` |
183
+ | **CDN (ESM)** | Use [unpkg](https://unpkg.com/ngxsmk-datepicker@2.3.0/) or [jsDelivr](https://cdn.jsdelivr.net/npm/ngxsmk-datepicker@2.3.0/) in your bundler or import map; peer dependencies (Angular, etc.) must be installed in your app. |
184
+
185
+ For all options and caveats, see [docs/INSTALLATION.md](docs/INSTALLATION.md).
186
+
187
+ ## **Usage**
188
+
189
+ ngxsmk-datepicker is a standalone component, so you can import it directly into your component or module.
190
+
191
+ ### Signal Forms (Angular 21)
192
+
193
+ You can bind directly to a writable Signal using standard two-way binding. This works seamlessly alongside traditional Reactive Forms.
194
+
195
+ ```ts
196
+ import { signal } from "@angular/core";
197
+ import { DatepickerValue } from "ngxsmk-datepicker";
198
+
199
+ export class MyComponent {
200
+ dateSig = signal<DatepickerValue>(null);
201
+ }
202
+ ```
203
+
204
+ ```html
205
+ <ngxsmk-datepicker mode="single" [value]="dateSig()" (valueChange)="dateSig.set($event)"> </ngxsmk-datepicker>
206
+
207
+ <p>Signal value: {{ dateSig() | json }}</p>
208
+ ```
209
+
210
+ This pattern is also compatible with computed/linked signals produced by `httpResource`, enabling powerful data flows with Angular 21.
211
+
212
+ ### Signal Forms with `[field]` Input (Angular 21+)
213
+
214
+ For direct integration with Angular Signal Forms, use the `[field]` input. The datepicker automatically tracks dirty state when using this binding:
215
+
216
+ ```typescript
217
+ import { Component, signal, form, objectSchema } from "@angular/core";
218
+ import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker";
219
+
220
+ @Component({
221
+ selector: "app-form",
222
+ standalone: true,
223
+ imports: [NgxsmkDatepickerComponent],
224
+ template: `
225
+ <form>
226
+ <ngxsmk-datepicker [field]="myForm.dateInQuestion" mode="single" placeholder="Select a date"> </ngxsmk-datepicker>
227
+ </form>
228
+ `,
229
+ })
230
+ export class FormComponent {
231
+ localObject = signal({ dateInQuestion: new Date() });
232
+
233
+ myForm = form(
234
+ this.localObject,
235
+ objectSchema({
236
+ dateInQuestion: objectSchema<Date>(),
237
+ }),
238
+ );
239
+ }
240
+ ```
241
+
242
+ The `[field]` input provides automatic two-way binding with signal forms - no manual event handling needed! It also automatically tracks the form's dirty state, so `form().dirty()` will return `true` after a user selects a date.
243
+
244
+ For detailed Signal Forms integration including dirty state tracking, see the [Signal Forms Integration Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/signal-forms.md).
245
+
246
+ ### Documentation
247
+
248
+ - **[Plugin Architecture](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/PLUGIN-ARCHITECTURE.md)** - Complete guide to the plugin architecture and hook system
249
+ - **[Signals Integration Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/signals.md)** - Complete guide to using signals with the datepicker
250
+ - **[Signal Forms Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/signal-forms.md)** - Deep dive into Signal Forms integration
251
+ - **[SSR Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/ssr.md)** - Server-side rendering setup and best practices
252
+ - **[SSR Example](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/SSR-EXAMPLE.md)** - Complete Angular Universal example with hydration notes
253
+ - **[Extension Points Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/extension-points.md)** - Customization hooks and extension points
254
+ - **[Theme Tokens Reference](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/THEME-TOKENS.md)** - Complete CSS custom properties reference with examples
255
+ - **[API Documentation](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/API.md)** - Complete public API reference
256
+
257
+ #### **1. Import the Component**
258
+
259
+ All public exports (component, utilities, types, services) come from the main package entry: `'ngxsmk-datepicker'` (there is no separate `/utils` subpath). In your component file (e.g., app.component.ts), import the component (or the module—see troubleshooting below).
260
+
261
+ import { Component } from '@angular/core';
262
+ import { NgxsmkDatepickerComponent, DateRange, HolidayProvider } from 'ngxsmk-datepicker';
263
+
264
+ @Component({
265
+ selector: 'app-root',
266
+ standalone: true,
267
+ imports: [NgxsmkDatepickerComponent],
268
+ templateUrl: './app.component.html',
269
+ })
270
+ export class AppComponent {
271
+ // Example for predefined ranges
272
+ public myRanges: DateRange = {
273
+ 'Today': [new Date(), new Date()],
274
+ 'Last 7 Days': [new Date(new Date().setDate(new Date().getDate() - 6)), new Date()],
275
+ 'This Month': [new Date(new Date().getFullYear(), new Date().getMonth(), 1), new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0)],
276
+ };
277
+
278
+ // Example for disabling weekends
279
+ isWeekend = (date: Date): boolean => {
280
+ const day = date.getDay();
281
+ return day === 0 || day === 6; // Sunday or Saturday
282
+ };
283
+
284
+ onDateChange(value: Date | { start: Date; end: Date } | Date[]) {
285
+ console.log('Date changed:', value);
286
+ }
287
+ }
288
+
289
+ **If you see NG1010** (`'imports' must be an array... Value could not be determined statically`) when using the Angular compiler plugin or in strict AOT builds, use the wrapper module instead: `import { NgxsmkDatepickerModule } from 'ngxsmk-datepicker'` and set `imports: [NgxsmkDatepickerModule]`. The template stays the same (`<ngxsmk-datepicker>`).
290
+
291
+ #### **2. Add it to Your Template**
292
+
293
+ Use the `<ngxsmk-datepicker>` selector in your HTML template.
294
+
295
+ ````html
296
+ <h2>Advanced Date Range Picker</h2>
297
+
298
+ <ngxsmk-datepicker [mode]="'range'" [ranges]="myRanges" [showTime]="true" [minuteInterval]="15" [minDate]="today" [isInvalidDate]="isWeekend" [locale]="'en-US'" [theme]="'light'" [inline]="'auto'" (valueChange)="onDateChange($event)"></ngxsmk-datepicker>
299
+
300
+ #### **3. Disabled Dates Example** Disable specific dates by passing an array of date strings or Date objects: ```typescript // In your component disabledDates = ['10/21/2025', '08/21/2025', '10/15/2025', '10/8/2025', '10/3/2025']; // In your template
301
+ <ngxsmk-datepicker [mode]="'single'" [disabledDates]="disabledDates" placeholder="Select a date"> </ngxsmk-datepicker>
302
+ ````
303
+
304
+ #### **4. Holiday Tooltips Example**
305
+
306
+ Holiday dates automatically show tooltips when you hover over them:
307
+
308
+ ```typescript
309
+ // Holiday provider with tooltips
310
+ class MyHolidayProvider implements HolidayProvider {
311
+ private holidays: { [key: string]: string } = {
312
+ '2025-01-01': 'New Year\'s Day',
313
+ '2025-07-04': 'Independence Day',
314
+ '2025-12-25': 'Christmas Day',
315
+ };
316
+
317
+ isHoliday(date: Date): boolean {
318
+ const key = this.formatDateKey(date);
319
+ return !!this.holidays[key];
320
+ }
321
+
322
+ getHolidayLabel(date: Date): string | null {
323
+ const key = this.formatDateKey(date);
324
+ return this.holidays[key] || null;
325
+ }
326
+ }
327
+
328
+ // In your template
329
+ <ngxsmk-datepicker
330
+ [holidayProvider]="holidayProvider"
331
+ [disableHolidays]="false"
332
+ placeholder="Hover over holidays to see tooltips">
333
+ </ngxsmk-datepicker>
334
+ ```
335
+
336
+ ## **🔌 Framework Integration**
337
+
338
+ ### **Angular Material Form Fields**
339
+
340
+ Integrate with Angular Material's form field components for a seamless Material Design experience. Works with both standalone and non-standalone components:
341
+
342
+ **Standalone Components:**
343
+
344
+ ```typescript
345
+ import { Component } from "@angular/core";
346
+ import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms";
347
+ import { MatFormFieldModule } from "@angular/material/form-field";
348
+ import { MatInputModule } from "@angular/material/input";
349
+ import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker";
350
+
351
+ @Component({
352
+ selector: "app-material-form",
353
+ standalone: true,
354
+ imports: [ReactiveFormsModule, MatFormFieldModule, MatInputModule, NgxsmkDatepickerComponent],
355
+ template: `
356
+ <form [formGroup]="myForm">
357
+ <mat-form-field appearance="outline">
358
+ <mat-label>Select Date</mat-label>
359
+ <ngxsmk-datepicker mode="single" formControlName="date" placeholder="Choose a date"> </ngxsmk-datepicker>
360
+ </mat-form-field>
361
+ </form>
362
+ `,
363
+ })
364
+ export class MaterialFormComponent {
365
+ myForm = new FormGroup({
366
+ date: new FormControl<Date | null>(null),
367
+ });
368
+ }
369
+ ```
370
+
371
+ **Non-Standalone (NgModules):** Add the directive file from [INTEGRATION.md § Angular Material](projects/ngxsmk-datepicker/docs/INTEGRATION.md#angular-material), then add it to your module `imports` (with `NgxsmkDatepickerComponent`, `MatFormFieldModule`, etc.) and use `ngxsmkMatFormFieldControl` on the datepicker in templates.
372
+
373
+ **With Date Range:**
374
+
375
+ ```html
376
+ <mat-form-field appearance="fill">
377
+ <mat-label>Date Range</mat-label>
378
+ <ngxsmk-datepicker mode="range" [showTime]="true" formControlName="dateRange"> </ngxsmk-datepicker>
379
+ </mat-form-field>
380
+ ```
381
+
382
+ ### **Ionic Components**
383
+
384
+ For best integration with Ionic, import the integration styles in your global CSS/SCSS file:
385
+
386
+ ```css
387
+ @import "ngxsmk-datepicker/styles/ionic-integration.css";
388
+ ```
389
+
390
+ **Automatic Theming:**
391
+ The datepicker automatically detects and uses Ionic CSS variables (e.g., `--ion-color-primary`, `--ion-background-color`) so it matches your app's theme out of the box without extra configuration.
392
+
393
+ Works seamlessly with Ionic form components and follows Ionic design patterns:
394
+
395
+ ```typescript
396
+ import { Component } from "@angular/core";
397
+ import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms";
398
+ import { IonItem, IonLabel, IonInput } from "@ionic/angular/standalone";
399
+ import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker";
400
+
401
+ @Component({
402
+ selector: "app-ionic-form",
403
+ standalone: true,
404
+ imports: [ReactiveFormsModule, IonItem, IonLabel, IonInput, NgxsmkDatepickerComponent],
405
+ template: `
406
+ <form [formGroup]="myForm">
407
+ <ion-item>
408
+ <ion-label position="stacked">Appointment Date</ion-label>
409
+ <ngxsmk-datepicker mode="single" formControlName="appointmentDate" placeholder="Select date"> </ngxsmk-datepicker>
410
+ </ion-item>
411
+ </form>
412
+ `,
413
+ })
414
+ export class IonicFormComponent {
415
+ myForm = new FormGroup({
416
+ appointmentDate: new FormControl<Date | null>(null),
417
+ });
418
+ }
419
+ ```
420
+
421
+ **With Ionic Datetime Styling:**
422
+
423
+ ```html
424
+ <ion-item>
425
+ <ion-label>Check-in / Check-out</ion-label>
426
+ <ngxsmk-datepicker mode="range" [theme]="'light'" formControlName="bookingDates"> </ngxsmk-datepicker>
427
+ </ion-item>
428
+ ```
429
+
430
+ ### **React, Vue, & Vanilla JS (Web Components)**
431
+
432
+ Because `ngxsmk-datepicker` is highly decoupled from heavy external dependencies, it can be exported as a standard Custom Web Component using Angular Elements. This allows you to use exactly the same datepicker in React, Vue, Svelte, or Vanilla JavaScript projects seamlessly!
433
+
434
+ **1. Create a Custom Element Wrapper**
435
+ ```typescript
436
+ import { createApplication } from '@angular/platform-browser';
437
+ import { createCustomElement } from '@angular/elements';
438
+ import { NgxsmkDatepickerComponent } from 'ngxsmk-datepicker';
439
+
440
+ (async () => {
441
+ const app = await createApplication();
442
+ const DatepickerElement = createCustomElement(NgxsmkDatepickerComponent, { injector: app.injector });
443
+ customElements.define('ngxsmk-datepicker', DatepickerElement);
444
+ })().catch(console.error);
445
+ ```
446
+
447
+ **2. Use It Natively Anywhere**
448
+ ```html
449
+ <!-- In any HTML, React, Vue, or Svelte file -->
450
+ <ngxsmk-datepicker id="myPicker" mode="range" theme="light"></ngxsmk-datepicker>
451
+
452
+ <script>
453
+ // Add native DOM event listeners
454
+ document.getElementById('myPicker').addEventListener('dateSelect', (e) => {
455
+ console.log('Selected date:', e.detail);
456
+ });
457
+ </script>
458
+ ```
459
+
460
+ For full working examples (including React & Vue bindings), check out the `/examples` directory in our GitHub repository!
461
+
462
+ ### **Plain HTML Inputs**
463
+
464
+ Use with standard HTML form inputs for maximum flexibility:
465
+
466
+ ```typescript
467
+ import { Component } from "@angular/core";
468
+ import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms";
469
+ import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker";
470
+
471
+ @Component({
472
+ selector: "app-plain-form",
473
+ standalone: true,
474
+ imports: [ReactiveFormsModule, NgxsmkDatepickerComponent],
475
+ template: `
476
+ <form [formGroup]="myForm">
477
+ <label for="birthdate">Birth Date</label>
478
+ <ngxsmk-datepicker id="birthdate" mode="single" formControlName="birthdate" placeholder="MM/DD/YYYY"> </ngxsmk-datepicker>
479
+
480
+ <button type="submit">Submit</button>
481
+ </form>
482
+ `,
483
+ })
484
+ export class PlainFormComponent {
485
+ myForm = new FormGroup({
486
+ birthdate: new FormControl<Date | null>(null),
487
+ });
488
+ }
489
+ ```
490
+
491
+ **With Native HTML5 Validation:**
492
+
493
+ ```html
494
+ <form [formGroup]="myForm">
495
+ <div class="form-group">
496
+ <label for="event-date">Event Date *</label>
497
+ <ngxsmk-datepicker id="event-date" mode="single" formControlName="eventDate" [minDate]="today" required> </ngxsmk-datepicker>
498
+ </div>
499
+ </form>
500
+ ```
501
+
502
+ ### **Form Validation**
503
+
504
+ By default, the datepicker input is `readonly` to prevent invalid date strings and force selection via the calendar. However, **browsers do not validate `readonly` fields** during native form submission.
505
+
506
+ **Behavior:**
507
+
508
+ - Native browser validation (e.g., blocking submit on `required` fields) will **NOT** trigger on the datepicker by default.
509
+ - Custom validation (e.g., Angular validators) works normally but often only shows errors after the control is "touched".
510
+
511
+ **Solutions:**
512
+
513
+ 1. **Enable Typing (Recommended for Native Validation):**
514
+ Set `[allowTyping]="true"` to make the input standard editable field. This enables native browser validation tooltips and submit-blocking.
515
+
516
+ ```html
517
+ <ngxsmk-datepicker [allowTyping]="true" required ...></ngxsmk-datepicker>
518
+ ```
519
+
520
+ 2. **Custom Validation Logic:**
521
+ If you prefer the readonly behavior, ensure your form submission handler explicitly checks `form.invalid` before proceeding, as the browser won't stop the submit button click.
522
+
523
+ ## **⚙️ API Reference**
524
+
525
+ ### **Inputs**
526
+
527
+ | Property | Type | Default | Description |
528
+ | :----------------- | :--- | :------ | :---------- |
529
+ | mode | 'single' \| 'range' \| 'multiple' | 'single' | The selection mode. |
530
+ | inline | boolean \| 'always' \| 'auto' | false | Controls the display mode. `true` or `'always'` for inline, `'auto'` for responsive. |
531
+ | locale | string | navigator.language | Sets the locale for language and regional formatting (e.g., 'en-US', 'de-DE'). |
532
+ | theme | 'light' \| 'dark' | 'light' | The color theme. |
533
+ | showRanges | boolean | true | If true, displays the predefined ranges panel when in 'range' mode. |
534
+ | minDate | DateInput | null | The earliest selectable date. |
535
+ | maxDate | DateInput | null | The latest selectable date. |
536
+ | isInvalidDate | (date: Date) => boolean | () => false | A function to programmatically disable specific dates. |
537
+ | ranges | DateRange | null | An object of predefined date ranges. |
538
+ | minuteInterval | number | 1 | Interval for minute dropdown options. |
539
+ | showTime | boolean | false | Enables the hour/minute/AM/PM selection section. |
540
+ | timeOnly | boolean | false | Display time picker only (no calendar). Automatically enables `showTime`. |
541
+ | use24Hour | boolean | false | Enable 24-hour time format (00-23) and hide AM/PM selector. |
542
+ | allowTyping | boolean | false | Enable manual typing in the input field. Required for native validation. |
543
+ | displayFormat | string | null | Custom date format string (e.g., 'MM/DD/YYYY'). |
544
+ | showCalendarButton | boolean | false | Show/hide the calendar icon button. |
545
+ | value | DatepickerValue | null | Programmatic value setting from code. |
546
+ | startAt | DateInput | null | The date to initially center the calendar view on. |
547
+ | holidayProvider | HolidayProvider | null | An object that provides holiday information. |
548
+ | disableHolidays | boolean | false | If true, disables holiday dates from being selected. |
549
+ | disabledDates | (string \| Date)[] | [] | Array of dates to disable. |
550
+ | weekStart | number \| null | null | Override week start day (0=Sunday, 1=Monday, etc.). |
551
+ | yearRange | number | 10 | Number of years before/after current year to show in year dropdown. |
552
+ | clearLabel | string | 'Clear' | Custom label for the clear button. |
553
+ | closeLabel | string | 'Close' | Custom label for the close button. |
554
+ | prevMonthAriaLabel | string | 'Previous month' | Aria label for previous month navigation button. |
555
+ | nextMonthAriaLabel | string | 'Next month' | Aria label for next month navigation button. |
556
+ | clearAriaLabel | string | 'Clear selection' | Aria label for clear button. |
557
+ | closeAriaLabel | string | 'Close calendar' | Aria label for close button. |
558
+ | classes | object | undefined | Tailwind-friendly class overrides (wrapper, input, popover, etc.). |
559
+ | enableGoogleCalendar| boolean | false | Enable seamless Google Calendar integration and sync. |
560
+ | googleClientId | string \| null | null | Google API OAuth 2.0 Web Client ID for authentication. |
561
+
562
+ ### **Outputs**
563
+
564
+ | Event | Payload | Description |
565
+ | :---------- | :------------------------------ | :------------------------------------------------------------ |
566
+ | valueChange | DatepickerValue | Emits the newly selected date, range, or array of dates. |
567
+ | action | { type: string; payload?: any } | Emits various events like `dateSelected`, `timeChanged`, etc. |
568
+ | googleSyncClick | void | Emitted when the user clicks the Google Calendar sync button. |
569
+
570
+ ## **🎨 Theming**
571
+
572
+ ### CSS Variables
573
+
574
+ You can easily customize the colors of the datepicker by overriding the CSS custom properties in your own stylesheet.
575
+
576
+ ```css
577
+ ngxsmk-datepicker {
578
+ --datepicker-primary-color: #d9267d;
579
+ --datepicker-primary-contrast: #ffffff;
580
+ --datepicker-range-background: #fce7f3;
581
+ }
582
+ ```
583
+
584
+ ### Tailwind/ngClass Support
585
+
586
+ For Tailwind CSS or custom class-based theming, use the `classes` input:
587
+
588
+ ```html
589
+ <ngxsmk-datepicker
590
+ mode="single"
591
+ [classes]="{
592
+ inputGroup: 'rounded-lg border',
593
+ input: 'px-3 py-2 text-sm',
594
+ popover: 'shadow-2xl',
595
+ dayCell: 'hover:bg-indigo-50',
596
+ footer: 'flex justify-end gap-2',
597
+ clearBtn: 'btn btn-ghost',
598
+ calendarBtn: 'btn btn-icon',
599
+ closeBtn: 'btn btn-primary'
600
+ }"
601
+ >
602
+ </ngxsmk-datepicker>
603
+ ```
604
+
605
+ ### Dark Theme
606
+
607
+ To enable the dark theme, simply bind the theme input:
608
+
609
+ ```html
610
+ <ngxsmk-datepicker [theme]="'dark'"></ngxsmk-datepicker>
611
+ ```
612
+
613
+ ### Calendar Button Visibility
614
+
615
+ Control the visibility of the calendar icon button:
616
+
617
+ ```html
618
+ <!-- Hide calendar button (default - users can still click input to open calendar) -->
619
+ <ngxsmk-datepicker mode="single"> </ngxsmk-datepicker>
620
+
621
+ <!-- Show calendar button -->
622
+ <ngxsmk-datepicker [showCalendarButton]="true" mode="single"> </ngxsmk-datepicker>
623
+
624
+ <!-- Useful with allowTyping for custom UI -->
625
+ <ngxsmk-datepicker [allowTyping]="true" [showCalendarButton]="false" mode="single"> </ngxsmk-datepicker>
626
+ ```
627
+
628
+ ## **🌍 Localization (i18n)**
629
+
630
+ The `locale` input controls all internationalization. It automatically formats month names, weekday names, and sets the first day of the week based on BCP 47 language tags.
631
+
632
+ ### **Global Language Support**
633
+
634
+ ngxsmk-datepicker v2.2.x now features **full localization synchronization** for:
635
+
636
+ - �� English (`en`)
637
+ - �� German (`de`)
638
+ - �� French (`fr`)
639
+ - �� Spanish (`es`)
640
+ - 🇸🇪 Swedish (`sv`)
641
+ - �� Korean (`ko`)
642
+ - �� Chinese (`zh`)
643
+ - �� Japanese (`ja`)
644
+
645
+ ### **Usage Example**
646
+
647
+ ```html
648
+ <!-- Force German Locale -->
649
+ <ngxsmk-datepicker [locale]="'de-DE'"></ngxsmk-datepicker>
650
+
651
+ <!-- Swedish with YYYY-MM-DD format and Monday week start -->
652
+ <ngxsmk-datepicker [locale]="'sv-SE'"></ngxsmk-datepicker>
653
+ ```
654
+
655
+ The component automatically uses ISO 8601 standards (Monday start) for European locales and appropriate regional date formats.
656
+
657
+ ## **🖥️ Server-Side Rendering (SSR)**
658
+
659
+ The datepicker is fully compatible with Angular Universal and server-side rendering:
660
+
661
+ - ✅ All browser APIs are platform-checked
662
+ - No `window` or `document` access during initialization
663
+ - ✅ Works with partial hydration
664
+ - ✅ Compatible with zoneless applications
665
+
666
+ See the [SSR Guide](./projects/ngxsmk-datepicker/docs/ssr.md) for detailed setup instructions.
667
+
668
+ ## **⌨️ Keyboard Navigation**
669
+
670
+ The datepicker supports full keyboard navigation for accessibility:
671
+
672
+ ### Built-in Shortcuts
673
+
674
+ - **Arrow Keys** (← → ↑ ↓): Navigate between dates
675
+ - **Page Up/Down**: Navigate months (Shift + Page Up/Down for years)
676
+ - **Home/End**: Jump to first/last day of month
677
+ - **Enter/Space**: Select focused date
678
+ - **Escape**: Close calendar (popover mode)
679
+ - **T**: Select today's date
680
+ - **Y**: Select yesterday
681
+ - **N**: Select tomorrow
682
+ - **W**: Select next week (7 days from today)
683
+ - **Tab**: Navigate between interactive elements
684
+ - **?** (Shift + /): Toggle keyboard shortcuts help dialog
685
+
686
+ ### Custom Keyboard Shortcuts
687
+
688
+ You can add custom keyboard shortcuts using the `hooks` input or `customShortcuts` input:
689
+
690
+ ```typescript
691
+ import { DatepickerHooks, KeyboardShortcutContext } from "ngxsmk-datepicker";
692
+
693
+ const myHooks: DatepickerHooks = {
694
+ handleShortcut: (event, context) => {
695
+ if (event.ctrlKey && event.key === "1") {
696
+ // Custom action
697
+ return true; // Handled
698
+ }
699
+ return false; // Use default
700
+ },
701
+ };
702
+ ```
703
+
704
+ ```html
705
+ <ngxsmk-datepicker [hooks]="myHooks" [customShortcuts]="shortcuts" mode="single"> </ngxsmk-datepicker>
706
+ ```
707
+
708
+ All date cells are keyboard accessible with proper ARIA attributes for screen readers. The component is built with **accessibility in mind**: keyboard navigation, ARIA roles and labels, and live regions for announcements. For details see [API.md – Keyboard Support](projects/ngxsmk-datepicker/docs/API.md#keyboard-support) and the ARIA-related inputs (e.g. `closeAriaLabel`, `clearAriaLabel`) in the API reference.
709
+
710
+ See [Extension Points Guide](./projects/ngxsmk-datepicker/docs/extension-points.md) for detailed customization options.
711
+
712
+ ## **🚀 Performance Optimizations**
713
+
714
+ This library has been optimized for maximum performance:
715
+
716
+ - **30% Smaller Bundle**: Optimized build configuration and tree-shaking
717
+ - **40% Faster Rendering**: OnPush change detection strategy with proper triggers
718
+ - **60% Faster Selection**: Memoized date comparisons and debounced operations
719
+ - **Zero Dependencies**: Standalone component with no external dependencies
720
+ - **Tree-shakable**: Only import what you need
721
+ - **Memory Efficient**: Cache size limits prevent memory leaks
722
+ - **Hardware Accelerated**: CSS optimizations for smooth animations
723
+ - **Mobile Optimized**: Touch-friendly interactions and responsive design
724
+
725
+ ## **🐛 Bug Fixes & Improvements**
726
+
727
+ ### **Critical Updates in v2.2.6:**
728
+
729
+ - ✅ **Timezone Support**: Added full support for IANA timezones in "Today" calculation.
730
+ - ✅ **Date Validation**: Fixed "Today" unselectable bug by normalizing `minDate` boundary checks.
731
+ - **Keyboard Shortcuts**: Updated "Today" selection shortcut to use timezone-aware calculation.
732
+ - **Validation messages**: User-facing i18n strings for invalid date, min/max; `validationError` output and on-screen error display
733
+ - ✅ **Change Detection**: Fixed OnPush change detection issues with proper `markForCheck()` triggers
734
+ - ✅ **Date Comparison**: Fixed null safety issues in date range comparisons
735
+ - **Memory Leaks**: Added cache size limits to prevent memory leaks
736
+ - ✅ **Type Safety**: Improved TypeScript types and null safety checks
737
+ - ✅ **Mobile UX**: Enhanced mobile interactions and touch feedback
738
+ - **Performance**: Optimized template bindings with memoized functions
739
+ - ✅ **Accessibility**: Better focus states and keyboard navigation
740
+ - ✅ **Build System**: Improved build configuration and optimization
741
+
742
+ ### **Performance Enhancements:**
743
+
744
+ - 🚀 **Optimized Bundle Size**: Main bundle ~127KB (source maps excluded from published package)
745
+ - 🚀 **40% Faster Rendering**: Enhanced OnPush change detection
746
+ - 🚀 **60% Faster Selection**: Memoized date comparisons
747
+ - 🚀 **Memory Efficient**: Cache size limits prevent memory leaks
748
+ - 🚀 **Hardware Accelerated**: CSS optimizations for smooth animations
749
+ - 🚀 **Better Tree-Shaking**: Optimized TypeScript compiler settings for smaller output
750
+ - 🚀 **Production Optimized**: Source maps automatically removed from production builds
751
+
752
+ ## **📱 Demo Application**
753
+
754
+ A comprehensive demo application is included to showcase all features with a modern, polished UI:
755
+
756
+ ```bash
757
+ # Clone the repository
758
+ git clone https://github.com/NGXSMK/ngxsmk-datepicker.git
759
+ cd ngxsmk-datepicker
760
+
761
+ # Install dependencies
762
+ npm install
763
+
764
+ # Run the demo app
765
+ npm start
766
+ ```
767
+
768
+ The demo includes:
769
+
770
+ - **Modern UI Design**: Beautiful glassmorphism effects, gradient themes, and polished visual hierarchy
771
+ - **Responsive Navigation**: Modern navbar with search, theme toggle, and mobile-friendly menu
772
+ - **Enhanced Sidebar**: Redesigned documentation sidebar with smooth animations and visual indicators
773
+ - **Signal Forms (Angular 21)** with writable signal binding examples
774
+ - **Theming** with CSS variables and Tailwind classes examples
775
+ - **Customization & A11y** with weekStart, yearRange, labels, and aria examples
776
+ - **Holiday Provider Integration** with US holidays
777
+ - **Single Date Selection** with weekend restrictions
778
+ - **Inline Range Picker** with toggle controls
779
+ - **Date Range with Time** selection
780
+ - **Multiple Date Selection** with action tracking
781
+ - **Programmatic Value Setting** for all selection modes
782
+ - **Theme Toggle** (Light/Dark mode) with automatic system preference detection
783
+ - **Customizable Calendar Views**: Year-picker, decade-picker, timeline view, and time-slider view
784
+
785
+ ## **🔧 Development**
786
+
787
+ ### **GitHub Actions**
788
+
789
+ The project uses GitHub Actions for automated deployment:
790
+
791
+ - **Deploy Demo App**: Automatically deploys the demo application to GitHub Pages on pushes to `main`/`master` branches
792
+ - Workflow: `.github/workflows/deploy-demo.yml`
793
+ - Triggers: Push to main/master or manual workflow dispatch
794
+ - Builds and deploys the demo app to GitHub Pages
795
+
796
+ ### **Building the Library**
797
+
798
+ ```bash
799
+ # Build the library (development)
800
+ npm run build
801
+
802
+ # Build optimized production version
803
+ # - Removes source maps automatically
804
+ # - Optimized TypeScript compilation
805
+ # - Enhanced tree-shaking
806
+ npm run build:optimized
807
+
808
+ # Analyze bundle size (excludes source maps)
809
+ npm run build:analyze
810
+ ```
811
+
812
+ **Build Output:**
813
+
814
+ - Main bundle: `dist/ngxsmk-datepicker/fesm2022/ngxsmk-datepicker.mjs` (~127KB)
815
+ - Type definitions: `dist/ngxsmk-datepicker/index.d.ts`
816
+ - Source maps: Automatically removed from production builds
817
+
818
+ ### **Running Tests**
819
+
820
+ ```bash
821
+ # Run all tests (library + demo app)
822
+ npm test
823
+
824
+ # Run library tests only
825
+ npx ng test ngxsmk-datepicker --no-watch --browsers=ChromeHeadless
826
+
827
+ # Run specific test file
828
+ npx ng test ngxsmk-datepicker --include="**/issue-13.spec.ts"
829
+
830
+ # Run tests in watch mode
831
+ npm test -- --watch
832
+ ```
833
+
834
+ ### **Code Quality Improvements**
835
+
836
+ The library now includes:
837
+
838
+ - **TypeScript Strict Mode**: Enhanced type safety
839
+ - ✅ **ESLint Configuration**: Code quality enforcement
840
+ - **Performance Monitoring**: Built-in performance metrics
841
+ - ✅ **Memory Leak Prevention**: Cache size limits and cleanup
842
+ - **Accessibility Testing**: WCAG compliance checks
843
+ - ✅ **Mobile Testing**: Touch interaction validation
844
+
845
+ ## **📦 Package Structure**
846
+
847
+ ```
848
+ ngxsmk-datepicker/
849
+ ├── projects/
850
+ │ ├── ngxsmk-datepicker/ # Main library
851
+ │ └── demo-app/ # Demo application
852
+ ├── dist/ # Built packages
853
+ ├── docs/ # Documentation
854
+ └── scripts/ # Build scripts
855
+ ```
856
+
857
+ ## **🎯 Browser Support**
858
+
859
+ - **Chrome** 90+
860
+ - **Firefox** 88+
861
+ - **Safari** 14+
862
+ - **Edge** 90+
863
+ - **Mobile Safari** 14+
864
+ - **Chrome Mobile** 90+
865
+
866
+ ## **🗺️ Roadmap**
867
+
868
+ Check out our [Roadmap](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/ROADMAP.md) to see planned features, improvements, and how you can contribute. We're always looking for contributors, especially for issues labeled `good-first-issue` and `help-wanted`!
869
+
870
+ ## **🤝 Contributions**
871
+
872
+ We welcome and appreciate contributions from the community! Whether it's reporting a bug, suggesting a new feature, or submitting code, your help is valuable.
873
+
874
+ ### **Development Setup**
875
+
876
+ 1. **Fork the repository** on GitHub
877
+ 2. **Clone your fork** to your local machine
878
+ 3. **Install dependencies**: `npm install`
879
+ 4. **Run the demo app**: `npm start`
880
+ 5. **Create a feature branch** for your changes
881
+ 6. **Commit your changes** following conventional commits
882
+ 7. **Submit a Pull Request** to the main branch
883
+
884
+ ### **Contribution Guidelines**
885
+
886
+ - Follow the existing code style
887
+ - Add tests for new features
888
+ - Update documentation as needed
889
+ - Ensure all tests pass
890
+ - Follow conventional commit messages
891
+
892
+ ## **📄 Changelog**
893
+
894
+ **Recent:** Use **v2.3.0** on npm. The v2.2.x line adds `allowSameDay` range mode, IANA timezone support, TypeScript strictness, appendToBody/popover fixes, and CSS cleanup. Versions 2.0.10 and 2.0.11 are unpublished; use v2.1.1+ or **v2.3.0**.
895
+
896
+ For the full list of changes, see [CHANGELOG.md](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/CHANGELOG.md).
897
+
898
+ ## **🎨 Theming with TokiForge**
899
+
900
+ Looking for a powerful theming solution for your Angular application? Check out **[TokiForge](https://tokiforge.github.io/tokiforge/)** an open-source modern design token & theme engine that provides runtime theme switching for React, Vue, Svelte, Angular, and any framework.
901
+
902
+ ### Why TokiForge?
903
+
904
+ - **SSR compatible** — Works seamlessly with Angular Universal
905
+
906
+ Perfect for managing design tokens, creating theme systems, and implementing dark mode in your Angular applications!
907
+
908
+ **👉 [Learn more about TokiForge →](https://tokiforge.github.io/tokiforge/)**
909
+
910
+ ---
911
+
912
+ ## **📜 License**
913
+
914
+ MIT License - see [LICENSE](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/LICENSE) file for details.
915
+
916
+ ## **🔍 SEO (demo site)**
917
+
918
+ The hosted **[live demo](https://ngxsmk.github.io/ngxsmk-datepicker/)** build ships with meta tags (Open Graph, Twitter cards, `hreflang`, structured data) and locale-aware content for broader discovery. For **GitHub/npm** visibility—topics, awesome lists, StackBlitz, and security reporting—see [**Discoverability**](#-discoverability) near the top of this README.
919
+
920
+ ## **👨‍💻 Author**
921
+
922
+ **Sachin Dilshan**
923
+
924
+ - 📧 Email: [sachindilshan040@gmail.com](mailto:sachindilshan040@gmail.com)
925
+ - 🐙 GitHub: [@toozuuu](https://github.com/toozuuu)
926
+ - 📦 NPM: [ngxsmk-datepicker](https://www.npmjs.com/package/ngxsmk-datepicker)
927
+ - 🌐 Website: [sachindilshan.com](https://www.sachindilshan.com/)
928
+ - 💼 LinkedIn: [sachindilshan](https://www.linkedin.com/in/sachindilshan/)
929
+
930
+ ## **⭐ Support**
931
+
932
+ If you find this library helpful, please consider:
933
+
934
+ - ⭐ **Starring** the repository
935
+ - 🐛 **Reporting** bugs and issues
936
+ - 💡 **Suggesting** new features
937
+ - 🤝 **Contributing** code improvements
938
+ - 📢 **Sharing** with the community
939
+