@oneluiz/dual-datepicker 3.0.1 → 3.1.1

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
@@ -48,7 +48,7 @@ npm install @oneluiz/dual-datepicker
48
48
  - 🎨 **Fully Customizable** – Every color, padding, border configurable
49
49
  - 📦 **Lightweight** – ~60 KB gzipped total bundle
50
50
  - 🚀 **Performance** – OnPush change detection + trackBy optimization
51
- - ♿ **Accessible** – ARIA labels, semantic HTML, keyboard navigation (in progress)
51
+ - ♿ **Accessible** – ARIA labels, semantic HTML, full keyboard navigation
52
52
  - 🌍 **i18n Ready** – Customizable month/day names
53
53
  - 📱 **Responsive** – Works on desktop and mobile
54
54
 
@@ -83,14 +83,50 @@ npm install @oneluiz/dual-datepicker
83
83
 
84
84
  ## ♿ Accessibility (A11y)
85
85
 
86
- **Current Status:**
87
- - ✅ **Screen reader support** - ARIA labels included for all interactive elements
88
- - ✅ **Semantic HTML** - Proper HTML structure
89
- - 🚧 **Full keyboard navigation** - In active development (see [Roadmap](#-roadmap))
90
- - Mouse/touch interaction: Fully supported
91
- - Keyboard navigation: 🚧 In progress
86
+ **✅ WCAG 2.1 Level AA Compliant**
87
+
88
+ - ✅ **Full keyboard navigation** Complete keyboard control (v3.1.0)
89
+ - **Screen reader support** ARIA labels included for all interactive elements
90
+ - **Semantic HTML** Proper HTML structure with `role` attributes
91
+ - **Focus management** Intelligent focus tracking and visual indicators
92
+
93
+ ### ⌨️ Keyboard Navigation (NEW in v3.1.0)
94
+
95
+ Navigate the datepicker entirely with your keyboard:
96
+
97
+ | Key(s) | Action |
98
+ |--------|--------|
99
+ | **Arrow Keys** | |
100
+ | `←` / `→` | Navigate between days (horizontal) |
101
+ | `↑` / `↓` | Navigate by weeks (vertical) |
102
+ | **Selection** | |
103
+ | `Enter` / `Space` | Select focused day |
104
+ | `Escape` | Close datepicker |
105
+ | **Navigation Shortcuts** | |
106
+ | `Home` | Jump to first day of visible range |
107
+ | `End` | Jump to last day of visible range |
108
+ | `PageUp` / `PageDown` | Navigate months |
109
+ | `Shift + PageUp` / `Shift + PageDown` | Navigate years |
110
+ | `Tab` | Navigate between input, presets, and calendar |
111
+
112
+ **Visual Indicators:**
113
+ - Blue outline ring indicates focused day
114
+ - Light blue background on keyboard-focused days
115
+ - Automatic focus management when opening/closing picker
116
+
117
+ **Screen Reader Support:**
118
+ - `role="combobox"` on input field
119
+ - `aria-expanded`, `aria-haspopup` states
120
+ - `aria-label`, `aria-selected`, `aria-current` on calendar days
121
+
122
+ **Configuration:**
123
+ ```typescript
124
+ // Keyboard navigation enabled by default
125
+ <ngx-dual-datepicker></ngx-dual-datepicker>
92
126
 
93
- > **Note:** Full keyboard navigation support is planned and will be included in a future release. This includes arrow key navigation, Enter/Space selection, and Escape to close.
127
+ // Disable if needed
128
+ <ngx-dual-datepicker [enableKeyboardNavigation]="false"></ngx-dual-datepicker>
129
+ ```
94
130
 
95
131
  ## 📦 Installation
96
132
 
@@ -35,6 +35,7 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
35
35
  closeOnSelection: boolean;
36
36
  closeOnPresetSelection: boolean;
37
37
  closeOnClickOutside: boolean;
38
+ enableKeyboardNavigation: boolean;
38
39
  presets: PresetConfig[];
39
40
  inputBackgroundColor: string;
40
41
  inputTextColor: string;
@@ -58,6 +59,10 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
58
59
  isDisabled: import("@angular/core").WritableSignal<boolean>;
59
60
  selectedRanges: import("@angular/core").WritableSignal<DateRange[]>;
60
61
  currentRangeIndex: import("@angular/core").WritableSignal<number>;
62
+ focusedDay: import("@angular/core").WritableSignal<{
63
+ date: string;
64
+ monthIndex: number;
65
+ }>;
61
66
  currentMonthName: import("@angular/core").Signal<string>;
62
67
  previousMonthName: import("@angular/core").Signal<string>;
63
68
  weekDayNames: import("@angular/core").Signal<string[]>;
@@ -69,6 +74,17 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
69
74
  private onTouched;
70
75
  constructor(elementRef: ElementRef);
71
76
  onClickOutside(event: MouseEvent): void;
77
+ handleKeyboardNavigation(event: KeyboardEvent): void;
78
+ private initializeFocus;
79
+ private isDateInMonth;
80
+ private moveFocusHorizontal;
81
+ private moveFocusVertical;
82
+ private moveFocusToFirstDay;
83
+ private moveFocusToLastDay;
84
+ private moveFocusYear;
85
+ private adjustFocusAfterMonthChange;
86
+ private selectFocusedDay;
87
+ hasKeyboardFocus(date: string, monthIndex: number): boolean;
72
88
  ngOnInit(): void;
73
89
  ngOnChanges(changes: SimpleChanges): void;
74
90
  formatDate(date: Date): string;
@@ -97,5 +113,5 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
97
113
  registerOnTouched(fn: () => void): void;
98
114
  setDisabledState(isDisabled: boolean): void;
99
115
  static ɵfac: i0.ɵɵFactoryDeclaration<DualDatepickerComponent, never>;
100
- 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; }; "presets": { "alias": "presets"; "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; }; }, { "dateRangeChange": "dateRangeChange"; "dateRangeSelected": "dateRangeSelected"; "multiDateRangeChange": "multiDateRangeChange"; "multiDateRangeSelected": "multiDateRangeSelected"; }, never, never, true, never>;
116
+ 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; }; "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; }; }, { "dateRangeChange": "dateRangeChange"; "dateRangeSelected": "dateRangeSelected"; "multiDateRangeChange": "multiDateRangeChange"; "multiDateRangeSelected": "multiDateRangeSelected"; }, never, never, true, never>;
101
117
  }