@oneluiz/dual-datepicker 3.4.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  A lightweight, zero-dependency date range picker for Angular 17+. Built with standalone components, Reactive Forms, and Angular Signals. No Angular Material required.
4
4
 
5
+ > **🆕 NEW in v3.5.0**: [**Headless Architecture**](HEADLESS.md) - Use date range state WITHOUT the UI component. Perfect for SSR, services, and global dashboard filters! 🎯
6
+
5
7
  [![npm version](https://img.shields.io/npm/v/@oneluiz/dual-datepicker)](https://www.npmjs.com/package/@oneluiz/dual-datepicker)
6
8
  [![npm provenance](https://img.shields.io/badge/provenance-available-brightgreen)](https://www.npmjs.com/package/@oneluiz/dual-datepicker)
7
9
  ![license](https://img.shields.io/npm/l/@oneluiz/dual-datepicker)
@@ -17,6 +19,35 @@ npm install @oneluiz/dual-datepicker
17
19
 
18
20
  ---
19
21
 
22
+ ## 🌟 What's New
23
+
24
+ ### Headless Architecture (v3.5.0)
25
+
26
+ Use date range logic **without the UI component**:
27
+
28
+ ```typescript
29
+ // Inject the store anywhere - no UI needed!
30
+ const rangeStore = inject(DualDateRangeStore);
31
+
32
+ // Apply preset
33
+ rangeStore.applyPreset('THIS_MONTH');
34
+
35
+ // Use in API calls
36
+ const range = rangeStore.range();
37
+ http.get(`/api/sales?start=${range.start}&end=${range.end}`);
38
+ ```
39
+
40
+ **Perfect for:**
41
+ - 📊 Dashboard filters (control multiple charts)
42
+ - 🏢 SSR applications
43
+ - 🔄 Global state management
44
+ - 🎯 Service-layer filtering
45
+ - 📈 Analytics and BI tools
46
+
47
+ **[📖 Read the Headless Architecture Guide →](HEADLESS.md)**
48
+
49
+ ---
50
+
20
51
  ## 📋 Table of Contents
21
52
 
22
53
  - [Features](#-features)
@@ -26,6 +57,7 @@ npm install @oneluiz/dual-datepicker
26
57
  - [Basic Usage](#basic-usage)
27
58
  - [Reactive Forms](#with-reactive-forms)
28
59
  - [Angular Signals](#with-angular-signals)
60
+ - [Headless Usage](#headless-usage-new) ⭐ NEW
29
61
  - [Advanced Features](#-advanced-features)
30
62
  - [Multi-Range Selection](#multi-range-support)
31
63
  - [Disabled Dates](#disabled-dates)
@@ -169,6 +201,52 @@ dateRange = signal<DateRange | null>(null);
169
201
  </ngx-dual-datepicker>
170
202
  ```
171
203
 
204
+ ### Headless Usage (NEW) ⭐
205
+
206
+ **Use date range state WITHOUT the UI component** - perfect for SSR, services, and global filters!
207
+
208
+ ```typescript
209
+ import { Component, inject } from '@angular/core';
210
+ import { DualDateRangeStore } from '@oneluiz/dual-datepicker';
211
+ import { HttpClient } from '@angular/common/http';
212
+
213
+ @Component({
214
+ template: `
215
+ <div class="dashboard">
216
+ <button (click)="setPreset('TODAY')">Today</button>
217
+ <button (click)="setPreset('THIS_MONTH')">This Month</button>
218
+ <p>{{ rangeText() }}</p>
219
+ </div>
220
+ `
221
+ })
222
+ export class DashboardComponent {
223
+ private rangeStore = inject(DualDateRangeStore);
224
+ private http = inject(HttpClient);
225
+
226
+ // Expose signals for template
227
+ rangeText = this.rangeStore.rangeText;
228
+
229
+ setPreset(key: string) {
230
+ this.rangeStore.applyPreset(key);
231
+
232
+ // Use in API call
233
+ const range = this.rangeStore.range();
234
+ this.http.get(`/api/sales`, {
235
+ params: { start: range.start, end: range.end }
236
+ }).subscribe(data => console.log(data));
237
+ }
238
+ }
239
+ ```
240
+
241
+ **Benefits:**
242
+ - ✅ No UI component needed
243
+ - ✅ SSR-compatible
244
+ - ✅ Global state management
245
+ - ✅ Perfect for services and guards
246
+ - ✅ Testable and deterministic
247
+
248
+ **[📖 Full Headless Architecture Guide →](HEADLESS.md)** | **[💻 Code Examples →](HEADLESS_EXAMPLES.ts)**
249
+
172
250
  ---
173
251
 
174
252
  ## 🎯 Advanced Features
@@ -1998,6 +2076,12 @@ export class ExampleComponent {
1998
2076
 
1999
2077
  Recently shipped:
2000
2078
 
2079
+ **v3.4.0:**
2080
+ - ✅ **Time Picker** - Select precise datetime ranges with 12h/24h format
2081
+ - ✅ **Configurable Minute Steps** - Choose 1, 5, 15, or 30-minute intervals
2082
+ - ✅ **Default Times** - Set default start/end times
2083
+ - ✅ **Full Theme Support** - Works seamlessly with all built-in themes
2084
+
2001
2085
  **v3.3.0:**
2002
2086
  - ✅ **Theming System** - Pre-built themes for Bootstrap, Bulma, Foundation, Tailwind CSS, and Custom
2003
2087
  - ✅ **CSS Variables Support** - 13 customizable variables for branding
@@ -2025,9 +2109,10 @@ Recently shipped:
2025
2109
 
2026
2110
  Planned features:
2027
2111
 
2028
- - ⬜ **Time Picker** - Select date + time ranges
2029
2112
  - ⬜ **Mobile Optimizations** - Enhanced touch gestures and responsive layout
2030
2113
  - ⬜ **Range Shortcuts** - Quick selection buttons (Today, This Week, etc.)
2114
+ - ⬜ **Time Constraints** - Min/max time validation and business hours
2115
+ - ⬜ **Multi-range + Time Picker** - Combined support for multiple datetime ranges
2031
2116
 
2032
2117
  ## 📄 License
2033
2118
 
@@ -0,0 +1,104 @@
1
+ import * as i0 from "@angular/core";
2
+ export interface DateRangeState {
3
+ start: string;
4
+ end: string;
5
+ startTime?: string;
6
+ endTime?: string;
7
+ }
8
+ export interface DateRangeConfig {
9
+ minDate?: Date;
10
+ maxDate?: Date;
11
+ disabledDates?: Date[] | ((date: Date) => boolean);
12
+ enableTimePicker?: boolean;
13
+ defaultStartTime?: string;
14
+ defaultEndTime?: string;
15
+ }
16
+ export declare class DualDateRangeStore {
17
+ private config;
18
+ private _startDate;
19
+ private _endDate;
20
+ private _leftMonth;
21
+ private _rightMonth;
22
+ private _selectingStart;
23
+ private _startTime;
24
+ private _endTime;
25
+ private _pendingStart;
26
+ private _pendingEnd;
27
+ private _hasPendingChanges;
28
+ readonly startDate: import("@angular/core").Signal<Date>;
29
+ readonly endDate: import("@angular/core").Signal<Date>;
30
+ readonly leftMonth: import("@angular/core").Signal<Date>;
31
+ readonly rightMonth: import("@angular/core").Signal<Date>;
32
+ readonly selectingStart: import("@angular/core").Signal<boolean>;
33
+ readonly startTime: import("@angular/core").Signal<string>;
34
+ readonly endTime: import("@angular/core").Signal<string>;
35
+ readonly hasPendingChanges: import("@angular/core").Signal<boolean>;
36
+ readonly range: import("@angular/core").Signal<DateRangeState>;
37
+ readonly isValid: import("@angular/core").Signal<boolean>;
38
+ readonly rangeText: import("@angular/core").Signal<string>;
39
+ /**
40
+ * Configure the store
41
+ */
42
+ configure(config: Partial<DateRangeConfig>): void;
43
+ /**
44
+ * Set start date (with validation)
45
+ */
46
+ setStart(date: Date | string | null): void;
47
+ /**
48
+ * Set end date (with validation)
49
+ */
50
+ setEnd(date: Date | string | null): void;
51
+ /**
52
+ * Set complete range at once
53
+ */
54
+ setRange(start: Date | string | null, end: Date | string | null): void;
55
+ /**
56
+ * Set pending selection (for requireApply mode)
57
+ */
58
+ setPendingStart(date: Date | string | null): void;
59
+ setPendingEnd(date: Date | string | null): void;
60
+ /**
61
+ * Apply pending changes
62
+ */
63
+ applyPending(): void;
64
+ /**
65
+ * Cancel pending changes
66
+ */
67
+ cancelPending(): void;
68
+ private clearPending;
69
+ /**
70
+ * Reset to empty state
71
+ */
72
+ reset(): void;
73
+ /**
74
+ * Apply a preset by key
75
+ */
76
+ applyPreset(presetKey: string, now?: Date): void;
77
+ /**
78
+ * Navigate left calendar month
79
+ */
80
+ setLeftMonth(date: Date): void;
81
+ /**
82
+ * Navigate right calendar month
83
+ */
84
+ setRightMonth(date: Date): void;
85
+ /**
86
+ * Set time values
87
+ */
88
+ setStartTime(time: string): void;
89
+ setEndTime(time: string): void;
90
+ /**
91
+ * Get current state as snapshot
92
+ */
93
+ getSnapshot(): DateRangeState;
94
+ /**
95
+ * Load state from snapshot
96
+ */
97
+ loadSnapshot(snapshot: DateRangeState): void;
98
+ private parseDate;
99
+ private getNextMonth;
100
+ private getPreviousMonth;
101
+ private formatDateShort;
102
+ static ɵfac: i0.ɵɵFactoryDeclaration<DualDateRangeStore, never>;
103
+ static ɵprov: i0.ɵɵInjectableDeclaration<DualDateRangeStore>;
104
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Core headless date range logic
3
+ * Import from here for clean barrel exports
4
+ */
5
+ export * from './dual-date-range.store';
6
+ export * from './preset.engine';
7
+ export * from './range.validator';
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Headless Preset Engine
3
+ * Pure functions that resolve date ranges WITHOUT render dependency
4
+ * Perfect for SSR, global state, dashboard filters
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
+ * Registry of built-in presets
22
+ * Can be extended by consumers
23
+ */
24
+ export declare class PresetEngine {
25
+ private presets;
26
+ constructor();
27
+ /**
28
+ * Register a custom preset
29
+ */
30
+ register(key: string, preset: RangePreset): void;
31
+ /**
32
+ * Resolve a preset to date range
33
+ */
34
+ resolve(key: string, now?: Date): PresetRange | null;
35
+ /**
36
+ * Get all available preset keys
37
+ */
38
+ getPresetKeys(): string[];
39
+ /**
40
+ * Register all built-in presets
41
+ */
42
+ private registerBuiltInPresets;
43
+ }
44
+ /**
45
+ * Create a custom preset from a function
46
+ */
47
+ export declare function createPreset(resolver: (now: Date) => {
48
+ start: Date;
49
+ end: Date;
50
+ }): RangePreset;
51
+ /**
52
+ * Singleton preset engine instance
53
+ */
54
+ export declare const presetEngine: PresetEngine;
@@ -0,0 +1,37 @@
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;
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Headless Date Range Store using Angular Signals
3
+ *
4
+ * Architecture:
5
+ * - State lives HERE, not in UI component
6
+ * - Deterministic: no hidden side effects
7
+ * - SSR-compatible: no window/document dependencies
8
+ * - Testable: pure signal-based state
9
+ * - Reusable: inject anywhere (services, components, guards)
10
+ *
11
+ * Usage:
12
+ * ```typescript
13
+ * // In component
14
+ * const rangeStore = inject(DualDateRangeStore);
15
+ * rangeStore.applyPreset('THIS_MONTH');
16
+ *
17
+ * // In service (headless!)
18
+ * const store = inject(DualDateRangeStore);
19
+ * const range = store.range();
20
+ * this.http.get(`/api/sales?start=${range.start}&end=${range.end}`);
21
+ * ```
22
+ */
23
+ import { Injectable, signal, computed } from '@angular/core';
24
+ import { validateRangeOrder, validateRangeBounds, isDateDisabled, applyBounds, parseISODate, formatISODate } from './range.validator';
25
+ import { presetEngine } from './preset.engine';
26
+ import * as i0 from "@angular/core";
27
+ export class DualDateRangeStore {
28
+ // Configuration
29
+ config = signal({
30
+ enableTimePicker: false,
31
+ defaultStartTime: '00:00',
32
+ defaultEndTime: '23:59'
33
+ });
34
+ // Core state - using signals
35
+ _startDate = signal(null);
36
+ _endDate = signal(null);
37
+ _leftMonth = signal(new Date());
38
+ _rightMonth = signal(this.getNextMonth(new Date()));
39
+ _selectingStart = signal(true);
40
+ // Time state
41
+ _startTime = signal('00:00');
42
+ _endTime = signal('23:59');
43
+ // Pending state for requireApply mode
44
+ _pendingStart = signal(null);
45
+ _pendingEnd = signal(null);
46
+ _hasPendingChanges = signal(false);
47
+ // Public read-only signals
48
+ startDate = this._startDate.asReadonly();
49
+ endDate = this._endDate.asReadonly();
50
+ leftMonth = this._leftMonth.asReadonly();
51
+ rightMonth = this._rightMonth.asReadonly();
52
+ selectingStart = this._selectingStart.asReadonly();
53
+ startTime = this._startTime.asReadonly();
54
+ endTime = this._endTime.asReadonly();
55
+ hasPendingChanges = this._hasPendingChanges.asReadonly();
56
+ // Computed: ISO range for API consumption
57
+ range = computed(() => {
58
+ const start = this._startDate();
59
+ const end = this._endDate();
60
+ const cfg = this.config();
61
+ const result = {
62
+ start: formatISODate(start),
63
+ end: formatISODate(end)
64
+ };
65
+ if (cfg.enableTimePicker) {
66
+ result.startTime = this._startTime();
67
+ result.endTime = this._endTime();
68
+ }
69
+ return result;
70
+ });
71
+ // Computed: validation state
72
+ isValid = computed(() => {
73
+ const start = this._startDate();
74
+ const end = this._endDate();
75
+ const cfg = this.config();
76
+ const orderValidation = validateRangeOrder(start, end);
77
+ if (!orderValidation.valid)
78
+ return false;
79
+ const boundsValidation = validateRangeBounds(start, end, cfg.minDate, cfg.maxDate);
80
+ return boundsValidation.valid;
81
+ });
82
+ // Computed: range text for display
83
+ rangeText = computed(() => {
84
+ const start = this._startDate();
85
+ const end = this._endDate();
86
+ if (!start && !end)
87
+ return '';
88
+ if (!start)
89
+ return `? - ${this.formatDateShort(end)}`;
90
+ if (!end)
91
+ return `${this.formatDateShort(start)}`;
92
+ return `${this.formatDateShort(start)} - ${this.formatDateShort(end)}`;
93
+ });
94
+ /**
95
+ * Configure the store
96
+ */
97
+ configure(config) {
98
+ this.config.update(current => ({ ...current, ...config }));
99
+ }
100
+ /**
101
+ * Set start date (with validation)
102
+ */
103
+ setStart(date) {
104
+ const parsedDate = this.parseDate(date);
105
+ if (parsedDate) {
106
+ const cfg = this.config();
107
+ // Apply bounds
108
+ const boundedDate = applyBounds(parsedDate, cfg.minDate, cfg.maxDate);
109
+ // Check if disabled
110
+ if (isDateDisabled(boundedDate, cfg.disabledDates)) {
111
+ console.warn('Cannot select disabled date');
112
+ return;
113
+ }
114
+ this._startDate.set(boundedDate);
115
+ this._selectingStart.set(false);
116
+ // Auto-adjust end if it becomes invalid
117
+ const end = this._endDate();
118
+ if (end && end < boundedDate) {
119
+ this._endDate.set(null);
120
+ }
121
+ }
122
+ else {
123
+ this._startDate.set(null);
124
+ }
125
+ }
126
+ /**
127
+ * Set end date (with validation)
128
+ */
129
+ setEnd(date) {
130
+ const parsedDate = this.parseDate(date);
131
+ if (parsedDate) {
132
+ const cfg = this.config();
133
+ // Apply bounds
134
+ const boundedDate = applyBounds(parsedDate, cfg.minDate, cfg.maxDate);
135
+ // Check if disabled
136
+ if (isDateDisabled(boundedDate, cfg.disabledDates)) {
137
+ console.warn('Cannot select disabled date');
138
+ return;
139
+ }
140
+ // Validate order
141
+ const start = this._startDate();
142
+ if (start && boundedDate < start) {
143
+ console.warn('End date cannot be before start date');
144
+ return;
145
+ }
146
+ this._endDate.set(boundedDate);
147
+ this._selectingStart.set(true); // Ready for next selection
148
+ }
149
+ else {
150
+ this._endDate.set(null);
151
+ }
152
+ }
153
+ /**
154
+ * Set complete range at once
155
+ */
156
+ setRange(start, end) {
157
+ this.setStart(start);
158
+ this.setEnd(end);
159
+ }
160
+ /**
161
+ * Set pending selection (for requireApply mode)
162
+ */
163
+ setPendingStart(date) {
164
+ const parsedDate = this.parseDate(date);
165
+ this._pendingStart.set(parsedDate);
166
+ this._hasPendingChanges.set(true);
167
+ }
168
+ setPendingEnd(date) {
169
+ const parsedDate = this.parseDate(date);
170
+ this._pendingEnd.set(parsedDate);
171
+ this._hasPendingChanges.set(true);
172
+ }
173
+ /**
174
+ * Apply pending changes
175
+ */
176
+ applyPending() {
177
+ const pendingStart = this._pendingStart();
178
+ const pendingEnd = this._pendingEnd();
179
+ if (pendingStart)
180
+ this.setStart(pendingStart);
181
+ if (pendingEnd)
182
+ this.setEnd(pendingEnd);
183
+ this.clearPending();
184
+ }
185
+ /**
186
+ * Cancel pending changes
187
+ */
188
+ cancelPending() {
189
+ this.clearPending();
190
+ }
191
+ clearPending() {
192
+ this._pendingStart.set(null);
193
+ this._pendingEnd.set(null);
194
+ this._hasPendingChanges.set(false);
195
+ }
196
+ /**
197
+ * Reset to empty state
198
+ */
199
+ reset() {
200
+ this._startDate.set(null);
201
+ this._endDate.set(null);
202
+ this._selectingStart.set(true);
203
+ this.clearPending();
204
+ }
205
+ /**
206
+ * Apply a preset by key
207
+ */
208
+ applyPreset(presetKey, now = new Date()) {
209
+ const range = presetEngine.resolve(presetKey, now);
210
+ if (range) {
211
+ this.setRange(range.start, range.end);
212
+ }
213
+ else {
214
+ console.warn(`Preset "${presetKey}" not found`);
215
+ }
216
+ }
217
+ /**
218
+ * Navigate left calendar month
219
+ */
220
+ setLeftMonth(date) {
221
+ this._leftMonth.set(date);
222
+ // Ensure right month is always after left
223
+ const right = this._rightMonth();
224
+ if (right <= date) {
225
+ this._rightMonth.set(this.getNextMonth(date));
226
+ }
227
+ }
228
+ /**
229
+ * Navigate right calendar month
230
+ */
231
+ setRightMonth(date) {
232
+ this._rightMonth.set(date);
233
+ // Ensure left month is always before right
234
+ const left = this._leftMonth();
235
+ if (left >= date) {
236
+ this._leftMonth.set(this.getPreviousMonth(date));
237
+ }
238
+ }
239
+ /**
240
+ * Set time values
241
+ */
242
+ setStartTime(time) {
243
+ this._startTime.set(time);
244
+ }
245
+ setEndTime(time) {
246
+ this._endTime.set(time);
247
+ }
248
+ /**
249
+ * Get current state as snapshot
250
+ */
251
+ getSnapshot() {
252
+ return this.range();
253
+ }
254
+ /**
255
+ * Load state from snapshot
256
+ */
257
+ loadSnapshot(snapshot) {
258
+ this.setRange(snapshot.start, snapshot.end);
259
+ if (snapshot.startTime) {
260
+ this.setStartTime(snapshot.startTime);
261
+ }
262
+ if (snapshot.endTime) {
263
+ this.setEndTime(snapshot.endTime);
264
+ }
265
+ }
266
+ // Helper methods
267
+ parseDate(date) {
268
+ if (!date)
269
+ return null;
270
+ if (date instanceof Date)
271
+ return date;
272
+ return parseISODate(date);
273
+ }
274
+ getNextMonth(date) {
275
+ return new Date(date.getFullYear(), date.getMonth() + 1, 1);
276
+ }
277
+ getPreviousMonth(date) {
278
+ return new Date(date.getFullYear(), date.getMonth() - 1, 1);
279
+ }
280
+ formatDateShort(date) {
281
+ const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
282
+ return `${date.getDate()} ${months[date.getMonth()]}`;
283
+ }
284
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDateRangeStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
285
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDateRangeStore, providedIn: 'root' });
286
+ }
287
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDateRangeStore, decorators: [{
288
+ type: Injectable,
289
+ args: [{
290
+ providedIn: 'root'
291
+ }]
292
+ }] });
293
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHVhbC1kYXRlLXJhbmdlLnN0b3JlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2NvcmUvZHVhbC1kYXRlLXJhbmdlLnN0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFFSCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQWtCLE1BQU0sZUFBZSxDQUFDO0FBQzdFLE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsbUJBQW1CLEVBQ25CLGNBQWMsRUFDZCxXQUFXLEVBQ1gsWUFBWSxFQUNaLGFBQWEsRUFDZCxNQUFNLG1CQUFtQixDQUFDO0FBQzNCLE9BQU8sRUFBRSxZQUFZLEVBQWUsTUFBTSxpQkFBaUIsQ0FBQzs7QUFxQjVELE1BQU0sT0FBTyxrQkFBa0I7SUFDN0IsZ0JBQWdCO0lBQ1IsTUFBTSxHQUFHLE1BQU0sQ0FBa0I7UUFDdkMsZ0JBQWdCLEVBQUUsS0FBSztRQUN2QixnQkFBZ0IsRUFBRSxPQUFPO1FBQ3pCLGNBQWMsRUFBRSxPQUFPO0tBQ3hCLENBQUMsQ0FBQztJQUVILDZCQUE2QjtJQUNyQixVQUFVLEdBQUcsTUFBTSxDQUFjLElBQUksQ0FBQyxDQUFDO0lBQ3ZDLFFBQVEsR0FBRyxNQUFNLENBQWMsSUFBSSxDQUFDLENBQUM7SUFDckMsVUFBVSxHQUFHLE1BQU0sQ0FBTyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUM7SUFDdEMsV0FBVyxHQUFHLE1BQU0sQ0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzFELGVBQWUsR0FBRyxNQUFNLENBQVUsSUFBSSxDQUFDLENBQUM7SUFFaEQsYUFBYTtJQUNMLFVBQVUsR0FBRyxNQUFNLENBQVMsT0FBTyxDQUFDLENBQUM7SUFDckMsUUFBUSxHQUFHLE1BQU0sQ0FBUyxPQUFPLENBQUMsQ0FBQztJQUUzQyxzQ0FBc0M7SUFDOUIsYUFBYSxHQUFHLE1BQU0sQ0FBYyxJQUFJLENBQUMsQ0FBQztJQUMxQyxXQUFXLEdBQUcsTUFBTSxDQUFjLElBQUksQ0FBQyxDQUFDO0lBQ3hDLGtCQUFrQixHQUFHLE1BQU0sQ0FBVSxLQUFLLENBQUMsQ0FBQztJQUVwRCwyQkFBMkI7SUFDbEIsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDekMsT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDckMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDekMsVUFBVSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDM0MsY0FBYyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDbkQsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDekMsT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDckMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFVBQVUsRUFBRSxDQUFDO0lBRWxFLDBDQUEwQztJQUNqQyxLQUFLLEdBQUcsUUFBUSxDQUFpQixHQUFHLEVBQUU7UUFDN0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM1QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFFMUIsTUFBTSxNQUFNLEdBQW1CO1lBQzdCLEtBQUssRUFBRSxhQUFhLENBQUMsS0FBSyxDQUFDO1lBQzNCLEdBQUcsRUFBRSxhQUFhLENBQUMsR0FBRyxDQUFDO1NBQ3hCLENBQUM7UUFFRixJQUFJLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3pCLE1BQU0sQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3JDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ25DLENBQUM7UUFFRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDLENBQUMsQ0FBQztJQUVILDZCQUE2QjtJQUNwQixPQUFPLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtRQUMvQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDaEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQzVCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUUxQixNQUFNLGVBQWUsR0FBRyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDdkQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFFekMsTUFBTSxnQkFBZ0IsR0FBRyxtQkFBbUIsQ0FDMUMsS0FBSyxFQUNMLEdBQUcsRUFDSCxHQUFHLENBQUMsT0FBTyxFQUNYLEdBQUcsQ0FBQyxPQUFPLENBQ1osQ0FBQztRQUNGLE9BQU8sZ0JBQWdCLENBQUMsS0FBSyxDQUFDO0lBQ2hDLENBQUMsQ0FBQyxDQUFDO0lBRUgsbUNBQW1DO0lBQzFCLFNBQVMsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1FBQ2pDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNoQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFNUIsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLEdBQUc7WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsS0FBSztZQUFFLE9BQU8sT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUksQ0FBQyxFQUFFLENBQUM7UUFDdkQsSUFBSSxDQUFDLEdBQUc7WUFBRSxPQUFPLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBRWxELE9BQU8sR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztJQUN6RSxDQUFDLENBQUMsQ0FBQztJQUVIOztPQUVHO0lBQ0gsU0FBUyxDQUFDLE1BQWdDO1FBQ3hDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsT0FBTyxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFFRDs7T0FFRztJQUNILFFBQVEsQ0FBQyxJQUEwQjtRQUNqQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXhDLElBQUksVUFBVSxFQUFFLENBQUM7WUFDZixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFFMUIsZUFBZTtZQUNmLE1BQU0sV0FBVyxHQUFHLFdBQVcsQ0FBQyxVQUFVLEVBQUUsR0FBRyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFdEUsb0JBQW9CO1lBQ3BCLElBQUksY0FBYyxDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztnQkFDbkQsT0FBTyxDQUFDLElBQUksQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO2dCQUM1QyxPQUFPO1lBQ1QsQ0FBQztZQUVELElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBRWhDLHdDQUF3QztZQUN4QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDNUIsSUFBSSxHQUFHLElBQUksR0FBRyxHQUFHLFdBQVcsRUFBRSxDQUFDO2dCQUM3QixJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMxQixDQUFDO1FBQ0gsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1QixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsTUFBTSxDQUFDLElBQTBCO1FBQy9CLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFeEMsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUUxQixlQUFlO1lBQ2YsTUFBTSxXQUFXLEdBQUcsV0FBVyxDQUFDLFVBQVUsRUFBRSxHQUFHLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUV0RSxvQkFBb0I7WUFDcEIsSUFBSSxjQUFjLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO2dCQUNuRCxPQUFPLENBQUMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUM7Z0JBQzVDLE9BQU87WUFDVCxDQUFDO1lBRUQsaUJBQWlCO1lBQ2pCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNoQyxJQUFJLEtBQUssSUFBSSxXQUFXLEdBQUcsS0FBSyxFQUFFLENBQUM7Z0JBQ2pDLE9BQU8sQ0FBQyxJQUFJLENBQUMsc0NBQXNDLENBQUMsQ0FBQztnQkFDckQsT0FBTztZQUNULENBQUM7WUFFRCxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUMvQixJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLDJCQUEyQjtRQUM3RCxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzFCLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxRQUFRLENBQUMsS0FBMkIsRUFBRSxHQUF5QjtRQUM3RCxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3JCLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsZUFBZSxDQUFDLElBQTBCO1FBQ3hDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQsYUFBYSxDQUFDLElBQTBCO1FBQ3RDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDakMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxZQUFZO1FBQ1YsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzFDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUV0QyxJQUFJLFlBQVk7WUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzlDLElBQUksVUFBVTtZQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFeEMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFRDs7T0FFRztJQUNILGFBQWE7UUFDWCxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVPLFlBQVk7UUFDbEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDN0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDM0IsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLO1FBQ0gsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDMUIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDeEIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFRDs7T0FFRztJQUNILFdBQVcsQ0FBQyxTQUFpQixFQUFFLE1BQVksSUFBSSxJQUFJLEVBQUU7UUFDbkQsTUFBTSxLQUFLLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFFbkQsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNWLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDeEMsQ0FBQzthQUFNLENBQUM7WUFDTixPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsU0FBUyxhQUFhLENBQUMsQ0FBQztRQUNsRCxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsWUFBWSxDQUFDLElBQVU7UUFDckIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFMUIsMENBQTBDO1FBQzFDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNqQyxJQUFJLEtBQUssSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNsQixJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDaEQsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILGFBQWEsQ0FBQyxJQUFVO1FBQ3RCLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTNCLDJDQUEyQztRQUMzQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDL0IsSUFBSSxJQUFJLElBQUksSUFBSSxFQUFFLENBQUM7WUFDakIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDbkQsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILFlBQVksQ0FBQyxJQUFZO1FBQ3ZCLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVCLENBQUM7SUFFRCxVQUFVLENBQUMsSUFBWTtRQUNyQixJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxXQUFXO1FBQ1QsT0FBTyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsWUFBWSxDQUFDLFFBQXdCO1FBQ25DLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFNUMsSUFBSSxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDeEMsQ0FBQztRQUVELElBQUksUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3BDLENBQUM7SUFDSCxDQUFDO0lBRUQsaUJBQWlCO0lBQ1QsU0FBUyxDQUFDLElBQTBCO1FBQzFDLElBQUksQ0FBQyxJQUFJO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDdkIsSUFBSSxJQUFJLFlBQVksSUFBSTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ3RDLE9BQU8sWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVCLENBQUM7SUFFTyxZQUFZLENBQUMsSUFBVTtRQUM3QixPQUFPLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzlELENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxJQUFVO1FBQ2pDLE9BQU8sSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLElBQUksQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVPLGVBQWUsQ0FBQyxJQUFVO1FBQ2hDLE1BQU0sTUFBTSxHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNwRyxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ3hELENBQUM7d0dBOVNVLGtCQUFrQjs0R0FBbEIsa0JBQWtCLGNBRmpCLE1BQU07OzRGQUVQLGtCQUFrQjtrQkFIOUIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEhlYWRsZXNzIERhdGUgUmFuZ2UgU3RvcmUgdXNpbmcgQW5ndWxhciBTaWduYWxzXG4gKiBcbiAqIEFyY2hpdGVjdHVyZTpcbiAqIC0gU3RhdGUgbGl2ZXMgSEVSRSwgbm90IGluIFVJIGNvbXBvbmVudFxuICogLSBEZXRlcm1pbmlzdGljOiBubyBoaWRkZW4gc2lkZSBlZmZlY3RzXG4gKiAtIFNTUi1jb21wYXRpYmxlOiBubyB3aW5kb3cvZG9jdW1lbnQgZGVwZW5kZW5jaWVzXG4gKiAtIFRlc3RhYmxlOiBwdXJlIHNpZ25hbC1iYXNlZCBzdGF0ZVxuICogLSBSZXVzYWJsZTogaW5qZWN0IGFueXdoZXJlIChzZXJ2aWNlcywgY29tcG9uZW50cywgZ3VhcmRzKVxuICogXG4gKiBVc2FnZTpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluIGNvbXBvbmVudFxuICogY29uc3QgcmFuZ2VTdG9yZSA9IGluamVjdChEdWFsRGF0ZVJhbmdlU3RvcmUpO1xuICogcmFuZ2VTdG9yZS5hcHBseVByZXNldCgnVEhJU19NT05USCcpO1xuICogXG4gKiAvLyBJbiBzZXJ2aWNlIChoZWFkbGVzcyEpXG4gKiBjb25zdCBzdG9yZSA9IGluamVjdChEdWFsRGF0ZVJhbmdlU3RvcmUpO1xuICogY29uc3QgcmFuZ2UgPSBzdG9yZS5yYW5nZSgpO1xuICogdGhpcy5odHRwLmdldChgL2FwaS9zYWxlcz9zdGFydD0ke3JhbmdlLnN0YXJ0fSZlbmQ9JHtyYW5nZS5lbmR9YCk7XG4gKiBgYGBcbiAqL1xuXG5pbXBvcnQgeyBJbmplY3RhYmxlLCBzaWduYWwsIGNvbXB1dGVkLCBlZmZlY3QsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgXG4gIHZhbGlkYXRlUmFuZ2VPcmRlciwgXG4gIHZhbGlkYXRlUmFuZ2VCb3VuZHMsIFxuICBpc0RhdGVEaXNhYmxlZCxcbiAgYXBwbHlCb3VuZHMsXG4gIHBhcnNlSVNPRGF0ZSxcbiAgZm9ybWF0SVNPRGF0ZVxufSBmcm9tICcuL3JhbmdlLnZhbGlkYXRvcic7XG5pbXBvcnQgeyBwcmVzZXRFbmdpbmUsIFByZXNldFJhbmdlIH0gZnJvbSAnLi9wcmVzZXQuZW5naW5lJztcblxuZXhwb3J0IGludGVyZmFjZSBEYXRlUmFuZ2VTdGF0ZSB7XG4gIHN0YXJ0OiBzdHJpbmc7IC8vIElTTyBkYXRlXG4gIGVuZDogc3RyaW5nOyAvLyBJU08gZGF0ZVxuICBzdGFydFRpbWU/OiBzdHJpbmc7IC8vIEhIOm1tXG4gIGVuZFRpbWU/OiBzdHJpbmc7IC8vIEhIOm1tXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGF0ZVJhbmdlQ29uZmlnIHtcbiAgbWluRGF0ZT86IERhdGU7XG4gIG1heERhdGU/OiBEYXRlO1xuICBkaXNhYmxlZERhdGVzPzogRGF0ZVtdIHwgKChkYXRlOiBEYXRlKSA9PiBib29sZWFuKTtcbiAgZW5hYmxlVGltZVBpY2tlcj86IGJvb2xlYW47XG4gIGRlZmF1bHRTdGFydFRpbWU/OiBzdHJpbmc7XG4gIGRlZmF1bHRFbmRUaW1lPzogc3RyaW5nO1xufVxuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBEdWFsRGF0ZVJhbmdlU3RvcmUge1xuICAvLyBDb25maWd1cmF0aW9uXG4gIHByaXZhdGUgY29uZmlnID0gc2lnbmFsPERhdGVSYW5nZUNvbmZpZz4oe1xuICAgIGVuYWJsZVRpbWVQaWNrZXI6IGZhbHNlLFxuICAgIGRlZmF1bHRTdGFydFRpbWU6ICcwMDowMCcsXG4gICAgZGVmYXVsdEVuZFRpbWU6ICcyMzo1OSdcbiAgfSk7XG5cbiAgLy8gQ29yZSBzdGF0ZSAtIHVzaW5nIHNpZ25hbHNcbiAgcHJpdmF0ZSBfc3RhcnREYXRlID0gc2lnbmFsPERhdGUgfCBudWxsPihudWxsKTtcbiAgcHJpdmF0ZSBfZW5kRGF0ZSA9IHNpZ25hbDxEYXRlIHwgbnVsbD4obnVsbCk7XG4gIHByaXZhdGUgX2xlZnRNb250aCA9IHNpZ25hbDxEYXRlPihuZXcgRGF0ZSgpKTtcbiAgcHJpdmF0ZSBfcmlnaHRNb250aCA9IHNpZ25hbDxEYXRlPih0aGlzLmdldE5leHRNb250aChuZXcgRGF0ZSgpKSk7XG4gIHByaXZhdGUgX3NlbGVjdGluZ1N0YXJ0ID0gc2lnbmFsPGJvb2xlYW4+KHRydWUpO1xuXG4gIC8vIFRpbWUgc3RhdGVcbiAgcHJpdmF0ZSBfc3RhcnRUaW1lID0gc2lnbmFsPHN0cmluZz4oJzAwOjAwJyk7XG4gIHByaXZhdGUgX2VuZFRpbWUgPSBzaWduYWw8c3RyaW5nPignMjM6NTknKTtcblxuICAvLyBQZW5kaW5nIHN0YXRlIGZvciByZXF1aXJlQXBwbHkgbW9kZVxuICBwcml2YXRlIF9wZW5kaW5nU3RhcnQgPSBzaWduYWw8RGF0ZSB8IG51bGw+KG51bGwpO1xuICBwcml2YXRlIF9wZW5kaW5nRW5kID0gc2lnbmFsPERhdGUgfCBudWxsPihudWxsKTtcbiAgcHJpdmF0ZSBfaGFzUGVuZGluZ0NoYW5nZXMgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gIC8vIFB1YmxpYyByZWFkLW9ubHkgc2lnbmFsc1xuICByZWFkb25seSBzdGFydERhdGUgPSB0aGlzLl9zdGFydERhdGUuYXNSZWFkb25seSgpO1xuICByZWFkb25seSBlbmREYXRlID0gdGhpcy5fZW5kRGF0ZS5hc1JlYWRvbmx5KCk7XG4gIHJlYWRvbmx5IGxlZnRNb250aCA9IHRoaXMuX2xlZnRNb250aC5hc1JlYWRvbmx5KCk7XG4gIHJlYWRvbmx5IHJpZ2h0TW9udGggPSB0aGlzLl9yaWdodE1vbnRoLmFzUmVhZG9ubHkoKTtcbiAgcmVhZG9ubHkgc2VsZWN0aW5nU3RhcnQgPSB0aGlzLl9zZWxlY3RpbmdTdGFydC5hc1JlYWRvbmx5KCk7XG4gIHJlYWRvbmx5IHN0YXJ0VGltZSA9IHRoaXMuX3N0YXJ0VGltZS5hc1JlYWRvbmx5KCk7XG4gIHJlYWRvbmx5IGVuZFRpbWUgPSB0aGlzLl9lbmRUaW1lLmFzUmVhZG9ubHkoKTtcbiAgcmVhZG9ubHkgaGFzUGVuZGluZ0NoYW5nZXMgPSB0aGlzLl9oYXNQZW5kaW5nQ2hhbmdlcy5hc1JlYWRvbmx5KCk7XG5cbiAgLy8gQ29tcHV0ZWQ6IElTTyByYW5nZSBmb3IgQVBJIGNvbnN1bXB0aW9uXG4gIHJlYWRvbmx5IHJhbmdlID0gY29tcHV0ZWQ8RGF0ZVJhbmdlU3RhdGU+KCgpID0+IHtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuX3N0YXJ0RGF0ZSgpO1xuICAgIGNvbnN0IGVuZCA9IHRoaXMuX2VuZERhdGUoKTtcbiAgICBjb25zdCBjZmcgPSB0aGlzLmNvbmZpZygpO1xuXG4gICAgY29uc3QgcmVzdWx0OiBEYXRlUmFuZ2VTdGF0ZSA9IHtcbiAgICAgIHN0YXJ0OiBmb3JtYXRJU09EYXRlKHN0YXJ0KSxcbiAgICAgIGVuZDogZm9ybWF0SVNPRGF0ZShlbmQpXG4gICAgfTtcblxuICAgIGlmIChjZmcuZW5hYmxlVGltZVBpY2tlcikge1xuICAgICAgcmVzdWx0LnN0YXJ0VGltZSA9IHRoaXMuX3N0YXJ0VGltZSgpO1xuICAgICAgcmVzdWx0LmVuZFRpbWUgPSB0aGlzLl9lbmRUaW1lKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSk7XG5cbiAgLy8gQ29tcHV0ZWQ6IHZhbGlkYXRpb24gc3RhdGVcbiAgcmVhZG9ubHkgaXNWYWxpZCA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuX3N0YXJ0RGF0ZSgpO1xuICAgIGNvbnN0IGVuZCA9IHRoaXMuX2VuZERhdGUoKTtcbiAgICBjb25zdCBjZmcgPSB0aGlzLmNvbmZpZygpO1xuXG4gICAgY29uc3Qgb3JkZXJWYWxpZGF0aW9uID0gdmFsaWRhdGVSYW5nZU9yZGVyKHN0YXJ0LCBlbmQpO1xuICAgIGlmICghb3JkZXJWYWxpZGF0aW9uLnZhbGlkKSByZXR1cm4gZmFsc2U7XG5cbiAgICBjb25zdCBib3VuZHNWYWxpZGF0aW9uID0gdmFsaWRhdGVSYW5nZUJvdW5kcyhcbiAgICAgIHN0YXJ0LFxuICAgICAgZW5kLFxuICAgICAgY2ZnLm1pbkRhdGUsXG4gICAgICBjZmcubWF4RGF0ZVxuICAgICk7XG4gICAgcmV0dXJuIGJvdW5kc1ZhbGlkYXRpb24udmFsaWQ7XG4gIH0pO1xuXG4gIC8vIENvbXB1dGVkOiByYW5nZSB0ZXh0IGZvciBkaXNwbGF5XG4gIHJlYWRvbmx5IHJhbmdlVGV4dCA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuX3N0YXJ0RGF0ZSgpO1xuICAgIGNvbnN0IGVuZCA9IHRoaXMuX2VuZERhdGUoKTtcblxuICAgIGlmICghc3RhcnQgJiYgIWVuZCkgcmV0dXJuICcnO1xuICAgIGlmICghc3RhcnQpIHJldHVybiBgPyAtICR7dGhpcy5mb3JtYXREYXRlU2hvcnQoZW5kISl9YDtcbiAgICBpZiAoIWVuZCkgcmV0dXJuIGAke3RoaXMuZm9ybWF0RGF0ZVNob3J0KHN0YXJ0KX1gO1xuXG4gICAgcmV0dXJuIGAke3RoaXMuZm9ybWF0RGF0ZVNob3J0KHN0YXJ0KX0gLSAke3RoaXMuZm9ybWF0RGF0ZVNob3J0KGVuZCl9YDtcbiAgfSk7XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZSB0aGUgc3RvcmVcbiAgICovXG4gIGNvbmZpZ3VyZShjb25maWc6IFBhcnRpYWw8RGF0ZVJhbmdlQ29uZmlnPik6IHZvaWQge1xuICAgIHRoaXMuY29uZmlnLnVwZGF0ZShjdXJyZW50ID0+ICh7IC4uLmN1cnJlbnQsIC4uLmNvbmZpZyB9KSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHN0YXJ0IGRhdGUgKHdpdGggdmFsaWRhdGlvbilcbiAgICovXG4gIHNldFN0YXJ0KGRhdGU6IERhdGUgfCBzdHJpbmcgfCBudWxsKTogdm9pZCB7XG4gICAgY29uc3QgcGFyc2VkRGF0ZSA9IHRoaXMucGFyc2VEYXRlKGRhdGUpO1xuICAgIFxuICAgIGlmIChwYXJzZWREYXRlKSB7XG4gICAgICBjb25zdCBjZmcgPSB0aGlzLmNvbmZpZygpO1xuICAgICAgXG4gICAgICAvLyBBcHBseSBib3VuZHNcbiAgICAgIGNvbnN0IGJvdW5kZWREYXRlID0gYXBwbHlCb3VuZHMocGFyc2VkRGF0ZSwgY2ZnLm1pbkRhdGUsIGNmZy5tYXhEYXRlKTtcbiAgICAgIFxuICAgICAgLy8gQ2hlY2sgaWYgZGlzYWJsZWRcbiAgICAgIGlmIChpc0RhdGVEaXNhYmxlZChib3VuZGVkRGF0ZSwgY2ZnLmRpc2FibGVkRGF0ZXMpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQ2Fubm90IHNlbGVjdCBkaXNhYmxlZCBkYXRlJyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fc3RhcnREYXRlLnNldChib3VuZGVkRGF0ZSk7XG4gICAgICB0aGlzLl9zZWxlY3RpbmdTdGFydC5zZXQoZmFsc2UpO1xuXG4gICAgICAvLyBBdXRvLWFkanVzdCBlbmQgaWYgaXQgYmVjb21lcyBpbnZhbGlkXG4gICAgICBjb25zdCBlbmQgPSB0aGlzLl9lbmREYXRlKCk7XG4gICAgICBpZiAoZW5kICYmIGVuZCA8IGJvdW5kZWREYXRlKSB7XG4gICAgICAgIHRoaXMuX2VuZERhdGUuc2V0KG51bGwpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9zdGFydERhdGUuc2V0KG51bGwpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgZW5kIGRhdGUgKHdpdGggdmFsaWRhdGlvbilcbiAgICovXG4gIHNldEVuZChkYXRlOiBEYXRlIHwgc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIGNvbnN0IHBhcnNlZERhdGUgPSB0aGlzLnBhcnNlRGF0ZShkYXRlKTtcbiAgICBcbiAgICBpZiAocGFyc2VkRGF0ZSkge1xuICAgICAgY29uc3QgY2ZnID0gdGhpcy5jb25maWcoKTtcbiAgICAgIFxuICAgICAgLy8gQXBwbHkgYm91bmRzXG4gICAgICBjb25zdCBib3VuZGVkRGF0ZSA9IGFwcGx5Qm91bmRzKHBhcnNlZERhdGUsIGNmZy5taW5EYXRlLCBjZmcubWF4RGF0ZSk7XG4gICAgICBcbiAgICAgIC8vIENoZWNrIGlmIGRpc2FibGVkXG4gICAgICBpZiAoaXNEYXRlRGlzYWJsZWQoYm91bmRlZERhdGUsIGNmZy5kaXNhYmxlZERhdGVzKSkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0Nhbm5vdCBzZWxlY3QgZGlzYWJsZWQgZGF0ZScpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIFZhbGlkYXRlIG9yZGVyXG4gICAgICBjb25zdCBzdGFydCA9IHRoaXMuX3N0YXJ0RGF0ZSgpO1xuICAgICAgaWYgKHN0YXJ0ICYmIGJvdW5kZWREYXRlIDwgc3RhcnQpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdFbmQgZGF0ZSBjYW5ub3QgYmUgYmVmb3JlIHN0YXJ0IGRhdGUnKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9lbmREYXRlLnNldChib3VuZGVkRGF0ZSk7XG4gICAgICB0aGlzLl9zZWxlY3RpbmdTdGFydC5zZXQodHJ1ZSk7IC8vIFJlYWR5IGZvciBuZXh0IHNlbGVjdGlvblxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9lbmREYXRlLnNldChudWxsKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0IGNvbXBsZXRlIHJhbmdlIGF0IG9uY2VcbiAgICovXG4gIHNldFJhbmdlKHN0YXJ0OiBEYXRlIHwgc3RyaW5nIHwgbnVsbCwgZW5kOiBEYXRlIHwgc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMuc2V0U3RhcnQoc3RhcnQpO1xuICAgIHRoaXMuc2V0RW5kKGVuZCk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHBlbmRpbmcgc2VsZWN0aW9uIChmb3IgcmVxdWlyZUFwcGx5IG1vZGUpXG4gICAqL1xuICBzZXRQZW5kaW5nU3RhcnQoZGF0ZTogRGF0ZSB8IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcbiAgICBjb25zdCBwYXJzZWREYXRlID0gdGhpcy5wYXJzZURhdGUoZGF0ZSk7XG4gICAgdGhpcy5fcGVuZGluZ1N0YXJ0LnNldChwYXJzZWREYXRlKTtcbiAgICB0aGlzLl9oYXNQZW5kaW5nQ2hhbmdlcy5zZXQodHJ1ZSk7XG4gIH1cblxuICBzZXRQZW5kaW5nRW5kKGRhdGU6IERhdGUgfCBzdHJpbmcgfCBudWxsKTogdm9pZCB7XG4gICAgY29uc3QgcGFyc2VkRGF0ZSA9IHRoaXMucGFyc2VEYXRlKGRhdGUpO1xuICAgIHRoaXMuX3BlbmRpbmdFbmQuc2V0KHBhcnNlZERhdGUpO1xuICAgIHRoaXMuX2hhc1BlbmRpbmdDaGFuZ2VzLnNldCh0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBseSBwZW5kaW5nIGNoYW5nZXNcbiAgICovXG4gIGFwcGx5UGVuZGluZygpOiB2b2lkIHtcbiAgICBjb25zdCBwZW5kaW5nU3RhcnQgPSB0aGlzLl9wZW5kaW5nU3RhcnQoKTtcbiAgICBjb25zdCBwZW5kaW5nRW5kID0gdGhpcy5fcGVuZGluZ0VuZCgpO1xuXG4gICAgaWYgKHBlbmRpbmdTdGFydCkgdGhpcy5zZXRTdGFydChwZW5kaW5nU3RhcnQpO1xuICAgIGlmIChwZW5kaW5nRW5kKSB0aGlzLnNldEVuZChwZW5kaW5nRW5kKTtcblxuICAgIHRoaXMuY2xlYXJQZW5kaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2FuY2VsIHBlbmRpbmcgY2hhbmdlc1xuICAgKi9cbiAgY2FuY2VsUGVuZGluZygpOiB2b2lkIHtcbiAgICB0aGlzLmNsZWFyUGVuZGluZygpO1xuICB9XG5cbiAgcHJpdmF0ZSBjbGVhclBlbmRpbmcoKTogdm9pZCB7XG4gICAgdGhpcy5fcGVuZGluZ1N0YXJ0LnNldChudWxsKTtcbiAgICB0aGlzLl9wZW5kaW5nRW5kLnNldChudWxsKTtcbiAgICB0aGlzLl9oYXNQZW5kaW5nQ2hhbmdlcy5zZXQoZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRvIGVtcHR5IHN0YXRlXG4gICAqL1xuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLl9zdGFydERhdGUuc2V0KG51bGwpO1xuICAgIHRoaXMuX2VuZERhdGUuc2V0KG51bGwpO1xuICAgIHRoaXMuX3NlbGVjdGluZ1N0YXJ0LnNldCh0cnVlKTtcbiAgICB0aGlzLmNsZWFyUGVuZGluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGx5IGEgcHJlc2V0IGJ5IGtleVxuICAgKi9cbiAgYXBwbHlQcmVzZXQocHJlc2V0S2V5OiBzdHJpbmcsIG5vdzogRGF0ZSA9IG5ldyBEYXRlKCkpOiB2b2lkIHtcbiAgICBjb25zdCByYW5nZSA9IHByZXNldEVuZ2luZS5yZXNvbHZlKHByZXNldEtleSwgbm93KTtcbiAgICBcbiAgICBpZiAocmFuZ2UpIHtcbiAgICAgIHRoaXMuc2V0UmFuZ2UocmFuZ2Uuc3RhcnQsIHJhbmdlLmVuZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUud2FybihgUHJlc2V0IFwiJHtwcmVzZXRLZXl9XCIgbm90IGZvdW5kYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE5hdmlnYXRlIGxlZnQgY2FsZW5kYXIgbW9udGhcbiAgICovXG4gIHNldExlZnRNb250aChkYXRlOiBEYXRlKTogdm9pZCB7XG4gICAgdGhpcy5fbGVmdE1vbnRoLnNldChkYXRlKTtcbiAgICBcbiAgICAvLyBFbnN1cmUgcmlnaHQgbW9udGggaXMgYWx3YXlzIGFmdGVyIGxlZnRcbiAgICBjb25zdCByaWdodCA9IHRoaXMuX3JpZ2h0TW9udGgoKTtcbiAgICBpZiAocmlnaHQgPD0gZGF0ZSkge1xuICAgICAgdGhpcy5fcmlnaHRNb250aC5zZXQodGhpcy5nZXROZXh0TW9udGgoZGF0ZSkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBOYXZpZ2F0ZSByaWdodCBjYWxlbmRhciBtb250aFxuICAgKi9cbiAgc2V0UmlnaHRNb250aChkYXRlOiBEYXRlKTogdm9pZCB7XG4gICAgdGhpcy5fcmlnaHRNb250aC5zZXQoZGF0ZSk7XG4gICAgXG4gICAgLy8gRW5zdXJlIGxlZnQgbW9udGggaXMgYWx3YXlzIGJlZm9yZSByaWdodFxuICAgIGNvbnN0IGxlZnQgPSB0aGlzLl9sZWZ0TW9udGgoKTtcbiAgICBpZiAobGVmdCA+PSBkYXRlKSB7XG4gICAgICB0aGlzLl9sZWZ0TW9udGguc2V0KHRoaXMuZ2V0UHJldmlvdXNNb250aChkYXRlKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aW1lIHZhbHVlc1xuICAgKi9cbiAgc2V0U3RhcnRUaW1lKHRpbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuX3N0YXJ0VGltZS5zZXQodGltZSk7XG4gIH1cblxuICBzZXRFbmRUaW1lKHRpbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuX2VuZFRpbWUuc2V0KHRpbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IHN0YXRlIGFzIHNuYXBzaG90XG4gICAqL1xuICBnZXRTbmFwc2hvdCgpOiBEYXRlUmFuZ2VTdGF0ZSB7XG4gICAgcmV0dXJuIHRoaXMucmFuZ2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkIHN0YXRlIGZyb20gc25hcHNob3RcbiAgICovXG4gIGxvYWRTbmFwc2hvdChzbmFwc2hvdDogRGF0ZVJhbmdlU3RhdGUpOiB2b2lkIHtcbiAgICB0aGlzLnNldFJhbmdlKHNuYXBzaG90LnN0YXJ0LCBzbmFwc2hvdC5lbmQpO1xuICAgIFxuICAgIGlmIChzbmFwc2hvdC5zdGFydFRpbWUpIHtcbiAgICAgIHRoaXMuc2V0U3RhcnRUaW1lKHNuYXBzaG90LnN0YXJ0VGltZSk7XG4gICAgfVxuICAgIFxuICAgIGlmIChzbmFwc2hvdC5lbmRUaW1lKSB7XG4gICAgICB0aGlzLnNldEVuZFRpbWUoc25hcHNob3QuZW5kVGltZSk7XG4gICAgfVxuICB9XG5cbiAgLy8gSGVscGVyIG1ldGhvZHNcbiAgcHJpdmF0ZSBwYXJzZURhdGUoZGF0ZTogRGF0ZSB8IHN0cmluZyB8IG51bGwpOiBEYXRlIHwgbnVsbCB7XG4gICAgaWYgKCFkYXRlKSByZXR1cm4gbnVsbDtcbiAgICBpZiAoZGF0ZSBpbnN0YW5jZW9mIERhdGUpIHJldHVybiBkYXRlO1xuICAgIHJldHVybiBwYXJzZUlTT0RhdGUoZGF0ZSk7XG4gIH1cblxuICBwcml2YXRlIGdldE5leHRNb250aChkYXRlOiBEYXRlKTogRGF0ZSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKGRhdGUuZ2V0RnVsbFllYXIoKSwgZGF0ZS5nZXRNb250aCgpICsgMSwgMSk7XG4gIH1cblxuICBwcml2YXRlIGdldFByZXZpb3VzTW9udGgoZGF0ZTogRGF0ZSk6IERhdGUge1xuICAgIHJldHVybiBuZXcgRGF0ZShkYXRlLmdldEZ1bGxZZWFyKCksIGRhdGUuZ2V0TW9udGgoKSAtIDEsIDEpO1xuICB9XG5cbiAgcHJpdmF0ZSBmb3JtYXREYXRlU2hvcnQoZGF0ZTogRGF0ZSk6IHN0cmluZyB7XG4gICAgY29uc3QgbW9udGhzID0gWydKYW4nLCAnRmViJywgJ01hcicsICdBcHInLCAnTWF5JywgJ0p1bicsICdKdWwnLCAnQXVnJywgJ1NlcCcsICdPY3QnLCAnTm92JywgJ0RlYyddO1xuICAgIHJldHVybiBgJHtkYXRlLmdldERhdGUoKX0gJHttb250aHNbZGF0ZS5nZXRNb250aCgpXX1gO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Core headless date range logic
3
+ * Import from here for clean barrel exports
4
+ */
5
+ export * from './dual-date-range.store';
6
+ export * from './preset.engine';
7
+ export * from './range.validator';
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29yZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyxtQkFBbUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29yZSBoZWFkbGVzcyBkYXRlIHJhbmdlIGxvZ2ljXG4gKiBJbXBvcnQgZnJvbSBoZXJlIGZvciBjbGVhbiBiYXJyZWwgZXhwb3J0c1xuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vZHVhbC1kYXRlLXJhbmdlLnN0b3JlJztcbmV4cG9ydCAqIGZyb20gJy4vcHJlc2V0LmVuZ2luZSc7XG5leHBvcnQgKiBmcm9tICcuL3JhbmdlLnZhbGlkYXRvcic7XG4iXX0=