@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,181 +0,0 @@
|
|
|
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
|
-
}
|
package/core/preset.engine.d.ts
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import * as i0 from "@angular/core";
|
|
2
|
-
/**
|
|
3
|
-
* @deprecated Use RangePresetPlugin from './range-preset.plugin' instead
|
|
4
|
-
* Kept for backward compatibility
|
|
5
|
-
*/
|
|
6
|
-
export interface RangePreset {
|
|
7
|
-
/**
|
|
8
|
-
* Resolve preset to actual date range
|
|
9
|
-
* @param now - Current date for deterministic calculation
|
|
10
|
-
*/
|
|
11
|
-
resolve(now: Date): {
|
|
12
|
-
start: Date;
|
|
13
|
-
end: Date;
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
export interface PresetRange {
|
|
17
|
-
start: string;
|
|
18
|
-
end: string;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Preset Engine - Plugin-Driven Architecture
|
|
22
|
-
*
|
|
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
|
|
29
|
-
*
|
|
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
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
export declare class PresetEngine {
|
|
53
|
-
private clock;
|
|
54
|
-
private adapter;
|
|
55
|
-
private registry;
|
|
56
|
-
constructor();
|
|
57
|
-
/**
|
|
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
|
|
65
|
-
*/
|
|
66
|
-
register(key: string, preset: RangePreset): void;
|
|
67
|
-
/**
|
|
68
|
-
* Resolve a preset to date range
|
|
69
|
-
*
|
|
70
|
-
* Plugin Architecture:
|
|
71
|
-
* 1. Looks up plugin in PresetRegistry
|
|
72
|
-
* 2. Calls plugin.resolve(clock, adapter)
|
|
73
|
-
* 3. Returns ISO date range
|
|
74
|
-
*
|
|
75
|
-
* SSR Note: Uses injected DateClock for deterministic resolution
|
|
76
|
-
* Timezone Note: Uses injected DateAdapter for consistent operations
|
|
77
|
-
*
|
|
78
|
-
* @param key - Preset key (e.g., 'TODAY', 'LAST_7_DAYS')
|
|
79
|
-
* @param now - Optional override for current date (defaults to clock.now())
|
|
80
|
-
* @returns ISO date range or null if preset not found
|
|
81
|
-
*/
|
|
82
|
-
resolve(key: string, now?: Date): PresetRange | null;
|
|
83
|
-
/**
|
|
84
|
-
* Get all available preset keys
|
|
85
|
-
*
|
|
86
|
-
* Delegates to PresetRegistry
|
|
87
|
-
*
|
|
88
|
-
* @returns Array of registered preset keys
|
|
89
|
-
*/
|
|
90
|
-
getPresetKeys(): string[];
|
|
91
|
-
/**
|
|
92
|
-
* Check if a preset exists
|
|
93
|
-
*
|
|
94
|
-
* @param key - Preset key to check
|
|
95
|
-
* @returns true if preset is registered
|
|
96
|
-
*/
|
|
97
|
-
hasPreset(key: string): boolean;
|
|
98
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<PresetEngine, never>;
|
|
99
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<PresetEngine>;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Create a custom preset from a function
|
|
103
|
-
*
|
|
104
|
-
* @deprecated Use RangePresetPlugin interface instead
|
|
105
|
-
* Kept for backward compatibility
|
|
106
|
-
*/
|
|
107
|
-
export declare function createPreset(resolver: (now: Date) => {
|
|
108
|
-
start: Date;
|
|
109
|
-
end: Date;
|
|
110
|
-
}): RangePreset;
|
|
111
|
-
/**
|
|
112
|
-
* @deprecated Use dependency injection instead:
|
|
113
|
-
* ```typescript
|
|
114
|
-
* private engine = inject(PresetEngine);
|
|
115
|
-
* ```
|
|
116
|
-
*
|
|
117
|
-
* Singleton preset engine instance for backward compatibility
|
|
118
|
-
*
|
|
119
|
-
* WARNING: This singleton uses SystemClock directly and is NOT SSR-safe.
|
|
120
|
-
* For SSR applications, inject PresetEngine and override DATE_CLOCK token.
|
|
121
|
-
*
|
|
122
|
-
* This export will be removed in v4.0.0
|
|
123
|
-
*/
|
|
124
|
-
export declare const presetEngine: PresetEngine;
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Range Preset Plugin System
|
|
3
|
-
*
|
|
4
|
-
* Version: 3.6.0
|
|
5
|
-
*
|
|
6
|
-
* Plugin-based architecture for date range presets following Open/Closed Principle.
|
|
7
|
-
*
|
|
8
|
-
* WHY THIS EXISTS:
|
|
9
|
-
* - Enterprise apps need industry-specific presets (fiscal, hotel, logistics)
|
|
10
|
-
* - Presets should be distributable as external packages
|
|
11
|
-
* - Core should NOT know about all possible presets
|
|
12
|
-
* - Users should extend presets without modifying library code
|
|
13
|
-
*
|
|
14
|
-
* ARCHITECTURE:
|
|
15
|
-
* ```
|
|
16
|
-
* RangePresetPlugin (interface) - Contract for all presets
|
|
17
|
-
* ↓
|
|
18
|
-
* PresetRegistry (service) - Manages plugin registration
|
|
19
|
-
* ↓
|
|
20
|
-
* PresetEngine (refactored) - Resolves presets via registry
|
|
21
|
-
* ↓
|
|
22
|
-
* DualDateRangeStore - No changes, backward compatible
|
|
23
|
-
* ```
|
|
24
|
-
*
|
|
25
|
-
* USAGE:
|
|
26
|
-
* ```typescript
|
|
27
|
-
* // Built-in presets work automatically
|
|
28
|
-
* store.applyPreset('LAST_7_DAYS'); // ✅ Works
|
|
29
|
-
*
|
|
30
|
-
* // Register custom preset
|
|
31
|
-
* const registry = inject(PresetRegistry);
|
|
32
|
-
* registry.register({
|
|
33
|
-
* key: 'THIS_FISCAL_QUARTER',
|
|
34
|
-
* resolve: (clock, adapter) => {
|
|
35
|
-
* const now = clock.now();
|
|
36
|
-
* const fiscalStart = adapter.startOfMonth(now);
|
|
37
|
-
* const fiscalEnd = adapter.endOfMonth(now);
|
|
38
|
-
* return { start: fiscalStart, end: fiscalEnd };
|
|
39
|
-
* }
|
|
40
|
-
* });
|
|
41
|
-
*
|
|
42
|
-
* // Use custom preset
|
|
43
|
-
* store.applyPreset('THIS_FISCAL_QUARTER'); // ✅ Works
|
|
44
|
-
* ```
|
|
45
|
-
*
|
|
46
|
-
* EXTERNAL PACKAGES:
|
|
47
|
-
* ```typescript
|
|
48
|
-
* // @acme/fiscal-presets package
|
|
49
|
-
* export const FISCAL_PRESETS: RangePresetPlugin[] = [
|
|
50
|
-
* { key: 'FISCAL_Q1', resolve: ... },
|
|
51
|
-
* { key: 'FISCAL_Q2', resolve: ... }
|
|
52
|
-
* ];
|
|
53
|
-
*
|
|
54
|
-
* // In app
|
|
55
|
-
* FISCAL_PRESETS.forEach(p => registry.register(p));
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
import { DateClock } from './date-clock';
|
|
59
|
-
import { DateAdapter } from './date-adapter';
|
|
60
|
-
/**
|
|
61
|
-
* Date range returned by preset plugins
|
|
62
|
-
*/
|
|
63
|
-
export interface DateRange {
|
|
64
|
-
/**
|
|
65
|
-
* Start date of the range (inclusive)
|
|
66
|
-
*/
|
|
67
|
-
start: Date;
|
|
68
|
-
/**
|
|
69
|
-
* End date of the range (inclusive)
|
|
70
|
-
*/
|
|
71
|
-
end: Date;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Range Preset Plugin Interface
|
|
75
|
-
*
|
|
76
|
-
* All date range presets (built-in or external) implement this interface.
|
|
77
|
-
*
|
|
78
|
-
* DESIGN PRINCIPLES:
|
|
79
|
-
* - **Deterministic**: Given the same clock.now(), always returns same range
|
|
80
|
-
* - **Timezone-safe**: Uses DateAdapter for all date operations
|
|
81
|
-
* - **SSR-compatible**: Uses DateClock injection, no global Date()
|
|
82
|
-
* - **Testable**: Pure function, no side effects
|
|
83
|
-
*
|
|
84
|
-
* EXAMPLE - Built-in preset:
|
|
85
|
-
* ```typescript
|
|
86
|
-
* const todayPreset: RangePresetPlugin = {
|
|
87
|
-
* key: 'TODAY',
|
|
88
|
-
* resolve: (clock, adapter) => {
|
|
89
|
-
* const now = clock.now();
|
|
90
|
-
* const normalized = adapter.normalize(now);
|
|
91
|
-
* return { start: normalized, end: normalized };
|
|
92
|
-
* }
|
|
93
|
-
* };
|
|
94
|
-
* ```
|
|
95
|
-
*
|
|
96
|
-
* EXAMPLE - Custom fiscal preset:
|
|
97
|
-
* ```typescript
|
|
98
|
-
* const fiscalQuarterPreset: RangePresetPlugin = {
|
|
99
|
-
* key: 'THIS_FISCAL_QUARTER',
|
|
100
|
-
* resolve: (clock, adapter) => {
|
|
101
|
-
* const now = clock.now();
|
|
102
|
-
* const month = adapter.getMonth(now); // 0-11
|
|
103
|
-
*
|
|
104
|
-
* // Fiscal year starts in April (month 3)
|
|
105
|
-
* const fiscalMonth = (month + 9) % 12; // Offset to fiscal calendar
|
|
106
|
-
* const quarterStartMonth = Math.floor(fiscalMonth / 3) * 3;
|
|
107
|
-
* const adjustedMonth = (quarterStartMonth - 9 + 12) % 12;
|
|
108
|
-
*
|
|
109
|
-
* const yearOffset = month < 3 ? -1 : 0;
|
|
110
|
-
* const year = adapter.getYear(now) + yearOffset;
|
|
111
|
-
*
|
|
112
|
-
* const start = new Date(year, adjustedMonth, 1);
|
|
113
|
-
* const end = new Date(year, adjustedMonth + 3, 0);
|
|
114
|
-
*
|
|
115
|
-
* return {
|
|
116
|
-
* start: adapter.normalize(start),
|
|
117
|
-
* end: adapter.normalize(end)
|
|
118
|
-
* };
|
|
119
|
-
* }
|
|
120
|
-
* };
|
|
121
|
-
* ```
|
|
122
|
-
*
|
|
123
|
-
* EXAMPLE - Hotel industry preset:
|
|
124
|
-
* ```typescript
|
|
125
|
-
* const checkInWeekPreset: RangePresetPlugin = {
|
|
126
|
-
* key: 'CHECK_IN_WEEK',
|
|
127
|
-
* resolve: (clock, adapter) => {
|
|
128
|
-
* const now = clock.now();
|
|
129
|
-
* // Hotel check-ins are Friday to Friday
|
|
130
|
-
* const dayOfWeek = adapter.getDayOfWeek(now);
|
|
131
|
-
* const daysToFriday = dayOfWeek <= 5 ? 5 - dayOfWeek : 7 - dayOfWeek + 5;
|
|
132
|
-
*
|
|
133
|
-
* const nextFriday = adapter.addDays(now, daysToFriday);
|
|
134
|
-
* const followingFriday = adapter.addDays(nextFriday, 7);
|
|
135
|
-
*
|
|
136
|
-
* return { start: nextFriday, end: followingFriday };
|
|
137
|
-
* }
|
|
138
|
-
* };
|
|
139
|
-
* ```
|
|
140
|
-
*/
|
|
141
|
-
export interface RangePresetPlugin {
|
|
142
|
-
/**
|
|
143
|
-
* Unique identifier for the preset
|
|
144
|
-
*
|
|
145
|
-
* Convention: SCREAMING_SNAKE_CASE
|
|
146
|
-
*
|
|
147
|
-
* Examples:
|
|
148
|
-
* - Built-in: 'TODAY', 'LAST_7_DAYS', 'THIS_MONTH'
|
|
149
|
-
* - Fiscal: 'FISCAL_Q1', 'FISCAL_YEAR_TO_DATE'
|
|
150
|
-
* - Hotel: 'CHECK_IN_WEEK', 'NEXT_30_NIGHTS'
|
|
151
|
-
* - Logistics: 'SHIPPING_WEEK', 'DELIVERY_WINDOW'
|
|
152
|
-
*/
|
|
153
|
-
key: string;
|
|
154
|
-
/**
|
|
155
|
-
* Resolve the date range for this preset
|
|
156
|
-
*
|
|
157
|
-
* MUST use:
|
|
158
|
-
* - `clock.now()` for current time (SSR-safe, deterministic)
|
|
159
|
-
* - `adapter.*` for all date operations (timezone-safe)
|
|
160
|
-
*
|
|
161
|
-
* MUST NOT use:
|
|
162
|
-
* - `new Date()` directly (breaks SSR determinism)
|
|
163
|
-
* - `date.toISOString()` (timezone bugs)
|
|
164
|
-
* - `date.setDate()` (mutates, use adapter.addDays() instead)
|
|
165
|
-
*
|
|
166
|
-
* @param clock - Injected DateClock for SSR-safe time access
|
|
167
|
-
* @param adapter - Injected DateAdapter for timezone-safe operations
|
|
168
|
-
* @returns Date range with start and end dates (both inclusive)
|
|
169
|
-
*
|
|
170
|
-
* @example
|
|
171
|
-
* ```typescript
|
|
172
|
-
* resolve: (clock, adapter) => {
|
|
173
|
-
* const now = clock.now();
|
|
174
|
-
* const start = adapter.addDays(now, -7);
|
|
175
|
-
* const end = adapter.normalize(now);
|
|
176
|
-
* return { start, end };
|
|
177
|
-
* }
|
|
178
|
-
* ```
|
|
179
|
-
*/
|
|
180
|
-
resolve(clock: DateClock, adapter: DateAdapter): DateRange;
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Type guard to check if object is a valid RangePresetPlugin
|
|
184
|
-
*
|
|
185
|
-
* @param obj - Object to check
|
|
186
|
-
* @returns true if object implements RangePresetPlugin interface
|
|
187
|
-
*/
|
|
188
|
-
export declare function isRangePresetPlugin(obj: any): obj is RangePresetPlugin;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure validation functions for date ranges
|
|
3
|
-
* No dependencies, no side effects - just logic
|
|
4
|
-
* Perfect for SSR, testing, and reusability
|
|
5
|
-
*/
|
|
6
|
-
export interface ValidationResult {
|
|
7
|
-
valid: boolean;
|
|
8
|
-
error?: string;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Validate that end date is not before start date
|
|
12
|
-
*/
|
|
13
|
-
export declare function validateRangeOrder(start: Date | null, end: Date | null): ValidationResult;
|
|
14
|
-
/**
|
|
15
|
-
* Validate that date is within min/max bounds
|
|
16
|
-
*/
|
|
17
|
-
export declare function validateDateBounds(date: Date | null, minDate?: Date, maxDate?: Date): ValidationResult;
|
|
18
|
-
/**
|
|
19
|
-
* Validate that a range is within bounds
|
|
20
|
-
*/
|
|
21
|
-
export declare function validateRangeBounds(start: Date | null, end: Date | null, minDate?: Date, maxDate?: Date): ValidationResult;
|
|
22
|
-
/**
|
|
23
|
-
* Check if a date is disabled
|
|
24
|
-
*/
|
|
25
|
-
export declare function isDateDisabled(date: Date, disabledDates?: Date[] | ((date: Date) => boolean)): boolean;
|
|
26
|
-
/**
|
|
27
|
-
* Apply bounds to a date (clamp it)
|
|
28
|
-
*/
|
|
29
|
-
export declare function applyBounds(date: Date, minDate?: Date, maxDate?: Date): Date;
|
|
30
|
-
/**
|
|
31
|
-
* Parse ISO date string to Date object (deterministic)
|
|
32
|
-
*/
|
|
33
|
-
export declare function parseISODate(dateStr: string): Date | null;
|
|
34
|
-
/**
|
|
35
|
-
* Format Date to ISO string (YYYY-MM-DD)
|
|
36
|
-
*/
|
|
37
|
-
export declare function formatISODate(date: Date | null): string;
|
package/core/system-clock.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { DateClock } from './date-clock';
|
|
2
|
-
import * as i0 from "@angular/core";
|
|
3
|
-
export declare class SystemClock implements DateClock {
|
|
4
|
-
/**
|
|
5
|
-
* Returns current system time
|
|
6
|
-
*
|
|
7
|
-
* This is the standard behavior for client-side applications.
|
|
8
|
-
* For SSR, override DATE_CLOCK token with a fixed Date.
|
|
9
|
-
*/
|
|
10
|
-
now(): Date;
|
|
11
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<SystemClock, never>;
|
|
12
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<SystemClock>;
|
|
13
|
-
}
|
package/date-adapter.d.ts
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { InjectionToken } from '@angular/core';
|
|
2
|
-
/**
|
|
3
|
-
* Abstract class for date adapters.
|
|
4
|
-
* Allows the component to work with different date libraries (Date, DayJS, date-fns, Luxon, etc.)
|
|
5
|
-
*/
|
|
6
|
-
export declare abstract class DateAdapter<T = any> {
|
|
7
|
-
/**
|
|
8
|
-
* Parses a value into a date object
|
|
9
|
-
* @param value - Value to parse (string, number, or date object)
|
|
10
|
-
* @returns Parsed date object
|
|
11
|
-
*/
|
|
12
|
-
abstract parse(value: any): T | null;
|
|
13
|
-
/**
|
|
14
|
-
* Formats a date object into a string
|
|
15
|
-
* @param date - Date object to format
|
|
16
|
-
* @param format - Optional format string
|
|
17
|
-
* @returns Formatted date string
|
|
18
|
-
*/
|
|
19
|
-
abstract format(date: T, format?: string): string;
|
|
20
|
-
/**
|
|
21
|
-
* Adds days to a date
|
|
22
|
-
* @param date - Date object
|
|
23
|
-
* @param days - Number of days to add (can be negative)
|
|
24
|
-
* @returns New date object
|
|
25
|
-
*/
|
|
26
|
-
abstract addDays(date: T, days: number): T;
|
|
27
|
-
/**
|
|
28
|
-
* Adds months to a date
|
|
29
|
-
* @param date - Date object
|
|
30
|
-
* @param months - Number of months to add (can be negative)
|
|
31
|
-
* @returns New date object
|
|
32
|
-
*/
|
|
33
|
-
abstract addMonths(date: T, months: number): T;
|
|
34
|
-
/**
|
|
35
|
-
* Gets the year from a date
|
|
36
|
-
* @param date - Date object
|
|
37
|
-
* @returns Year number
|
|
38
|
-
*/
|
|
39
|
-
abstract getYear(date: T): number;
|
|
40
|
-
/**
|
|
41
|
-
* Gets the month from a date (0-11)
|
|
42
|
-
* @param date - Date object
|
|
43
|
-
* @returns Month number (0-11)
|
|
44
|
-
*/
|
|
45
|
-
abstract getMonth(date: T): number;
|
|
46
|
-
/**
|
|
47
|
-
* Gets the day of month from a date
|
|
48
|
-
* @param date - Date object
|
|
49
|
-
* @returns Day of month (1-31)
|
|
50
|
-
*/
|
|
51
|
-
abstract getDate(date: T): number;
|
|
52
|
-
/**
|
|
53
|
-
* Gets the day of week from a date (0-6, Sunday = 0)
|
|
54
|
-
* @param date - Date object
|
|
55
|
-
* @returns Day of week (0-6)
|
|
56
|
-
*/
|
|
57
|
-
abstract getDay(date: T): number;
|
|
58
|
-
/**
|
|
59
|
-
* Creates a new date object
|
|
60
|
-
* @param year - Year
|
|
61
|
-
* @param month - Month (0-11)
|
|
62
|
-
* @param date - Day of month (1-31)
|
|
63
|
-
* @returns New date object
|
|
64
|
-
*/
|
|
65
|
-
abstract createDate(year: number, month: number, date: number): T;
|
|
66
|
-
/**
|
|
67
|
-
* Gets today's date
|
|
68
|
-
* @returns Today's date object
|
|
69
|
-
*/
|
|
70
|
-
abstract today(): T;
|
|
71
|
-
/**
|
|
72
|
-
* Checks if two dates are the same day
|
|
73
|
-
* @param a - First date
|
|
74
|
-
* @param b - Second date
|
|
75
|
-
* @returns True if same day
|
|
76
|
-
*/
|
|
77
|
-
abstract isSameDay(a: T | null, b: T | null): boolean;
|
|
78
|
-
/**
|
|
79
|
-
* Checks if a date is before another
|
|
80
|
-
* @param a - First date
|
|
81
|
-
* @param b - Second date
|
|
82
|
-
* @returns True if a is before b
|
|
83
|
-
*/
|
|
84
|
-
abstract isBefore(a: T | null, b: T | null): boolean;
|
|
85
|
-
/**
|
|
86
|
-
* Checks if a date is after another
|
|
87
|
-
* @param a - First date
|
|
88
|
-
* @param b - Second date
|
|
89
|
-
* @returns True if a is after b
|
|
90
|
-
*/
|
|
91
|
-
abstract isAfter(a: T | null, b: T | null): boolean;
|
|
92
|
-
/**
|
|
93
|
-
* Checks if a date is between two other dates
|
|
94
|
-
* @param date - Date to check
|
|
95
|
-
* @param start - Start date
|
|
96
|
-
* @param end - End date
|
|
97
|
-
* @returns True if date is between start and end
|
|
98
|
-
*/
|
|
99
|
-
abstract isBetween(date: T | null, start: T | null, end: T | null): boolean;
|
|
100
|
-
/**
|
|
101
|
-
* Clones a date object
|
|
102
|
-
* @param date - Date to clone
|
|
103
|
-
* @returns Cloned date object
|
|
104
|
-
*/
|
|
105
|
-
abstract clone(date: T): T;
|
|
106
|
-
/**
|
|
107
|
-
* Checks if a value is a valid date
|
|
108
|
-
* @param date - Value to check
|
|
109
|
-
* @returns True if valid date
|
|
110
|
-
*/
|
|
111
|
-
abstract isValid(date: any): boolean;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Injection token for DateAdapter
|
|
115
|
-
*/
|
|
116
|
-
export declare const DATE_ADAPTER: InjectionToken<DateAdapter<any>>;
|