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