@oneluiz/dual-datepicker 3.9.2 → 4.0.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/dual-datepicker.component.d.ts +4 -4
- package/esm2022/core/internal.mjs +92 -0
- package/esm2022/core/public.mjs +94 -0
- package/esm2022/core/testing/date.helpers.mjs +49 -0
- package/esm2022/core/testing/fixed-clock.mjs +30 -0
- package/esm2022/core/testing/index.mjs +8 -0
- package/esm2022/dual-datepicker.component.mjs +34 -32
- package/esm2022/public-api.mjs +39 -9
- package/fesm2022/oneluiz-dual-datepicker.mjs +629 -975
- package/fesm2022/oneluiz-dual-datepicker.mjs.map +1 -1
- package/package.json +11 -1
- package/public-api.d.ts +39 -4
- package/core/built-in-presets.d.ts +0 -98
- package/core/calendar-grid/cache.config.d.ts +0 -34
- package/core/calendar-grid/calendar-grid.cache.d.ts +0 -39
- package/core/calendar-grid/calendar-grid.factory.d.ts +0 -26
- package/core/calendar-grid/calendar-grid.types.d.ts +0 -57
- package/core/calendar-grid/index.d.ts +0 -56
- package/core/calendar-grid/range-highlighter.cache.d.ts +0 -106
- package/core/calendar-grid/range-highlighter.d.ts +0 -85
- package/core/calendar-grid/range-highlighter.types.d.ts +0 -182
- package/core/calendar-grid/virtual-weeks.logic.d.ts +0 -116
- package/core/calendar-grid/virtual-weeks.types.d.ts +0 -71
- package/core/date-adapter.d.ts +0 -298
- package/core/date-clock.d.ts +0 -82
- package/core/dual-date-range.store.d.ts +0 -113
- package/core/index.d.ts +0 -33
- package/core/native-date-adapter.d.ts +0 -152
- package/core/preset-providers.d.ts +0 -176
- package/core/preset-registry.d.ts +0 -181
- package/core/preset.engine.d.ts +0 -124
- package/core/range-preset.plugin.d.ts +0 -188
- package/core/range.validator.d.ts +0 -37
- package/core/system-clock.d.ts +0 -13
- package/date-adapter.d.ts +0 -116
- package/esm2022/core/calendar-grid/index.mjs +0 -57
- package/esm2022/core/index.mjs +0 -37
- package/esm2022/date-adapter.mjs +0 -12
- package/esm2022/native-date-adapter.mjs +0 -117
- package/esm2022/preset-utils.mjs +0 -276
- package/native-date-adapter.d.ts +0 -26
- package/preset-utils.d.ts +0 -91
- package/src/themes/bootstrap.scss +0 -202
- package/src/themes/bulma.scss +0 -209
- package/src/themes/custom.scss +0 -236
- package/src/themes/foundation.scss +0 -201
- package/src/themes/tailwind.scss +0 -109
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Range Highlighter Types
|
|
3
|
-
*
|
|
4
|
-
* Type definitions for calendar cell decorations with range highlighting.
|
|
5
|
-
* Used by RangeHighlighter to cache decorated grids and avoid recomputations.
|
|
6
|
-
*
|
|
7
|
-
* @module core/calendar-grid/range-highlighter.types
|
|
8
|
-
* @version 3.8.0
|
|
9
|
-
*/
|
|
10
|
-
import { CalendarCell, CalendarGrid } from './calendar-grid.types';
|
|
11
|
-
/**
|
|
12
|
-
* Calendar cell with range highlight decorations
|
|
13
|
-
*
|
|
14
|
-
* Extends base CalendarCell with computed properties for:
|
|
15
|
-
* - Start/end markers (selected range boundaries)
|
|
16
|
-
* - Range membership (cell within selected range)
|
|
17
|
-
* - Hover preview (temporary range during mouse hover)
|
|
18
|
-
* - Disabled state (constraints, custom predicates)
|
|
19
|
-
*/
|
|
20
|
-
export interface DecoratedCell extends CalendarCell {
|
|
21
|
-
/**
|
|
22
|
-
* True if this cell is the selected start date
|
|
23
|
-
*/
|
|
24
|
-
isSelectedStart: boolean;
|
|
25
|
-
/**
|
|
26
|
-
* True if this cell is the selected end date
|
|
27
|
-
*/
|
|
28
|
-
isSelectedEnd: boolean;
|
|
29
|
-
/**
|
|
30
|
-
* True if this cell is within the selected range (inclusive)
|
|
31
|
-
*/
|
|
32
|
-
isInRange: boolean;
|
|
33
|
-
/**
|
|
34
|
-
* True if this cell is within the hover preview range
|
|
35
|
-
*/
|
|
36
|
-
isInHoverRange: boolean;
|
|
37
|
-
/**
|
|
38
|
-
* True if this cell is disabled (via constraints or custom logic)
|
|
39
|
-
*/
|
|
40
|
-
isDisabled: boolean;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Calendar grid with decorated cells
|
|
44
|
-
*
|
|
45
|
-
* Contains:
|
|
46
|
-
* - base: Original CalendarGrid (from CalendarGridCache)
|
|
47
|
-
* - weeks: 2D array of decorated cells (6 × 7)
|
|
48
|
-
* - cells: Flat array of decorated cells (42 cells)
|
|
49
|
-
*/
|
|
50
|
-
export interface DecoratedGrid {
|
|
51
|
-
/**
|
|
52
|
-
* Base grid structure (memoized by CalendarGridCache)
|
|
53
|
-
*/
|
|
54
|
-
base: CalendarGrid;
|
|
55
|
-
/**
|
|
56
|
-
* Decorated cells organized as weeks (6 weeks × 7 days)
|
|
57
|
-
*/
|
|
58
|
-
weeks: DecoratedCell[][];
|
|
59
|
-
/**
|
|
60
|
-
* Decorated cells as flat array (42 cells for layout stability)
|
|
61
|
-
*/
|
|
62
|
-
cells: DecoratedCell[];
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Parameters for range decoration
|
|
66
|
-
*
|
|
67
|
-
* All dates must be Date objects (pre-parsed by component).
|
|
68
|
-
* Cache key is built from ISO dates (via DateAdapter.toISODate).
|
|
69
|
-
*
|
|
70
|
-
* Constraints:
|
|
71
|
-
* - start/end: Selected range boundaries (null if not selected)
|
|
72
|
-
* - minDate/maxDate: Hard constraints (optional, for future use)
|
|
73
|
-
* - hoverDate: Current hover date (null if not hovering)
|
|
74
|
-
* - disabledDates: Array of disabled dates OR function predicate
|
|
75
|
-
*/
|
|
76
|
-
export interface RangeDecorationParams {
|
|
77
|
-
/**
|
|
78
|
-
* Selected start date (null if not selected yet)
|
|
79
|
-
*/
|
|
80
|
-
start: Date | null;
|
|
81
|
-
/**
|
|
82
|
-
* Selected end date (null if not selected yet)
|
|
83
|
-
*/
|
|
84
|
-
end: Date | null;
|
|
85
|
-
/**
|
|
86
|
-
* Minimum allowed date (optional, for future constraint support)
|
|
87
|
-
* All dates before this will be disabled.
|
|
88
|
-
*/
|
|
89
|
-
minDate?: Date | null;
|
|
90
|
-
/**
|
|
91
|
-
* Maximum allowed date (optional, for future constraint support)
|
|
92
|
-
* All dates after this will be disabled.
|
|
93
|
-
*/
|
|
94
|
-
maxDate?: Date | null;
|
|
95
|
-
/**
|
|
96
|
-
* Current hover date (null if not hovering)
|
|
97
|
-
* Used to calculate hover preview range.
|
|
98
|
-
*/
|
|
99
|
-
hoverDate?: string | null;
|
|
100
|
-
/**
|
|
101
|
-
* Disabled dates specification
|
|
102
|
-
*
|
|
103
|
-
* Can be one of:
|
|
104
|
-
* - Array of Date objects to disable (exact matches)
|
|
105
|
-
* - Function predicate (date) => boolean
|
|
106
|
-
* - undefined/null (no dates disabled)
|
|
107
|
-
*
|
|
108
|
-
* NOTE: Functions cannot be cached reliably (no stable key).
|
|
109
|
-
* If using function, cache will be bypassed for isDisabled computation.
|
|
110
|
-
*/
|
|
111
|
-
disabledDates?: Date[] | ((date: Date) => boolean) | null;
|
|
112
|
-
/**
|
|
113
|
-
* Multi-range mode flag (affects hover range behavior)
|
|
114
|
-
* Default: false
|
|
115
|
-
*/
|
|
116
|
-
multiRange?: boolean;
|
|
117
|
-
/**
|
|
118
|
-
* Currently selecting start date (affects hover preview)
|
|
119
|
-
* Default: false
|
|
120
|
-
*/
|
|
121
|
-
selectingStartDate?: boolean;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Cache key for decorated grid
|
|
125
|
-
*
|
|
126
|
-
* Built from:
|
|
127
|
-
* - monthKey: `${year}-${month}-${weekStart}-${locale}`
|
|
128
|
-
* - startISO, endISO: ISO dates or 'null'
|
|
129
|
-
* - minISO, maxISO: ISO dates or 'null' (optional)
|
|
130
|
-
* - hoverISO: ISO date or 'null'
|
|
131
|
-
* - disabledSignature: Hash of disabled dates (or 'none' / 'function')
|
|
132
|
-
*
|
|
133
|
-
* Example:
|
|
134
|
-
* "2026-1-0-|2026-01-15|2026-01-25|null|null|2026-01-20|2026-01-10,2026-01-11"
|
|
135
|
-
*
|
|
136
|
-
* Segment breakdown:
|
|
137
|
-
* 1. 2026-1-0- (month: Jan 2026, weekStart: Sunday, no locale)
|
|
138
|
-
* 2. 2026-01-15 (start date)
|
|
139
|
-
* 3. 2026-01-25 (end date)
|
|
140
|
-
* 4. null (no minDate)
|
|
141
|
-
* 5. null (no maxDate)
|
|
142
|
-
* 6. 2026-01-20 (hovering over Jan 20)
|
|
143
|
-
* 7. 2026-01-10,2026-01-11 (disabled dates: Jan 10 & 11)
|
|
144
|
-
*/
|
|
145
|
-
export interface DecoratedGridCacheKey {
|
|
146
|
-
/**
|
|
147
|
-
* Combined month key (from base grid)
|
|
148
|
-
*/
|
|
149
|
-
monthKey: string;
|
|
150
|
-
/**
|
|
151
|
-
* Start date ISO (YYYY-MM-DD) or 'null'
|
|
152
|
-
*/
|
|
153
|
-
startISO: string;
|
|
154
|
-
/**
|
|
155
|
-
* End date ISO (YYYY-MM-DD) or 'null'
|
|
156
|
-
*/
|
|
157
|
-
endISO: string;
|
|
158
|
-
/**
|
|
159
|
-
* Min date ISO (YYYY-MM-DD) or 'null'
|
|
160
|
-
*/
|
|
161
|
-
minISO: string;
|
|
162
|
-
/**
|
|
163
|
-
* Max date ISO (YYYY-MM-DD) or 'null'
|
|
164
|
-
*/
|
|
165
|
-
maxISO: string;
|
|
166
|
-
/**
|
|
167
|
-
* Hover date ISO (YYYY-MM-DD) or 'null'
|
|
168
|
-
*/
|
|
169
|
-
hoverISO: string;
|
|
170
|
-
/**
|
|
171
|
-
* Disabled dates signature
|
|
172
|
-
*
|
|
173
|
-
* - 'none': No dates disabled
|
|
174
|
-
* - 'function': Using predicate function (not cacheable)
|
|
175
|
-
* - sorted ISO string: "2026-01-10,2026-01-11,..." (for array)
|
|
176
|
-
*/
|
|
177
|
-
disabledSignature: string;
|
|
178
|
-
/**
|
|
179
|
-
* Full cache key (concatenation of all segments)
|
|
180
|
-
*/
|
|
181
|
-
full: string;
|
|
182
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Virtual Weeks Logic (Pure Functions)
|
|
3
|
-
*
|
|
4
|
-
* Pure computation layer for windowed week rendering.
|
|
5
|
-
* No side effects, fully testable with node:test.
|
|
6
|
-
*
|
|
7
|
-
* @module core/calendar-grid/virtual-weeks.logic
|
|
8
|
-
* @version 3.9.0
|
|
9
|
-
*/
|
|
10
|
-
import { VirtualWeekWindow } from './virtual-weeks.types';
|
|
11
|
-
/**
|
|
12
|
-
* Get visible weeks from total weeks array
|
|
13
|
-
*
|
|
14
|
-
* Pure function: Given weeks array and window config, returns visible slice.
|
|
15
|
-
*
|
|
16
|
-
* @param weeks Total weeks array (usually 6 weeks)
|
|
17
|
-
* @param startIndex Start index of visible window (0-based)
|
|
18
|
-
* @param windowSize How many weeks to show
|
|
19
|
-
* @returns Visible weeks slice
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```typescript
|
|
23
|
-
* const allWeeks = [week0, week1, week2, week3, week4, week5]; // 6 weeks
|
|
24
|
-
* const visible = getVisibleWeeks(allWeeks, 0, 3);
|
|
25
|
-
* // Returns [week0, week1, week2]
|
|
26
|
-
*
|
|
27
|
-
* const visible2 = getVisibleWeeks(allWeeks, 3, 3);
|
|
28
|
-
* // Returns [week3, week4, week5]
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
|
-
export declare function getVisibleWeeks<T>(weeks: T[], startIndex: number, windowSize: number): T[];
|
|
32
|
-
/**
|
|
33
|
-
* Clamp week start index to valid range
|
|
34
|
-
*
|
|
35
|
-
* Ensures startIndex is within bounds [0, totalWeeks - windowSize].
|
|
36
|
-
* Prevents scrolling beyond available weeks.
|
|
37
|
-
*
|
|
38
|
-
* @param startIndex Desired start index
|
|
39
|
-
* @param totalWeeks Total weeks available
|
|
40
|
-
* @param windowSize Window size
|
|
41
|
-
* @returns Clamped start index
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```typescript
|
|
45
|
-
* clampWeekStart(0, 6, 3); // 0 (valid)
|
|
46
|
-
* clampWeekStart(3, 6, 3); // 3 (valid, shows weeks 3-5)
|
|
47
|
-
* clampWeekStart(4, 6, 3); // 3 (clamped, can't show beyond week 5)
|
|
48
|
-
* clampWeekStart(-1, 6, 3); // 0 (clamped, can't go negative)
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
export declare function clampWeekStart(startIndex: number, totalWeeks: number, windowSize: number): number;
|
|
52
|
-
/**
|
|
53
|
-
* Navigate week window (scroll up/down)
|
|
54
|
-
*
|
|
55
|
-
* Returns new start index after navigation.
|
|
56
|
-
* Handles clamping automatically.
|
|
57
|
-
*
|
|
58
|
-
* @param currentStart Current start index
|
|
59
|
-
* @param direction Navigation direction (+1 = down/later, -1 = up/earlier)
|
|
60
|
-
* @param totalWeeks Total weeks available
|
|
61
|
-
* @param windowSize Window size
|
|
62
|
-
* @returns New start index after navigation
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* ```typescript
|
|
66
|
-
* // Start at week 0, navigate down
|
|
67
|
-
* navigateWeekWindow(0, 1, 6, 3); // Returns 1 (now showing weeks 1-3)
|
|
68
|
-
*
|
|
69
|
-
* // At week 3 (last valid position), navigate down
|
|
70
|
-
* navigateWeekWindow(3, 1, 6, 3); // Returns 3 (can't go further)
|
|
71
|
-
*
|
|
72
|
-
* // At week 1, navigate up
|
|
73
|
-
* navigateWeekWindow(1, -1, 6, 3); // Returns 0 (now showing weeks 0-2)
|
|
74
|
-
* ```
|
|
75
|
-
*/
|
|
76
|
-
export declare function navigateWeekWindow(currentStart: number, direction: number, totalWeeks: number, windowSize: number): number;
|
|
77
|
-
/**
|
|
78
|
-
* Get virtual week window state
|
|
79
|
-
*
|
|
80
|
-
* Computes full window state including navigation capabilities.
|
|
81
|
-
*
|
|
82
|
-
* @param startIndex Current start index
|
|
83
|
-
* @param totalWeeks Total weeks available
|
|
84
|
-
* @param windowSize Window size
|
|
85
|
-
* @returns Complete window state
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* ```typescript
|
|
89
|
-
* const state = getVirtualWeekWindow(0, 6, 3);
|
|
90
|
-
* // {
|
|
91
|
-
* // startIndex: 0,
|
|
92
|
-
* // windowSize: 3,
|
|
93
|
-
* // totalWeeks: 6,
|
|
94
|
-
* // canNavigateUp: false, // Already at top
|
|
95
|
-
* // canNavigateDown: true // Can scroll down
|
|
96
|
-
* // }
|
|
97
|
-
*
|
|
98
|
-
* const state2 = getVirtualWeekWindow(3, 6, 3);
|
|
99
|
-
* // {
|
|
100
|
-
* // startIndex: 3,
|
|
101
|
-
* // windowSize: 3,
|
|
102
|
-
* // totalWeeks: 6,
|
|
103
|
-
* // canNavigateUp: true, // Can scroll up
|
|
104
|
-
* // canNavigateDown: false // Already at bottom
|
|
105
|
-
* // }
|
|
106
|
-
* ```
|
|
107
|
-
*/
|
|
108
|
-
export declare function getVirtualWeekWindow(startIndex: number, totalWeeks: number, windowSize: number): VirtualWeekWindow;
|
|
109
|
-
/**
|
|
110
|
-
* Check if virtual weeks mode is enabled
|
|
111
|
-
*
|
|
112
|
-
* @param windowSize Window size from config (undefined = disabled)
|
|
113
|
-
* @param totalWeeks Total weeks available
|
|
114
|
-
* @returns True if windowing should be applied
|
|
115
|
-
*/
|
|
116
|
-
export declare function isVirtualWeeksEnabled(windowSize: number | undefined, totalWeeks: number): boolean;
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Virtual Weeks Types
|
|
3
|
-
*
|
|
4
|
-
* Type definitions for windowed week rendering (virtual scrolling).
|
|
5
|
-
* Reduces DOM nodes by rendering only visible weeks instead of full month.
|
|
6
|
-
*
|
|
7
|
-
* @module core/calendar-grid/virtual-weeks.types
|
|
8
|
-
* @version 3.9.0
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* Virtual weeks configuration
|
|
12
|
-
*
|
|
13
|
-
* Controls how many weeks to render at once (windowed rendering).
|
|
14
|
-
* Reduces DOM complexity for better mobile performance.
|
|
15
|
-
*
|
|
16
|
-
* Example:
|
|
17
|
-
* ```typescript
|
|
18
|
-
* <ngx-dual-datepicker
|
|
19
|
-
* [virtualWeeks]="{ windowSize: 3 }"
|
|
20
|
-
* </ngx-dual-datepicker>
|
|
21
|
-
* ```
|
|
22
|
-
*
|
|
23
|
-
* With windowSize=3:
|
|
24
|
-
* - Renders only 3 weeks at a time (21 cells vs 42 cells)
|
|
25
|
-
* - User can navigate between week windows
|
|
26
|
-
* - ~50% reduction in DOM nodes per calendar
|
|
27
|
-
* - ~50% reduction in reflow/repaint cost
|
|
28
|
-
*/
|
|
29
|
-
export interface VirtualWeeksConfig {
|
|
30
|
-
/**
|
|
31
|
-
* Number of weeks to render at once
|
|
32
|
-
*
|
|
33
|
-
* Default: undefined (render all 6 weeks - backward compatible)
|
|
34
|
-
*
|
|
35
|
-
* Recommended values:
|
|
36
|
-
* - 3: Good balance (21 cells)
|
|
37
|
-
* - 4: More context (28 cells)
|
|
38
|
-
* - 2: Minimal (14 cells, may feel cramped)
|
|
39
|
-
*/
|
|
40
|
-
windowSize: number;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Virtual week window state
|
|
44
|
-
*
|
|
45
|
-
* Tracks which weeks are currently visible in the window.
|
|
46
|
-
* Managed by component signals.
|
|
47
|
-
*/
|
|
48
|
-
export interface VirtualWeekWindow {
|
|
49
|
-
/**
|
|
50
|
-
* Start index of visible week range (0-based)
|
|
51
|
-
*
|
|
52
|
-
* Range: [0, totalWeeks - windowSize]
|
|
53
|
-
*/
|
|
54
|
-
startIndex: number;
|
|
55
|
-
/**
|
|
56
|
-
* Window size (how many weeks visible)
|
|
57
|
-
*/
|
|
58
|
-
windowSize: number;
|
|
59
|
-
/**
|
|
60
|
-
* Total weeks available in month (usually 6, sometimes 5)
|
|
61
|
-
*/
|
|
62
|
-
totalWeeks: number;
|
|
63
|
-
/**
|
|
64
|
-
* Whether user can scroll/navigate up (to earlier weeks)
|
|
65
|
-
*/
|
|
66
|
-
canNavigateUp: boolean;
|
|
67
|
-
/**
|
|
68
|
-
* Whether user can scroll/navigate down (to later weeks)
|
|
69
|
-
*/
|
|
70
|
-
canNavigateDown: boolean;
|
|
71
|
-
}
|
package/core/date-adapter.d.ts
DELETED
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Date Adapter Abstraction for Timezone-Safe Date Operations
|
|
3
|
-
*
|
|
4
|
-
* Problem:
|
|
5
|
-
* Using Date natively in calendar/range logic causes enterprise bugs:
|
|
6
|
-
* - Date ranges shift by 1 day due to timezone/DST
|
|
7
|
-
* - Server (UTC) vs Client (local timezone) discrepancies
|
|
8
|
-
* - Inconsistent reporting in BI/ERP/invoicing/hotel systems
|
|
9
|
-
*
|
|
10
|
-
* Solution:
|
|
11
|
-
* All date calculations go through an adapter layer.
|
|
12
|
-
* This allows:
|
|
13
|
-
* - Timezone-safe operations by default (NativeDateAdapter normalizes to day boundaries)
|
|
14
|
-
* - Optional integration with Luxon/DayJS/date-fns for advanced timezone handling
|
|
15
|
-
* - Consistent behavior across SSR and client
|
|
16
|
-
* - Migration path to timezone-aware libraries without breaking changes
|
|
17
|
-
*
|
|
18
|
-
* Architecture:
|
|
19
|
-
* ```
|
|
20
|
-
* DualDateRangeStore
|
|
21
|
-
* ↓ uses
|
|
22
|
-
* DateAdapter ← Inject via DATE_ADAPTER token
|
|
23
|
-
* ↓ implements
|
|
24
|
-
* NativeDateAdapter (default, zero deps)
|
|
25
|
-
* LuxonDateAdapter (optional, full timezone support)
|
|
26
|
-
* DayJSDateAdapter (optional, lightweight)
|
|
27
|
-
* ```
|
|
28
|
-
*
|
|
29
|
-
* Usage:
|
|
30
|
-
* ```typescript
|
|
31
|
-
* // Default (NativeDateAdapter)
|
|
32
|
-
* bootstrapApplication(AppComponent);
|
|
33
|
-
*
|
|
34
|
-
* // Advanced (Luxon with timezone)
|
|
35
|
-
* import { LuxonDateAdapter } from '@oneluiz/dual-datepicker/luxon';
|
|
36
|
-
*
|
|
37
|
-
* bootstrapApplication(AppComponent, {
|
|
38
|
-
* providers: [
|
|
39
|
-
* { provide: DATE_ADAPTER, useClass: LuxonDateAdapter }
|
|
40
|
-
* ]
|
|
41
|
-
* });
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
import { InjectionToken } from '@angular/core';
|
|
45
|
-
/**
|
|
46
|
-
* Date adapter interface for all calendar/range operations
|
|
47
|
-
*
|
|
48
|
-
* All methods operate on "calendar day" level, ignoring time components.
|
|
49
|
-
* Implementations must ensure timezone-safe behavior.
|
|
50
|
-
*
|
|
51
|
-
* Implementations:
|
|
52
|
-
* - NativeDateAdapter: Default, zero dependencies, uses Date with normalization
|
|
53
|
-
* - LuxonDateAdapter: Optional, full timezone support with Luxon
|
|
54
|
-
* - DayJSDateAdapter: Optional, lightweight timezone support
|
|
55
|
-
* - Custom: Implement for your specific backend/timezone requirements
|
|
56
|
-
*/
|
|
57
|
-
export interface DateAdapter {
|
|
58
|
-
/**
|
|
59
|
-
* Normalize date to start of day (00:00:00.000)
|
|
60
|
-
*
|
|
61
|
-
* Critical for timezone-safe comparisons.
|
|
62
|
-
*
|
|
63
|
-
* Example:
|
|
64
|
-
* ```typescript
|
|
65
|
-
* const date = new Date('2026-02-21T15:30:00');
|
|
66
|
-
* const normalized = adapter.normalize(date);
|
|
67
|
-
* // → 2026-02-21T00:00:00.000 (in local timezone)
|
|
68
|
-
* ```
|
|
69
|
-
*
|
|
70
|
-
* @param date - Date to normalize
|
|
71
|
-
* @returns Date with time set to 00:00:00.000
|
|
72
|
-
*/
|
|
73
|
-
normalize(date: Date): Date;
|
|
74
|
-
/**
|
|
75
|
-
* Check if two dates represent the same calendar day
|
|
76
|
-
*
|
|
77
|
-
* Ignores time component. Timezone-safe.
|
|
78
|
-
*
|
|
79
|
-
* Example:
|
|
80
|
-
* ```typescript
|
|
81
|
-
* const a = new Date('2026-02-21T23:59:59');
|
|
82
|
-
* const b = new Date('2026-02-21T00:00:01');
|
|
83
|
-
* adapter.isSameDay(a, b); // → true
|
|
84
|
-
* ```
|
|
85
|
-
*/
|
|
86
|
-
isSameDay(a: Date, b: Date): boolean;
|
|
87
|
-
/**
|
|
88
|
-
* Check if date A is before date B (calendar day level)
|
|
89
|
-
*
|
|
90
|
-
* Example:
|
|
91
|
-
* ```typescript
|
|
92
|
-
* adapter.isBeforeDay(new Date('2026-02-20'), new Date('2026-02-21')); // → true
|
|
93
|
-
* adapter.isBeforeDay(new Date('2026-02-21'), new Date('2026-02-21')); // → false
|
|
94
|
-
* ```
|
|
95
|
-
*/
|
|
96
|
-
isBeforeDay(a: Date, b: Date): boolean;
|
|
97
|
-
/**
|
|
98
|
-
* Check if date A is after date B (calendar day level)
|
|
99
|
-
*
|
|
100
|
-
* Example:
|
|
101
|
-
* ```typescript
|
|
102
|
-
* adapter.isAfterDay(new Date('2026-02-22'), new Date('2026-02-21')); // → true
|
|
103
|
-
* adapter.isAfterDay(new Date('2026-02-21'), new Date('2026-02-21')); // → false
|
|
104
|
-
* ```
|
|
105
|
-
*/
|
|
106
|
-
isAfterDay(a: Date, b: Date): boolean;
|
|
107
|
-
/**
|
|
108
|
-
* Add days to a date
|
|
109
|
-
*
|
|
110
|
-
* Must handle DST transitions correctly.
|
|
111
|
-
*
|
|
112
|
-
* Example:
|
|
113
|
-
* ```typescript
|
|
114
|
-
* const date = new Date('2026-02-21');
|
|
115
|
-
* const future = adapter.addDays(date, 7);
|
|
116
|
-
* // → 2026-02-28
|
|
117
|
-
* ```
|
|
118
|
-
*/
|
|
119
|
-
addDays(date: Date, days: number): Date;
|
|
120
|
-
/**
|
|
121
|
-
* Add months to a date
|
|
122
|
-
*
|
|
123
|
-
* Must handle month overflow (e.g., Jan 31 + 1 month → Feb 28).
|
|
124
|
-
*
|
|
125
|
-
* Example:
|
|
126
|
-
* ```typescript
|
|
127
|
-
* const date = new Date('2026-01-31');
|
|
128
|
-
* const next = adapter.addMonths(date, 1);
|
|
129
|
-
* // → 2026-02-28 (not March 3rd)
|
|
130
|
-
* ```
|
|
131
|
-
*/
|
|
132
|
-
addMonths(date: Date, months: number): Date;
|
|
133
|
-
/**
|
|
134
|
-
* Get start of day (00:00:00.000)
|
|
135
|
-
*
|
|
136
|
-
* Similar to normalize() but explicit intent.
|
|
137
|
-
*/
|
|
138
|
-
startOfDay(date: Date): Date;
|
|
139
|
-
/**
|
|
140
|
-
* Get end of day (23:59:59.999)
|
|
141
|
-
*
|
|
142
|
-
* Useful for range queries that need to include entire day.
|
|
143
|
-
*
|
|
144
|
-
* Example:
|
|
145
|
-
* ```typescript
|
|
146
|
-
* const date = new Date('2026-02-21');
|
|
147
|
-
* const end = adapter.endOfDay(date);
|
|
148
|
-
* // → 2026-02-21T23:59:59.999
|
|
149
|
-
* ```
|
|
150
|
-
*/
|
|
151
|
-
endOfDay(date: Date): Date;
|
|
152
|
-
/**
|
|
153
|
-
* Get first day of month (00:00:00.000)
|
|
154
|
-
*
|
|
155
|
-
* Example:
|
|
156
|
-
* ```typescript
|
|
157
|
-
* const date = new Date('2026-02-21');
|
|
158
|
-
* const start = adapter.startOfMonth(date);
|
|
159
|
-
* // → 2026-02-01T00:00:00.000
|
|
160
|
-
* ```
|
|
161
|
-
*/
|
|
162
|
-
startOfMonth(date: Date): Date;
|
|
163
|
-
/**
|
|
164
|
-
* Get last day of month (23:59:59.999)
|
|
165
|
-
*
|
|
166
|
-
* Example:
|
|
167
|
-
* ```typescript
|
|
168
|
-
* const date = new Date('2026-02-21');
|
|
169
|
-
* const end = adapter.endOfMonth(date);
|
|
170
|
-
* // → 2026-02-28T23:59:59.999
|
|
171
|
-
* ```
|
|
172
|
-
*/
|
|
173
|
-
endOfMonth(date: Date): Date;
|
|
174
|
-
/**
|
|
175
|
-
* Get year (4-digit)
|
|
176
|
-
*
|
|
177
|
-
* Example:
|
|
178
|
-
* ```typescript
|
|
179
|
-
* adapter.getYear(new Date('2026-02-21')); // → 2026
|
|
180
|
-
* ```
|
|
181
|
-
*/
|
|
182
|
-
getYear(date: Date): number;
|
|
183
|
-
/**
|
|
184
|
-
* Get month (0-11, where 0 = January)
|
|
185
|
-
*
|
|
186
|
-
* Example:
|
|
187
|
-
* ```typescript
|
|
188
|
-
* adapter.getMonth(new Date('2026-02-21')); // → 1 (February)
|
|
189
|
-
* ```
|
|
190
|
-
*/
|
|
191
|
-
getMonth(date: Date): number;
|
|
192
|
-
/**
|
|
193
|
-
* Get day of month (1-31)
|
|
194
|
-
*
|
|
195
|
-
* Example:
|
|
196
|
-
* ```typescript
|
|
197
|
-
* adapter.getDate(new Date('2026-02-21')); // → 21
|
|
198
|
-
* ```
|
|
199
|
-
*/
|
|
200
|
-
getDate(date: Date): number;
|
|
201
|
-
/**
|
|
202
|
-
* Get day of week (0-6, where 0 = Sunday)
|
|
203
|
-
*
|
|
204
|
-
* Example:
|
|
205
|
-
* ```typescript
|
|
206
|
-
* adapter.getDay(new Date('2026-02-21')); // → 6 (Saturday)
|
|
207
|
-
* ```
|
|
208
|
-
*/
|
|
209
|
-
getDay(date: Date): number;
|
|
210
|
-
/**
|
|
211
|
-
* Convert Date to ISO date string (YYYY-MM-DD)
|
|
212
|
-
*
|
|
213
|
-
* CRITICAL: Must be timezone-safe!
|
|
214
|
-
* DO NOT use date.toISOString() as it converts to UTC.
|
|
215
|
-
*
|
|
216
|
-
* Example:
|
|
217
|
-
* ```typescript
|
|
218
|
-
* // Local timezone GMT-6 (CST)
|
|
219
|
-
* const date = new Date('2026-02-21T23:00:00'); // 11 PM CST
|
|
220
|
-
*
|
|
221
|
-
* // ❌ WRONG: date.toISOString().split('T')[0]
|
|
222
|
-
* // Returns "2026-02-22" (shifted to UTC!)
|
|
223
|
-
*
|
|
224
|
-
* // ✅ CORRECT: adapter.toISODate(date)
|
|
225
|
-
* // Returns "2026-02-21" (local date preserved)
|
|
226
|
-
* ```
|
|
227
|
-
*
|
|
228
|
-
* @param date - Date to format (or null)
|
|
229
|
-
* @returns ISO date string in YYYY-MM-DD format (local timezone), empty string if null
|
|
230
|
-
*/
|
|
231
|
-
toISODate(date: Date | null): string;
|
|
232
|
-
/**
|
|
233
|
-
* Parse ISO date string (YYYY-MM-DD) to Date
|
|
234
|
-
*
|
|
235
|
-
* CRITICAL: Must be timezone-safe!
|
|
236
|
-
* DO NOT use new Date(isoString) as it may parse as UTC.
|
|
237
|
-
*
|
|
238
|
-
* Example:
|
|
239
|
-
* ```typescript
|
|
240
|
-
* // ❌ WRONG: new Date('2026-02-21')
|
|
241
|
-
* // May parse as UTC midnight, which is previous day in some timezones
|
|
242
|
-
*
|
|
243
|
-
* // ✅ CORRECT: adapter.parseISODate('2026-02-21')
|
|
244
|
-
* // Returns Date representing 2026-02-21 00:00:00 in local timezone
|
|
245
|
-
* ```
|
|
246
|
-
*
|
|
247
|
-
* @param isoDate - ISO date string (YYYY-MM-DD) or null
|
|
248
|
-
* @returns Date object or null if invalid
|
|
249
|
-
*/
|
|
250
|
-
parseISODate(isoDate: string | null): Date | null;
|
|
251
|
-
/**
|
|
252
|
-
* Get week start day for locale
|
|
253
|
-
*
|
|
254
|
-
* 0 = Sunday, 1 = Monday, etc.
|
|
255
|
-
*
|
|
256
|
-
* Example:
|
|
257
|
-
* ```typescript
|
|
258
|
-
* adapter.getWeekStart('en-US'); // → 0 (Sunday)
|
|
259
|
-
* adapter.getWeekStart('en-GB'); // → 1 (Monday)
|
|
260
|
-
* ```
|
|
261
|
-
*
|
|
262
|
-
* @param locale - Locale string (e.g., 'en-US', 'es-ES')
|
|
263
|
-
* @returns Day number (0-6)
|
|
264
|
-
*/
|
|
265
|
-
getWeekStart(locale?: string): 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* Injection token for DateAdapter
|
|
269
|
-
*
|
|
270
|
-
* Default: NativeDateAdapter (zero dependencies)
|
|
271
|
-
*
|
|
272
|
-
* Override for advanced timezone handling:
|
|
273
|
-
*
|
|
274
|
-
* ```typescript
|
|
275
|
-
* // Luxon with timezone
|
|
276
|
-
* import { LuxonDateAdapter } from '@oneluiz/dual-datepicker/luxon';
|
|
277
|
-
*
|
|
278
|
-
* bootstrapApplication(AppComponent, {
|
|
279
|
-
* providers: [
|
|
280
|
-
* {
|
|
281
|
-
* provide: DATE_ADAPTER,
|
|
282
|
-
* useClass: LuxonDateAdapter
|
|
283
|
-
* }
|
|
284
|
-
* ]
|
|
285
|
-
* });
|
|
286
|
-
* ```
|
|
287
|
-
*
|
|
288
|
-
* Custom implementation:
|
|
289
|
-
*
|
|
290
|
-
* ```typescript
|
|
291
|
-
* class CustomDateAdapter implements DateAdapter {
|
|
292
|
-
* // Your implementation for backend-specific date handling
|
|
293
|
-
* }
|
|
294
|
-
*
|
|
295
|
-
* provide(DATE_ADAPTER, { useClass: CustomDateAdapter });
|
|
296
|
-
* ```
|
|
297
|
-
*/
|
|
298
|
-
export declare const DATE_ADAPTER: InjectionToken<DateAdapter>;
|