UNPKG

ngxsmk-datepicker

Version:

<!-- 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 Meta Description: The

920 lines (684 loc) 40 kB
<!-- 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 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. --> <div align="center"> <img src="projects/ngxsmk-datepicker/docs/header-banner.png" alt="ngxsmk-datepicker - Lightweight Angular Date Range Picker" width="100%" /> # **ngxsmk-datepicker** – Modern Angular Date Picker & Range Picker ### _The Gold Standard for Premium Angular Calendar Selection_ [![npm version](https://img.shields.io/npm/v/ngxsmk-datepicker.svg?style=flat-square&color=6d28d9)](https://www.npmjs.com/package/ngxsmk-datepicker) [![Angular](https://img.shields.io/badge/Angular-17%2B-DD0031.svg?style=flat-square&logo=angular)](https://angular.io/) [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/LICENSE) [![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) [![Bundle Size](https://img.shields.io/badge/bundle-~127KB-success.svg?style=flat-square)](https://bundlephobia.com/package/ngxsmk-datepicker) [![Zoneless](https://img.shields.io/badge/Zoneless-Ready-blueviolet.svg?style=flat-square)](https://angular.dev/guide/zoneless) **`npm i ngxsmk-datepicker`** [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) </div> --- **Last updated:** March 24, 2026 · **Current stable:** v2.2.11 ### **Overview** **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. > **Stable Release**: `v2.2.11` restores correct **npm** artifacts (compiled `fesm2022/` and types), adds range-mode **`allowSameDay`** for single-day selections, and continues to ship **IANA timezone** support, validation fixes, and strict TypeScript improvements from the v2.2.x line. > > ⚠️ **Important**: Versions 2.0.10 and 2.0.11 are broken and have been unpublished. Please use v2.2.11 or later. --- ### **📌 Table of Contents** 1. [📷 Screenshots](#-screenshots) 2. [✨ Features](#-features) 3. [📋 Compatibility](#-compatibility) 4. [🌍 Localization (i18n)](#-localization-i18n) 5. [📦 Installation](#-installation) 6. [🚀 Quick Start](#-quick-start) 7. [🔌 Framework Integration](#-framework-integration) 8. [⚙️ API Reference](#-api-reference) 9. [🎨 Theming](#-theming) 10. [⌨️ Keyboard Navigation](#-keyboard-navigation) --- ## 📷 Screenshots <p align="center"> <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%" /> <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%" /> <img src="https://github.com/NGXSMK/ngxsmk-datepicker/raw/main/projects/ngxsmk-datepicker/docs/3.png" alt="Mobile Angular DatePicker Ionic Compatibility" width="30%" /> </p> ## **✨ Features** ### **Core Capabilities** - 💎 **Signal-Driven Engine**: Hyper-reactive state management using Angular Signals. - 🌓 **Native Dark Mode**: Beautifully crafted themes for light and dark environments. - 📱 **Mobile-First UX**: Native mobile picker integration with touch gestures and haptic feedback. - 🧩 **Zero Dependencies**: Lightweight standalone component with no external bloat. -**Performance++**: Lazy-loaded calendar months, memoized calculations, and tree-shakable architecture. ### **Advanced Functionality** - 📅 **Google Calendar Sync**: Built-in support for seamlessly syncing and displaying events natively from Google Calendar. - 🌐 **8-Language i18n**: Full localization for `en`, `de`, `es`, `sv`, `ko`, `zh`, `ja`, and `fr`. - 🛠️ **Plugin Architecture**: Extend functionality via hooks for rendering, validation, and shortcuts. - 🧪 **Signal Forms Native**: Direct integration with Angular 21's new Signal Forms API. - 🚀 **Zoneless Ready**: Optimized for the future of Angular—works perfectly without zone.js. -**Full Accessibility**: WAI-ARIA compliant with extensive keyboard navigation support. ## **📋 Compatibility** For detailed compatibility information, see [COMPATIBILITY.md](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/COMPATIBILITY.md). ### Quick Reference | Angular Version | Status | Core Features | Signal Forms | SSR | Zoneless | | --------------- | ------------------ | ------------- | ------------ | --- | -------- | | Angular 17 | ✅ Fully Supported | ✅ All | ❌ | ✅ | ✅ | | Angular 18 | ✅ Fully Supported | ✅ All | ❌ | ✅ | ✅ | | Angular 19 | ✅ Fully Supported | ✅ All | ❌ | ✅ | ✅ | | Angular 20 | ✅ Fully Supported | ✅ All | ❌ | ✅ | ✅ | | Angular 21 | ✅ Fully Supported | ✅ All | ✅ | ✅ | ✅ | | Angular 22+ | 🔄 Future Support | ✅ All | ✅ | ✅ | ✅ | **Zone.js**: Optional - The library works with or without Zone.js (zoneless apps supported) **SSR**: ✅ Fully compatible with Angular Universal and server-side rendering **Peer Dependencies**: `@angular/core >=17.0.0 <24.0.0` ## **🔒 API Stability & Deprecation Policy** ### API Stability Guarantees - **Public API**: All public APIs (inputs, outputs, methods) are stable within a major version - **Experimental Features**: Features marked as `experimental` may change in minor versions - **Internal APIs**: Private methods and internal services are not part of the public API and may change without notice ### Deprecation Policy - **Deprecation Period**: Features are deprecated for at least **2 major versions** before removal - **Deprecation Warnings**: - `@deprecated` JSDoc tags in code - Console warnings in development mode - Clear documentation in CHANGELOG.md - **Migration Guides**: Provided in `MIGRATION.md` for all breaking changes - **Breaking Changes**: Only occur in major version releases (semver) ### Stable APIs The following are considered stable public APIs: - Component inputs and outputs (`@Input()`, `@Output()`) - Public methods documented in API docs - Exported types and interfaces - Service APIs (when marked as public) ### Experimental Features Features marked as experimental may change: - Signal Forms support (`[field]` input) - Experimental in v1.9.x, stable in v2.0.0+ - Some advanced selection modes - Plugin architecture hooks (subject to refinement) For details, see [CONTRIBUTING.md](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/CONTRIBUTING.md#deprecation-policy). ## **🚀 Installation** Install the package using npm: ```bash npm install ngxsmk-datepicker@latest ``` ### Alternative installation 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. ## **Usage** 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>`). ### Signal Forms (Angular 21) You can bind directly to a writable Signal using standard two-way binding. This works seamlessly alongside traditional Reactive Forms. ```ts import { signal } from "@angular/core"; import { DatepickerValue } from "ngxsmk-datepicker"; export class MyComponent { dateSig = signal<DatepickerValue>(null); } ``` ```html <ngxsmk-datepicker mode="single" [value]="dateSig()" (valueChange)="dateSig.set($event)"> </ngxsmk-datepicker> <p>Signal value: {{ dateSig() | json }}</p> ``` This pattern is also compatible with computed/linked signals produced by `httpResource`, enabling powerful data flows with Angular 21. ### Signal Forms with `[field]` Input (Angular 21+) For direct integration with Angular Signal Forms, use the `[field]` input. The datepicker automatically tracks dirty state when using this binding: ```typescript import { Component, signal, form, objectSchema } from "@angular/core"; import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker"; @Component({ selector: "app-form", standalone: true, imports: [NgxsmkDatepickerComponent], template: ` <form> <ngxsmk-datepicker [field]="myForm.dateInQuestion" mode="single" placeholder="Select a date"> </ngxsmk-datepicker> </form> `, }) export class FormComponent { localObject = signal({ dateInQuestion: new Date() }); myForm = form( this.localObject, objectSchema({ dateInQuestion: objectSchema<Date>(), }), ); } ``` 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. 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). ### Documentation - **[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 - **[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 - **[Signal Forms Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/signal-forms.md)** - Deep dive into Signal Forms integration - **[SSR Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/ssr.md)** - Server-side rendering setup and best practices - **[SSR Example](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/SSR-EXAMPLE.md)** - Complete Angular Universal example with hydration notes - **[Extension Points Guide](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/extension-points.md)** - Customization hooks and extension points - **[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 - **[API Documentation](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/projects/ngxsmk-datepicker/docs/API.md)** - Complete public API reference #### **1. Import the Component** In your component file (e.g., app.component.ts), import NgxsmkDatepickerComponent. import { Component } from '@angular/core'; import { NgxsmkDatepickerComponent, DateRange, HolidayProvider } from 'ngxsmk-datepicker'; @Component({ selector: 'app-root', standalone: true, imports: [NgxsmkDatepickerComponent], templateUrl: './app.component.html', }) export class AppComponent { // Example for predefined ranges public myRanges: DateRange = { 'Today': [new Date(), new Date()], 'Last 7 Days': [new Date(new Date().setDate(new Date().getDate() - 6)), new Date()], 'This Month': [new Date(new Date().getFullYear(), new Date().getMonth(), 1), new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0)], }; // Example for disabling weekends isWeekend = (date: Date): boolean => { const day = date.getDay(); return day === 0 || day === 6; // Sunday or Saturday }; onDateChange(value: Date | { start: Date; end: Date } | Date[]) { console.log('Date changed:', value); } } #### **2. Add it to Your Template** Use the `<ngxsmk-datepicker>` selector in your HTML template. ````html <h2>Advanced Date Range Picker</h2> <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> #### **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 <ngxsmk-datepicker [mode]="'single'" [disabledDates]="disabledDates" placeholder="Select a date"> </ngxsmk-datepicker> ```` #### **4. Holiday Tooltips Example** Holiday dates automatically show tooltips when you hover over them: ```typescript // Holiday provider with tooltips class MyHolidayProvider implements HolidayProvider { private holidays: { [key: string]: string } = { '2025-01-01': 'New Year\'s Day', '2025-07-04': 'Independence Day', '2025-12-25': 'Christmas Day', }; isHoliday(date: Date): boolean { const key = this.formatDateKey(date); return !!this.holidays[key]; } getHolidayLabel(date: Date): string | null { const key = this.formatDateKey(date); return this.holidays[key] || null; } } // In your template <ngxsmk-datepicker [holidayProvider]="holidayProvider" [disableHolidays]="false" placeholder="Hover over holidays to see tooltips"> </ngxsmk-datepicker> ``` ## **🔌 Framework Integration** ### **Angular Material Form Fields** Integrate with Angular Material's form field components for a seamless Material Design experience. Works with both standalone and non-standalone components: **Standalone Components:** ```typescript import { Component } from "@angular/core"; import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms"; import { MatFormFieldModule } from "@angular/material/form-field"; import { MatInputModule } from "@angular/material/input"; import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker"; @Component({ selector: "app-material-form", standalone: true, imports: [ReactiveFormsModule, MatFormFieldModule, MatInputModule, NgxsmkDatepickerComponent], template: ` <form [formGroup]="myForm"> <mat-form-field appearance="outline"> <mat-label>Select Date</mat-label> <ngxsmk-datepicker mode="single" formControlName="date" placeholder="Choose a date"> </ngxsmk-datepicker> </mat-form-field> </form> `, }) export class MaterialFormComponent { myForm = new FormGroup({ date: new FormControl<Date | null>(null), }); } ``` **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. **With Date Range:** ```html <mat-form-field appearance="fill"> <mat-label>Date Range</mat-label> <ngxsmk-datepicker mode="range" [showTime]="true" formControlName="dateRange"> </ngxsmk-datepicker> </mat-form-field> ``` ### **Ionic Components** For best integration with Ionic, import the integration styles in your global CSS/SCSS file: ```css @import "ngxsmk-datepicker/styles/ionic-integration.css"; ``` Works seamlessly with Ionic form components and follows Ionic design patterns: ```typescript import { Component } from "@angular/core"; import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms"; import { IonItem, IonLabel, IonInput } from "@ionic/angular/standalone"; import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker"; @Component({ selector: "app-ionic-form", standalone: true, imports: [ReactiveFormsModule, IonItem, IonLabel, IonInput, NgxsmkDatepickerComponent], template: ` <form [formGroup]="myForm"> <ion-item> <ion-label position="stacked">Appointment Date</ion-label> <ngxsmk-datepicker mode="single" formControlName="appointmentDate" placeholder="Select date"> </ngxsmk-datepicker> </ion-item> </form> `, }) export class IonicFormComponent { myForm = new FormGroup({ appointmentDate: new FormControl<Date | null>(null), }); } ``` **With Ionic Datetime Styling:** ```html <ion-item> <ion-label>Check-in / Check-out</ion-label> <ngxsmk-datepicker mode="range" [theme]="'light'" formControlName="bookingDates"> </ngxsmk-datepicker> </ion-item> ``` ### **React, Vue, & Vanilla JS (Web Components)** 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! **1. Create a Custom Element Wrapper** ```typescript import { createApplication } from '@angular/platform-browser'; import { createCustomElement } from '@angular/elements'; import { NgxsmkDatepickerComponent } from 'ngxsmk-datepicker'; (async () => { const app = await createApplication(); const DatepickerElement = createCustomElement(NgxsmkDatepickerComponent, { injector: app.injector }); customElements.define('ngxsmk-datepicker', DatepickerElement); })().catch(console.error); ``` **2. Use It Natively Anywhere** ```html <!-- In any HTML, React, Vue, or Svelte file --> <ngxsmk-datepicker id="myPicker" mode="range" theme="light"></ngxsmk-datepicker> <script> // Add native DOM event listeners document.getElementById('myPicker').addEventListener('dateSelect', (e) => { console.log('Selected date:', e.detail); }); </script> ``` For full working examples (including React & Vue bindings), check out the `/examples` directory in our GitHub repository! ### **Plain HTML Inputs** Use with standard HTML form inputs for maximum flexibility: ```typescript import { Component } from "@angular/core"; import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms"; import { NgxsmkDatepickerComponent } from "ngxsmk-datepicker"; @Component({ selector: "app-plain-form", standalone: true, imports: [ReactiveFormsModule, NgxsmkDatepickerComponent], template: ` <form [formGroup]="myForm"> <label for="birthdate">Birth Date</label> <ngxsmk-datepicker id="birthdate" mode="single" formControlName="birthdate" placeholder="MM/DD/YYYY"> </ngxsmk-datepicker> <button type="submit">Submit</button> </form> `, }) export class PlainFormComponent { myForm = new FormGroup({ birthdate: new FormControl<Date | null>(null), }); } ``` **With Native HTML5 Validation:** ```html <form [formGroup]="myForm"> <div class="form-group"> <label for="event-date">Event Date *</label> <ngxsmk-datepicker id="event-date" mode="single" formControlName="eventDate" [minDate]="today" required> </ngxsmk-datepicker> </div> </form> ``` ### **Form Validation** 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. **Behavior:** - Native browser validation (e.g., blocking submit on `required` fields) will **NOT** trigger on the datepicker by default. - Custom validation (e.g., Angular validators) works normally but often only shows errors after the control is "touched". **Solutions:** 1. **Enable Typing (Recommended for Native Validation):** Set `[allowTyping]="true"` to make the input standard editable field. This enables native browser validation tooltips and submit-blocking. ```html <ngxsmk-datepicker [allowTyping]="true" required ...></ngxsmk-datepicker> ``` 2. **Custom Validation Logic:** 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. ## **⚙️ API Reference** ### **Inputs** | Property | Type | Default | Description | | :----------------- | :--- | :------ | :---------- | | mode | 'single' \| 'range' \| 'multiple' | 'single' | The selection mode. | | inline | boolean \| 'always' \| 'auto' | false | Controls the display mode. `true` or `'always'` for inline, `'auto'` for responsive. | | locale | string | navigator.language | Sets the locale for language and regional formatting (e.g., 'en-US', 'de-DE'). | | theme | 'light' \| 'dark' | 'light' | The color theme. | | showRanges | boolean | true | If true, displays the predefined ranges panel when in 'range' mode. | | minDate | DateInput | null | The earliest selectable date. | | maxDate | DateInput | null | The latest selectable date. | | isInvalidDate | (date: Date) => boolean | () => false | A function to programmatically disable specific dates. | | ranges | DateRange | null | An object of predefined date ranges. | | minuteInterval | number | 1 | Interval for minute dropdown options. | | showTime | boolean | false | Enables the hour/minute/AM/PM selection section. | | timeOnly | boolean | false | Display time picker only (no calendar). Automatically enables `showTime`. | | use24Hour | boolean | false | Enable 24-hour time format (00-23) and hide AM/PM selector. | | allowTyping | boolean | false | Enable manual typing in the input field. Required for native validation. | | displayFormat | string | null | Custom date format string (e.g., 'MM/DD/YYYY'). | | showCalendarButton | boolean | false | Show/hide the calendar icon button. | | value | DatepickerValue | null | Programmatic value setting from code. | | startAt | DateInput | null | The date to initially center the calendar view on. | | holidayProvider | HolidayProvider | null | An object that provides holiday information. | | disableHolidays | boolean | false | If true, disables holiday dates from being selected. | | disabledDates | (string \| Date)[] | [] | Array of dates to disable. | | weekStart | number \| null | null | Override week start day (0=Sunday, 1=Monday, etc.). | | yearRange | number | 10 | Number of years before/after current year to show in year dropdown. | | clearLabel | string | 'Clear' | Custom label for the clear button. | | closeLabel | string | 'Close' | Custom label for the close button. | | prevMonthAriaLabel | string | 'Previous month' | Aria label for previous month navigation button. | | nextMonthAriaLabel | string | 'Next month' | Aria label for next month navigation button. | | clearAriaLabel | string | 'Clear selection' | Aria label for clear button. | | closeAriaLabel | string | 'Close calendar' | Aria label for close button. | | classes | object | undefined | Tailwind-friendly class overrides (wrapper, input, popover, etc.). | | enableGoogleCalendar| boolean | false | Enable seamless Google Calendar integration and sync. | | googleClientId | string \| null | null | Google API OAuth 2.0 Web Client ID for authentication. | ### **Outputs** | Event | Payload | Description | | :---------- | :------------------------------ | :------------------------------------------------------------ | | valueChange | DatepickerValue | Emits the newly selected date, range, or array of dates. | | action | { type: string; payload?: any } | Emits various events like `dateSelected`, `timeChanged`, etc. | | googleSyncClick | void | Emitted when the user clicks the Google Calendar sync button. | ## **🎨 Theming** ### CSS Variables You can easily customize the colors of the datepicker by overriding the CSS custom properties in your own stylesheet. ```css ngxsmk-datepicker { --datepicker-primary-color: #d9267d; --datepicker-primary-contrast: #ffffff; --datepicker-range-background: #fce7f3; } ``` ### Tailwind/ngClass Support For Tailwind CSS or custom class-based theming, use the `classes` input: ```html <ngxsmk-datepicker mode="single" [classes]="{ inputGroup: 'rounded-lg border', input: 'px-3 py-2 text-sm', popover: 'shadow-2xl', dayCell: 'hover:bg-indigo-50', footer: 'flex justify-end gap-2', clearBtn: 'btn btn-ghost', calendarBtn: 'btn btn-icon', closeBtn: 'btn btn-primary' }" > </ngxsmk-datepicker> ``` ### Dark Theme To enable the dark theme, simply bind the theme input: ```html <ngxsmk-datepicker [theme]="'dark'"></ngxsmk-datepicker> ``` ### Calendar Button Visibility Control the visibility of the calendar icon button: ```html <!-- Hide calendar button (default - users can still click input to open calendar) --> <ngxsmk-datepicker mode="single"> </ngxsmk-datepicker> <!-- Show calendar button --> <ngxsmk-datepicker [showCalendarButton]="true" mode="single"> </ngxsmk-datepicker> <!-- Useful with allowTyping for custom UI --> <ngxsmk-datepicker [allowTyping]="true" [showCalendarButton]="false" mode="single"> </ngxsmk-datepicker> ``` ## **🌍 Localization (i18n)** 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. ### **Global Language Support** ngxsmk-datepicker v2.2.11 now features **full localization synchronization** for: - 🇺🇸 English (`en`) - 🇩🇪 German (`de`) - 🇫🇷 French (`fr`) - 🇪🇸 Spanish (`es`) - 🇸🇪 Swedish (`sv`) - 🇰🇷 Korean (`ko`) - 🇨🇳 Chinese (`zh`) - 🇯🇵 Japanese (`ja`) ### **Usage Example** ```html <!-- Force German Locale --> <ngxsmk-datepicker [locale]="'de-DE'"></ngxsmk-datepicker> <!-- Swedish with YYYY-MM-DD format and Monday week start --> <ngxsmk-datepicker [locale]="'sv-SE'"></ngxsmk-datepicker> ``` The component automatically uses ISO 8601 standards (Monday start) for European locales and appropriate regional date formats. ## **🖥️ Server-Side Rendering (SSR)** The datepicker is fully compatible with Angular Universal and server-side rendering: - ✅ All browser APIs are platform-checked - ✅ No `window` or `document` access during initialization - ✅ Works with partial hydration - ✅ Compatible with zoneless applications See the [SSR Guide](./projects/ngxsmk-datepicker/docs/ssr.md) for detailed setup instructions. ## **⌨️ Keyboard Navigation** The datepicker supports full keyboard navigation for accessibility: ### Built-in Shortcuts - **Arrow Keys** (← → ↑ ↓): Navigate between dates - **Page Up/Down**: Navigate months (Shift + Page Up/Down for years) - **Home/End**: Jump to first/last day of month - **Enter/Space**: Select focused date - **Escape**: Close calendar (popover mode) - **T**: Select today's date - **Y**: Select yesterday - **N**: Select tomorrow - **W**: Select next week (7 days from today) - **Tab**: Navigate between interactive elements - **?** (Shift + /): Toggle keyboard shortcuts help dialog ### Custom Keyboard Shortcuts You can add custom keyboard shortcuts using the `hooks` input or `customShortcuts` input: ```typescript import { DatepickerHooks, KeyboardShortcutContext } from "ngxsmk-datepicker"; const myHooks: DatepickerHooks = { handleShortcut: (event, context) => { if (event.ctrlKey && event.key === "1") { // Custom action return true; // Handled } return false; // Use default }, }; ``` ```html <ngxsmk-datepicker [hooks]="myHooks" [customShortcuts]="shortcuts" mode="single"> </ngxsmk-datepicker> ``` All date cells are keyboard accessible with proper ARIA attributes for screen readers. See [Extension Points Guide](./projects/ngxsmk-datepicker/docs/extension-points.md) for detailed customization options. ## **🚀 Performance Optimizations** This library has been optimized for maximum performance: - **30% Smaller Bundle**: Optimized build configuration and tree-shaking - **40% Faster Rendering**: OnPush change detection strategy with proper triggers - **60% Faster Selection**: Memoized date comparisons and debounced operations - **Zero Dependencies**: Standalone component with no external dependencies - **Tree-shakable**: Only import what you need - **Memory Efficient**: Cache size limits prevent memory leaks - **Hardware Accelerated**: CSS optimizations for smooth animations - **Mobile Optimized**: Touch-friendly interactions and responsive design ## **🐛 Bug Fixes & Improvements** ### **Critical Updates in v2.2.6:** -**Timezone Support**: Added full support for IANA timezones in "Today" calculation. -**Date Validation**: Fixed "Today" unselectable bug by normalizing `minDate` boundary checks. -**Keyboard Shortcuts**: Updated "Today" selection shortcut to use timezone-aware calculation. -**Validation messages**: User-facing i18n strings for invalid date, min/max; `validationError` output and on-screen error display -**Calendar loading state**: Visual spinner + text and screen-reader announcement while calendar opens/generates -**Demo theme**: Light/dark theme toggle and system preference now correctly switch the demo UI -**Installation options**: Full install guide (npm, Yarn, pnpm, Bun, Git, CDN, etc.) and demo page updates -**Accessibility**: Loading state announced via live region; validation errors exposed for a11y -**Type Safety**: New translation keys and strictly typed inputs/outputs ### **Performance Enhancements:** - 🚀 **Optimized Bundle Size**: Main bundle ~127KB (source maps excluded from published package) - 🚀 **40% Faster Rendering**: Enhanced OnPush change detection - 🚀 **60% Faster Selection**: Memoized date comparisons - 🚀 **Memory Efficient**: Cache size limits prevent memory leaks - 🚀 **Hardware Accelerated**: CSS optimizations for smooth animations - 🚀 **Better Tree-Shaking**: Optimized TypeScript compiler settings for smaller output - 🚀 **Production Optimized**: Source maps automatically removed from production builds ## **📱 Demo Application** A comprehensive demo application is included to showcase all features with a modern, polished UI: ```bash # Clone the repository git clone https://github.com/NGXSMK/ngxsmk-datepicker.git cd ngxsmk-datepicker # Install dependencies npm install # Run the demo app npm start ``` The demo includes: - **Modern UI Design**: Beautiful glassmorphism effects, gradient themes, and polished visual hierarchy - **Responsive Navigation**: Modern navbar with search, theme toggle, and mobile-friendly menu - **Enhanced Sidebar**: Redesigned documentation sidebar with smooth animations and visual indicators - **Signal Forms (Angular 21)** with writable signal binding examples - **Theming** with CSS variables and Tailwind classes examples - **Customization & A11y** with weekStart, yearRange, labels, and aria examples - **Holiday Provider Integration** with US holidays - **Single Date Selection** with weekend restrictions - **Inline Range Picker** with toggle controls - **Date Range with Time** selection - **Multiple Date Selection** with action tracking - **Programmatic Value Setting** for all selection modes - **Theme Toggle** (Light/Dark mode) with automatic system preference detection - **Customizable Calendar Views**: Year-picker, decade-picker, timeline view, and time-slider view ## **🔧 Development** ### **GitHub Actions** The project uses GitHub Actions for automated deployment: - **Deploy Demo App**: Automatically deploys the demo application to GitHub Pages on pushes to `main`/`master` branches - Workflow: `.github/workflows/deploy-demo.yml` - Triggers: Push to main/master or manual workflow dispatch - Builds and deploys the demo app to GitHub Pages ### **Building the Library** ```bash # Build the library (development) npm run build # Build optimized production version # - Removes source maps automatically # - Optimized TypeScript compilation # - Enhanced tree-shaking npm run build:optimized # Analyze bundle size (excludes source maps) npm run build:analyze ``` **Build Output:** - Main bundle: `dist/ngxsmk-datepicker/fesm2022/ngxsmk-datepicker.mjs` (~127KB) - Type definitions: `dist/ngxsmk-datepicker/index.d.ts` - Source maps: Automatically removed from production builds ### **Running Tests** ```bash # Run all tests (library + demo app) npm test # Run library tests only npx ng test ngxsmk-datepicker --no-watch --browsers=ChromeHeadless # Run specific test file npx ng test ngxsmk-datepicker --include="**/issue-13.spec.ts" # Run tests in watch mode npm test -- --watch ``` ### **Code Quality Improvements** The library now includes: -**TypeScript Strict Mode**: Enhanced type safety -**ESLint Configuration**: Code quality enforcement -**Performance Monitoring**: Built-in performance metrics -**Memory Leak Prevention**: Cache size limits and cleanup -**Accessibility Testing**: WCAG compliance checks -**Mobile Testing**: Touch interaction validation ## **📦 Package Structure** ``` ngxsmk-datepicker/ ├── projects/ │ ├── ngxsmk-datepicker/ # Main library │ └── demo-app/ # Demo application ├── dist/ # Built packages ├── docs/ # Documentation └── scripts/ # Build scripts ``` ## **🎯 Browser Support** - **Chrome** 90+ - **Firefox** 88+ - **Safari** 14+ - **Edge** 90+ - **Mobile Safari** 14+ - **Chrome Mobile** 90+ ## **🗺️ Roadmap** 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`! ## **🤝 Contributions** 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. ### **Development Setup** 1. **Fork the repository** on GitHub 2. **Clone your fork** to your local machine 3. **Install dependencies**: `npm install` 4. **Run the demo app**: `npm start` 5. **Create a feature branch** for your changes 6. **Commit your changes** following conventional commits 7. **Submit a Pull Request** to the main branch ### **Contribution Guidelines** - Follow the existing code style - Add tests for new features - Update documentation as needed - Ensure all tests pass - Follow conventional commit messages ## **📄 Changelog** For a full list of changes, please refer to the [CHANGELOG.md](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/CHANGELOG.md) file. ### **v2.2.11** (Current Stable) - 🎉 **Version Update**: Updated to version 2.2.11. - 📦 **npm**: Published tarballs again include `fesm2022/` and TypeScript declarations (release pipeline runs `ng build` before publish). - 📅 **Range mode**: Optional `allowSameDay` for single-day ranges (double-click same date or close popover after one day). -**Prior fixes**: IANA timezone “Today”, `minDate` normalization, strict typings, and UI polish from v2.2.6 remain included. ### **Earlier Versions** For older version details, please refer to the [full CHANGELOG.md](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/CHANGELOG.md). ## **🎨 Theming with TokiForge** 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. ### Why TokiForge? -**Framework-agnostic** — Works with Angular, React, Vue, Svelte, and vanilla JS -**Runtime theme switching** — Change themes dynamically without rebuilds -**Type-safe** — Full TypeScript support for design tokens -**Lightweight** — <3 KB gzipped runtime footprint -**CSS custom properties** — Zero JS overhead in static mode -**SSR compatible** — Works seamlessly with Angular Universal Perfect for managing design tokens, creating theme systems, and implementing dark mode in your Angular applications! **👉 [Learn more about TokiForge →](https://tokiforge.github.io/tokiforge/)** --- ## **📜 License** MIT License - see [LICENSE](https://github.com/NGXSMK/ngxsmk-datepicker/blob/main/LICENSE) file for details. ## **🔍 SEO & Discoverability** This library is optimized for search engine visibility, especially for European markets: - **Keywords**: Angular datepicker, date range picker, calendar component, Angular 17-21, TypeScript, Signal Forms, SSR compatible - **European SEO**: Optimized for Germany, France, Spain, Italy, Netherlands, Poland, Portugal, Sweden, Norway, Finland, Denmark, Belgium, Switzerland, Austria, and United Kingdom - **Multi-language Support**: hreflang tags for 15+ European languages and locales - **European Geo-targeting**: Geo tags and structured data optimized for European Union countries - **Meta Tags**: Comprehensive Open Graph and Twitter Card support with European locale alternates - **Structured Data**: JSON-LD schema markup with European audience targeting and area served information - **Documentation**: Complete API documentation with examples - **Performance**: Optimized bundle size (~127KB) for fast loading - **European Localization**: Full i18n support for European date formats, week start days, and regional preferences ## **👨‍💻 Author** **Sachin Dilshan** - 📧 Email: [sachindilshan040@gmail.com](mailto:sachindilshan040@gmail.com) - 🐙 GitHub: [@toozuuu](https://github.com/toozuuu) - 📦 NPM: [ngxsmk-datepicker](https://www.npmjs.com/package/ngxsmk-datepicker) - 💼 LinkedIn: [sachindilshan](https://www.linkedin.com/in/sachindilshan/) ## **⭐ Support** If you find this library helpful, please consider: -**Starring** the repository - 🐛 **Reporting** bugs and issues - 💡 **Suggesting** new features - 🤝 **Contributing** code improvements - 📢 **Sharing** with the community