@oneluiz/dual-datepicker 3.3.0 → 3.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
@@ -31,6 +31,7 @@ npm install @oneluiz/dual-datepicker
31
31
  - [Disabled Dates](#disabled-dates)
32
32
  - [Display Format](#display-format)
33
33
  - [Apply/Confirm Button](#applyconfirm-button)
34
+ - [Time Picker](#time-picker)
34
35
  - [Hover Range Preview](#hover-range-preview)
35
36
  - [Custom Presets](#custom-presets)
36
37
  - [Date Adapter System](#date-adapter-system)
@@ -470,6 +471,109 @@ export class DashboardExample {
470
471
  | User control | Automatic | Explicit confirmation |
471
472
  | Best for | Simple forms | Dashboards, reports |
472
473
 
474
+ ---
475
+
476
+ ### Time Picker
477
+
478
+ **Select precise datetime ranges with optional time picker.** Choose exact start and end times in addition to dates, with support for 12h/24h formats and configurable minute steps.
479
+
480
+ #### Basic Usage
481
+
482
+ ```typescript
483
+ import { Component } from '@angular/core';
484
+ import { DateRange } from '@oneluiz/dual-datepicker';
485
+
486
+ @Component({
487
+ template: `
488
+ <ngx-dual-datepicker
489
+ [enableTimePicker]="true"
490
+ (dateRangeChange)="onDateRangeChange($event)">
491
+ </ngx-dual-datepicker>
492
+ `
493
+ })
494
+ export class AppointmentComponent {
495
+ onDateRangeChange(range: DateRange) {
496
+ console.log('Start:', range.startDate, 'at', range.startTime);
497
+ console.log('End:', range.endDate, 'at', range.endTime);
498
+ // startTime and endTime are in 'HH:mm' format
499
+ }
500
+ }
501
+ ```
502
+
503
+ #### Configuration Options
504
+
505
+ ```typescript
506
+ // 12-hour format with AM/PM
507
+ <ngx-dual-datepicker
508
+ [enableTimePicker]="true"
509
+ timeFormat="12h"
510
+ defaultStartTime="09:00"
511
+ defaultEndTime="17:00"
512
+ (dateRangeChange)="onDateRangeChange($event)">
513
+ </ngx-dual-datepicker>
514
+
515
+ // 30-minute intervals
516
+ <ngx-dual-datepicker
517
+ [enableTimePicker]="true"
518
+ [minuteStep]="30"
519
+ (dateRangeChange)="onDateRangeChange($event)">
520
+ </ngx-dual-datepicker>
521
+
522
+ // With Apply button for controlled changes
523
+ <ngx-dual-datepicker
524
+ [enableTimePicker]="true"
525
+ [requireApply]="true"
526
+ (dateRangeChange)="onDateRangeChange($event)">
527
+ </ngx-dual-datepicker>
528
+ ```
529
+
530
+ #### DateRange with Time
531
+
532
+ When `enableTimePicker` is true, the DateRange includes optional time properties:
533
+
534
+ ```typescript
535
+ interface DateRange {
536
+ startDate: string; // 'YYYY-MM-DD'
537
+ endDate: string; // 'YYYY-MM-DD'
538
+ rangeText: string; // Display text
539
+ startTime?: string; // 'HH:mm' or 'HH:mm AM/PM'
540
+ endTime?: string; // 'HH:mm' or 'HH:mm AM/PM'
541
+ }
542
+ ```
543
+
544
+ #### Configuration Inputs
545
+
546
+ | Input | Type | Default | Description |
547
+ |-------|------|---------|-------------|
548
+ | `enableTimePicker` | boolean | `false` | Enable time selection |
549
+ | `timeFormat` | `'12h'` \| `'24h'` | `'24h'` | Time display format |
550
+ | `minuteStep` | number | `15` | Minute intervals (1, 5, 15, or 30) |
551
+ | `defaultStartTime` | string | `'00:00'` | Default start time (HH:mm) |
552
+ | `defaultEndTime` | string | `'23:59'` | Default end time (HH:mm) |
553
+
554
+ #### Perfect Use Cases
555
+
556
+ - 📅 **Appointment booking systems** - Schedule meetings with exact times
557
+ - 🎫 **Event scheduling** - Create events with start and end times
558
+ - 🏢 **Meeting planners** - Book conference rooms with time slots
559
+ - 📊 **Time-based reporting** - Generate reports for specific time ranges
560
+ - 👥 **Shift management** - Assign work shifts with precise times
561
+ - 🎬 **Reservation systems** - Book resources with time constraints
562
+
563
+ #### Key Features
564
+
565
+ - ✅ Optional - disabled by default (backward compatible)
566
+ - ✅ 12h (AM/PM) or 24h time format
567
+ - ✅ Configurable minute steps (1, 5, 15, 30)
568
+ - ✅ Default start/end times support
569
+ - ✅ Works with all themes
570
+ - ✅ Integrates with requireApply mode
571
+ - ✅ Fully accessible with keyboard navigation
572
+
573
+ **For complete documentation, see [TIME_PICKER.md](TIME_PICKER.md)**
574
+
575
+ ---
576
+
473
577
  ### Hover Range Preview
474
578
 
475
579
  **Automatic visual feedback while selecting dates.** Provides instant visual preview of the date range when hovering over dates before clicking to confirm.
@@ -759,6 +863,12 @@ spanishLocale: LocaleConfig = {
759
863
  | `disabledDates` | `Date[] \| ((date: Date) => boolean)` | `undefined` | Array of dates or function to disable specific dates |
760
864
  | `displayFormat` | `string` | `'D MMM'` | Format for displaying dates in input (tokens: YYYY, YY, MMMM, MMM, MM, M, DD, D) |
761
865
  | `requireApply` | `boolean` | `false` | Require Apply button confirmation before emitting changes |
866
+ | `enableTimePicker` | `boolean` | `false` | Enable time selection |
867
+ | `timeFormat` | `'12h' \| '24h'` | `'24h'` | Time display format (12-hour with AM/PM or 24-hour) |
868
+ | `minuteStep` | `number` | `15` | Step for minute selector (1, 5, 15, or 30) |
869
+ | `defaultStartTime` | `string` | `'00:00'` | Default start time in HH:mm format |
870
+ | `defaultEndTime` | `string` | `'23:59'` | Default end time in HH:mm format |
871
+ | `theme` | `ThemeType` | `'default'` | Theme preset: 'default', 'bootstrap', 'bulma', 'foundation', 'tailwind', 'custom' |
762
872
  | `enableKeyboardNavigation` | `boolean` | `true` | Enable keyboard navigation |
763
873
  | `inputBackgroundColor` | `string` | `'#fff'` | Input background color |
764
874
  | `inputTextColor` | `string` | `'#495057'` | Input text color |
@@ -809,6 +919,8 @@ interface DateRange {
809
919
  startDate: string; // ISO format: 'YYYY-MM-DD'
810
920
  endDate: string; // ISO format: 'YYYY-MM-DD'
811
921
  rangeText: string; // Display text: 'DD Mon - DD Mon'
922
+ startTime?: string; // Optional: 'HH:mm' or 'HH:mm AM/PM' (when enableTimePicker=true)
923
+ endTime?: string; // Optional: 'HH:mm' or 'HH:mm AM/PM' (when enableTimePicker=true)
812
924
  }
813
925
 
814
926
  interface MultiDateRange {
@@ -1886,20 +1998,36 @@ export class ExampleComponent {
1886
1998
 
1887
1999
  Recently shipped:
1888
2000
 
2001
+ **v3.3.0:**
2002
+ - ✅ **Theming System** - Pre-built themes for Bootstrap, Bulma, Foundation, Tailwind CSS, and Custom
2003
+ - ✅ **CSS Variables Support** - 13 customizable variables for branding
2004
+ - ✅ **Framework Integration** - Match your existing design system seamlessly
2005
+
2006
+ **v3.2.0:**
2007
+ - ✅ **Hover Range Preview** - Visual feedback before confirming selection
2008
+ - ✅ **Apply/Confirm Button** - Require confirmation for enterprise dashboards
2009
+ - ✅ **Display Format** - Customize date display (DD/MM/YYYY, MM/DD/YYYY, etc.)
2010
+ - ✅ **Disabled Dates** - Block weekends, holidays, or custom logic
2011
+
2012
+ **v3.1.0:**
2013
+ - ✅ **Complete Keyboard Navigation** - Arrow keys, Enter/Space, Tab, Escape, Home/End, PageUp/Down
2014
+ - ✅ **Full Accessibility Audit** - WCAG 2.1 Level AA compliance
2015
+
2016
+ **v2.7.0:**
2017
+ - ✅ **Multi-range Support** - Select UNLIMITED date ranges (Material CAN'T do this!)
2018
+
1889
2019
  **v2.6.0:**
1890
- - ✅ **Flexible Preset System** - `getValue()` pattern for custom date logic (This month, Last month, Quarter to date, etc.)
2020
+ - ✅ **Flexible Preset System** - `getValue()` pattern for custom date logic
1891
2021
  - ✅ **Pre-built Preset Utilities** - CommonPresets for Dashboard, Reporting, Financial, Analytics
1892
- - ✅ **Real Differentiator** - Perfect for ERP, BI, POS, and Reporting systems
1893
2022
 
1894
2023
  **v2.5.0:**
1895
2024
  - ✅ **Date Adapter System** - Support for DayJS, date-fns, Luxon, and custom date libraries
1896
2025
 
1897
- Planned features and improvements:
2026
+ Planned features:
1898
2027
 
1899
- - ⬜ **Complete keyboard navigation** - Arrow keys, Enter/Space, Tab, Escape
1900
- - ⬜ **Full accessibility audit** - WCAG 2.1 AA compliance
1901
- - ⬜ **Multi-range support** - Select multiple date ranges
1902
- - ⬜ **Theming system** - Pre-built theme presets
2028
+ - ⬜ **Time Picker** - Select date + time ranges
2029
+ - ⬜ **Mobile Optimizations** - Enhanced touch gestures and responsive layout
2030
+ - ⬜ **Range Shortcuts** - Quick selection buttons (Today, This Week, etc.)
1903
2031
 
1904
2032
  ## 📄 License
1905
2033
 
@@ -5,6 +5,8 @@ export interface DateRange {
5
5
  startDate: string;
6
6
  endDate: string;
7
7
  rangeText: string;
8
+ startTime?: string;
9
+ endTime?: string;
8
10
  }
9
11
  export interface MultiDateRange {
10
12
  ranges: DateRange[];
@@ -49,6 +51,11 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
49
51
  disabledDates: Date[] | ((date: Date) => boolean) | undefined;
50
52
  displayFormat: string;
51
53
  requireApply: boolean;
54
+ enableTimePicker: boolean;
55
+ timeFormat: '12h' | '24h';
56
+ minuteStep: number;
57
+ defaultStartTime: string;
58
+ defaultEndTime: string;
52
59
  dateRangeChange: EventEmitter<DateRange>;
53
60
  dateRangeSelected: EventEmitter<DateRange>;
54
61
  multiDateRangeChange: EventEmitter<MultiDateRange>;
@@ -65,6 +72,12 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
65
72
  pendingStartDate: string;
66
73
  pendingEndDate: string;
67
74
  hasPendingChanges: import("@angular/core").WritableSignal<boolean>;
75
+ startHour: number;
76
+ startMinute: number;
77
+ endHour: number;
78
+ endMinute: number;
79
+ showStartTimePicker: import("@angular/core").WritableSignal<boolean>;
80
+ showEndTimePicker: import("@angular/core").WritableSignal<boolean>;
68
81
  hoverDate: import("@angular/core").WritableSignal<string>;
69
82
  selectedRanges: import("@angular/core").WritableSignal<DateRange[]>;
70
83
  currentRangeIndex: import("@angular/core").WritableSignal<number>;
@@ -123,10 +136,25 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
123
136
  private emitMultiChange;
124
137
  private emitMultiSelection;
125
138
  private getDateRangeValue;
139
+ toggleStartTimePicker(): void;
140
+ toggleEndTimePicker(): void;
141
+ incrementStartHour(): void;
142
+ decrementStartHour(): void;
143
+ incrementStartMinute(): void;
144
+ decrementStartMinute(): void;
145
+ incrementEndHour(): void;
146
+ decrementEndHour(): void;
147
+ incrementEndMinute(): void;
148
+ decrementEndMinute(): void;
149
+ formatTime(hour: number, minute: number): string;
150
+ parseTime(timeString: string): {
151
+ hour: number;
152
+ minute: number;
153
+ };
126
154
  writeValue(value: DateRange | null): void;
127
155
  registerOnChange(fn: (value: DateRange | null) => void): void;
128
156
  registerOnTouched(fn: () => void): void;
129
157
  setDisabledState(isDisabled: boolean): void;
130
158
  static ɵfac: i0.ɵɵFactoryDeclaration<DualDatepickerComponent, never>;
131
- static ɵcmp: i0.ɵɵComponentDeclaration<DualDatepickerComponent, "ngx-dual-datepicker", never, { "placeholder": { "alias": "placeholder"; "required": false; }; "startDate": { "alias": "startDate"; "required": false; }; "endDate": { "alias": "endDate"; "required": false; }; "showPresets": { "alias": "showPresets"; "required": false; }; "showClearButton": { "alias": "showClearButton"; "required": false; }; "multiRange": { "alias": "multiRange"; "required": false; }; "closeOnSelection": { "alias": "closeOnSelection"; "required": false; }; "closeOnPresetSelection": { "alias": "closeOnPresetSelection"; "required": false; }; "closeOnClickOutside": { "alias": "closeOnClickOutside"; "required": false; }; "enableKeyboardNavigation": { "alias": "enableKeyboardNavigation"; "required": false; }; "presets": { "alias": "presets"; "required": false; }; "theme": { "alias": "theme"; "required": false; }; "inputBackgroundColor": { "alias": "inputBackgroundColor"; "required": false; }; "inputTextColor": { "alias": "inputTextColor"; "required": false; }; "inputBorderColor": { "alias": "inputBorderColor"; "required": false; }; "inputBorderColorHover": { "alias": "inputBorderColorHover"; "required": false; }; "inputBorderColorFocus": { "alias": "inputBorderColorFocus"; "required": false; }; "inputPadding": { "alias": "inputPadding"; "required": false; }; "locale": { "alias": "locale"; "required": false; }; "disabledDates": { "alias": "disabledDates"; "required": false; }; "displayFormat": { "alias": "displayFormat"; "required": false; }; "requireApply": { "alias": "requireApply"; "required": false; }; }, { "dateRangeChange": "dateRangeChange"; "dateRangeSelected": "dateRangeSelected"; "multiDateRangeChange": "multiDateRangeChange"; "multiDateRangeSelected": "multiDateRangeSelected"; }, never, never, true, never>;
159
+ static ɵcmp: i0.ɵɵComponentDeclaration<DualDatepickerComponent, "ngx-dual-datepicker", never, { "placeholder": { "alias": "placeholder"; "required": false; }; "startDate": { "alias": "startDate"; "required": false; }; "endDate": { "alias": "endDate"; "required": false; }; "showPresets": { "alias": "showPresets"; "required": false; }; "showClearButton": { "alias": "showClearButton"; "required": false; }; "multiRange": { "alias": "multiRange"; "required": false; }; "closeOnSelection": { "alias": "closeOnSelection"; "required": false; }; "closeOnPresetSelection": { "alias": "closeOnPresetSelection"; "required": false; }; "closeOnClickOutside": { "alias": "closeOnClickOutside"; "required": false; }; "enableKeyboardNavigation": { "alias": "enableKeyboardNavigation"; "required": false; }; "presets": { "alias": "presets"; "required": false; }; "theme": { "alias": "theme"; "required": false; }; "inputBackgroundColor": { "alias": "inputBackgroundColor"; "required": false; }; "inputTextColor": { "alias": "inputTextColor"; "required": false; }; "inputBorderColor": { "alias": "inputBorderColor"; "required": false; }; "inputBorderColorHover": { "alias": "inputBorderColorHover"; "required": false; }; "inputBorderColorFocus": { "alias": "inputBorderColorFocus"; "required": false; }; "inputPadding": { "alias": "inputPadding"; "required": false; }; "locale": { "alias": "locale"; "required": false; }; "disabledDates": { "alias": "disabledDates"; "required": false; }; "displayFormat": { "alias": "displayFormat"; "required": false; }; "requireApply": { "alias": "requireApply"; "required": false; }; "enableTimePicker": { "alias": "enableTimePicker"; "required": false; }; "timeFormat": { "alias": "timeFormat"; "required": false; }; "minuteStep": { "alias": "minuteStep"; "required": false; }; "defaultStartTime": { "alias": "defaultStartTime"; "required": false; }; "defaultEndTime": { "alias": "defaultEndTime"; "required": false; }; }, { "dateRangeChange": "dateRangeChange"; "dateRangeSelected": "dateRangeSelected"; "multiDateRangeChange": "multiDateRangeChange"; "multiDateRangeSelected": "multiDateRangeSelected"; }, never, never, true, never>;
132
160
  }