@oneluiz/dual-datepicker 3.5.0 → 3.5.1

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,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==