@oneluiz/dual-datepicker 3.5.1 → 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.
@@ -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[];
package/core/index.d.ts CHANGED
@@ -1,5 +1,12 @@
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';
@@ -9,3 +16,7 @@ export * from './date-clock';
9
16
  export * from './system-clock';
10
17
  export * from './date-adapter';
11
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';
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Provider Functions for Built-in Presets
3
+ *
4
+ * Version: 3.6.0
5
+ *
6
+ * Automatic registration of built-in date range presets.
7
+ * These providers ensure backward compatibility by auto-registering
8
+ * all standard presets (TODAY, LAST_7_DAYS, THIS_MONTH, etc.)
9
+ *
10
+ * USAGE IN LIBRARY (Internal):
11
+ * Built-in presets are registered automatically via Angular providers.
12
+ * Library consumers don't need to do anything.
13
+ *
14
+ * USAGE IN APP (Custom Presets):
15
+ * ```typescript
16
+ * // app.config.ts
17
+ * export const appConfig: ApplicationConfig = {
18
+ * providers: [
19
+ * // ... other providers
20
+ * provideCustomPresets([
21
+ * {
22
+ * key: 'THIS_FISCAL_QUARTER',
23
+ * resolve: (clock, adapter) => {
24
+ * const now = clock.now();
25
+ * // ... fiscal logic
26
+ * return { start, end };
27
+ * }
28
+ * }
29
+ * ])
30
+ * ]
31
+ * };
32
+ * ```
33
+ */
34
+ import { EnvironmentProviders } from '@angular/core';
35
+ import { RangePresetPlugin } from './range-preset.plugin';
36
+ /**
37
+ * Provide built-in date range presets
38
+ *
39
+ * This provider is automatically included in the library's root providers.
40
+ * Library consumers don't need to add this manually.
41
+ *
42
+ * @returns EnvironmentProviders for built-in presets
43
+ *
44
+ * @internal
45
+ */
46
+ export declare function provideBuiltInPresets(): EnvironmentProviders;
47
+ /**
48
+ * Provide custom date range presets
49
+ *
50
+ * Use this to register your own industry-specific presets:
51
+ * - Fiscal presets
52
+ * - Hotel/hospitality presets
53
+ * - Logistics presets
54
+ * - Custom business logic
55
+ *
56
+ * @param presets - Array of custom RangePresetPlugin implementations
57
+ * @returns EnvironmentProviders for custom presets
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * // Fiscal presets
62
+ * const FISCAL_PRESETS: RangePresetPlugin[] = [
63
+ * {
64
+ * key: 'THIS_FISCAL_QUARTER',
65
+ * resolve: (clock, adapter) => {
66
+ * const now = clock.now();
67
+ * const month = adapter.getMonth(now);
68
+ *
69
+ * // Fiscal year starts April (month 3)
70
+ * const fiscalMonth = (month + 9) % 12;
71
+ * const quarterStart = Math.floor(fiscalMonth / 3) * 3;
72
+ * const calendarMonth = (quarterStart - 9 + 12) % 12;
73
+ *
74
+ * const year = adapter.getYear(now);
75
+ * const fiscalYear = month < 3 ? year - 1 : year;
76
+ *
77
+ * const start = new Date(fiscalYear, calendarMonth, 1);
78
+ * const end = new Date(fiscalYear, calendarMonth + 3, 0);
79
+ *
80
+ * return {
81
+ * start: adapter.normalize(start),
82
+ * end: adapter.normalize(end)
83
+ * };
84
+ * }
85
+ * },
86
+ * {
87
+ * key: 'FISCAL_YEAR_TO_DATE',
88
+ * resolve: (clock, adapter) => {
89
+ * const now = clock.now();
90
+ * const month = adapter.getMonth(now);
91
+ * const year = adapter.getYear(now);
92
+ *
93
+ * // Fiscal year starts April 1
94
+ * const fiscalYearStart = month >= 3
95
+ * ? new Date(year, 3, 1)
96
+ * : new Date(year - 1, 3, 1);
97
+ *
98
+ * return {
99
+ * start: adapter.normalize(fiscalYearStart),
100
+ * end: adapter.normalize(now)
101
+ * };
102
+ * }
103
+ * }
104
+ * ];
105
+ *
106
+ * // In app.config.ts
107
+ * export const appConfig: ApplicationConfig = {
108
+ * providers: [
109
+ * provideCustomPresets(FISCAL_PRESETS)
110
+ * ]
111
+ * };
112
+ *
113
+ * // Use in components
114
+ * store.applyPreset('THIS_FISCAL_QUARTER');
115
+ * store.applyPreset('FISCAL_YEAR_TO_DATE');
116
+ * ```
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * // Hotel presets
121
+ * const HOTEL_PRESETS: RangePresetPlugin[] = [
122
+ * {
123
+ * key: 'CHECK_IN_WEEK',
124
+ * resolve: (clock, adapter) => {
125
+ * const now = clock.now();
126
+ * const dayOfWeek = adapter.getDayOfWeek(now);
127
+ *
128
+ * // Check-in week: Friday to Friday
129
+ * const daysToNextFriday = dayOfWeek <= 5
130
+ * ? 5 - dayOfWeek
131
+ * : 7 - dayOfWeek + 5;
132
+ *
133
+ * const nextFriday = adapter.addDays(now, daysToNextFriday);
134
+ * const followingFriday = adapter.addDays(nextFriday, 7);
135
+ *
136
+ * return { start: nextFriday, end: followingFriday };
137
+ * }
138
+ * },
139
+ * {
140
+ * key: 'NEXT_30_NIGHTS',
141
+ * resolve: (clock, adapter) => {
142
+ * const now = clock.now();
143
+ * const tomorrow = adapter.addDays(now, 1);
144
+ * const end = adapter.addDays(tomorrow, 30);
145
+ * return { start: tomorrow, end };
146
+ * }
147
+ * }
148
+ * ];
149
+ *
150
+ * providers: [provideCustomPresets(HOTEL_PRESETS)]
151
+ * ```
152
+ */
153
+ export declare function provideCustomPresets(presets: RangePresetPlugin[]): EnvironmentProviders;
154
+ /**
155
+ * Provide preset package
156
+ *
157
+ * Convenience function for external preset packages.
158
+ *
159
+ * @param packageName - Name of the preset package (for logging)
160
+ * @param presets - Array of presets from the package
161
+ * @returns EnvironmentProviders
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * // @acme/fiscal-presets package
166
+ * export function provideFiscalPresets(): EnvironmentProviders {
167
+ * return providePresetPackage('@acme/fiscal-presets', FISCAL_PRESETS);
168
+ * }
169
+ *
170
+ * // In app
171
+ * import { provideFiscalPresets } from '@acme/fiscal-presets';
172
+ *
173
+ * providers: [provideFiscalPresets()]
174
+ * ```
175
+ */
176
+ export declare function providePresetPackage(packageName: string, presets: RangePresetPlugin[]): EnvironmentProviders;
@@ -0,0 +1,181 @@
1
+ import { RangePresetPlugin } from './range-preset.plugin';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Preset Registry Service
5
+ *
6
+ * Manages registration and retrieval of date range preset plugins.
7
+ *
8
+ * DESIGN:
9
+ * - Uses Map for O(1) lookups
10
+ * - Immutable getAll() returns copy
11
+ * - Supports plugin override (last registration wins)
12
+ * - Validates plugins before registration
13
+ */
14
+ export declare class PresetRegistry {
15
+ /**
16
+ * Internal map of registered presets
17
+ * Key: preset key (e.g., 'TODAY', 'LAST_7_DAYS')
18
+ * Value: RangePresetPlugin instance
19
+ */
20
+ private readonly presets;
21
+ /**
22
+ * Register a date range preset plugin
23
+ *
24
+ * If a preset with the same key already exists, it will be overridden.
25
+ * This is useful for:
26
+ * - Testing (override built-in presets with mocks)
27
+ * - Customization (replace default behavior)
28
+ * - Hot-reload scenarios
29
+ *
30
+ * @param plugin - The preset plugin to register
31
+ * @throws Error if plugin is invalid (missing key or resolve function)
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * registry.register({
36
+ * key: 'LAST_BUSINESS_WEEK',
37
+ * resolve: (clock, adapter) => {
38
+ * const now = clock.now();
39
+ * const dayOfWeek = adapter.getDayOfWeek(now);
40
+ *
41
+ * // Go back to last Friday
42
+ * const daysToLastFriday = dayOfWeek === 0 ? 2 : (dayOfWeek + 2) % 7;
43
+ * const lastFriday = adapter.addDays(now, -daysToLastFriday);
44
+ *
45
+ * // Business week: Monday to Friday
46
+ * const monday = adapter.addDays(lastFriday, -4);
47
+ *
48
+ * return { start: monday, end: lastFriday };
49
+ * }
50
+ * });
51
+ * ```
52
+ */
53
+ register(plugin: RangePresetPlugin): void;
54
+ /**
55
+ * Register multiple preset plugins at once
56
+ *
57
+ * Convenience method for bulk registration.
58
+ * Useful when importing preset packages.
59
+ *
60
+ * @param plugins - Array of preset plugins to register
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * import { FISCAL_PRESETS } from '@acme/fiscal-presets';
65
+ *
66
+ * registry.registerAll(FISCAL_PRESETS);
67
+ * ```
68
+ */
69
+ registerAll(plugins: RangePresetPlugin[]): void;
70
+ /**
71
+ * Get a preset plugin by key
72
+ *
73
+ * @param key - Preset key (case-insensitive, e.g., 'today' or 'TODAY')
74
+ * @returns The preset plugin or undefined if not found
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * const preset = registry.get('LAST_7_DAYS');
79
+ * if (preset) {
80
+ * const range = preset.resolve(clock, adapter);
81
+ * console.log('Range:', range);
82
+ * }
83
+ * ```
84
+ */
85
+ get(key: string): RangePresetPlugin | undefined;
86
+ /**
87
+ * Check if a preset exists in the registry
88
+ *
89
+ * @param key - Preset key (case-insensitive)
90
+ * @returns true if preset exists, false otherwise
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * if (registry.has('THIS_FISCAL_QUARTER')) {
95
+ * store.applyPreset('THIS_FISCAL_QUARTER');
96
+ * } else {
97
+ * console.error('Fiscal quarter preset not registered');
98
+ * }
99
+ * ```
100
+ */
101
+ has(key: string): boolean;
102
+ /**
103
+ * Get all registered preset plugins
104
+ *
105
+ * Returns a NEW array (immutable) to prevent external modification.
106
+ *
107
+ * @returns Array of all registered preset plugins
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * const allPresets = registry.getAll();
112
+ * console.log('Available presets:');
113
+ * allPresets.forEach(preset => {
114
+ * console.log(`- ${preset.key}`);
115
+ * });
116
+ * ```
117
+ */
118
+ getAll(): RangePresetPlugin[];
119
+ /**
120
+ * Get all preset keys
121
+ *
122
+ * Convenience method to list available preset identifiers.
123
+ *
124
+ * @returns Array of preset keys (uppercase)
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const keys = registry.getAllKeys();
129
+ * // ['TODAY', 'YESTERDAY', 'LAST_7_DAYS', 'THIS_MONTH', ...]
130
+ * ```
131
+ */
132
+ getAllKeys(): string[];
133
+ /**
134
+ * Get count of registered presets
135
+ *
136
+ * @returns Number of registered presets
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * console.log(`${registry.count()} presets available`);
141
+ * ```
142
+ */
143
+ count(): number;
144
+ /**
145
+ * Unregister a preset plugin
146
+ *
147
+ * Useful for:
148
+ * - Testing cleanup
149
+ * - Dynamic preset management
150
+ * - Removing deprecated presets
151
+ *
152
+ * @param key - Preset key to remove (case-insensitive)
153
+ * @returns true if preset was removed, false if it didn't exist
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * registry.unregister('MY_TEMPORARY_PRESET');
158
+ * ```
159
+ */
160
+ unregister(key: string): boolean;
161
+ /**
162
+ * Clear all registered presets
163
+ *
164
+ * ⚠️ USE WITH CAUTION: This removes ALL presets including built-ins.
165
+ *
166
+ * Useful for:
167
+ * - Test teardown
168
+ * - Complete re-initialization scenarios
169
+ *
170
+ * @example
171
+ * ```typescript
172
+ * // In test cleanup
173
+ * afterEach(() => {
174
+ * registry.clear();
175
+ * });
176
+ * ```
177
+ */
178
+ clear(): void;
179
+ static ɵfac: i0.ɵɵFactoryDeclaration<PresetRegistry, never>;
180
+ static ɵprov: i0.ɵɵInjectableDeclaration<PresetRegistry>;
181
+ }
@@ -1,4 +1,8 @@
1
1
  import * as i0 from "@angular/core";
