@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 +51 -3
- package/core/built-in-presets.d.ts +98 -0
- package/core/date-adapter.d.ts +298 -0
- package/core/date-clock.d.ts +82 -0
- package/core/dual-date-range.store.d.ts +9 -0
- package/core/index.d.ts +15 -0
- package/core/native-date-adapter.d.ts +152 -0
- package/core/preset-providers.d.ts +176 -0
- package/core/preset-registry.d.ts +181 -0
- package/core/preset.engine.d.ts +79 -9
- package/core/range-preset.plugin.d.ts +188 -0
- package/core/system-clock.d.ts +13 -0
- package/dual-datepicker.component.d.ts +17 -11
- package/esm2022/core/built-in-presets.mjs +289 -0
- package/esm2022/core/date-adapter.mjs +77 -0
- package/esm2022/core/date-clock.mjs +65 -0
- package/esm2022/core/dual-date-range.store.mjs +51 -15
- package/esm2022/core/index.mjs +17 -1
- package/esm2022/core/native-date-adapter.mjs +286 -0
- package/esm2022/core/preset-providers.mjs +243 -0
- package/esm2022/core/preset-registry.mjs +277 -0
- package/esm2022/core/preset.engine.mjs +139 -169
- package/esm2022/core/range-preset.plugin.mjs +70 -0
- package/esm2022/core/system-clock.mjs +34 -0
- package/esm2022/dual-datepicker.component.mjs +264 -196
- package/fesm2022/oneluiz-dual-datepicker.mjs +3219 -1822
- package/fesm2022/oneluiz-dual-datepicker.mjs.map +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Date Adapter Implementation
|
|
3
|
+
*
|
|
4
|
+
* Default adapter using JavaScript Date with timezone-safe operations.
|
|
5
|
+
*
|
|
6
|
+
* Zero dependencies. Conservative implementation that:
|
|
7
|
+
* - Normalizes all dates to start of day (00:00:00.000)
|
|
8
|
+
* - Uses manual YYYY-MM-DD construction (avoids toISOString() timezone shift)
|
|
9
|
+
* - Parses ISO dates to local timezone (avoids UTC interpretation)
|
|
10
|
+
* - Handles month overflow correctly (Jan 31 + 1 month = Feb 28, not Mar 3)
|
|
11
|
+
* - All comparisons work on normalized dates
|
|
12
|
+
*
|
|
13
|
+
* Limitations:
|
|
14
|
+
* - No timezone awareness (all operations in local timezone)
|
|
15
|
+
* - No DST-safe calculations across timezone changes
|
|
16
|
+
* - For advanced timezone needs, use LuxonDateAdapter or DayJSDateAdapter
|
|
17
|
+
*
|
|
18
|
+
* Perfect for:
|
|
19
|
+
* ✅ Most enterprise apps (ERP, POS, BI) where local timezone is sufficient
|
|
20
|
+
* ✅ Applications without cross-timezone requirements
|
|
21
|
+
* ✅ Minimizing bundle size (zero deps)
|
|
22
|
+
* ✅ Simple, predictable date handling
|
|
23
|
+
*/
|
|
24
|
+
import { Injectable } from '@angular/core';
|
|
25
|
+
import * as i0 from "@angular/core";
|
|
26
|
+
export class NativeDateAdapter {
|
|
27
|
+
/**
|
|
28
|
+
* Normalize date to start of day (00:00:00.000) in local timezone
|
|
29
|
+
*
|
|
30
|
+
* This is the foundation of timezone-safe operations.
|
|
31
|
+
* All other methods use normalized dates for comparisons.
|
|
32
|
+
*/
|
|
33
|
+
normalize(date) {
|
|
34
|
+
const normalized = new Date(date);
|
|
35
|
+
normalized.setHours(0, 0, 0, 0);
|
|
36
|
+
return normalized;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Check if two dates are the same calendar day
|
|
40
|
+
*
|
|
41
|
+
* Implementation: Compare YYYY-MM-DD components directly
|
|
42
|
+
* Avoids timezone issues from valueOf() comparisons
|
|
43
|
+
*/
|
|
44
|
+
isSameDay(a, b) {
|
|
45
|
+
return (a.getFullYear() === b.getFullYear() &&
|
|
46
|
+
a.getMonth() === b.getMonth() &&
|
|
47
|
+
a.getDate() === b.getDate());
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if date A is before date B (calendar day level)
|
|
51
|
+
*
|
|
52
|
+
* Implementation: Compare normalized dates using valueOf()
|
|
53
|
+
*/
|
|
54
|
+
isBeforeDay(a, b) {
|
|
55
|
+
return this.normalize(a).valueOf() < this.normalize(b).valueOf();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Check if date A is after date B (calendar day level)
|
|
59
|
+
*
|
|
60
|
+
* Implementation: Compare normalized dates using valueOf()
|
|
61
|
+
*/
|
|
62
|
+
isAfterDay(a, b) {
|
|
63
|
+
return this.normalize(a).valueOf() > this.normalize(b).valueOf();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Add days to a date
|
|
67
|
+
*
|
|
68
|
+
* Implementation: Use setDate() which handles month rollover automatically
|
|
69
|
+
*
|
|
70
|
+
* Example:
|
|
71
|
+
* Jan 31 + 3 days → Feb 3 ✅
|
|
72
|
+
* Feb 28 + 1 day → Mar 1 ✅ (non-leap year)
|
|
73
|
+
*/
|
|
74
|
+
addDays(date, days) {
|
|
75
|
+
const result = new Date(date);
|
|
76
|
+
result.setDate(result.getDate() + days);
|
|
77
|
+
return this.normalize(result);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Add months to a date
|
|
81
|
+
*
|
|
82
|
+
* CRITICAL: Handles month overflow correctly
|
|
83
|
+
*
|
|
84
|
+
* Algorithm:
|
|
85
|
+
* 1. Add months using setMonth()
|
|
86
|
+
* 2. If day-of-month changed (overflow), set to last day of target month
|
|
87
|
+
*
|
|
88
|
+
* Examples:
|
|
89
|
+
* - Jan 31 + 1 month → Feb 28 (or Feb 29 in leap year) ✅
|
|
90
|
+
* - Jan 31 + 2 months → Mar 31 ✅
|
|
91
|
+
* - Mar 31 + 1 month → Apr 30 ✅
|
|
92
|
+
* - Dec 31 + 1 month → Jan 31 (next year) ✅
|
|
93
|
+
*/
|
|
94
|
+
addMonths(date, months) {
|
|
95
|
+
const result = new Date(date);
|
|
96
|
+
const originalDay = result.getDate();
|
|
97
|
+
// Add months
|
|
98
|
+
result.setMonth(result.getMonth() + months);
|
|
99
|
+
// Check for day overflow (e.g., Jan 31 → Feb 31 becomes Mar 3)
|
|
100
|
+
if (result.getDate() !== originalDay) {
|
|
101
|
+
// Overflow detected: set to last day of target month
|
|
102
|
+
// Go to 1st of next month, then subtract 1 day
|
|
103
|
+
result.setDate(0); // Sets to last day of previous month
|
|
104
|
+
}
|
|
105
|
+
return this.normalize(result);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get start of day (00:00:00.000)
|
|
109
|
+
*
|
|
110
|
+
* Alias for normalize() with explicit intent
|
|
111
|
+
*/
|
|
112
|
+
startOfDay(date) {
|
|
113
|
+
return this.normalize(date);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get end of day (23:59:59.999)
|
|
117
|
+
*
|
|
118
|
+
* Useful for inclusive range queries
|
|
119
|
+
*/
|
|
120
|
+
endOfDay(date) {
|
|
121
|
+
const result = new Date(date);
|
|
122
|
+
result.setHours(23, 59, 59, 999);
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get first day of month (00:00:00.000)
|
|
127
|
+
*/
|
|
128
|
+
startOfMonth(date) {
|
|
129
|
+
const result = new Date(date);
|
|
130
|
+
result.setDate(1);
|
|
131
|
+
return this.normalize(result);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get last day of month (23:59:59.999)
|
|
135
|
+
*
|
|
136
|
+
* Algorithm: Go to 1st of next month, subtract 1 day
|
|
137
|
+
*/
|
|
138
|
+
endOfMonth(date) {
|
|
139
|
+
const result = new Date(date);
|
|
140
|
+
result.setMonth(result.getMonth() + 1, 0); // Day 0 = last day of previous month
|
|
141
|
+
return this.endOfDay(result);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get year (4-digit)
|
|
145
|
+
*/
|
|
146
|
+
getYear(date) {
|
|
147
|
+
return date.getFullYear();
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get month (0-11)
|
|
151
|
+
*/
|
|
152
|
+
getMonth(date) {
|
|
153
|
+
return date.getMonth();
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get day of month (1-31)
|
|
157
|
+
*/
|
|
158
|
+
getDate(date) {
|
|
159
|
+
return date.getDate();
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get day of week (0-6, Sunday=0)
|
|
163
|
+
*/
|
|
164
|
+
getDay(date) {
|
|
165
|
+
return date.getDay();
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Convert Date to ISO date string (YYYY-MM-DD)
|
|
169
|
+
*
|
|
170
|
+
* CRITICAL: DO NOT use toISOString() - it converts to UTC!
|
|
171
|
+
*
|
|
172
|
+
* Manual construction ensures local timezone is preserved:
|
|
173
|
+
*
|
|
174
|
+
* Example problem with toISOString():
|
|
175
|
+
* ```
|
|
176
|
+
* // Local timezone: GMT-6 (CST)
|
|
177
|
+
* const date = new Date('2026-02-21T23:00:00'); // 11 PM Feb 21 local
|
|
178
|
+
*
|
|
179
|
+
* // WRONG ❌
|
|
180
|
+
* date.toISOString().split('T')[0]
|
|
181
|
+
* // Returns "2026-02-22" (converted to UTC = Feb 22 05:00 AM)
|
|
182
|
+
*
|
|
183
|
+
* // CORRECT ✅
|
|
184
|
+
* toISODate(date)
|
|
185
|
+
* // Returns "2026-02-21" (local date preserved)
|
|
186
|
+
* ```
|
|
187
|
+
*
|
|
188
|
+
* Implementation: Build YYYY-MM-DD manually from local date components
|
|
189
|
+
*/
|
|
190
|
+
toISODate(date) {
|
|
191
|
+
const year = date.getFullYear();
|
|
192
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
193
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
194
|
+
return `${year}-${month}-${day}`;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Parse ISO date string (YYYY-MM-DD) to Date
|
|
198
|
+
*
|
|
199
|
+
* CRITICAL: DO NOT use new Date(isoString) - may parse as UTC!
|
|
200
|
+
*
|
|
201
|
+
* Example problem with Date constructor:
|
|
202
|
+
* ```
|
|
203
|
+
* // Local timezone: GMT-6 (CST)
|
|
204
|
+
*
|
|
205
|
+
* // WRONG ❌
|
|
206
|
+
* new Date('2026-02-21')
|
|
207
|
+
* // Parsed as UTC: 2026-02-21T00:00:00Z
|
|
208
|
+
* // In local timezone: Feb 20, 2026 6:00 PM (previous day!)
|
|
209
|
+
*
|
|
210
|
+
* // CORRECT ✅
|
|
211
|
+
* parseISODate('2026-02-21')
|
|
212
|
+
* // Returns: 2026-02-21T00:00:00 local time
|
|
213
|
+
* ```
|
|
214
|
+
*
|
|
215
|
+
* Implementation: Parse components and construct Date in local timezone
|
|
216
|
+
*/
|
|
217
|
+
parseISODate(isoDate) {
|
|
218
|
+
if (!isoDate || typeof isoDate !== 'string') {
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
// Match YYYY-MM-DD format
|
|
222
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(isoDate.trim());
|
|
223
|
+
if (!match) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
const year = parseInt(match[1], 10);
|
|
227
|
+
const month = parseInt(match[2], 10) - 1; // 0-indexed
|
|
228
|
+
const day = parseInt(match[3], 10);
|
|
229
|
+
// Validate ranges
|
|
230
|
+
if (month < 0 || month > 11) {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
if (day < 1 || day > 31) {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
// Construct date in local timezone
|
|
237
|
+
const date = new Date(year, month, day);
|
|
238
|
+
// Verify date is valid (e.g., Feb 31 would roll to Mar 3)
|
|
239
|
+
if (date.getFullYear() !== year ||
|
|
240
|
+
date.getMonth() !== month ||
|
|
241
|
+
date.getDate() !== day) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
return this.normalize(date);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Get week start day for locale
|
|
248
|
+
*
|
|
249
|
+
* Default: Sunday (0) for most locales
|
|
250
|
+
* Monday (1) for Europe, ISO 8601
|
|
251
|
+
*
|
|
252
|
+
* Implementation: Simple locale detection
|
|
253
|
+
* For advanced needs, use Intl.Locale or external library
|
|
254
|
+
*/
|
|
255
|
+
getWeekStart(locale) {
|
|
256
|
+
if (!locale) {
|
|
257
|
+
locale = typeof navigator !== 'undefined' ? navigator.language : 'en-US';
|
|
258
|
+
}
|
|
259
|
+
// ISO 8601: Monday start
|
|
260
|
+
const mondayStartLocales = [
|
|
261
|
+
'en-GB', 'en-IE', 'en-AU', 'en-NZ', 'en-CA',
|
|
262
|
+
'es', 'es-ES', 'es-MX',
|
|
263
|
+
'fr', 'fr-FR', 'fr-CA',
|
|
264
|
+
'de', 'de-DE', 'de-AT', 'de-CH',
|
|
265
|
+
'it', 'it-IT',
|
|
266
|
+
'pt', 'pt-PT', 'pt-BR',
|
|
267
|
+
'nl', 'nl-NL', 'nl-BE',
|
|
268
|
+
'ru', 'ru-RU',
|
|
269
|
+
'zh', 'zh-CN', 'zh-TW',
|
|
270
|
+
'ja', 'ja-JP',
|
|
271
|
+
'ko', 'ko-KR'
|
|
272
|
+
];
|
|
273
|
+
const normalizedLocale = locale.toLowerCase();
|
|
274
|
+
const startsWithMonday = mondayStartLocales.some(loc => normalizedLocale.startsWith(loc.toLowerCase()));
|
|
275
|
+
return startsWithMonday ? 1 : 0;
|
|
276
|
+
}
|
|
277
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NativeDateAdapter, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
278
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NativeDateAdapter, providedIn: 'root' });
|
|
279
|
+
}
|
|
280
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NativeDateAdapter, decorators: [{
|
|
281
|
+
type: Injectable,
|
|
282
|
+
args: [{
|
|
283
|
+
providedIn: 'root'
|
|
284
|
+
}]
|
|
285
|
+
}] });
|
|
286
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF0aXZlLWRhdGUtYWRhcHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb3JlL25hdGl2ZS1kYXRlLWFkYXB0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FzQkc7QUFFSCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDOztBQU0zQyxNQUFNLE9BQU8saUJBQWlCO0lBQzVCOzs7OztPQUtHO0lBQ0gsU0FBUyxDQUFDLElBQVU7UUFDbEIsTUFBTSxVQUFVLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNoQyxPQUFPLFVBQVUsQ0FBQztJQUNwQixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxTQUFTLENBQUMsQ0FBTyxFQUFFLENBQU87UUFDeEIsT0FBTyxDQUNMLENBQUMsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUMsV0FBVyxFQUFFO1lBQ25DLENBQUMsQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUMsUUFBUSxFQUFFO1lBQzdCLENBQUMsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQzVCLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILFdBQVcsQ0FBQyxDQUFPLEVBQUUsQ0FBTztRQUMxQixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNuRSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILFVBQVUsQ0FBQyxDQUFPLEVBQUUsQ0FBTztRQUN6QixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFD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QixJQUFJLEVBQUUsT0FBTztZQUNiLElBQUksRUFBRSxPQUFPO1NBQ2QsQ0FBQztRQUVGLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzlDLE1BQU0sZ0JBQWdCLEdBQUcsa0JBQWtCLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQ3JELGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FDL0MsQ0FBQztRQUVGLE9BQU8sZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xDLENBQUM7d0dBOVJVLGlCQUFpQjs0R0FBakIsaUJBQWlCLGNBRmhCLE1BQU07OzRGQUVQLGlCQUFpQjtrQkFIN0IsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE5hdGl2ZSBEYXRlIEFkYXB0ZXIgSW1wbGVtZW50YXRpb25cbiAqIFxuICogRGVmYXVsdCBhZGFwdGVyIHVzaW5nIEphdmFTY3JpcHQgRGF0ZSB3aXRoIHRpbWV6b25lLXNhZmUgb3BlcmF0aW9ucy5cbiAqIFxuICogWmVybyBkZXBlbmRlbmNpZXMuIENvbnNlcnZhdGl2ZSBpbXBsZW1lbnRhdGlvbiB0aGF0OlxuICogLSBOb3JtYWxpemVzIGFsbCBkYXRlcyB0byBzdGFydCBvZiBkYXkgKDAwOjAwOjAwLjAwMClcbiAqIC0gVXNlcyBtYW51YWwgWVlZWS1NTS1ERCBjb25zdHJ1Y3Rpb24gKGF2b2lkcyB0b0lTT1N0cmluZygpIHRpbWV6b25lIHNoaWZ0KVxuICogLSBQYXJzZXMgSVNPIGRhdGVzIHRvIGxvY2FsIHRpbWV6b25lIChhdm9pZHMgVVRDIGludGVycHJldGF0aW9uKVxuICogLSBIYW5kbGVzIG1vbnRoIG92ZXJmbG93IGNvcnJlY3RseSAoSmFuIDMxICsgMSBtb250aCA9IEZlYiAyOCwgbm90IE1hciAzKVxuICogLSBBbGwgY29tcGFyaXNvbnMgd29yayBvbiBub3JtYWxpemVkIGRhdGVzXG4gKiBcbiAqIExpbWl0YXRpb25zOlxuICogLSBObyB0aW1lem9uZSBhd2FyZW5lc3MgKGFsbCBvcGVyYXRpb25zIGluIGxvY2FsIHRpbWV6b25lKVxuICogLSBObyBEU1Qtc2FmZSBjYWxjdWxhdGlvbnMgYWNyb3NzIHRpbWV6b25lIGNoYW5nZXNcbiAqIC0gRm9yIGFkdmFuY2VkIHRpbWV6b25lIG5lZWRzLCB1c2UgTHV4b25EYXRlQWRhcHRlciBvciBEYXlKU0RhdGVBZGFwdGVyXG4gKiBcbiAqIFBlcmZlY3QgZm9yOlxuICog4pyFIE1vc3QgZW50ZXJwcmlzZSBhcHBzIChFUlAsIFBPUywgQkkpIHdoZXJlIGxvY2FsIHRpbWV6b25lIGlzIHN1ZmZpY2llbnRcbiAqIOKchSBBcHBsaWNhdGlvbnMgd2l0aG91dCBjcm9zcy10aW1lem9uZSByZXF1aXJlbWVudHNcbiAqIOKchSBNaW5pbWl6aW5nIGJ1bmRsZSBzaXplICh6ZXJvIGRlcHMpXG4gKiDinIUgU2ltcGxlLCBwcmVkaWN0YWJsZSBkYXRlIGhhbmRsaW5nXG4gKi9cblxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRGF0ZUFkYXB0ZXIgfSBmcm9tICcuL2RhdGUtYWRhcHRlcic7XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIE5hdGl2ZURhdGVBZGFwdGVyIGltcGxlbWVudHMgRGF0ZUFkYXB0ZXIge1xuICAvKipcbiAgICogTm9ybWFsaXplIGRhdGUgdG8gc3RhcnQgb2YgZGF5ICgwMDowMDowMC4wMDApIGluIGxvY2FsIHRpbWV6b25lXG4gICAqIFxuICAgKiBUaGlzIGlzIHRoZSBmb3VuZGF0aW9uIG9mIHRpbWV6b25lLXNhZmUgb3BlcmF0aW9ucy5cbiAgICogQWxsIG90aGVyIG1ldGhvZHMgdXNlIG5vcm1hbGl6ZWQgZGF0ZXMgZm9yIGNvbXBhcmlzb25zLlxuICAgKi9cbiAgbm9ybWFsaXplKGRhdGU6IERhdGUpOiBEYXRlIHtcbiAgICBjb25zdCBub3JtYWxpemVkID0gbmV3IERhdGUoZGF0ZSk7XG4gICAgbm9ybWFsaXplZC5zZXRIb3VycygwLCAwLCAwLCAwKTtcbiAgICByZXR1cm4gbm9ybWFsaXplZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0d28gZGF0ZXMgYXJlIHRoZSBzYW1lIGNhbGVuZGFyIGRheVxuICAgKiBcbiAgICogSW1wbGVtZW50YXRpb246IENvbXBhcmUgWVlZWS1NTS1ERCBjb21wb25lbnRzIGRpcmVjdGx5XG4gICAqIEF2b2lkcyB0aW1lem9uZSBpc3N1ZXMgZnJvbSB2YWx1ZU9mKCkgY29tcGFyaXNvbnNcbiAgICovXG4gIGlzU2FtZURheShhOiBEYXRlLCBiOiBEYXRlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIGEuZ2V0RnVsbFllYXIoKSA9PT0gYi5nZXRGdWxsWWVhcigpICYmXG4gICAgICBhLmdldE1vbnRoKCkgPT09IGIuZ2V0TW9udGgoKSAmJlxuICAgICAgYS5nZXREYXRlKCkgPT09IGIuZ2V0RGF0ZSgpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBkYXRlIEEgaXMgYmVmb3JlIGRhdGUgQiAoY2FsZW5kYXIgZGF5IGxldmVsKVxuICAgKiBcbiAgICogSW1wbGVtZW50YXRpb246IENvbXBhcmUgbm9ybWFsaXplZCBkYXRlcyB1c2luZyB2YWx1ZU9mKClcbiAgICovXG4gIGlzQmVmb3JlRGF5KGE6IERhdGUsIGI6IERhdGUpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5ub3JtYWxpemUoYSkudmFsdWVPZigpIDwgdGhpcy5ub3JtYWxpemUoYikudmFsdWVPZigpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGRhdGUgQSBpcyBhZnRlciBkYXRlIEIgKGNhbGVuZGFyIGRheSBsZXZlbClcbiAgICogXG4gICAqIEltcGxlbWVudGF0aW9uOiBDb21wYXJlIG5vcm1hbGl6ZWQgZGF0ZXMgdXNpbmcgdmFsdWVPZigpXG4gICAqL1xuICBpc0FmdGVyRGF5KGE6IERhdGUsIGI6IERhdGUpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5ub3JtYWxpemUoYSkudmFsdWVPZigpID4gdGhpcy5ub3JtYWxpemUoYikudmFsdWVPZigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBkYXlzIHRvIGEgZGF0ZVxuICAgKiBcbiAgICogSW1wbGVtZW50YXRpb246IFVzZSBzZXREYXRlKCkgd2hpY2ggaGFuZGxlcyBtb250aCByb2xsb3ZlciBhdXRvbWF0aWNhbGx5XG4gICAqIFxuICAgKiBFeGFtcGxlOlxuICAgKiBKYW4gMzEgKyAzIGRheXMg4oaSIEZlYiAzIOKchVxuICAgKiBGZWIgMjggKyAxIGRheSDihpIgTWFyIDEg4pyFIChub24tbGVhcCB5ZWFyKVxuICAgKi9cbiAgYWRkRGF5cyhkYXRlOiBEYXRlLCBkYXlzOiBudW1iZXIpOiBEYXRlIHtcbiAgICBjb25zdCByZXN1bHQgPSBuZXcgRGF0ZShkYXRlKTtcbiAgICByZXN1bHQuc2V0RGF0ZShyZXN1bHQuZ2V0RGF0ZSgpICsgZGF5cyk7XG4gICAgcmV0dXJuIHRoaXMubm9ybWFsaXplKHJlc3VsdCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIG1vbnRocyB0byBhIGRhdGVcbiAgICogXG4gICAqIENSSVRJQ0FMOiBIYW5kbGVzIG1vbnRoIG92ZXJmbG93IGNvcnJlY3RseVxuICAgKiBcbiAgICogQWxnb3JpdGhtOlxuICAgKiAxLiBBZGQgbW9udGhzIHVzaW5nIHNldE1vbnRoKClcbiAgICogMi4gSWYgZGF5LW9mLW1vbnRoIGNoYW5nZWQgKG92ZXJmbG93KSwgc2V0IHRvIGxhc3QgZGF5IG9mIHRhcmdldCBtb250aFxuICAgKiBcbiAgICogRXhhbXBsZXM6XG4gICAqIC0gSmFuIDMxICsgMSBtb250aCDihpIgRmViIDI4IChvciBGZWIgMjkgaW4gbGVhcCB5ZWFyKSDinIVcbiAgICogLSBKYW4gMzEgKyAyIG1vbnRocyDihpIgTWFyIDMxIOKchVxuICAgKiAtIE1hciAzMSArIDEgbW9udGgg4oaSIEFwciAzMCDinIVcbiAgICogLSBEZWMgMzEgKyAxIG1vbnRoIOKGkiBKYW4gMzEgKG5leHQgeWVhcikg4pyFXG4gICAqL1xuICBhZGRNb250aHMoZGF0ZTogRGF0ZSwgbW9udGhzOiBudW1iZXIpOiBEYXRlIHtcbiAgICBjb25zdCByZXN1bHQgPSBuZXcgRGF0ZShkYXRlKTtcbiAgICBjb25zdCBvcmlnaW5hbERheSA9IHJlc3VsdC5nZXREYXRlKCk7XG4gICAgXG4gICAgLy8gQWRkIG1vbnRoc1xuICAgIHJlc3VsdC5zZXRNb250aChyZXN1bHQuZ2V0TW9udGgoKSArIG1vbnRocyk7XG4gICAgXG4gICAgLy8gQ2hlY2sgZm9yIGRheSBvdmVyZmxvdyAoZS5nLiwgSmFuIDMxIOKGkiBGZWIgMzEgYmVjb21lcyBNYXIgMylcbiAgICBpZiAocmVzdWx0LmdldERhdGUoKSAhPT0gb3JpZ2luYWxEYXkpIHtcbiAgICAgIC8vIE92ZXJmbG93IGRldGVjdGVkOiBzZXQgdG8gbGFzdCBkYXkgb2YgdGFyZ2V0IG1vbnRoXG4gICAgICAvLyBHbyB0byAxc3Qgb2YgbmV4dCBtb250aCwgdGhlbiBzdWJ0cmFjdCAxIGRheVxuICAgICAgcmVzdWx0LnNldERhdGUoMCk7IC8vIFNldHMgdG8gbGFzdCBkYXkgb2YgcHJldmlvdXMgbW9udGhcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIHRoaXMubm9ybWFsaXplKHJlc3VsdCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHN0YXJ0IG9mIGRheSAoMDA6MDA6MDAuMDAwKVxuICAgKiBcbiAgICogQWxpYXMgZm9yIG5vcm1hbGl6ZSgpIHdpdGggZXhwbGljaXQgaW50ZW50XG4gICAqL1xuICBzdGFydE9mRGF5KGRhdGU6IERhdGUpOiBEYXRlIHtcbiAgICByZXR1cm4gdGhpcy5ub3JtYWxpemUoZGF0ZSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGVuZCBvZiBkYXkgKDIzOjU5OjU5Ljk5OSlcbiAgICogXG4gICAqIFVzZWZ1bCBmb3IgaW5jbHVzaXZlIHJhbmdlIHF1ZXJpZXNcbiAgICovXG4gIGVuZE9mRGF5KGRhdGU6IERhdGUpOiBEYXRlIHtcbiAgICBjb25zdCByZXN1bHQgPSBuZXcgRGF0ZShkYXRlKTtcbiAgICByZXN1bHQuc2V0SG91cnMoMjMsIDU5LCA1OSwgOTk5KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBmaXJzdCBkYXkgb2YgbW9udGggKDAwOjAwOjAwLjAwMClcbiAgICovXG4gIHN0YXJ0T2ZNb250aChkYXRlOiBEYXRlKTogRGF0ZSB7XG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IERhdGUoZGF0ZSk7XG4gICAgcmVzdWx0LnNldERhdGUoMSk7XG4gICAgcmV0dXJuIHRoaXMubm9ybWFsaXplKHJlc3VsdCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGxhc3QgZGF5IG9mIG1vbnRoICgyMzo1OTo1OS45OTkpXG4gICAqIFxuICAgKiBBbGdvcml0aG06IEdvIHRvIDFzdCBvZiBuZXh0IG1vbnRoLCBzdWJ0cmFjdCAxIGRheVxuICAgKi9cbiAgZW5kT2ZNb250aChkYXRlOiBEYXRlKTogRGF0ZSB7XG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IERhdGUoZGF0ZSk7XG4gICAgcmVzdWx0LnNldE1vbnRoKHJlc3VsdC5nZXRNb250aCgpICsgMSwgMCk7IC8vIERheSAwID0gbGFzdCBkYXkgb2YgcHJldmlvdXMgbW9udGhcbiAgICByZXR1cm4gdGhpcy5lbmRPZkRheShyZXN1bHQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB5ZWFyICg0LWRpZ2l0KVxuICAgKi9cbiAgZ2V0WWVhcihkYXRlOiBEYXRlKTogbnVtYmVyIHtcbiAgICByZXR1cm4gZGF0ZS5nZXRGdWxsWWVhcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBtb250aCAoMC0xMSlcbiAgICovXG4gIGdldE1vbnRoKGRhdGU6IERhdGUpOiBudW1iZXIge1xuICAgIHJldHVybiBkYXRlLmdldE1vbnRoKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGRheSBvZiBtb250aCAoMS0zMSlcbiAgICovXG4gIGdldERhdGUoZGF0ZTogRGF0ZSk6IG51bWJlciB7XG4gICAgcmV0dXJuIGRhdGUuZ2V0RGF0ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBkYXkgb2Ygd2VlayAoMC02LCBTdW5kYXk9MClcbiAgICovXG4gIGdldERheShkYXRlOiBEYXRlKTogbnVtYmVyIHtcbiAgICByZXR1cm4gZGF0ZS5nZXREYXkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IERhdGUgdG8gSVNPIGRhdGUgc3RyaW5nIChZWVlZLU1NLUREKVxuICAgKiBcbiAgICogQ1JJVElDQUw6IERPIE5PVCB1c2UgdG9JU09TdHJpbmcoKSAtIGl0IGNvbnZlcnRzIHRvIFVUQyFcbiAgICogXG4gICAqIE1hbnVhbCBjb25zdHJ1Y3Rpb24gZW5zdXJlcyBsb2NhbCB0aW1lem9uZSBpcyBwcmVzZXJ2ZWQ6XG4gICAqIFxuICAgKiBFeGFtcGxlIHByb2JsZW0gd2l0aCB0b0lTT1N0cmluZygpOlxuICAgKiBgYGBcbiAgICogLy8gTG9jYWwgdGltZXpvbmU6IEdNVC02IChDU1QpXG4gICAqIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSgnMjAyNi0wMi0yMVQyMzowMDowMCcpOyAvLyAxMSBQTSBGZWIgMjEgbG9jYWxcbiAgICogXG4gICAqIC8vIFdST05HIOKdjFxuICAgKiBkYXRlLnRvSVNPU3RyaW5nKCkuc3BsaXQoJ1QnKVswXVxuICAgKiAvLyBSZXR1cm5zIFwiMjAyNi0wMi0yMlwiIChjb252ZXJ0ZWQgdG8gVVRDID0gRmViIDIyIDA1OjAwIEFNKVxuICAgKiBcbiAgICogLy8gQ09SUkVDVCDinIVcbiAgICogdG9JU09EYXRlKGRhdGUpXG4gICAqIC8vIFJldHVybnMgXCIyMDI2LTAyLTIxXCIgKGxvY2FsIGRhdGUgcHJlc2VydmVkKVxuICAgKiBgYGBcbiAgICogXG4gICAqIEltcGxlbWVudGF0aW9uOiBCdWlsZCBZWVlZLU1NLUREIG1hbnVhbGx5IGZyb20gbG9jYWwgZGF0ZSBjb21wb25lbnRzXG4gICAqL1xuICB0b0lTT0RhdGUoZGF0ZTogRGF0ZSk6IHN0cmluZyB7XG4gICAgY29uc3QgeWVhciA9IGRhdGUuZ2V0RnVsbFllYXIoKTtcbiAgICBjb25zdCBtb250aCA9IFN0cmluZyhkYXRlLmdldE1vbnRoKCkgKyAxKS5wYWRTdGFydCgyLCAnMCcpO1xuICAgIGNvbnN0IGRheSA9IFN0cmluZyhkYXRlLmdldERhdGUoKSkucGFkU3RhcnQoMiwgJzAnKTtcbiAgICByZXR1cm4gYCR7eWVhcn0tJHttb250aH0tJHtkYXl9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSBJU08gZGF0ZSBzdHJpbmcgKFlZWVktTU0tREQpIHRvIERhdGVcbiAgICogXG4gICAqIENSSVRJQ0FMOiBETyBOT1QgdXNlIG5ldyBEYXRlKGlzb1N0cmluZykgLSBtYXkgcGFyc2UgYXMgVVRDIVxuICAgKiBcbiAgICogRXhhbXBsZSBwcm9ibGVtIHdpdGggRGF0ZSBjb25zdHJ1Y3RvcjpcbiAgICogYGBgXG4gICAqIC8vIExvY2FsIHRpbWV6b25lOiBHTVQtNiAoQ1NUKVxuICAgKiBcbiAgICogLy8gV1JPTkcg4p2MXG4gICAqIG5ldyBEYXRlKCcyMDI2LTAyLTIxJylcbiAgICogLy8gUGFyc2VkIGFzIFVUQzogMjAyNi0wMi0yMVQwMDowMDowMFpcbiAgICogLy8gSW4gbG9jYWwgdGltZXpvbmU6IEZlYiAyMCwgMjAyNiA2OjAwIFBNIChwcmV2aW91cyBkYXkhKVxuICAgKiBcbiAgICogLy8gQ09SUkVDVCDinIVcbiAgICogcGFyc2VJU09EYXRlKCcyMDI2LTAyLTIxJylcbiAgICogLy8gUmV0dXJuczogMjAyNi0wMi0yMVQwMDowMDowMCBsb2NhbCB0aW1lXG4gICAqIGBgYFxuICAgKiBcbiAgICogSW1wbGVtZW50YXRpb246IFBhcnNlIGNvbXBvbmVudHMgYW5kIGNvbnN0cnVjdCBEYXRlIGluIGxvY2FsIHRpbWV6b25lXG4gICAqL1xuICBwYXJzZUlTT0RhdGUoaXNvRGF0ZTogc3RyaW5nKTogRGF0ZSB8IG51bGwge1xuICAgIGlmICghaXNvRGF0ZSB8fCB0eXBlb2YgaXNvRGF0ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIE1hdGNoIFlZWVktTU0tREQgZm9ybWF0XG4gICAgY29uc3QgbWF0Y2ggPSAvXihcXGR7NH0pLShcXGR7Mn0pLShcXGR7Mn0pJC8uZXhlYyhpc29EYXRlLnRyaW0oKSk7XG4gICAgXG4gICAgaWYgKCFtYXRjaCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgeWVhciA9IHBhcnNlSW50KG1hdGNoWzFdLCAxMCk7XG4gICAgY29uc3QgbW9udGggPSBwYXJzZUludChtYXRjaFsyXSwgMTApIC0gMTsgLy8gMC1pbmRleGVkXG4gICAgY29uc3QgZGF5ID0gcGFyc2VJbnQobWF0Y2hbM10sIDEwKTtcblxuICAgIC8vIFZhbGlkYXRlIHJhbmdlc1xuICAgIGlmIChtb250aCA8IDAgfHwgbW9udGggPiAxMSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKGRheSA8IDEgfHwgZGF5ID4gMzEpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIENvbnN0cnVjdCBkYXRlIGluIGxvY2FsIHRpbWV6b25lXG4gICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKHllYXIsIG1vbnRoLCBkYXkpO1xuICAgIFxuICAgIC8vIFZlcmlmeSBkYXRlIGlzIHZhbGlkIChlLmcuLCBGZWIgMzEgd291bGQgcm9sbCB0byBNYXIgMylcbiAgICBpZiAoXG4gICAgICBkYXRlLmdldEZ1bGxZZWFyKCkgIT09IHllYXIgfHxcbiAgICAgIGRhdGUuZ2V0TW9udGgoKSAhPT0gbW9udGggfHxcbiAgICAgIGRhdGUuZ2V0RGF0ZSgpICE9PSBkYXlcbiAgICApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZShkYXRlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgd2VlayBzdGFydCBkYXkgZm9yIGxvY2FsZVxuICAgKiBcbiAgICogRGVmYXVsdDogU3VuZGF5ICgwKSBmb3IgbW9zdCBsb2NhbGVzXG4gICAqIE1vbmRheSAoMSkgZm9yIEV1cm9wZSwgSVNPIDg2MDFcbiAgICogXG4gICAqIEltcGxlbWVudGF0aW9uOiBTaW1wbGUgbG9jYWxlIGRldGVjdGlvblxuICAgKiBGb3IgYWR2YW5jZWQgbmVlZHMsIHVzZSBJbnRsLkxvY2FsZSBvciBleHRlcm5hbCBsaWJyYXJ5XG4gICAqL1xuICBnZXRXZWVrU3RhcnQobG9jYWxlPzogc3RyaW5nKTogMCB8IDEgfCAyIHwgMyB8IDQgfCA1IHwgNiB7XG4gICAgaWYgKCFsb2NhbGUpIHtcbiAgICAgIGxvY2FsZSA9IHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnID8gbmF2aWdhdG9yLmxhbmd1YWdlIDogJ2VuLVVTJztcbiAgICB9XG5cbiAgICAvLyBJU08gODYwMTogTW9uZGF5IHN0YXJ0XG4gICAgY29uc3QgbW9uZGF5U3RhcnRMb2NhbGVzID0gW1xuICAgICAgJ2VuLUdCJywgJ2VuLUlFJywgJ2VuLUFVJywgJ2VuLU5aJywgJ2VuLUNBJyxcbiAgICAgICdlcycsICdlcy1FUycsICdlcy1NWCcsXG4gICAgICAnZnInLCAnZnItRlInLCAnZnItQ0EnLFxuICAgICAgJ2RlJywgJ2RlLURFJywgJ2RlLUFUJywgJ2RlLUNIJyxcbiAgICAgICdpdCcsICdpdC1JVCcsXG4gICAgICAncHQnLCAncHQtUFQnLCAncHQtQlInLFxuICAgICAgJ25sJywgJ25sLU5MJywgJ25sLUJFJyxcbiAgICAgICdydScsICdydS1SVScsXG4gICAgICAnemgnLCAnemgtQ04nLCAnemgtVFcnLFxuICAgICAgJ2phJywgJ2phLUpQJyxcbiAgICAgICdrbycsICdrby1LUidcbiAgICBdO1xuXG4gICAgY29uc3Qgbm9ybWFsaXplZExvY2FsZSA9IGxvY2FsZS50b0xvd2VyQ2FzZSgpO1xuICAgIGNvbnN0IHN0YXJ0c1dpdGhNb25kYXkgPSBtb25kYXlTdGFydExvY2FsZXMuc29tZShsb2MgPT4gXG4gICAgICBub3JtYWxpemVkTG9jYWxlLnN0YXJ0c1dpdGgobG9jLnRvTG93ZXJDYXNlKCkpXG4gICAgKTtcblxuICAgIHJldHVybiBzdGFydHNXaXRoTW9uZGF5ID8gMSA6IDA7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,243 @@
|
|
|
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 { APP_INITIALIZER, makeEnvironmentProviders } from '@angular/core';
|
|
35
|
+
import { PresetRegistry } from './preset-registry';
|
|
36
|
+
import { BUILT_IN_PRESETS } from './built-in-presets';
|
|
37
|
+
/**
|
|
38
|
+
* Initializer function that registers built-in presets
|
|
39
|
+
*
|
|
40
|
+
* Runs at application startup (APP_INITIALIZER)
|
|
41
|
+
*
|
|
42
|
+
* @param registry - PresetRegistry instance
|
|
43
|
+
* @returns Initialization function
|
|
44
|
+
*/
|
|
45
|
+
function initializeBuiltInPresets(registry) {
|
|
46
|
+
return () => {
|
|
47
|
+
// Register all built-in presets
|
|
48
|
+
BUILT_IN_PRESETS.forEach(preset => {
|
|
49
|
+
registry.register(preset);
|
|
50
|
+
});
|
|
51
|
+
// Log registration for debugging (can be removed in production)
|
|
52
|
+
if (typeof console !== 'undefined' && console.debug) {
|
|
53
|
+
console.debug(`[ng-dual-datepicker] Registered ${BUILT_IN_PRESETS.length} built-in presets:`, BUILT_IN_PRESETS.map(p => p.key).join(', '));
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Provide built-in date range presets
|
|
59
|
+
*
|
|
60
|
+
* This provider is automatically included in the library's root providers.
|
|
61
|
+
* Library consumers don't need to add this manually.
|
|
62
|
+
*
|
|
63
|
+
* @returns EnvironmentProviders for built-in presets
|
|
64
|
+
*
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
67
|
+
export function provideBuiltInPresets() {
|
|
68
|
+
return makeEnvironmentProviders([
|
|
69
|
+
{
|
|
70
|
+
provide: APP_INITIALIZER,
|
|
71
|
+
multi: true,
|
|
72
|
+
useFactory: initializeBuiltInPresets,
|
|
73
|
+
deps: [PresetRegistry]
|
|
74
|
+
}
|
|
75
|
+
]);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Provide custom date range presets
|
|
79
|
+
*
|
|
80
|
+
* Use this to register your own industry-specific presets:
|
|
81
|
+
* - Fiscal presets
|
|
82
|
+
* - Hotel/hospitality presets
|
|
83
|
+
* - Logistics presets
|
|
84
|
+
* - Custom business logic
|
|
85
|
+
*
|
|
86
|
+
* @param presets - Array of custom RangePresetPlugin implementations
|
|
87
|
+
* @returns EnvironmentProviders for custom presets
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* // Fiscal presets
|
|
92
|
+
* const FISCAL_PRESETS: RangePresetPlugin[] = [
|
|
93
|
+
* {
|
|
94
|
+
* key: 'THIS_FISCAL_QUARTER',
|
|
95
|
+
* resolve: (clock, adapter) => {
|
|
96
|
+
* const now = clock.now();
|
|
97
|
+
* const month = adapter.getMonth(now);
|
|
98
|
+
*
|
|
99
|
+
* // Fiscal year starts April (month 3)
|
|
100
|
+
* const fiscalMonth = (month + 9) % 12;
|
|
101
|
+
* const quarterStart = Math.floor(fiscalMonth / 3) * 3;
|
|
102
|
+
* const calendarMonth = (quarterStart - 9 + 12) % 12;
|
|
103
|
+
*
|
|
104
|
+
* const year = adapter.getYear(now);
|
|
105
|
+
* const fiscalYear = month < 3 ? year - 1 : year;
|
|
106
|
+
*
|
|
107
|
+
* const start = new Date(fiscalYear, calendarMonth, 1);
|
|
108
|
+
* const end = new Date(fiscalYear, calendarMonth + 3, 0);
|
|
109
|
+
*
|
|
110
|
+
* return {
|
|
111
|
+
* start: adapter.normalize(start),
|
|
112
|
+
* end: adapter.normalize(end)
|
|
113
|
+
* };
|
|
114
|
+
* }
|
|
115
|
+
* },
|
|
116
|
+
* {
|
|
117
|
+
* key: 'FISCAL_YEAR_TO_DATE',
|
|
118
|
+
* resolve: (clock, adapter) => {
|
|
119
|
+
* const now = clock.now();
|
|
120
|
+
* const month = adapter.getMonth(now);
|
|
121
|
+
* const year = adapter.getYear(now);
|
|
122
|
+
*
|
|
123
|
+
* // Fiscal year starts April 1
|
|
124
|
+
* const fiscalYearStart = month >= 3
|
|
125
|
+
* ? new Date(year, 3, 1)
|
|
126
|
+
* : new Date(year - 1, 3, 1);
|
|
127
|
+
*
|
|
128
|
+
* return {
|
|
129
|
+
* start: adapter.normalize(fiscalYearStart),
|
|
130
|
+
* end: adapter.normalize(now)
|
|
131
|
+
* };
|
|
132
|
+
* }
|
|
133
|
+
* }
|
|
134
|
+
* ];
|
|
135
|
+
*
|
|
136
|
+
* // In app.config.ts
|
|
137
|
+
* export const appConfig: ApplicationConfig = {
|
|
138
|
+
* providers: [
|
|
139
|
+
* provideCustomPresets(FISCAL_PRESETS)
|
|
140
|
+
* ]
|
|
141
|
+
* };
|
|
142
|
+
*
|
|
143
|
+
* // Use in components
|
|
144
|
+
* store.applyPreset('THIS_FISCAL_QUARTER');
|
|
145
|
+
* store.applyPreset('FISCAL_YEAR_TO_DATE');
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* // Hotel presets
|
|
151
|
+
* const HOTEL_PRESETS: RangePresetPlugin[] = [
|
|
152
|
+
* {
|
|
153
|
+
* key: 'CHECK_IN_WEEK',
|
|
154
|
+
* resolve: (clock, adapter) => {
|
|
155
|
+
* const now = clock.now();
|
|
156
|
+
* const dayOfWeek = adapter.getDayOfWeek(now);
|
|
157
|
+
*
|
|
158
|
+
* // Check-in week: Friday to Friday
|
|
159
|
+
* const daysToNextFriday = dayOfWeek <= 5
|
|
160
|
+
* ? 5 - dayOfWeek
|
|
161
|
+
* : 7 - dayOfWeek + 5;
|
|
162
|
+
*
|
|
163
|
+
* const nextFriday = adapter.addDays(now, daysToNextFriday);
|
|
164
|
+
* const followingFriday = adapter.addDays(nextFriday, 7);
|
|
165
|
+
*
|
|
166
|
+
* return { start: nextFriday, end: followingFriday };
|
|
167
|
+
* }
|
|
168
|
+
* },
|
|
169
|
+
* {
|
|
170
|
+
* key: 'NEXT_30_NIGHTS',
|
|
171
|
+
* resolve: (clock, adapter) => {
|
|
172
|
+
* const now = clock.now();
|
|
173
|
+
* const tomorrow = adapter.addDays(now, 1);
|
|
174
|
+
* const end = adapter.addDays(tomorrow, 30);
|
|
175
|
+
* return { start: tomorrow, end };
|
|
176
|
+
* }
|
|
177
|
+
* }
|
|
178
|
+
* ];
|
|
179
|
+
*
|
|
180
|
+
* providers: [provideCustomPresets(HOTEL_PRESETS)]
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export function provideCustomPresets(presets) {
|
|
184
|
+
return makeEnvironmentProviders([
|
|
185
|
+
{
|
|
186
|
+
provide: APP_INITIALIZER,
|
|
187
|
+
multi: true,
|
|
188
|
+
useFactory: (registry) => {
|
|
189
|
+
return () => {
|
|
190
|
+
presets.forEach(preset => {
|
|
191
|
+
registry.register(preset);
|
|
192
|
+
});
|
|
193
|
+
if (typeof console !== 'undefined' && console.debug) {
|
|
194
|
+
console.debug(`[ng-dual-datepicker] Registered ${presets.length} custom presets:`, presets.map(p => p.key).join(', '));
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
deps: [PresetRegistry]
|
|
199
|
+
}
|
|
200
|
+
]);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Provide preset package
|
|
204
|
+
*
|
|
205
|
+
* Convenience function for external preset packages.
|
|
206
|
+
*
|
|
207
|
+
* @param packageName - Name of the preset package (for logging)
|
|
208
|
+
* @param presets - Array of presets from the package
|
|
209
|
+
* @returns EnvironmentProviders
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```typescript
|
|
213
|
+
* // @acme/fiscal-presets package
|
|
214
|
+
* export function provideFiscalPresets(): EnvironmentProviders {
|
|
215
|
+
* return providePresetPackage('@acme/fiscal-presets', FISCAL_PRESETS);
|
|
216
|
+
* }
|
|
217
|
+
*
|
|
218
|
+
* // In app
|
|
219
|
+
* import { provideFiscalPresets } from '@acme/fiscal-presets';
|
|
220
|
+
*
|
|
221
|
+
* providers: [provideFiscalPresets()]
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
export function providePresetPackage(packageName, presets) {
|
|
225
|
+
return makeEnvironmentProviders([
|
|
226
|
+
{
|
|
227
|
+
provide: APP_INITIALIZER,
|
|
228
|
+
multi: true,
|
|
229
|
+
useFactory: (registry) => {
|
|
230
|
+
return () => {
|
|
231
|
+
presets.forEach(preset => {
|
|
232
|
+
registry.register(preset);
|
|
233
|
+
});
|
|
234
|
+
if (typeof console !== 'undefined' && console.debug) {
|
|
235
|
+
console.debug(`[${packageName}] Registered ${presets.length} presets:`, presets.map(p => p.key).join(', '));
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
},
|
|
239
|
+
deps: [PresetRegistry]
|
|
240
|
+
}
|
|
241
|
+
]);
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlc2V0LXByb3ZpZGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb3JlL3ByZXNldC1wcm92aWRlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBZ0NHO0FBRUgsT0FBTyxFQUFFLGVBQWUsRUFBd0Isd0JBQXdCLEVBQVUsTUFBTSxlQUFlLENBQUM7QUFDeEcsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBR3REOzs7Ozs7O0dBT0c7QUFDSCxTQUFTLHdCQUF3QixDQUFDLFFBQXdCO0lBQ3hELE9BQU8sR0FBRyxFQUFFO1FBQ1YsZ0NBQWdDO1FBQ2hDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUNoQyxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzVCLENBQUMsQ0FBQyxDQUFDO1FBRUgsZ0VBQWdFO1FBQ2hFLElBQUksT0FBTyxPQUFPLEtBQUssV0FBVyxJQUFJLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNwRCxPQUFPLENBQUMsS0FBSyxDQUNYLG1DQUFtQyxnQkFBZ0IsQ0FBQyxNQUFNLG9CQUFvQixFQUM5RSxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUM1QyxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUMsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLFVBQVUscUJBQXFCO0lBQ25DLE9BQU8sd0JBQXdCLENBQUM7UUFDOUI7WUFDRSxPQUFPLEVBQUUsZUFBZTtZQUN4QixLQUFLLEVBQUUsSUFBSTtZQUNYLFVBQVUsRUFBRSx3QkFBd0I7WUFDcEMsSUFBSSxFQUFFLENBQUMsY0FBYyxDQUFDO1NBQ3ZCO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5R0c7QUFDSCxNQUFNLFVBQVUsb0JBQW9CLENBQUMsT0FBNEI7SUFDL0QsT0FBTyx3QkFBd0IsQ0FBQztRQUM5QjtZQUNFLE9BQU8sRUFBRSxlQUFlO1lBQ3hCLEtBQUssRUFBRSxJQUFJO1lBQ1gsVUFBVSxFQUFFLENBQUMsUUFBd0IsRUFBRSxFQUFFO2dCQUN2QyxPQUFPLEdBQUcsRUFBRTtvQkFDVixPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFO3dCQUN2QixRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUM1QixDQUFDLENBQUMsQ0FBQztvQkFFSCxJQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVcsSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7d0JBQ3BELE9BQU8sQ0FBQyxLQUFLLENBQ1gsbUNBQW1DLE9BQU8sQ0FBQyxNQUFNLGtCQUFrQixFQUNuRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FDbkMsQ0FBQztvQkFDSixDQUFDO2dCQUNILENBQUMsQ0FBQztZQUNKLENBQUM7WUFDRCxJQUFJLEVBQUUsQ0FBQyxjQUFjLENBQUM7U0FDdkI7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUNILE1BQU0sVUFBVSxvQkFBb0IsQ0FDbEMsV0FBbUIsRUFDbkIsT0FBNEI7SUFFNUIsT0FBTyx3QkFBd0IsQ0FBQztRQUM5QjtZQUNFLE9BQU8sRUFBRSxlQUFlO1lBQ3hCLEtBQUssRUFBRSxJQUFJO1lBQ1gsVUFBVSxFQUFFLENBQUMsUUFBd0IsRUFBRSxFQUFFO2dCQUN2QyxPQUFPLEdBQUcsRUFBRTtvQkFDVixPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFO3dCQUN2QixRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUM1QixDQUFDLENBQUMsQ0FBQztvQkFFSCxJQUFJLE9BQU8sT0FBTyxLQUFLLFdBQVcsSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7d0JBQ3BELE9BQU8sQ0FBQyxLQUFLLENBQ1gsSUFBSSxXQUFXLGdCQUFnQixPQUFPLENBQUMsTUFBTSxXQUFXLEVBQ3hELE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUNuQyxDQUFDO29CQUNKLENBQUM7Z0JBQ0gsQ0FBQyxDQUFDO1lBQ0osQ0FBQztZQUNELElBQUksRUFBRSxDQUFDLGNBQWMsQ0FBQztTQUN2QjtLQUNGLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFByb3ZpZGVyIEZ1bmN0aW9ucyBmb3IgQnVpbHQtaW4gUHJlc2V0c1xuICogXG4gKiBWZXJzaW9uOiAzLjYuMFxuICogXG4gKiBBdXRvbWF0aWMgcmVnaXN0cmF0aW9uIG9mIGJ1aWx0LWluIGRhdGUgcmFuZ2UgcHJlc2V0cy5cbiAqIFRoZXNlIHByb3ZpZGVycyBlbnN1cmUgYmFja3dhcmQgY29tcGF0aWJpbGl0eSBieSBhdXRvLXJlZ2lzdGVyaW5nXG4gKiBhbGwgc3RhbmRhcmQgcHJlc2V0cyAoVE9EQVksIExBU1RfN19EQVlTLCBUSElTX01PTlRILCBldGMuKVxuICogXG4gKiBVU0FHRSBJTiBMSUJSQVJZIChJbnRlcm5hbCk6XG4gKiBCdWlsdC1pbiBwcmVzZXRzIGFyZSByZWdpc3RlcmVkIGF1dG9tYXRpY2FsbHkgdmlhIEFuZ3VsYXIgcHJvdmlkZXJzLlxuICogTGlicmFyeSBjb25zdW1lcnMgZG9uJ3QgbmVlZCB0byBkbyBhbnl0aGluZy5cbiAqIFxuICogVVNBR0UgSU4gQVBQIChDdXN0b20gUHJlc2V0cyk6XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBhcHAuY29uZmlnLnRzXG4gKiBleHBvcnQgY29uc3QgYXBwQ29uZmlnOiBBcHBsaWNhdGlvbkNvbmZpZyA9IHtcbiAqICAgcHJvdmlkZXJzOiBbXG4gKiAgICAgLy8gLi4uIG90aGVyIHByb3ZpZGVyc1xuICogICAgIHByb3ZpZGVDdXN0b21QcmVzZXRzKFtcbiAqICAgICAgIHtcbiAqICAgICAgICAga2V5OiAnVEhJU19GSVNDQUxfUVVBUlRFUicsXG4gKiAgICAgICAgIHJlc29sdmU6IChjbG9jaywgYWRhcHRlcikgPT4ge1xuICogICAgICAgICAgIGNvbnN0IG5vdyA9IGNsb2NrLm5vdygpO1xuICogICAgICAgICAgIC8vIC4uLiBmaXNjYWwgbG9naWNcbiAqICAgICAgICAgICByZXR1cm4geyBzdGFydCwgZW5kIH07XG4gKiAgICAgICAgIH1cbiAqICAgICAgIH1cbiAqICAgICBdKVxuICogICBdXG4gKiB9O1xuICogYGBgXG4gKi9cblxuaW1wb3J0IHsgQVBQX0lOSVRJQUxJWkVSLCBFbnZpcm9ubWVudFByb3ZpZGVycywgbWFrZUVudmlyb25tZW50UHJvdmlkZXJzLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFByZXNldFJlZ2lzdHJ5IH0gZnJvbSAnLi9wcmVzZXQtcmVnaXN0cnknO1xuaW1wb3J0IHsgQlVJTFRfSU5fUFJFU0VUUyB9IGZyb20gJy4vYnVpbHQtaW4tcHJlc2V0cyc7XG5pbXBvcnQgeyBSYW5nZVByZXNldFBsdWdpbiB9IGZyb20gJy4vcmFuZ2UtcHJlc2V0LnBsdWdpbic7XG5cbi8qKlxuICogSW5pdGlhbGl6ZXIgZnVuY3Rpb24gdGhhdCByZWdpc3RlcnMgYnVpbHQtaW4gcHJlc2V0c1xuICogXG4gKiBSdW5zIGF0IGFwcGxpY2F0aW9uIHN0YXJ0dXAgKEFQUF9JTklUSUFMSVpFUilcbiAqIFxuICogQHBhcmFtIHJlZ2lzdHJ5IC0gUHJlc2V0UmVnaXN0cnkgaW5zdGFuY2VcbiAqIEByZXR1cm5zIEluaXRpYWxpemF0aW9uIGZ1bmN0aW9uXG4gKi9cbmZ1bmN0aW9uIGluaXRpYWxpemVCdWlsdEluUHJlc2V0cyhyZWdpc3RyeTogUHJlc2V0UmVnaXN0cnkpOiAoKSA9PiB2b2lkIHtcbiAgcmV0dXJuICgpID0+IHtcbiAgICAvLyBSZWdpc3RlciBhbGwgYnVpbHQtaW4gcHJlc2V0c1xuICAgIEJVSUxUX0lOX1BSRVNFVFMuZm9yRWFjaChwcmVzZXQgPT4ge1xuICAgICAgcmVnaXN0cnkucmVnaXN0ZXIocHJlc2V0KTtcbiAgICB9KTtcblxuICAgIC8vIExvZyByZWdpc3RyYXRpb24gZm9yIGRlYnVnZ2luZyAoY2FuIGJlIHJlbW92ZWQgaW4gcHJvZHVjdGlvbilcbiAgICBpZiAodHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnICYmIGNvbnNvbGUuZGVidWcpIHtcbiAgICAgIGNvbnNvbGUuZGVidWcoXG4gICAgICAgIGBbbmctZHVhbC1kYXRlcGlja2VyXSBSZWdpc3RlcmVkICR7QlVJTFRfSU5fUFJFU0VUUy5sZW5ndGh9IGJ1aWx0LWluIHByZXNldHM6YCxcbiAgICAgICAgQlVJTFRfSU5fUFJFU0VUUy5tYXAocCA9PiBwLmtleSkuam9pbignLCAnKVxuICAgICAgKTtcbiAgICB9XG4gIH07XG59XG5cbi8qKlxuICogUHJvdmlkZSBidWlsdC1pbiBkYXRlIHJhbmdlIHByZXNldHNcbiAqIFxuICogVGhpcyBwcm92aWRlciBpcyBhdXRvbWF0aWNhbGx5IGluY2x1ZGVkIGluIHRoZSBsaWJyYXJ5J3Mgcm9vdCBwcm92aWRlcnMuXG4gKiBMaWJyYXJ5IGNvbnN1bWVycyBkb24ndCBuZWVkIHRvIGFkZCB0aGlzIG1hbnVhbGx5LlxuICogXG4gKiBAcmV0dXJucyBFbnZpcm9ubWVudFByb3ZpZGVycyBmb3IgYnVpbHQtaW4gcHJlc2V0c1xuICogXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb3ZpZGVCdWlsdEluUHJlc2V0cygpOiBFbnZpcm9ubWVudFByb3ZpZGVycyB7XG4gIHJldHVybiBtYWtlRW52aXJvbm1lbnRQcm92aWRlcnMoW1xuICAgIHtcbiAgICAgIHByb3ZpZGU6IEFQUF9JTklUSUFMSVpFUixcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgICAgdXNlRmFjdG9yeTogaW5pdGlhbGl6ZUJ1aWx0SW5QcmVzZXRzLFxuICAgICAgZGVwczogW1ByZXNldFJlZ2lzdHJ5XVxuICAgIH1cbiAgXSk7XG59XG5cbi8qKlxuICogUHJvdmlkZSBjdXN0b20gZGF0ZSByYW5nZSBwcmVzZXRzXG4gKiBcbiAqIFVzZSB0aGlzIHRvIHJlZ2lzdGVyIHlvdXIgb3duIGluZHVzdHJ5LXNwZWNpZmljIHByZXNldHM6XG4gKiAtIEZpc2NhbCBwcmVzZXRzXG4gKiAtIEhvdGVsL2hvc3BpdGFsaXR5IHByZXNldHNcbiAqIC0gTG9naXN0aWNzIHByZXNldHNcbiAqIC0gQ3VzdG9tIGJ1c2luZXNzIGxvZ2ljXG4gKiBcbiAqIEBwYXJhbSBwcmVzZXRzIC0gQXJyYXkgb2YgY3VzdG9tIFJhbmdlUHJlc2V0UGx1Z2luIGltcGxlbWVudGF0aW9uc1xuICogQHJldHVybnMgRW52aXJvbm1lbnRQcm92aWRlcnMgZm9yIGN1c3RvbSBwcmVzZXRzXG4gKiBcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBGaXNjYWwgcHJlc2V0c1xuICogY29uc3QgRklTQ0FMX1BSRVNFVFM6IFJhbmdlUHJlc2V0UGx1Z2luW10gPSBbXG4gKiAgIHtcbiAqICAgICBrZXk6ICdUSElTX0ZJU0NBTF9RVUFSVEVSJyxcbiAqICAgICByZXNvbHZlOiAoY2xvY2ssIGFkYXB0ZXIpID0+IHtcbiAqICAgICAgIGNvbnN0IG5vdyA9IGNsb2NrLm5vdygpO1xuICogICAgICAgY29uc3QgbW9udGggPSBhZGFwdGVyLmdldE1vbnRoKG5vdyk7XG4gKiAgICAgICBcbiAqICAgICAgIC8vIEZpc2NhbCB5ZWFyIHN0YXJ0cyBBcHJpbCAobW9udGggMylcbiAqICAgICAgIGNvbnN0IGZpc2NhbE1vbnRoID0gKG1vbnRoICsgOSkgJSAxMjtcbiAqICAgICAgIGNvbnN0IHF1YXJ0ZXJTdGFydCA9IE1hdGguZmxvb3IoZmlzY2FsTW9udGggLyAzKSAqIDM7XG4gKiAgICAgICBjb25zdCBjYWxlbmRhck1vbnRoID0gKHF1YXJ0ZXJTdGFydCAtIDkgKyAxMikgJSAxMjtcbiAqICAgICAgIFxuICogICAgICAgY29uc3QgeWVhciA9IGFkYXB0ZXIuZ2V0WWVhcihub3cpO1xuICogICAgICAgY29uc3QgZmlzY2FsWWVhciA9IG1vbnRoIDwgMyA/IHllYXIgLSAxIDogeWVhcjtcbiAqICAgICAgIFxuICogICAgICAgY29uc3Qgc3RhcnQgPSBuZXcgRGF0ZShmaXNjYWxZZWFyLCBjYWxlbmRhck1vbnRoLCAxKTtcbiAqICAgICAgIGNvbnN0IGVuZCA9IG5ldyBEYXRlKGZpc2NhbFllYXIsIGNhbGVuZGFyTW9udGggKyAzLCAwKTtcbiAqICAgICAgIFxuICogICAgICAgcmV0dXJuIHtcbiAqICAgICAgICAgc3RhcnQ6IGFkYXB0ZXIubm9ybWFsaXplKHN0YXJ0KSxcbiAqICAgICAgICAgZW5kOiBhZGFwdGVyLm5vcm1hbGl6ZShlbmQpXG4gKiAgICAgICB9O1xuICogICAgIH1cbiAqICAgfSxcbiAqICAge1xuICogICAgIGtleTogJ0ZJU0NBTF9ZRUFSX1RPX0RBVEUnLFxuICogICAgIHJlc29sdmU6IChjbG9jaywgYWRhcHRlcikgPT4ge1xuICogICAgICAgY29uc3Qgbm93ID0gY2xvY2subm93KCk7XG4gKiAgICAgICBjb25zdCBtb250aCA9IGFkYXB0ZXIuZ2V0TW9udGgobm93KTtcbiAqICAgICAgIGNvbnN0IHllYXIgPSBhZGFwdGVyLmdldFllYXIobm93KTtcbiAqICAgICAgIFxuICogICAgICAgLy8gRmlzY2FsIHllYXIgc3RhcnRzIEFwcmlsIDFcbiAqICAgICAgIGNvbnN0IGZpc2NhbFllYXJTdGFydCA9IG1vbnRoID49IDMgXG4gKiAgICAgICAgID8gbmV3IERhdGUoeWVhciwgMywgMSlcbiAqICAgICAgICAgOiBuZXcgRGF0ZSh5ZWFyIC0gMSwgMywgMSk7XG4gKiAgICAgICBcbiAqICAgICAgIHJldHVybiB7XG4gKiAgICAgICAgIHN0YXJ0OiBhZGFwdGVyLm5vcm1hbGl6ZShmaXNjYWxZZWFyU3RhcnQpLFxuICogICAgICAgICBlbmQ6IGFkYXB0ZXIubm9ybWFsaXplKG5vdylcbiAqICAgICAgIH07XG4gKiAgICAgfVxuICogICB9XG4gKiBdO1xuICogXG4gKiAvLyBJbiBhcHAuY29uZmlnLnRzXG4gKiBleHBvcnQgY29uc3QgYXBwQ29uZmlnOiBBcHBsaWNhdGlvbkNvbmZpZyA9IHtcbiAqICAgcHJvdmlkZXJzOiBbXG4gKiAgICAgcHJvdmlkZUN1c3RvbVByZXNldHMoRklTQ0FMX1BSRVNFVFMpXG4gKiAgIF1cbiAqIH07XG4gKiBcbiAqIC8vIFVzZSBpbiBjb21wb25lbnRzXG4gKiBzdG9yZS5hcHBseVByZXNldCgnVEhJU19GSVNDQUxfUVVBUlRFUicpO1xuICogc3RvcmUuYXBwbHlQcmVzZXQoJ0ZJU0NBTF9ZRUFSX1RPX0RBVEUnKTtcbiAqIGBgYFxuICogXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gSG90ZWwgcHJlc2V0c1xuICogY29uc3QgSE9URUxfUFJFU0VUUzogUmFuZ2VQcmVzZXRQbHVnaW5bXSA9IFtcbiAqICAge1xuICogICAgIGtleTogJ0NIRUNLX0lOX1dFRUsnLFxuICogICAgIHJlc29sdmU6IChjbG9jaywgYWRhcHRlcikgPT4ge1xuICogICAgICAgY29uc3Qgbm93ID0gY2xvY2subm93KCk7XG4gKiAgICAgICBjb25zdCBkYXlPZldlZWsgPSBhZGFwdGVyLmdldERheU9mV2Vlayhub3cpO1xuICogICAgICAgXG4gKiAgICAgICAvLyBDaGVjay1pbiB3ZWVrOiBGcmlkYXkgdG8gRnJpZGF5XG4gKiAgICAgICBjb25zdCBkYXlzVG9OZXh0RnJpZGF5ID0gZGF5T2ZXZWVrIDw9IDUgXG4gKiAgICAgICAgID8gNSAtIGRheU9mV2VlayBcbiAqICAgICAgICAgOiA3IC0gZGF5T2ZXZWVrICsgNTtcbiAqICAgICAgIFxuICogICAgICAgY29uc3QgbmV4dEZyaWRheSA9IGFkYXB0ZXIuYWRkRGF5cyhub3csIGRheXNUb05leHRGcmlkYXkpO1xuICogICAgICAgY29uc3QgZm9sbG93aW5nRnJpZGF5ID0gYWRhcHRlci5hZGREYXlzKG5leHRGcmlkYXksIDcpO1xuICogICAgICAgXG4gKiAgICAgICByZXR1cm4geyBzdGFydDogbmV4dEZyaWRheSwgZW5kOiBmb2xsb3dpbmdGcmlkYXkgfTtcbiAqICAgICB9XG4gKiAgIH0sXG4gKiAgIHtcbiAqICAgICBrZXk6ICdORVhUXzMwX05JR0hUUycsXG4gKiAgICAgcmVzb2x2ZTogKGNsb2NrLCBhZGFwdGVyKSA9PiB7XG4gKiAgICAgICBjb25zdCBub3cgPSBjbG9jay5ub3coKTtcbiAqICAgICAgIGNvbnN0IHRvbW9ycm93ID0gYWRhcHRlci5hZGREYXlzKG5vdywgMSk7XG4gKiAgICAgICBjb25zdCBlbmQgPSBhZGFwdGVyLmFkZERheXModG9tb3Jyb3csIDMwKTtcbiAqICAgICAgIHJldHVybiB7IHN0YXJ0OiB0b21vcnJvdywgZW5kIH07XG4gKiAgICAgfVxuICogICB9XG4gKiBdO1xuICogXG4gKiBwcm92aWRlcnM6IFtwcm92aWRlQ3VzdG9tUHJlc2V0cyhIT1RFTF9QUkVTRVRTKV1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvdmlkZUN1c3RvbVByZXNldHMocHJlc2V0czogUmFuZ2VQcmVzZXRQbHVnaW5bXSk6IEVudmlyb25tZW50UHJvdmlkZXJzIHtcbiAgcmV0dXJuIG1ha2VFbnZpcm9ubWVudFByb3ZpZGVycyhbXG4gICAge1xuICAgICAgcHJvdmlkZTogQVBQX0lOSVRJQUxJWkVSLFxuICAgICAgbXVsdGk6IHRydWUsXG4gICAgICB1c2VGYWN0b3J5OiAocmVnaXN0cnk6IFByZXNldFJlZ2lzdHJ5KSA9PiB7XG4gICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgcHJlc2V0cy5mb3JFYWNoKHByZXNldCA9PiB7XG4gICAgICAgICAgICByZWdpc3RyeS5yZWdpc3RlcihwcmVzZXQpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25zb2xlICE9PSAndW5kZWZpbmVkJyAmJiBjb25zb2xlLmRlYnVnKSB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKFxuICAgICAgICAgICAgICBgW25nLWR1YWwtZGF0ZXBpY2tlcl0gUmVnaXN0ZXJlZCAke3ByZXNldHMubGVuZ3RofSBjdXN0b20gcHJlc2V0czpgLFxuICAgICAgICAgICAgICBwcmVzZXRzLm1hcChwID0+IHAua2V5KS5qb2luKCcsICcpXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICBkZXBzOiBbUHJlc2V0UmVnaXN0cnldXG4gICAgfVxuICBdKTtcbn1cblxuLyoqXG4gKiBQcm92aWRlIHByZXNldCBwYWNrYWdlXG4gKiBcbiAqIENvbnZlbmllbmNlIGZ1bmN0aW9uIGZvciBleHRlcm5hbCBwcmVzZXQgcGFja2FnZXMuXG4gKiBcbiAqIEBwYXJhbSBwYWNrYWdlTmFtZSAtIE5hbWUgb2YgdGhlIHByZXNldCBwYWNrYWdlIChmb3IgbG9nZ2luZylcbiAqIEBwYXJhbSBwcmVzZXRzIC0gQXJyYXkgb2YgcHJlc2V0cyBmcm9tIHRoZSBwYWNrYWdlXG4gKiBAcmV0dXJucyBFbnZpcm9ubWVudFByb3ZpZGVyc1xuICogXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gQGFjbWUvZmlzY2FsLXByZXNldHMgcGFja2FnZVxuICogZXhwb3J0IGZ1bmN0aW9uIHByb3ZpZGVGaXNjYWxQcmVzZXRzKCk6IEVudmlyb25tZW50UHJvdmlkZXJzIHtcbiAqICAgcmV0dXJuIHByb3ZpZGVQcmVzZXRQYWNrYWdlKCdAYWNtZS9maXNjYWwtcHJlc2V0cycsIEZJU0NBTF9QUkVTRVRTKTtcbiAqIH1cbiAqIFxuICogLy8gSW4gYXBwXG4gKiBpbXBvcnQgeyBwcm92aWRlRmlzY2FsUHJlc2V0cyB9IGZyb20gJ0BhY21lL2Zpc2NhbC1wcmVzZXRzJztcbiAqIFxuICogcHJvdmlkZXJzOiBbcHJvdmlkZUZpc2NhbFByZXNldHMoKV1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvdmlkZVByZXNldFBhY2thZ2UoXG4gIHBhY2thZ2VOYW1lOiBzdHJpbmcsXG4gIHByZXNldHM6IFJhbmdlUHJlc2V0UGx1Z2luW11cbik6IEVudmlyb25tZW50UHJvdmlkZXJzIHtcbiAgcmV0dXJuIG1ha2VFbnZpcm9ubWVudFByb3ZpZGVycyhbXG4gICAge1xuICAgICAgcHJvdmlkZTogQVBQX0lOSVRJQUxJWkVSLFxuICAgICAgbXVsdGk6IHRydWUsXG4gICAgICB1c2VGYWN0b3J5OiAocmVnaXN0cnk6IFByZXNldFJlZ2lzdHJ5KSA9PiB7XG4gICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgcHJlc2V0cy5mb3JFYWNoKHByZXNldCA9PiB7XG4gICAgICAgICAgICByZWdpc3RyeS5yZWdpc3RlcihwcmVzZXQpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKHR5cGVvZiBjb25zb2xlICE9PSAndW5kZWZpbmVkJyAmJiBjb25zb2xlLmRlYnVnKSB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnKFxuICAgICAgICAgICAgICBgWyR7cGFja2FnZU5hbWV9XSBSZWdpc3RlcmVkICR7cHJlc2V0cy5sZW5ndGh9IHByZXNldHM6YCxcbiAgICAgICAgICAgICAgcHJlc2V0cy5tYXAocCA9PiBwLmtleSkuam9pbignLCAnKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgZGVwczogW1ByZXNldFJlZ2lzdHJ5XVxuICAgIH1cbiAgXSk7XG59XG4iXX0=
|