@oneluiz/dual-datepicker 3.5.0 → 3.6.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
@@ -2,7 +2,8 @@
2
2
 
3
3
  A lightweight, zero-dependency date range picker for Angular 17+. Built with standalone components, Reactive Forms, and Angular Signals. No Angular Material required.
4
4
 
5
- > **🆕 NEW in v3.5.0**: [**Headless Architecture**](HEADLESS.md) - Use date range state WITHOUT the UI component. Perfect for SSR, services, and global dashboard filters! 🎯
5
+ > **🆕 NEW in v3.5.1**: [**Timezone-Safe Date Adapter**](docs/TIMEZONE_ADAPTER.md) - Fixes enterprise-critical timezone bugs in ERP, BI, POS, and invoicing systems 🛡️
6
+ > **🆕 NEW in v3.5.0**: [**Headless Architecture**](docs/HEADLESS.md) - Use date range state WITHOUT the UI component. Perfect for SSR, services, and global dashboard filters! 🎯
6
7
 
7
8
  [![npm version](https://img.shields.io/npm/v/@oneluiz/dual-datepicker)](https://www.npmjs.com/package/@oneluiz/dual-datepicker)
8
9
  [![npm provenance](https://img.shields.io/badge/provenance-available-brightgreen)](https://www.npmjs.com/package/@oneluiz/dual-datepicker)
@@ -21,6 +22,25 @@ npm install @oneluiz/dual-datepicker
21
22
 
22
23
  ## 🌟 What's New
23
24
 
25
+ ### Timezone-Safe Date Adapter (v3.5.1)
26
+
27
+ **Fixed**: Enterprise timezone bugs that caused date ranges to shift by ±1 day.
28
+
29
+ ```typescript
30
+ // ✅ No more timezone shift bugs!
31
+ const store = inject(DualDateRangeStore);
32
+ store.applyPreset('THIS_MONTH');
33
+ const range = store.range(); // { start: "2024-03-01", end: "2024-03-31" }
34
+ // Always correct, even across timezones and DST transitions
35
+
36
+ // ✅ Optional: Use your preferred date library
37
+ providers: [
38
+ { provide: DATE_ADAPTER, useClass: LuxonDateAdapter }
39
+ ]
40
+ ```
41
+
42
+ **[📖 Read the Timezone Adapter Guide →](docs/TIMEZONE_ADAPTER.md)**
43
+
24
44
  ### Headless Architecture (v3.5.0)
25
45
 
26
46
  Use date range logic **without the UI component**:
@@ -44,7 +64,7 @@ http.get(`/api/sales?start=${range.start}&end=${range.end}`);
44
64
  - 🎯 Service-layer filtering
45
65
  - 📈 Analytics and BI tools
46
66
 
47
- **[📖 Read the Headless Architecture Guide →](HEADLESS.md)**
67
+ **[📖 Read the Headless Architecture Guide →](docs/HEADLESS.md)**
48
68
 
49
69
  ---
50
70
 
@@ -245,7 +265,35 @@ export class DashboardComponent {
245
265
  - ✅ Perfect for services and guards
246
266
  - ✅ Testable and deterministic
247
267
 
248
- **[📖 Full Headless Architecture Guide →](HEADLESS.md)** | **[💻 Code Examples →](HEADLESS_EXAMPLES.ts)**
268
+ #### SSR-Safe Clock Injection
269
+
270
+ Presets like "Last 7 Days" now use **clock injection** for SSR hydration consistency:
271
+
272
+ ```typescript
273
+ // Server (SSR)
274
+ import { DATE_CLOCK } from '@oneluiz/dual-datepicker';
275
+
276
+ const requestTime = new Date();
277
+
278
+ renderApplication(AppComponent, {
279
+ providers: [
280
+ { provide: DATE_CLOCK, useValue: { now: () => requestTime } }
281
+ ]
282
+ });
283
+ ```
284
+
285
+ ```typescript
286
+ // Client (Browser)
287
+ bootstrapApplication(AppComponent, {
288
+ providers: [
289
+ { provide: DATE_CLOCK, useValue: { now: () => new Date(getServerTime()) } }
290
+ ]
291
+ });
292
+ ```
293
+
294
+ **Result**: Server and client resolve identical presets ✅ No hydration mismatch!
295
+
296
+ **[📖 Full Headless Architecture Guide →](HEADLESS.md)** | **[💻 Code Examples →](HEADLESS_EXAMPLES.ts)** | **[🚀 SSR Clock Injection Guide →](SSR_CLOCK_INJECTION.md)**
249
297
 
250
298
  ---
251
299
 
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Built-in Date Range Preset Plugins
3
+ *
4
+ * Version: 3.6.0
5
+ *
6
+ * Standard presets provided by the library.
7
+ * All presets use DateClock and DateAdapter for SSR-safety and timezone-safety.
8
+ *
9
+ * PRESETS INCLUDED:
10
+ * - TODAY, YESTERDAY
11
+ * - LAST_7_DAYS, LAST_14_DAYS, LAST_30_DAYS, LAST_60_DAYS, LAST_90_DAYS
12
+ * - THIS_WEEK, LAST_WEEK
13
+ * - THIS_MONTH, LAST_MONTH, MONTH_TO_DATE
14
+ * - THIS_QUARTER, LAST_QUARTER, QUARTER_TO_DATE
15
+ * - THIS_YEAR, LAST_YEAR, YEAR_TO_DATE
16
+ */
17
+ import { RangePresetPlugin } from './range-preset.plugin';
18
+ /**
19
+ * TODAY - Current day
20
+ */
21
+ export declare const TODAY_PRESET: RangePresetPlugin;
22
+ /**
23
+ * YESTERDAY - Previous day
24
+ */
25
+ export declare const YESTERDAY_PRESET: RangePresetPlugin;
26
+ /**
27
+ * LAST_7_DAYS - Last 7 days including today
28
+ */
29
+ export declare const LAST_7_DAYS_PRESET: RangePresetPlugin;
30
+ /**
31
+ * LAST_14_DAYS - Last 14 days including today
32
+ */
33
+ export declare const LAST_14_DAYS_PRESET: RangePresetPlugin;
34
+ /**
35
+ * LAST_30_DAYS - Last 30 days including today
36
+ */
37
+ export declare const LAST_30_DAYS_PRESET: RangePresetPlugin;
38
+ /**
39
+ * LAST_60_DAYS - Last 60 days including today
40
+ */
41
+ export declare const LAST_60_DAYS_PRESET: RangePresetPlugin;
42
+ /**
43
+ * LAST_90_DAYS - Last 90 days including today
44
+ */
45
+ export declare const LAST_90_DAYS_PRESET: RangePresetPlugin;
46
+ /**
47
+ * THIS_WEEK - Current week (Monday to Sunday)
48
+ */
49
+ export declare const THIS_WEEK_PRESET: RangePresetPlugin;
50
+ /**
51
+ * LAST_WEEK - Previous week (Monday to Sunday)
52
+ */
53
+ export declare const LAST_WEEK_PRESET: RangePresetPlugin;
54
+ /**
55
+ * THIS_MONTH - Current calendar month (1st to last day)
56
+ */
57
+ export declare const THIS_MONTH_PRESET: RangePresetPlugin;
58
+ /**
59
+ * LAST_MONTH - Previous calendar month
60
+ */
61
+ export declare const LAST_MONTH_PRESET: RangePresetPlugin;
62
+ /**
63
+ * MONTH_TO_DATE - From start of current month to today
64
+ */
65
+ export declare const MONTH_TO_DATE_PRESET: RangePresetPlugin;
66
+ /**
67
+ * THIS_QUARTER - Current quarter (Q1: Jan-Mar, Q2: Apr-Jun, Q3: Jul-Sep, Q4: Oct-Dec)
68
+ */
69
+ export declare const THIS_QUARTER_PRESET: RangePresetPlugin;
70
+ /**
71
+ * LAST_QUARTER - Previous quarter
72
+ */
73
+ export declare const LAST_QUARTER_PRESET: RangePresetPlugin;
74
+ /**
75
+ * QUARTER_TO_DATE - From start of current quarter to today
76
+ */
77
+ export declare const QUARTER_TO_DATE_PRESET: RangePresetPlugin;
78
+ /**
79
+ * THIS_YEAR - Current calendar year (Jan 1 to Dec 31)
80
+ */
81
+ export declare const THIS_YEAR_PRESET: RangePresetPlugin;
82
+ /**
83
+ * LAST_YEAR - Previous calendar year
84
+ */
85
+ export declare const LAST_YEAR_PRESET: RangePresetPlugin;
86
+ /**
87
+ * YEAR_TO_DATE - From start of current year to today
88
+ */
89
+ export declare const YEAR_TO_DATE_PRESET: RangePresetPlugin;
90
+ /**
91
+ * All built-in presets as an array
92
+ *
93
+ * Use this to register all built-in presets at once:
94
+ * ```typescript
95
+ * BUILT_IN_PRESETS.forEach(preset => registry.register(preset));
96
+ * ```
97
+ */
98
+ export declare const BUILT_IN_PRESETS: RangePresetPlugin[];
@@ -0,0 +1,298 @@
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>;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Date Clock Abstraction for SSR-Safe Date Resolution
3
+ *
4
+ * Problem:
5
+ * Presets like "Last 7 Days" or "This Month" use new Date() which causes:
6
+ * - SSR hydration mismatch
7
+ * - Server renders "2026-02-14", client renders "2026-02-15"
8
+ * - Different filters in dashboards
9
+ * - Different queries in ERP/BI
10
+ * - Cache inconsistency
11
+ *
12
+ * Solution:
13
+ * Inject a DateClock to control time deterministically:
14
+ *
15
+ * Server (SSR):
16
+ * provide(DATE_CLOCK, {
17
+ * useValue: { now: () => new Date('2026-02-21T00:00:00Z') }
18
+ * })
19
+ *
20
+ * Client (Browser):
21
+ * Uses SystemClock by default (new Date())
22
+ *
23
+ * Testing:
24
+ * provide(DATE_CLOCK, {
25
+ * useValue: { now: () => new Date('2026-01-15T10:30:00Z') }
26
+ * })
27
+ *
28
+ * Architecture:
29
+ * - PresetEngine receives DateClock via DI
30
+ * - All preset calculations use clock.now() instead of new Date()
31
+ * - Deterministic: Same clock.now() → Same preset result
32
+ * - SSR-compatible: Server and client resolve identical ranges
33
+ */
34
+ import { InjectionToken } from '@angular/core';
35
+ /**
36
+ * Clock abstraction for deterministic date resolution
37
+ *
38
+ * Use cases:
39
+ * - SSR: Ensure server and client generate identical presets
40
+ * - Testing: Control time for predictable test results
41
+ * - Replay: Reproduce exact user state from past sessions
42
+ * - Demo: Freeze time for reproducible demos
43
+ */
44
+ export interface DateClock {
45
+ /**
46
+ * Get current date/time
47
+ *
48
+ * Default implementation returns new Date()
49
+ * Override for SSR, testing, or time-travel scenarios
50
+ */
51
+ now(): Date;
52
+ }
53
+ /**
54
+ * Injection token for DateClock
55
+ *
56
+ * Usage:
57
+ * ```typescript
58
+ * // Default (uses SystemClock)
59
+ * bootstrapApplication(AppComponent);
60
+ *
61
+ * // SSR Override
62
+ * bootstrapApplication(AppComponent, {
63
+ * providers: [
64
+ * {
65
+ * provide: DATE_CLOCK,
66
+ * useValue: { now: () => new Date('2026-02-21T00:00:00Z') }
67
+ * }
68
+ * ]
69
+ * });
70
+ *
71
+ * // Testing Override
72
+ * TestBed.configureTestingModule({
73
+ * providers: [
74
+ * {
75
+ * provide: DATE_CLOCK,
76
+ * useValue: { now: () => new Date('2026-01-15T12:00:00Z') }
77
+ * }
78
+ * ]
79
+ * });
80
+ * ```
81
+ */
82
+ export declare const DATE_CLOCK: InjectionToken<DateClock>;
@@ -14,6 +14,10 @@ export interface DateRangeConfig {
14
14
  defaultEndTime?: string;
15
15
  }
16
16
  export declare class DualDateRangeStore {
17
+ private presetEngine;
18
+ private clock;
19
+ private adapter;
20
+ constructor();
17
21
  private config;
18
22
  private _startDate;
19
23
  private _endDate;
@@ -72,6 +76,11 @@ export declare class DualDateRangeStore {
72
76
  reset(): void;
73
77
  /**
74
78
  * Apply a preset by key
79
+ *
80
+ * SSR-Safe: Uses injected DateClock for deterministic resolution
81
+ *
82
+ * @param presetKey - Preset identifier (e.g., 'TODAY', 'LAST_7_DAYS')
83
+ * @param now - Optional date override (defaults to clock.now())
75
84
  */
76
85
  applyPreset(presetKey: string, now?: Date): void;
77
86
  /**
package/core/index.d.ts CHANGED
@@ -1,7 +1,22 @@
1
1
  /**
2
2
  * Core headless date range logic
3
+ *
4
+ * v3.6.0: Plugin Architecture
5
+ * - RangePresetPlugin interface for extensible presets
6
+ * - PresetRegistry for plugin management
7
+ * - Built-in presets as plugins
8
+ * - Provider functions for custom presets
9
+ *
3
10
  * Import from here for clean barrel exports
4
11
  */
5
12
  export * from './dual-date-range.store';
6
13
  export * from './preset.engine';
7
14
  export * from './range.validator';
15
+ export * from './date-clock';
16
+ export * from './system-clock';
17
+ export * from './date-adapter';
18
+ export * from './native-date-adapter';
19
+ export * from './range-preset.plugin';
20
+ export * from './preset-registry';
21
+ export * from './built-in-presets';
22
+ export * from './preset-providers';