2
+ /**
3
+ * @deprecated Use RangePresetPlugin from './range-preset.plugin' instead
4
+ * Kept for backward compatibility
5
+ */
2
6
  export interface RangePreset {
3
7
  /**
4
8
  * Resolve preset to actual date range
@@ -14,59 +18,91 @@ export interface PresetRange {
14
18
  end: string;
15
19
  }
16
20
  /**
17
- * Registry of built-in presets
18
- * Can be extended by consumers
21
+ * Preset Engine - Plugin-Driven Architecture
19
22
  *
20
- * SSR-Safe Architecture:
21
- * - Injects DateClock via DI
22
- * - All presets use clock.now() instead of new Date()
23
- * - Deterministic: same clock.now() same preset
24
- * - Override DATE_CLOCK token in SSR to ensure consistency
23
+ * ARCHITECTURE (v3.6.0):
24
+ * - NO longer contains presets internally
25
+ * - Uses PresetRegistry for plugin management
26
+ * - Injects DateClock for SSR-safe time
27
+ * - Injects DateAdapter for timezone-safe operations
28
+ * - Follows Open/Closed Principle
25
29
  *
26
- * Timezone-Safe Architecture:
27
- * - Injects DateAdapter via DI
28
- * - All date operations use adapter methods
29
- * - Prevents timezone bugs in cross-timezone scenarios
30
- * - Override DATE_ADAPTER for Luxon/DayJS/custom implementations
30
+ * BACKWARD COMPATIBILITY:
31
+ * - Old API unchanged: resolve(), register(), getPresetKeys()
32
+ * - Built-in presets auto-registered via provider
33
+ * - Existing code continues to work
34
+ *
35
+ * EXTENSIBILITY:
36
+ * ```typescript
37
+ * // Register custom preset via registry
38
+ * const registry = inject(PresetRegistry);
39
+ * registry.register({
40
+ * key: 'MY_PRESET',
41
+ * resolve: (clock, adapter) => {
42
+ * const now = clock.now();
43
+ * return { start: now, end: now };
44
+ * }
45
+ * });
46
+ *
47
+ * // Use via engine
48
+ * const engine = inject(PresetEngine);
49
+ * const range = engine.resolve('MY_PRESET');
50
+ * ```
31
51
  */
32
52
  export declare class PresetEngine {
33
- private presets;
34
53
  private clock;
35
54
  private adapter;
55
+ private registry;
36
56
  constructor();
37
57
  /**
38
58
  * Register a custom preset
59
+ *
60
+ * @deprecated Use PresetRegistry.register() directly for new code
61
+ * Kept for backward compatibility
62
+ *
63
+ * @param key - Preset key (e.g., 'MY_CUSTOM_PRESET')
64
+ * @param preset - Legacy RangePreset object
39
65
  */
40
66
  register(key: string, preset: RangePreset): void;
41
67
  /**
42
68
  * Resolve a preset to date range
43
69
  *
44
- * SSR Note: Uses injected DateClock for deterministic resolution
45
- * Timezone Note: Uses injected DateAdapter for consistent date operations
70
+ * Plugin Architecture:
71
+ * 1. Looks up plugin in PresetRegistry
72
+ * 2. Calls plugin.resolve(clock, adapter)
73
+ * 3. Returns ISO date range
46
74
  *
47
- * Override tokens in SSR scenarios:
48
- * - DATE_CLOCK: Control current time
49
- * - DATE_ADAPTER: Control date operations (e.g., Luxon for timezone support)
75
+ * SSR Note: Uses injected DateClock for deterministic resolution
76
+ * Timezone Note: Uses injected DateAdapter for consistent operations
50
77
  *
51
78
  * @param key - Preset key (e.g., 'TODAY', 'LAST_7_DAYS')
52
79
  * @param now - Optional override for current date (defaults to clock.now())
80
+ * @returns ISO date range or null if preset not found
53
81
  */
54
82
  resolve(key: string, now?: Date): PresetRange | null;
55
83
  /**
56
84
  * Get all available preset keys
85
+ *
86
+ * Delegates to PresetRegistry
87
+ *
88
+ * @returns Array of registered preset keys
57
89
  */
58
90
  getPresetKeys(): string[];
59
91
  /**
60
- * Register all built-in presets
92
+ * Check if a preset exists
61
93
  *
62
- * All presets now use DateAdapter for timezone-safe operations
94
+ * @param key - Preset key to check
95
+ * @returns true if preset is registered
63
96
  */
64
- private registerBuiltInPresets;
97
+ hasPreset(key: string): boolean;
65
98
  static ɵfac: i0.ɵɵFactoryDeclaration<PresetEngine, never>;
66
99
  static ɵprov: i0.ɵɵInjectableDeclaration<PresetEngine>;
67
100
  }
68
101
  /**
69
102
  * Create a custom preset from a function
103
+ *
104
+ * @deprecated Use RangePresetPlugin interface instead
105
+ * Kept for backward compatibility
70
106
  */
71
107
  export declare function createPreset(resolver: (now: Date) => {
72
108
  start: Date;