@oneluiz/dual-datepicker 2.7.0 → 3.0.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,448 @@
1
+ import { Component, Input, Output, EventEmitter, HostListener, forwardRef, signal, computed, effect, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
4
+ import { DATE_ADAPTER } from './date-adapter';
5
+ import { NativeDateAdapter } from './native-date-adapter';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "@angular/common";
8
+ export class DualDatepickerComponent {
9
+ elementRef;
10
+ placeholder = 'Select date range';
11
+ startDate = '';
12
+ endDate = '';
13
+ showPresets = true;
14
+ showClearButton = false;
15
+ multiRange = false;
16
+ closeOnSelection = true;
17
+ closeOnPresetSelection = true;
18
+ closeOnClickOutside = true;
19
+ presets = [];
20
+ inputBackgroundColor = '#fff';
21
+ inputTextColor = '#495057';
22
+ inputBorderColor = '#ced4da';
23
+ inputBorderColorHover = '#ced4da';
24
+ inputBorderColorFocus = '#80bdff';
25
+ inputPadding = '0.375rem 0.75rem';
26
+ locale = {};
27
+ dateRangeChange = new EventEmitter();
28
+ dateRangeSelected = new EventEmitter();
29
+ multiDateRangeChange = new EventEmitter();
30
+ multiDateRangeSelected = new EventEmitter();
31
+ // Date adapter injection
32
+ dateAdapter = inject(DATE_ADAPTER);
33
+ // Signals for reactive state
34
+ showDatePicker = signal(false);
35
+ dateRangeText = signal('');
36
+ selectingStartDate = signal(true);
37
+ currentMonth = signal(this.dateAdapter.today());
38
+ previousMonth = signal(this.dateAdapter.today());
39
+ currentMonthDays = signal([]);
40
+ previousMonthDays = signal([]);
41
+ isDisabled = signal(false);
42
+ // Multi-range support
43
+ selectedRanges = signal([]);
44
+ currentRangeIndex = signal(-1);
45
+ // Computed values
46
+ currentMonthName = computed(() => this.getMonthName(this.currentMonth()));
47
+ previousMonthName = computed(() => this.getMonthName(this.previousMonth()));
48
+ weekDayNames = computed(() => this.getDayNames());
49
+ defaultMonthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
50
+ defaultMonthNamesShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
51
+ defaultDayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
52
+ defaultDayNamesShort = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
53
+ // ControlValueAccessor callbacks
54
+ onChange = () => { };
55
+ onTouched = () => { };
56
+ constructor(elementRef) {
57
+ this.elementRef = elementRef;
58
+ // Effect to emit changes when dates change
59
+ effect(() => {
60
+ const range = this.dateRangeText();
61
+ if (this.startDate || this.endDate) {
62
+ this.onChange(this.getDateRangeValue());
63
+ }
64
+ });
65
+ }
66
+ onClickOutside(event) {
67
+ if (this.showDatePicker() && this.closeOnClickOutside) {
68
+ const clickedInside = this.elementRef.nativeElement.contains(event.target);
69
+ if (!clickedInside) {
70
+ this.closeDatePicker();
71
+ }
72
+ }
73
+ }
74
+ ngOnInit() {
75
+ if (this.startDate && this.endDate) {
76
+ this.updateDateRangeText();
77
+ this.generateCalendars();
78
+ }
79
+ }
80
+ ngOnChanges(changes) {
81
+ if (changes['startDate'] || changes['endDate']) {
82
+ if (this.startDate && this.endDate) {
83
+ this.updateDateRangeText();
84
+ this.generateCalendars();
85
+ }
86
+ else if (!this.startDate && !this.endDate) {
87
+ this.dateRangeText.set('');
88
+ }
89
+ }
90
+ }
91
+ formatDate(date) {
92
+ const year = this.dateAdapter.getYear(date);
93
+ const month = String(this.dateAdapter.getMonth(date) + 1).padStart(2, '0');
94
+ const day = String(this.dateAdapter.getDate(date)).padStart(2, '0');
95
+ return `${year}-${month}-${day}`;
96
+ }
97
+ formatDateDisplay(dateStr) {
98
+ if (!dateStr)
99
+ return '';
100
+ const date = this.dateAdapter.parse(dateStr);
101
+ if (!date)
102
+ return '';
103
+ const monthNames = this.locale.monthNamesShort || this.defaultMonthNamesShort;
104
+ return `${this.dateAdapter.getDate(date)} ${monthNames[this.dateAdapter.getMonth(date)]}`;
105
+ }
106
+ updateDateRangeText() {
107
+ if (this.startDate && this.endDate) {
108
+ const start = this.formatDateDisplay(this.startDate);
109
+ const end = this.formatDateDisplay(this.endDate);
110
+ this.dateRangeText.set(`${start} - ${end}`);
111
+ }
112
+ else {
113
+ this.dateRangeText.set('');
114
+ }
115
+ }
116
+ toggleDatePicker() {
117
+ this.showDatePicker.update(value => !value);
118
+ if (this.showDatePicker()) {
119
+ this.selectingStartDate.set(true);
120
+ const currentMonthValue = this.currentMonth();
121
+ const year = this.dateAdapter.getYear(currentMonthValue);
122
+ const month = this.dateAdapter.getMonth(currentMonthValue);
123
+ const previousMonthDate = this.dateAdapter.createDate(year, month - 1, 1);
124
+ this.previousMonth.set(previousMonthDate);
125
+ this.generateCalendars();
126
+ }
127
+ this.onTouched();
128
+ }
129
+ closeDatePicker() {
130
+ this.showDatePicker.set(false);
131
+ this.onTouched();
132
+ }
133
+ generateCalendars() {
134
+ this.previousMonthDays.set(this.generateMonthCalendar(this.previousMonth()));
135
+ this.currentMonthDays.set(this.generateMonthCalendar(this.currentMonth()));
136
+ }
137
+ generateMonthCalendar(date) {
138
+ const year = this.dateAdapter.getYear(date);
139
+ const month = this.dateAdapter.getMonth(date);
140
+ const firstDay = this.dateAdapter.createDate(year, month, 1);
141
+ const lastDay = this.dateAdapter.createDate(year, month + 1, 0);
142
+ const daysInMonth = this.dateAdapter.getDate(lastDay);
143
+ const firstDayOfWeek = this.dateAdapter.getDay(firstDay);
144
+ const monthDays = [];
145
+ for (let i = 0; i < firstDayOfWeek; i++) {
146
+ monthDays.push({ day: null, isCurrentMonth: false });
147
+ }
148
+ for (let day = 1; day <= daysInMonth; day++) {
149
+ const dayDate = this.dateAdapter.createDate(year, month, day);
150
+ const dateStr = this.formatDate(dayDate);
151
+ monthDays.push({
152
+ day: day,
153
+ date: dateStr,
154
+ isCurrentMonth: true,
155
+ isStart: this.startDate === dateStr,
156
+ isEnd: this.endDate === dateStr,
157
+ inRange: this.isInRange(dateStr)
158
+ });
159
+ }
160
+ return monthDays;
161
+ }
162
+ isInRange(dateStr) {
163
+ if (this.multiRange) {
164
+ // Check if date is in any of the selected ranges
165
+ return this.selectedRanges().some(range => {
166
+ return dateStr >= range.startDate && dateStr <= range.endDate;
167
+ });
168
+ }
169
+ else {
170
+ if (!this.startDate || !this.endDate)
171
+ return false;
172
+ return dateStr >= this.startDate && dateStr <= this.endDate;
173
+ }
174
+ }
175
+ selectDay(dayObj) {
176
+ if (!dayObj.isCurrentMonth || this.isDisabled())
177
+ return;
178
+ if (this.multiRange) {
179
+ // Multi-range mode: add ranges to array
180
+ if (this.selectingStartDate()) {
181
+ this.startDate = dayObj.date;
182
+ this.endDate = '';
183
+ this.dateRangeText.set('');
184
+ this.selectingStartDate.set(false);
185
+ }
186
+ else {
187
+ if (dayObj.date < this.startDate) {
188
+ this.endDate = this.startDate;
189
+ this.startDate = dayObj.date;
190
+ }
191
+ else {
192
+ this.endDate = dayObj.date;
193
+ }
194
+ // Add the new range to the array
195
+ const newRange = {
196
+ startDate: this.startDate,
197
+ endDate: this.endDate,
198
+ rangeText: this.formatDateDisplay(this.startDate) + ' – ' + this.formatDateDisplay(this.endDate)
199
+ };
200
+ const currentRanges = [...this.selectedRanges()];
201
+ currentRanges.push(newRange);
202
+ this.selectedRanges.set(currentRanges);
203
+ // Reset for next range selection
204
+ this.startDate = '';
205
+ this.endDate = '';
206
+ this.selectingStartDate.set(true);
207
+ // Update display text
208
+ this.updateMultiRangeText();
209
+ // Don't close if multiRange, allow adding more ranges
210
+ if (this.closeOnSelection && !this.multiRange) {
211
+ this.showDatePicker.set(false);
212
+ }
213
+ this.emitMultiChange();
214
+ this.emitMultiSelection();
215
+ }
216
+ this.generateCalendars();
217
+ }
218
+ else {
219
+ // Single range mode (original behavior)
220
+ if (this.selectingStartDate()) {
221
+ this.startDate = dayObj.date;
222
+ this.endDate = '';
223
+ this.dateRangeText.set('');
224
+ this.selectingStartDate.set(false);
225
+ this.emitChange();
226
+ }
227
+ else {
228
+ if (dayObj.date < this.startDate) {
229
+ this.endDate = this.startDate;
230
+ this.startDate = dayObj.date;
231
+ }
232
+ else {
233
+ this.endDate = dayObj.date;
234
+ }
235
+ this.updateDateRangeText();
236
+ if (this.closeOnSelection) {
237
+ this.showDatePicker.set(false);
238
+ }
239
+ this.selectingStartDate.set(true);
240
+ this.emitChange();
241
+ this.emitSelection();
242
+ }
243
+ this.generateCalendars();
244
+ }
245
+ }
246
+ changeMonth(direction) {
247
+ const currentMonthValue = this.currentMonth();
248
+ const year = this.dateAdapter.getYear(currentMonthValue);
249
+ const month = this.dateAdapter.getMonth(currentMonthValue);
250
+ const newCurrentMonth = this.dateAdapter.createDate(year, month + direction, 1);
251
+ this.currentMonth.set(newCurrentMonth);
252
+ const newYear = this.dateAdapter.getYear(newCurrentMonth);
253
+ const newMonth = this.dateAdapter.getMonth(newCurrentMonth);
254
+ const newPreviousMonth = this.dateAdapter.createDate(newYear, newMonth - 1, 1);
255
+ this.previousMonth.set(newPreviousMonth);
256
+ this.generateCalendars();
257
+ }
258
+ getMonthName(date) {
259
+ const monthNames = this.locale.monthNames || this.defaultMonthNames;
260
+ return `${monthNames[this.dateAdapter.getMonth(date)]} ${this.dateAdapter.getYear(date)}`;
261
+ }
262
+ getDayNames() {
263
+ return this.locale.dayNamesShort || this.defaultDayNamesShort;
264
+ }
265
+ selectPresetRange(preset) {
266
+ if (!preset.getValue) {
267
+ console.error('PresetConfig must have getValue() function');
268
+ return;
269
+ }
270
+ const range = preset.getValue();
271
+ this.startDate = range.start;
272
+ this.endDate = range.end;
273
+ this.updateDateRangeText();
274
+ this.generateCalendars();
275
+ if (this.closeOnPresetSelection) {
276
+ this.showDatePicker.set(false);
277
+ }
278
+ this.emitSelection();
279
+ }
280
+ clear() {
281
+ this.startDate = '';
282
+ this.endDate = '';
283
+ this.dateRangeText.set('');
284
+ this.showDatePicker.set(false);
285
+ this.selectingStartDate.set(true);
286
+ if (this.multiRange) {
287
+ this.selectedRanges.set([]);
288
+ this.currentRangeIndex.set(-1);
289
+ this.emitMultiChange();
290
+ }
291
+ else {
292
+ this.emitChange();
293
+ }
294
+ this.onTouched();
295
+ this.generateCalendars();
296
+ }
297
+ removeRange(index) {
298
+ if (!this.multiRange)
299
+ return;
300
+ const currentRanges = [...this.selectedRanges()];
301
+ currentRanges.splice(index, 1);
302
+ this.selectedRanges.set(currentRanges);
303
+ this.updateMultiRangeText();
304
+ this.emitMultiChange();
305
+ this.emitMultiSelection();
306
+ this.generateCalendars();
307
+ }
308
+ updateMultiRangeText() {
309
+ const count = this.selectedRanges().length;
310
+ if (count === 0) {
311
+ this.dateRangeText.set('');
312
+ }
313
+ else if (count === 1) {
314
+ this.dateRangeText.set('1 range selected');
315
+ }
316
+ else {
317
+ this.dateRangeText.set(`${count} ranges selected`);
318
+ }
319
+ }
320
+ emitChange() {
321
+ this.dateRangeChange.emit({
322
+ startDate: this.startDate,
323
+ endDate: this.endDate,
324
+ rangeText: this.dateRangeText()
325
+ });
326
+ }
327
+ emitSelection() {
328
+ this.dateRangeSelected.emit({
329
+ startDate: this.startDate,
330
+ endDate: this.endDate,
331
+ rangeText: this.dateRangeText()
332
+ });
333
+ }
334
+ emitMultiChange() {
335
+ this.multiDateRangeChange.emit({
336
+ ranges: this.selectedRanges()
337
+ });
338
+ }
339
+ emitMultiSelection() {
340
+ this.multiDateRangeSelected.emit({
341
+ ranges: this.selectedRanges()
342
+ });
343
+ }
344
+ getDateRangeValue() {
345
+ return {
346
+ startDate: this.startDate,
347
+ endDate: this.endDate,
348
+ rangeText: this.dateRangeText()
349
+ };
350
+ }
351
+ // ControlValueAccessor implementation
352
+ writeValue(value) {
353
+ if (value) {
354
+ this.startDate = value.startDate || '';
355
+ this.endDate = value.endDate || '';
356
+ if (this.startDate && this.endDate) {
357
+ this.updateDateRangeText();
358
+ this.generateCalendars();
359
+ }
360
+ }
361
+ else {
362
+ this.startDate = '';
363
+ this.endDate = '';
364
+ this.dateRangeText.set('');
365
+ }
366
+ }
367
+ registerOnChange(fn) {
368
+ this.onChange = fn;
369
+ }
370
+ registerOnTouched(fn) {
371
+ this.onTouched = fn;
372
+ }
373
+ setDisabledState(isDisabled) {
374
+ this.isDisabled.set(isDisabled);
375
+ }
376
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDatepickerComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
377
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: DualDatepickerComponent, isStandalone: true, selector: "ngx-dual-datepicker", inputs: { placeholder: "placeholder", startDate: "startDate", endDate: "endDate", showPresets: "showPresets", showClearButton: "showClearButton", multiRange: "multiRange", closeOnSelection: "closeOnSelection", closeOnPresetSelection: "closeOnPresetSelection", closeOnClickOutside: "closeOnClickOutside", presets: "presets", inputBackgroundColor: "inputBackgroundColor", inputTextColor: "inputTextColor", inputBorderColor: "inputBorderColor", inputBorderColorHover: "inputBorderColorHover", inputBorderColorFocus: "inputBorderColorFocus", inputPadding: "inputPadding", locale: "locale" }, outputs: { dateRangeChange: "dateRangeChange", dateRangeSelected: "dateRangeSelected", multiDateRangeChange: "multiDateRangeChange", multiDateRangeSelected: "multiDateRangeSelected" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, providers: [
378
+ {
379
+ provide: NG_VALUE_ACCESSOR,
380
+ useExisting: forwardRef(() => DualDatepickerComponent),
381
+ multi: true
382
+ },
383
+ {
384
+ provide: DATE_ADAPTER,
385
+ useClass: NativeDateAdapter
386
+ }
387
+ ], usesOnChanges: true, ngImport: i0, template: "<div class=\"datepicker-wrapper\" \n [style.--input-border-hover]=\"inputBorderColorHover\"\n [style.--input-border-focus]=\"inputBorderColorFocus\">\n <input \n type=\"text\" \n class=\"datepicker-input\" \n [value]=\"dateRangeText()\" \n (click)=\"toggleDatePicker()\" \n [placeholder]=\"placeholder\"\n [disabled]=\"isDisabled()\"\n [ngStyle]=\"{\n 'background-color': inputBackgroundColor,\n 'color': inputTextColor,\n 'border-color': inputBorderColor,\n 'padding': inputPadding\n }\"\n readonly>\n\n @if (showDatePicker()) {\n <div class=\"date-picker-dropdown\">\n @if (showPresets) {\n <div class=\"date-picker-presets\">\n @for (preset of presets; track preset.label) {\n <button type=\"button\" (click)=\"selectPresetRange(preset)\">{{ preset.label }}</button>\n }\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n @if (!showPresets) {\n <div class=\"date-picker-header-only-close\">\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n <!-- Calendars -->\n <div class=\"date-picker-calendars\">\n <!-- Previous month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" (click)=\"changeMonth(-1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ previousMonthName() }}</span>\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of previousMonthDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n (click)=\"selectDay(dayObj)\"\n [disabled]=\"!dayObj.isCurrentMonth\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n\n <!-- Current month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ currentMonthName() }}</span>\n <button type=\"button\" (click)=\"changeMonth(1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of currentMonthDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n (click)=\"selectDay(dayObj)\"\n [disabled]=\"!dayObj.isCurrentMonth\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Multi-Range List -->\n @if (multiRange && selectedRanges().length > 0) {\n <div class=\"multi-range-list\">\n <div class=\"multi-range-header\">\n <span class=\"multi-range-title\">Selected Ranges ({{ selectedRanges().length }})</span>\n </div>\n <div class=\"multi-range-items\">\n @for (range of selectedRanges(); track $index) {\n <div class=\"multi-range-item\">\n <span class=\"multi-range-text\">{{ range.rangeText }}</span>\n <button \n type=\"button\" \n class=\"btn-remove-range\" \n (click)=\"removeRange($index)\"\n title=\"Remove this range\">\n <svg width=\"14\" height=\"14\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Footer with clear button -->\n @if (showClearButton || multiRange) {\n <div class=\"date-picker-footer\">\n @if (multiRange) {\n <div class=\"multi-range-footer-actions\">\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear all ranges\">\n Clear All\n </button>\n <button type=\"button\" class=\"btn-done\" (click)=\"closeDatePicker()\" title=\"Done selecting\">\n Done\n </button>\n </div>\n }\n @if (!multiRange && showClearButton) {\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear selection\">\n Clear\n </button>\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".datepicker-wrapper{position:relative;width:100%}.datepicker-wrapper .datepicker-input{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;cursor:pointer}.datepicker-wrapper .datepicker-input:hover{border-color:var(--input-border-hover, #ced4da)}.datepicker-wrapper .datepicker-input:focus{border-color:var(--input-border-focus, #80bdff);box-shadow:0 0 0 .2rem #007bff40;outline:0}.datepicker-wrapper .datepicker-input::placeholder{color:#6c757d;opacity:1}.datepicker-wrapper .datepicker-input:disabled,.datepicker-wrapper .datepicker-input[readonly]{background-color:#e9ecef;opacity:1}.date-picker-dropdown{position:absolute;top:100%;left:0;margin-top:4px;background:#fff;border:1px solid #e1e4e8;border-radius:8px;box-shadow:0 4px 12px #00000014,0 0 1px #00000014;padding:16px;z-index:1060;min-width:680px}@media (max-width: 768px){.date-picker-dropdown{min-width:100%;left:0;right:0}}.date-picker-header-only-close{display:flex;justify-content:flex-end;margin-bottom:12px}.date-picker-header-only-close .btn-close-calendar{background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;border-radius:6px;cursor:pointer;transition:all .15s ease;font-size:1.5rem;line-height:1}.date-picker-header-only-close .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-header-only-close .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-presets{display:flex;gap:6px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid #e5e7eb;align-items:center}@media (max-width: 768px){.date-picker-presets{flex-wrap:wrap}}.date-picker-presets button{font-size:.75rem;padding:6px 14px;border:none;background-color:#f9fafb;color:#374151;border-radius:6px;transition:all .15s ease;font-weight:500;cursor:pointer;border:1px solid #e5e7eb}.date-picker-presets button:hover{background-color:#f3f4f6;border-color:#d1d5db;transform:translateY(-1px);box-shadow:0 2px 4px #0000000f}.date-picker-presets button:active{transform:translateY(0);box-shadow:none}.date-picker-presets .btn-close-calendar{margin-left:auto;background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;font-size:1.5rem;line-height:1}.date-picker-presets .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-presets .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-calendars{display:flex;gap:32px}@media (max-width: 768px){.date-picker-calendars{flex-direction:column;gap:16px}}.date-picker-calendar{flex:1}.date-picker-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 4px}.date-picker-header span{font-size:.813rem;font-weight:600;color:#111827}.date-picker-header button{padding:4px;color:#6b7280;text-decoration:none;border-radius:6px;transition:all .15s ease;border:none;background:transparent;cursor:pointer}.date-picker-header button:hover{background-color:#f3f4f6;color:#111827}.date-picker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.date-picker-weekdays span{text-align:center;font-size:.625rem;font-weight:600;color:#6b7280;padding:6px}.date-picker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.date-picker-day{aspect-ratio:1;border:none;background:transparent;border-radius:50%;font-size:.75rem;cursor:pointer;transition:all .15s ease;color:#374151;font-weight:400}.date-picker-day:hover:not(:disabled):not(.selected){background-color:#f3f4f6;color:#111827}.date-picker-day.empty{visibility:hidden}.date-picker-day.selected{background-color:#222;color:#fff;font-weight:600}.date-picker-day.in-range{background-color:#f9fafb;border-radius:0}.date-picker-day:disabled{cursor:not-allowed;opacity:.3}.date-picker-footer{padding:12px;border-top:1px solid #e1e4e8;display:flex;justify-content:center;gap:8px}.date-picker-footer .btn-clear{padding:8px 16px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-clear:hover{background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-clear:active{transform:translateY(0);box-shadow:none;background-color:#e9ecef}.date-picker-footer .btn-done{padding:8px 16px;background-color:#222;border:1px solid #222;border-radius:6px;font-size:.875rem;font-weight:500;color:#fff;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-done:hover{background-color:#000;border-color:#000;transform:translateY(-1px);box-shadow:0 2px 4px #00000026}.date-picker-footer .btn-done:active{transform:translateY(0);box-shadow:none}.date-picker-footer .multi-range-footer-actions{display:flex;gap:8px;width:100%;justify-content:space-between}.multi-range-list{border-top:1px solid #e1e4e8;border-bottom:1px solid #e1e4e8;padding:12px;margin-top:12px}.multi-range-list .multi-range-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.multi-range-list .multi-range-header .multi-range-title{font-size:.8125rem;font-weight:600;color:#24292f;text-transform:uppercase;letter-spacing:.025em}.multi-range-list .multi-range-items{display:flex;flex-direction:column;gap:6px;max-height:150px;overflow-y:auto}.multi-range-list .multi-range-items::-webkit-scrollbar{width:6px}.multi-range-list .multi-range-items::-webkit-scrollbar-track{background:#f1f3f4;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb{background:#cbd5e0;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb:hover{background:#a0aec0}.multi-range-list .multi-range-item{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;transition:all .15s ease}.multi-range-list .multi-range-item:hover{background-color:#f3f4f6;border-color:#8c959f}.multi-range-list .multi-range-item .multi-range-text{font-size:.875rem;color:#24292f;font-weight:500}.multi-range-list .multi-range-item .btn-remove-range{padding:4px;background-color:transparent;border:1px solid transparent;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#6b7280;transition:all .15s ease}.multi-range-list .multi-range-item .btn-remove-range:hover{background-color:#fee;border-color:#fcc;color:#dc2626}.multi-range-list .multi-range-item .btn-remove-range:hover svg{transform:scale(1.1)}.multi-range-list .multi-range-item .btn-remove-range:active{transform:scale(.95)}.multi-range-list .multi-range-item .btn-remove-range svg{transition:transform .15s ease}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
388
+ }
389
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDatepickerComponent, decorators: [{
390
+ type: Component,
391
+ args: [{ selector: 'ngx-dual-datepicker', standalone: true, imports: [CommonModule, FormsModule, ReactiveFormsModule], providers: [
392
+ {
393
+ provide: NG_VALUE_ACCESSOR,
394
+ useExisting: forwardRef(() => DualDatepickerComponent),
395
+ multi: true
396
+ },
397
+ {
398
+ provide: DATE_ADAPTER,
399
+ useClass: NativeDateAdapter
400
+ }
401
+ ], template: "<div class=\"datepicker-wrapper\" \n [style.--input-border-hover]=\"inputBorderColorHover\"\n [style.--input-border-focus]=\"inputBorderColorFocus\">\n <input \n type=\"text\" \n class=\"datepicker-input\" \n [value]=\"dateRangeText()\" \n (click)=\"toggleDatePicker()\" \n [placeholder]=\"placeholder\"\n [disabled]=\"isDisabled()\"\n [ngStyle]=\"{\n 'background-color': inputBackgroundColor,\n 'color': inputTextColor,\n 'border-color': inputBorderColor,\n 'padding': inputPadding\n }\"\n readonly>\n\n @if (showDatePicker()) {\n <div class=\"date-picker-dropdown\">\n @if (showPresets) {\n <div class=\"date-picker-presets\">\n @for (preset of presets; track preset.label) {\n <button type=\"button\" (click)=\"selectPresetRange(preset)\">{{ preset.label }}</button>\n }\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n @if (!showPresets) {\n <div class=\"date-picker-header-only-close\">\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"closeDatePicker()\" title=\"Close\">\n \u00D7\n </button>\n </div>\n }\n\n <!-- Calendars -->\n <div class=\"date-picker-calendars\">\n <!-- Previous month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" (click)=\"changeMonth(-1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ previousMonthName() }}</span>\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of previousMonthDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n (click)=\"selectDay(dayObj)\"\n [disabled]=\"!dayObj.isCurrentMonth\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n\n <!-- Current month calendar -->\n <div class=\"date-picker-calendar\">\n <div class=\"date-picker-header\">\n <button type=\"button\" style=\"visibility: hidden;\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z\"/>\n </svg>\n </button>\n <span>{{ currentMonthName() }}</span>\n <button type=\"button\" (click)=\"changeMonth(1)\">\n <svg width=\"16\" height=\"16\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path fill-rule=\"evenodd\" d=\"M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z\"/>\n </svg>\n </button>\n </div>\n <div class=\"date-picker-weekdays\">\n @for (dayName of weekDayNames(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (dayObj of currentMonthDays(); track dayObj.date || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!dayObj.isCurrentMonth\"\n [class.selected]=\"dayObj.isStart || dayObj.isEnd\"\n [class.in-range]=\"dayObj.inRange && !dayObj.isStart && !dayObj.isEnd\"\n (click)=\"selectDay(dayObj)\"\n [disabled]=\"!dayObj.isCurrentMonth\">\n {{ dayObj.day }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Multi-Range List -->\n @if (multiRange && selectedRanges().length > 0) {\n <div class=\"multi-range-list\">\n <div class=\"multi-range-header\">\n <span class=\"multi-range-title\">Selected Ranges ({{ selectedRanges().length }})</span>\n </div>\n <div class=\"multi-range-items\">\n @for (range of selectedRanges(); track $index) {\n <div class=\"multi-range-item\">\n <span class=\"multi-range-text\">{{ range.rangeText }}</span>\n <button \n type=\"button\" \n class=\"btn-remove-range\" \n (click)=\"removeRange($index)\"\n title=\"Remove this range\">\n <svg width=\"14\" height=\"14\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\n <path d=\"M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z\"/>\n </svg>\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Footer with clear button -->\n @if (showClearButton || multiRange) {\n <div class=\"date-picker-footer\">\n @if (multiRange) {\n <div class=\"multi-range-footer-actions\">\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear all ranges\">\n Clear All\n </button>\n <button type=\"button\" class=\"btn-done\" (click)=\"closeDatePicker()\" title=\"Done selecting\">\n Done\n </button>\n </div>\n }\n @if (!multiRange && showClearButton) {\n <button type=\"button\" class=\"btn-clear\" (click)=\"clear()\" title=\"Clear selection\">\n Clear\n </button>\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".datepicker-wrapper{position:relative;width:100%}.datepicker-wrapper .datepicker-input{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;cursor:pointer}.datepicker-wrapper .datepicker-input:hover{border-color:var(--input-border-hover, #ced4da)}.datepicker-wrapper .datepicker-input:focus{border-color:var(--input-border-focus, #80bdff);box-shadow:0 0 0 .2rem #007bff40;outline:0}.datepicker-wrapper .datepicker-input::placeholder{color:#6c757d;opacity:1}.datepicker-wrapper .datepicker-input:disabled,.datepicker-wrapper .datepicker-input[readonly]{background-color:#e9ecef;opacity:1}.date-picker-dropdown{position:absolute;top:100%;left:0;margin-top:4px;background:#fff;border:1px solid #e1e4e8;border-radius:8px;box-shadow:0 4px 12px #00000014,0 0 1px #00000014;padding:16px;z-index:1060;min-width:680px}@media (max-width: 768px){.date-picker-dropdown{min-width:100%;left:0;right:0}}.date-picker-header-only-close{display:flex;justify-content:flex-end;margin-bottom:12px}.date-picker-header-only-close .btn-close-calendar{background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;border-radius:6px;cursor:pointer;transition:all .15s ease;font-size:1.5rem;line-height:1}.date-picker-header-only-close .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-header-only-close .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-presets{display:flex;gap:6px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid #e5e7eb;align-items:center}@media (max-width: 768px){.date-picker-presets{flex-wrap:wrap}}.date-picker-presets button{font-size:.75rem;padding:6px 14px;border:none;background-color:#f9fafb;color:#374151;border-radius:6px;transition:all .15s ease;font-weight:500;cursor:pointer;border:1px solid #e5e7eb}.date-picker-presets button:hover{background-color:#f3f4f6;border-color:#d1d5db;transform:translateY(-1px);box-shadow:0 2px 4px #0000000f}.date-picker-presets button:active{transform:translateY(0);box-shadow:none}.date-picker-presets .btn-close-calendar{margin-left:auto;background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;font-size:1.5rem;line-height:1}.date-picker-presets .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-presets .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-calendars{display:flex;gap:32px}@media (max-width: 768px){.date-picker-calendars{flex-direction:column;gap:16px}}.date-picker-calendar{flex:1}.date-picker-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 4px}.date-picker-header span{font-size:.813rem;font-weight:600;color:#111827}.date-picker-header button{padding:4px;color:#6b7280;text-decoration:none;border-radius:6px;transition:all .15s ease;border:none;background:transparent;cursor:pointer}.date-picker-header button:hover{background-color:#f3f4f6;color:#111827}.date-picker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.date-picker-weekdays span{text-align:center;font-size:.625rem;font-weight:600;color:#6b7280;padding:6px}.date-picker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.date-picker-day{aspect-ratio:1;border:none;background:transparent;border-radius:50%;font-size:.75rem;cursor:pointer;transition:all .15s ease;color:#374151;font-weight:400}.date-picker-day:hover:not(:disabled):not(.selected){background-color:#f3f4f6;color:#111827}.date-picker-day.empty{visibility:hidden}.date-picker-day.selected{background-color:#222;color:#fff;font-weight:600}.date-picker-day.in-range{background-color:#f9fafb;border-radius:0}.date-picker-day:disabled{cursor:not-allowed;opacity:.3}.date-picker-footer{padding:12px;border-top:1px solid #e1e4e8;display:flex;justify-content:center;gap:8px}.date-picker-footer .btn-clear{padding:8px 16px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-clear:hover{background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-clear:active{transform:translateY(0);box-shadow:none;background-color:#e9ecef}.date-picker-footer .btn-done{padding:8px 16px;background-color:#222;border:1px solid #222;border-radius:6px;font-size:.875rem;font-weight:500;color:#fff;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-done:hover{background-color:#000;border-color:#000;transform:translateY(-1px);box-shadow:0 2px 4px #00000026}.date-picker-footer .btn-done:active{transform:translateY(0);box-shadow:none}.date-picker-footer .multi-range-footer-actions{display:flex;gap:8px;width:100%;justify-content:space-between}.multi-range-list{border-top:1px solid #e1e4e8;border-bottom:1px solid #e1e4e8;padding:12px;margin-top:12px}.multi-range-list .multi-range-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.multi-range-list .multi-range-header .multi-range-title{font-size:.8125rem;font-weight:600;color:#24292f;text-transform:uppercase;letter-spacing:.025em}.multi-range-list .multi-range-items{display:flex;flex-direction:column;gap:6px;max-height:150px;overflow-y:auto}.multi-range-list .multi-range-items::-webkit-scrollbar{width:6px}.multi-range-list .multi-range-items::-webkit-scrollbar-track{background:#f1f3f4;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb{background:#cbd5e0;border-radius:4px}.multi-range-list .multi-range-items::-webkit-scrollbar-thumb:hover{background:#a0aec0}.multi-range-list .multi-range-item{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;transition:all .15s ease}.multi-range-list .multi-range-item:hover{background-color:#f3f4f6;border-color:#8c959f}.multi-range-list .multi-range-item .multi-range-text{font-size:.875rem;color:#24292f;font-weight:500}.multi-range-list .multi-range-item .btn-remove-range{padding:4px;background-color:transparent;border:1px solid transparent;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#6b7280;transition:all .15s ease}.multi-range-list .multi-range-item .btn-remove-range:hover{background-color:#fee;border-color:#fcc;color:#dc2626}.multi-range-list .multi-range-item .btn-remove-range:hover svg{transform:scale(1.1)}.multi-range-list .multi-range-item .btn-remove-range:active{transform:scale(.95)}.multi-range-list .multi-range-item .btn-remove-range svg{transition:transform .15s ease}\n"] }]
402
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { placeholder: [{
403
+ type: Input
404
+ }], startDate: [{
405
+ type: Input
406
+ }], endDate: [{
407
+ type: Input
408
+ }], showPresets: [{
409
+ type: Input
410
+ }], showClearButton: [{
411
+ type: Input
412
+ }], multiRange: [{
413
+ type: Input
414
+ }], closeOnSelection: [{
415
+ type: Input
416
+ }], closeOnPresetSelection: [{
417
+ type: Input
418
+ }], closeOnClickOutside: [{
419
+ type: Input
420
+ }], presets: [{
421
+ type: Input
422
+ }], inputBackgroundColor: [{
423
+ type: Input
424
+ }], inputTextColor: [{
425
+ type: Input
426
+ }], inputBorderColor: [{
427
+ type: Input
428
+ }], inputBorderColorHover: [{
429
+ type: Input
430
+ }], inputBorderColorFocus: [{
431
+ type: Input
432
+ }], inputPadding: [{
433
+ type: Input
434
+ }], locale: [{
435
+ type: Input
436
+ }], dateRangeChange: [{
437
+ type: Output
438
+ }], dateRangeSelected: [{
439
+ type: Output
440
+ }], multiDateRangeChange: [{
441
+ type: Output
442
+ }], multiDateRangeSelected: [{
443
+ type: Output
444
+ }], onClickOutside: [{
445
+ type: HostListener,
446
+ args: ['document:click', ['$event']]
447
+ }] } });
448
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHVhbC1kYXRlcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kdWFsLWRhdGVwaWNrZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vc3JjL2R1YWwtZGF0ZXBpY2tlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFvQyxZQUFZLEVBQWMsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqTCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzRyxPQUFPLEVBQWUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7OztBQWdEMUQsTUFBTSxPQUFPLHVCQUF1QjtJQXVEZDtJQXREWCxXQUFXLEdBQVcsbUJBQW1CLENBQUM7SUFDMUMsU0FBUyxHQUFXLEVBQUUsQ0FBQztJQUN2QixPQUFPLEdBQVcsRUFBRSxDQUFDO0lBQ3JCLFdBQVcsR0FBWSxJQUFJLENBQUM7SUFDNUIsZUFBZSxHQUFZLEtBQUssQ0FBQztJQUNqQyxVQUFVLEdBQVksS0FBSyxDQUFDO0lBQzVCLGdCQUFnQixHQUFZLElBQUksQ0FBQztJQUNqQyxzQkFBc0IsR0FBWSxJQUFJLENBQUM7SUFDdkMsbUJBQW1CLEdBQVksSUFBSSxDQUFDO0lBQ3BDLE9BQU8sR0FBbUIsRUFBRSxDQUFDO0lBQzdCLG9CQUFvQixHQUFXLE1BQU0sQ0FBQztJQUN0QyxjQUFjLEdBQVcsU0FBUyxDQUFDO0lBQ25DLGdCQUFnQixHQUFXLFNBQVMsQ0FBQztJ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QUF4QixLQUFLO2dCQUNHLHNCQUFzQjtzQkFBOUIsS0FBSztnQkFDRyxtQkFBbUI7c0JBQTNCLEtBQUs7Z0JBQ0csT0FBTztzQkFBZixLQUFLO2dCQUNHLG9CQUFvQjtzQkFBNUIsS0FBSztnQkFDRyxjQUFjO3NCQUF0QixLQUFLO2dCQUNHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFDRyxxQkFBcUI7c0JBQTdCLEtBQUs7Z0JBQ0cscUJBQXFCO3NCQUE3QixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUVJLGVBQWU7c0JBQXhCLE1BQU07Z0JBQ0csaUJBQWlCO3NCQUExQixNQUFNO2dCQUNHLG9CQUFvQjtzQkFBN0IsTUFBTTtnQkFDRyxzQkFBc0I7c0JBQS9CLE1BQU07Z0JBNENQLGNBQWM7c0JBRGIsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBPbkluaXQsIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlcywgSG9zdExpc3RlbmVyLCBFbGVtZW50UmVmLCBmb3J3YXJkUmVmLCBzaWduYWwsIGNvbXB1dGVkLCBlZmZlY3QsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlLCBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBEYXRlQWRhcHRlciwgREFURV9BREFQVEVSIH0gZnJvbSAnLi9kYXRlLWFkYXB0ZXInO1xuaW1wb3J0IHsgTmF0aXZlRGF0ZUFkYXB0ZXIgfSBmcm9tICcuL25hdGl2ZS1kYXRlLWFkYXB0ZXInO1xuXG5leHBvcnQgaW50ZXJmYWNlIERhdGVSYW5nZSB7XG4gIHN0YXJ0RGF0ZTogc3RyaW5nO1xuICBlbmREYXRlOiBzdHJpbmc7XG4gIHJhbmdlVGV4dDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE11bHRpRGF0ZVJhbmdlIHtcbiAgcmFuZ2VzOiBEYXRlUmFuZ2VbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcmVzZXRSYW5nZSB7XG4gIHN0YXJ0OiBzdHJpbmc7XG4gIGVuZDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByZXNldENvbmZpZyB7XG4gIGxhYmVsOiBzdHJpbmc7XG4gIGdldFZhbHVlOiAoKSA9PiBQcmVzZXRSYW5nZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBMb2NhbGVDb25maWcge1xuICBtb250aE5hbWVzPzogc3RyaW5nW107XG4gIG1vbnRoTmFtZXNTaG9ydD86IHN0cmluZ1tdO1xuICBkYXlOYW1lcz86IHN0cmluZ1tdO1xuICBkYXlOYW1lc1Nob3J0Pzogc3RyaW5nW107XG4gIGZpcnN0RGF5T2ZXZWVrPzogbnVtYmVyOyAvLyAwID0gU3VuZGF5LCAxID0gTW9uZGF5LCBldGMuXG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1kdWFsLWRhdGVwaWNrZXInLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBGb3Jtc01vZHVsZSwgUmVhY3RpdmVGb3Jtc01vZHVsZV0sXG4gIHRlbXBsYXRlVXJsOiAnLi9kdWFsLWRhdGVwaWNrZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vZHVhbC1kYXRlcGlja2VyLmNvbXBvbmVudC5zY3NzJyxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBEdWFsRGF0ZXBpY2tlckNvbXBvbmVudCksXG4gICAgICBtdWx0aTogdHJ1ZVxuICAgIH0sXG4gICAge1xuICAgICAgcHJvdmlkZTogREFURV9BREFQVEVSLFxuICAgICAgdXNlQ2xhc3M6IE5hdGl2ZURhdGVBZGFwdGVyXG4gICAgfVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIER1YWxEYXRlcGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcbiAgQElucHV0KCkgcGxhY2Vob2xkZXI6IHN0cmluZyA9ICdTZWxlY3QgZGF0ZSByYW5nZSc7XG4gIEBJbnB1dCgpIHN0YXJ0RGF0ZTogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIGVuZERhdGU6IHN0cmluZyA9ICcnO1xuICBASW5wdXQoKSBzaG93UHJlc2V0czogYm9vbGVhbiA9IHRydWU7XG4gIEBJbnB1dCgpIHNob3dDbGVhckJ1dHRvbjogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBtdWx0aVJhbmdlOiBib29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIGNsb3NlT25TZWxlY3Rpb246IGJvb2xlYW4gPSB0cnVlO1xuICBASW5wdXQoKSBjbG9zZU9uUHJlc2V0U2VsZWN0aW9uOiBib29sZWFuID0gdHJ1ZTtcbiAgQElucHV0KCkgY2xvc2VPbkNsaWNrT3V0c2lkZTogYm9vbGVhbiA9IHRydWU7XG4gIEBJbnB1dCgpIHByZXNldHM6IFByZXNldENvbmZpZ1tdID0gW107XG4gIEBJbnB1dCgpIGlucHV0QmFja2dyb3VuZENvbG9yOiBzdHJpbmcgPSAnI2ZmZic7XG4gIEBJbnB1dCgpIGlucHV0VGV4dENvbG9yOiBzdHJpbmcgPSAnIzQ5NTA1Nyc7XG4gIEBJbnB1dCgpIGlucHV0Qm9yZGVyQ29sb3I6IHN0cmluZyA9ICcjY2VkNGRhJztcbiAgQElucHV0KCkgaW5wdXRCb3JkZXJDb2xvckhvdmVyOiBzdHJpbmcgPSAnI2NlZDRkYSc7XG4gIEBJbnB1dCgpIGlucHV0Qm9yZGVyQ29sb3JGb2N1czogc3RyaW5nID0gJyM4MGJkZmYnO1xuICBASW5wdXQoKSBpbnB1dFBhZGRpbmc6IHN0cmluZyA9ICcwLjM3NXJlbSAwLjc1cmVtJztcbiAgQElucHV0KCkgbG9jYWxlOiBMb2NhbGVDb25maWcgPSB7fTtcblxuICBAT3V0cHV0KCkgZGF0ZVJhbmdlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlUmFuZ2U+KCk7XG4gIEBPdXRwdXQoKSBkYXRlUmFuZ2VTZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXI8RGF0ZVJhbmdlPigpO1xuICBAT3V0cHV0KCkgbXVsdGlEYXRlUmFuZ2VDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPE11bHRpRGF0ZVJhbmdlPigpO1xuICBAT3V0cHV0KCkgbXVsdGlEYXRlUmFuZ2VTZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXI8TXVsdGlEYXRlUmFuZ2U+KCk7XG5cbiAgLy8gRGF0ZSBhZGFwdGVyIGluamVjdGlvblxuICBwcml2YXRlIGRhdGVBZGFwdGVyID0gaW5qZWN0PERhdGVBZGFwdGVyPihEQVRFX0FEQVBURVIpO1xuXG4gIC8vIFNpZ25hbHMgZm9yIHJlYWN0aXZlIHN0YXRlXG4gIHNob3dEYXRlUGlja2VyID0gc2lnbmFsKGZhbHNlKTtcbiAgZGF0ZVJhbmdlVGV4dCA9IHNpZ25hbCgnJyk7XG4gIHNlbGVjdGluZ1N0YXJ0RGF0ZSA9IHNpZ25hbCh0cnVlKTtcbiAgY3VycmVudE1vbnRoID0gc2lnbmFsKHRoaXMuZGF0ZUFkYXB0ZXIudG9kYXkoKSk7XG4gIHByZXZpb3VzTW9udGggPSBzaWduYWwodGhpcy5kYXRlQWRhcHRlci50b2RheSgpKTtcbiAgY3VycmVudE1vbnRoRGF5cyA9IHNpZ25hbDxhbnlbXT4oW10pO1xuICBwcmV2aW91c01vbnRoRGF5cyA9IHNpZ25hbDxhbnlbXT4oW10pO1xuICBpc0Rpc2FibGVkID0gc2lnbmFsKGZhbHNlKTtcbiAgXG4gIC8vIE11bHRpLXJhbmdlIHN1cHBvcnRcbiAgc2VsZWN0ZWRSYW5nZXMgPSBzaWduYWw8RGF0ZVJhbmdlW10+KFtdKTtcbiAgY3VycmVudFJhbmdlSW5kZXggPSBzaWduYWw8bnVtYmVyPigtMSk7XG5cbiAgLy8gQ29tcHV0ZWQgdmFsdWVzXG4gIGN1cnJlbnRNb250aE5hbWUgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmdldE1vbnRoTmFtZSh0aGlzLmN1cnJlbnRNb250aCgpKSk7XG4gIHByZXZpb3VzTW9udGhOYW1lID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5nZXRNb250aE5hbWUodGhpcy5wcmV2aW91c01vbnRoKCkpKTtcbiAgd2Vla0RheU5hbWVzID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5nZXREYXlOYW1lcygpKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHRNb250aE5hbWVzID0gWydKYW51YXJ5JywgJ0ZlYnJ1YXJ5JywgJ01hcmNoJywgJ0FwcmlsJywgJ01heScsICdKdW5lJywgJ0p1bHknLCAnQXVndXN0JywgJ1NlcHRlbWJlcicsICdPY3RvYmVyJywgJ05vdmVtYmVyJywgJ0RlY2VtYmVyJ107XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdE1vbnRoTmFtZXNTaG9ydCA9IFsnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLCAnSnVsJywgJ0F1ZycsICdTZXAnLCAnT2N0JywgJ05vdicsICdEZWMnXTtcbiAgcHJpdmF0ZSByZWFkb25seSBkZWZhdWx0RGF5TmFtZXMgPSBbJ1N1bmRheScsICdNb25kYXknLCAnVHVlc2RheScsICdXZWRuZXNkYXknLCAnVGh1cnNkYXknLCAnRnJpZGF5JywgJ1NhdHVyZGF5J107XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdERheU5hbWVzU2hvcnQgPSBbJ1MnLCAnTScsICdUJywgJ1cnLCAnVCcsICdGJywgJ1MnXTtcblxuICAvLyBDb250cm9sVmFsdWVBY2Nlc3NvciBjYWxsYmFja3NcbiAgcHJpdmF0ZSBvbkNoYW5nZTogKHZhbHVlOiBEYXRlUmFuZ2UgfCBudWxsKSA9PiB2b2lkID0gKCkgPT4ge307XG4gIHByaXZhdGUgb25Ub3VjaGVkOiAoKSA9PiB2b2lkID0gKCkgPT4ge307XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBlbGVtZW50UmVmOiBFbGVtZW50UmVmKSB7XG4gICAgLy8gRWZmZWN0IHRvIGVtaXQgY2hhbmdlcyB3aGVuIGRhdGVzIGNoYW5nZVxuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICBjb25zdCByYW5nZSA9IHRoaXMuZGF0ZVJhbmdlVGV4dCgpO1xuICAgICAgaWYgKHRoaXMuc3RhcnREYXRlIHx8IHRoaXMuZW5kRGF0ZSkge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlKHRoaXMuZ2V0RGF0ZVJhbmdlVmFsdWUoKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDpjbGljaycsIFsnJGV2ZW50J10pXG4gIG9uQ2xpY2tPdXRzaWRlKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2hvd0RhdGVQaWNrZXIoKSAmJiB0aGlzLmNsb3NlT25DbGlja091dHNpZGUpIHtcbiAgICAgIGNvbnN0IGNsaWNrZWRJbnNpZGUgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5jb250YWlucyhldmVudC50YXJnZXQpO1xuICAgICAgaWYgKCFjbGlja2VkSW5zaWRlKSB7XG4gICAgICAgIHRoaXMuY2xvc2VEYXRlUGlja2VyKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc3RhcnREYXRlICYmIHRoaXMuZW5kRGF0ZSkge1xuICAgICAgdGhpcy51cGRhdGVEYXRlUmFuZ2VUZXh0KCk7XG4gICAgICB0aGlzLmdlbmVyYXRlQ2FsZW5kYXJzKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzWydzdGFydERhdGUnXSB8fCBjaGFuZ2VzWydlbmREYXRlJ10pIHtcbiAgICAgIGlmICh0aGlzLnN0YXJ0RGF0ZSAmJiB0aGlzLmVuZERhdGUpIHtcbiAgICAgICAgdGhpcy51cGRhdGVEYXRlUmFuZ2VUZXh0KCk7XG4gICAgICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcnMoKTtcbiAgICAgIH0gZWxzZSBpZiAoIXRoaXMuc3RhcnREYXRlICYmICF0aGlzLmVuZERhdGUpIHtcbiAgICAgICAgdGhpcy5kYXRlUmFuZ2VUZXh0LnNldCgnJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZm9ybWF0RGF0ZShkYXRlOiBEYXRlKTogc3RyaW5nIHtcbiAgICBjb25zdCB5ZWFyID0gdGhpcy5kYXRlQWRhcHRlci5nZXRZZWFyKGRhdGUpO1xuICAgIGNvbnN0IG1vbnRoID0gU3RyaW5nKHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0TW9udGgoZGF0ZSkgKyAxKS5wYWRTdGFydCgyLCAnMCcpO1xuICAgIGNvbnN0IGRheSA9IFN0cmluZyh0aGlzLmRhdGVBZGFwdGVyLmdldERhdGUoZGF0ZSkpLnBhZFN0YXJ0KDIsICcwJyk7XG4gICAgcmV0dXJuIGAke3llYXJ9LSR7bW9udGh9LSR7ZGF5fWA7XG4gIH1cblxuICBmb3JtYXREYXRlRGlzcGxheShkYXRlU3RyOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICghZGF0ZVN0cikgcmV0dXJuICcnO1xuICAgIGNvbnN0IGRhdGUgPSB0aGlzLmRhdGVBZGFwdGVyLnBhcnNlKGRhdGVTdHIpO1xuICAgIGlmICghZGF0ZSkgcmV0dXJuICcnO1xuICAgIGNvbnN0IG1vbnRoTmFtZXMgPSB0aGlzLmxvY2FsZS5tb250aE5hbWVzU2hvcnQgfHwgdGhpcy5kZWZhdWx0TW9udGhOYW1lc1Nob3J0O1xuICAgIHJldHVybiBgJHt0aGlzLmRhdGVBZGFwdGVyLmdldERhdGUoZGF0ZSl9ICR7bW9udGhOYW1lc1t0aGlzLmRhdGVBZGFwdGVyLmdldE1vbnRoKGRhdGUpXX1gO1xuICB9XG5cbiAgdXBkYXRlRGF0ZVJhbmdlVGV4dCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zdGFydERhdGUgJiYgdGhpcy5lbmREYXRlKSB7XG4gICAgICBjb25zdCBzdGFydCA9IHRoaXMuZm9ybWF0RGF0ZURpc3BsYXkodGhpcy5zdGFydERhdGUpO1xuICAgICAgY29uc3QgZW5kID0gdGhpcy5mb3JtYXREYXRlRGlzcGxheSh0aGlzLmVuZERhdGUpO1xuICAgICAgdGhpcy5kYXRlUmFuZ2VUZXh0LnNldChgJHtzdGFydH0gLSAke2VuZH1gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kYXRlUmFuZ2VUZXh0LnNldCgnJyk7XG4gICAgfVxuICB9XG5cbiAgdG9nZ2xlRGF0ZVBpY2tlcigpOiB2b2lkIHtcbiAgICB0aGlzLnNob3dEYXRlUGlja2VyLnVwZGF0ZSh2YWx1ZSA9PiAhdmFsdWUpO1xuICAgIGlmICh0aGlzLnNob3dEYXRlUGlja2VyKCkpIHtcbiAgICAgIHRoaXMuc2VsZWN0aW5nU3RhcnREYXRlLnNldCh0cnVlKTtcbiAgICAgIGNvbnN0IGN1cnJlbnRNb250aFZhbHVlID0gdGhpcy5jdXJyZW50TW9udGgoKTtcbiAgICAgIGNvbnN0IHllYXIgPSB0aGlzLmRhdGVBZGFwdGVyLmdldFllYXIoY3VycmVudE1vbnRoVmFsdWUpO1xuICAgICAgY29uc3QgbW9udGggPSB0aGlzLmRhdGVBZGFwdGVyLmdldE1vbnRoKGN1cnJlbnRNb250aFZhbHVlKTtcbiAgICAgIGNvbnN0IHByZXZpb3VzTW9udGhEYXRlID0gdGhpcy5kYXRlQWRhcHRlci5jcmVhdGVEYXRlKHllYXIsIG1vbnRoIC0gMSwgMSk7XG4gICAgICB0aGlzLnByZXZpb3VzTW9udGguc2V0KHByZXZpb3VzTW9udGhEYXRlKTtcbiAgICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcnMoKTtcbiAgICB9XG4gICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgfVxuXG4gIGNsb3NlRGF0ZVBpY2tlcigpOiB2b2lkIHtcbiAgICB0aGlzLnNob3dEYXRlUGlja2VyLnNldChmYWxzZSk7XG4gICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgfVxuXG4gIGdlbmVyYXRlQ2FsZW5kYXJzKCk6IHZvaWQge1xuICAgIHRoaXMucHJldmlvdXNNb250aERheXMuc2V0KHRoaXMuZ2VuZXJhdGVNb250aENhbGVuZGFyKHRoaXMucHJldmlvdXNNb250aCgpKSk7XG4gICAgdGhpcy5jdXJyZW50TW9udGhEYXlzLnNldCh0aGlzLmdlbmVyYXRlTW9udGhDYWxlbmRhcih0aGlzLmN1cnJlbnRNb250aCgpKSk7XG4gIH1cblxuICBnZW5lcmF0ZU1vbnRoQ2FsZW5kYXIoZGF0ZTogRGF0ZSk6IGFueVtdIHtcbiAgICBjb25zdCB5ZWFyID0gdGhpcy5kYXRlQWRhcHRlci5nZXRZZWFyKGRhdGUpO1xuICAgIGNvbnN0IG1vbnRoID0gdGhpcy5kYXRlQWRhcHRlci5nZXRNb250aChkYXRlKTtcbiAgICBjb25zdCBmaXJzdERheSA9IHRoaXMuZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZSh5ZWFyLCBtb250aCwgMSk7XG4gICAgY29uc3QgbGFzdERheSA9IHRoaXMuZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZSh5ZWFyLCBtb250aCArIDEsIDApO1xuICAgIGNvbnN0IGRheXNJbk1vbnRoID0gdGhpcy5kYXRlQWRhcHRlci5nZXREYXRlKGxhc3REYXkpO1xuICAgIGNvbnN0IGZpcnN0RGF5T2ZXZWVrID0gdGhpcy5kYXRlQWRhcHRlci5nZXREYXkoZmlyc3REYXkpO1xuXG4gICAgY29uc3QgbW9udGhEYXlzID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZpcnN0RGF5T2ZXZWVrOyBpKyspIHtcbiAgICAgIG1vbnRoRGF5cy5wdXNoKHsgZGF5OiBudWxsLCBpc0N1cnJlbnRNb250aDogZmFsc2UgfSk7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgZGF5ID0gMTsgZGF5IDw9IGRheXNJbk1vbnRoOyBkYXkrKykge1xuICAgICAgY29uc3QgZGF5RGF0ZSA9IHRoaXMuZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZSh5ZWFyLCBtb250aCwgZGF5KTtcbiAgICAgIGNvbnN0IGRhdGVTdHIgPSB0aGlzLmZvcm1hdERhdGUoZGF5RGF0ZSk7XG4gICAgICBtb250aERheXMucHVzaCh7XG4gICAgICAgIGRheTogZGF5LFxuICAgICAgICBkYXRlOiBkYXRlU3RyLFxuICAgICAgICBpc0N1cnJlbnRNb250aDogdHJ1ZSxcbiAgICAgICAgaXNTdGFydDogdGhpcy5zdGFydERhdGUgPT09IGRhdGVTdHIsXG4gICAgICAgIGlzRW5kOiB0aGlzLmVuZERhdGUgPT09IGRhdGVTdHIsXG4gICAgICAgIGluUmFuZ2U6IHRoaXMuaXNJblJhbmdlKGRhdGVTdHIpXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbW9udGhEYXlzO1xuICB9XG5cbiAgaXNJblJhbmdlKGRhdGVTdHI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLm11bHRpUmFuZ2UpIHtcbiAgICAgIC8vIENoZWNrIGlmIGRhdGUgaXMgaW4gYW55IG9mIHRoZSBzZWxlY3RlZCByYW5nZXNcbiAgICAgIHJldHVybiB0aGlzLnNlbGVjdGVkUmFuZ2VzKCkuc29tZShyYW5nZSA9PiB7XG4gICAgICAgIHJldHVybiBkYXRlU3RyID49IHJhbmdlLnN0YXJ0RGF0ZSAmJiBkYXRlU3RyIDw9IHJhbmdlLmVuZERhdGU7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCF0aGlzLnN0YXJ0RGF0ZSB8fCAhdGhpcy5lbmREYXRlKSByZXR1cm4gZmFsc2U7XG4gICAgICByZXR1cm4gZGF0ZVN0ciA+PSB0aGlzLnN0YXJ0RGF0ZSAmJiBkYXRlU3RyIDw9IHRoaXMuZW5kRGF0ZTtcbiAgICB9XG4gIH1cblxuICBzZWxlY3REYXkoZGF5T2JqOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAoIWRheU9iai5pc0N1cnJlbnRNb250aCB8fCB0aGlzLmlzRGlzYWJsZWQoKSkgcmV0dXJuO1xuXG4gICAgaWYgKHRoaXMubXVsdGlSYW5nZSkge1xuICAgICAgLy8gTXVsdGktcmFuZ2UgbW9kZTogYWRkIHJhbmdlcyB0byBhcnJheVxuICAgICAgaWYgKHRoaXMuc2VsZWN0aW5nU3RhcnREYXRlKCkpIHtcbiAgICAgICAgdGhpcy5zdGFydERhdGUgPSBkYXlPYmouZGF0ZTtcbiAgICAgICAgdGhpcy5lbmREYXRlID0gJyc7XG4gICAgICAgIHRoaXMuZGF0ZVJhbmdlVGV4dC5zZXQoJycpO1xuICAgICAgICB0aGlzLnNlbGVjdGluZ1N0YXJ0RGF0ZS5zZXQoZmFsc2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGRheU9iai5kYXRlIDwgdGhpcy5zdGFydERhdGUpIHtcbiAgICAgICAgICB0aGlzLmVuZERhdGUgPSB0aGlzLnN0YXJ0RGF0ZTtcbiAgICAgICAgICB0aGlzLnN0YXJ0RGF0ZSA9IGRheU9iai5kYXRlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuZW5kRGF0ZSA9IGRheU9iai5kYXRlO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvLyBBZGQgdGhlIG5ldyByYW5nZSB0byB0aGUgYXJyYXlcbiAgICAgICAgY29uc3QgbmV3UmFuZ2U6IERhdGVSYW5nZSA9IHtcbiAgICAgICAgICBzdGFydERhdGU6IHRoaXMuc3RhcnREYXRlLFxuICAgICAgICAgIGVuZERhdGU6IHRoaXMuZW5kRGF0ZSxcbiAgICAgICAgICByYW5nZVRleHQ6IHRoaXMuZm9ybWF0RGF0ZURpc3BsYXkodGhpcy5zdGFydERhdGUpICsgJyDigJMgJyArIHRoaXMuZm9ybWF0RGF0ZURpc3BsYXkodGhpcy5lbmREYXRlKVxuICAgICAgICB9O1xuICAgICAgICBcbiAgICAgICAgY29uc3QgY3VycmVudFJhbmdlcyA9IFsuLi50aGlzLnNlbGVjdGVkUmFuZ2VzKCldO1xuICAgICAgICBjdXJyZW50UmFuZ2VzLnB1c2gobmV3UmFuZ2UpO1xuICAgICAgICB0aGlzLnNlbGVjdGVkUmFuZ2VzLnNldChjdXJyZW50UmFuZ2VzKTtcbiAgICAgICAgXG4gICAgICAgIC8vIFJlc2V0IGZvciBuZXh0IHJhbmdlIHNlbGVjdGlvblxuICAgICAgICB0aGlzLnN0YXJ0RGF0ZSA9ICcnO1xuICAgICAgICB0aGlzLmVuZERhdGUgPSAnJztcbiAgICAgICAgdGhpcy5zZWxlY3RpbmdTdGFydERhdGUuc2V0KHRydWUpO1xuICAgICAgICBcbiAgICAgICAgLy8gVXBkYXRlIGRpc3BsYXkgdGV4dFxuICAgICAgICB0aGlzLnVwZGF0ZU11bHRpUmFuZ2VUZXh0KCk7XG4gICAgICAgIFxuICAgICAgICAvLyBEb24ndCBjbG9zZSBpZiBtdWx0aVJhbmdlLCBhbGxvdyBhZGRpbmcgbW9yZSByYW5nZXNcbiAgICAgICAgaWYgKHRoaXMuY2xvc2VPblNlbGVjdGlvbiAmJiAhdGhpcy5tdWx0aVJhbmdlKSB7XG4gICAgICAgICAgdGhpcy5zaG93RGF0ZVBpY2tlci5zZXQoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICB0aGlzLmVtaXRNdWx0aUNoYW5nZSgpO1xuICAgICAgICB0aGlzLmVtaXRNdWx0aVNlbGVjdGlvbigpO1xuICAgICAgfVxuICAgICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFycygpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBTaW5nbGUgcmFuZ2UgbW9kZSAob3JpZ2luYWwgYmVoYXZpb3IpXG4gICAgICBpZiAodGhpcy5zZWxlY3RpbmdTdGFydERhdGUoKSkge1xuICAgICAgICB0aGlzLnN0YXJ0RGF0ZSA9IGRheU9iai5kYXRlO1xuICAgICAgICB0aGlzLmVuZERhdGUgPSAnJztcbiAgICAgICAgdGhpcy5kYXRlUmFuZ2VUZXh0LnNldCgnJyk7XG4gICAgICAgIHRoaXMuc2VsZWN0aW5nU3RhcnREYXRlLnNldChmYWxzZSk7XG4gICAgICAgIHRoaXMuZW1pdENoYW5nZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGRheU9iai5kYXRlIDwgdGhpcy5zdGFydERhdGUpIHtcbiAgICAgICAgICB0aGlzLmVuZERhdGUgPSB0aGlzLnN0YXJ0RGF0ZTtcbiAgICAgICAgICB0aGlzLnN0YXJ0RGF0ZSA9IGRheU9iai5kYXRlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuZW5kRGF0ZSA9IGRheU9iai5kYXRlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXBkYXRlRGF0ZVJhbmdlVGV4dCgpO1xuICAgICAgICBpZiAodGhpcy5jbG9zZU9uU2VsZWN0aW9uKSB7XG4gICAgICAgICAgdGhpcy5zaG93RGF0ZVBpY2tlci5zZXQoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2VsZWN0aW5nU3RhcnREYXRlLnNldCh0cnVlKTtcbiAgICAgICAgdGhpcy5lbWl0Q2hhbmdlKCk7XG4gICAgICAgIHRoaXMuZW1pdFNlbGVjdGlvbigpO1xuICAgICAgfVxuICAgICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFycygpO1xuICAgIH1cbiAgfVxuXG4gIGNoYW5nZU1vbnRoKGRpcmVjdGlvbjogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudE1vbnRoVmFsdWUgPSB0aGlzLmN1cnJlbnRNb250aCgpO1xuICAgIGNvbnN0IHllYXIgPSB0aGlzLmRhdGVBZGFwdGVyLmdldFllYXIoY3VycmVudE1vbnRoVmFsdWUpO1xuICAgIGNvbnN0IG1vbnRoID0gdGhpcy5kYXRlQWRhcHRlci5nZXRNb250aChjdXJyZW50TW9udGhWYWx1ZSk7XG4gICAgY29uc3QgbmV3Q3VycmVudE1vbnRoID0gdGhpcy5kYXRlQWRhcHRlci5jcmVhdGVEYXRlKHllYXIsIG1vbnRoICsgZGlyZWN0aW9uLCAxKTtcbiAgICB0aGlzLmN1cnJlbnRNb250aC5zZXQobmV3Q3VycmVudE1vbnRoKTtcbiAgICBcbiAgICBjb25zdCBuZXdZZWFyID0gdGhpcy5kYXRlQWRhcHRlci5nZXRZZWFyKG5ld0N1cnJlbnRNb250aCk7XG4gICAgY29uc3QgbmV3TW9udGggPSB0aGlzLmRhdGVBZGFwdGVyLmdldE1vbnRoKG5ld0N1cnJlbnRNb250aCk7XG4gICAgY29uc3QgbmV3UHJldmlvdXNNb250aCA9IHRoaXMuZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZShuZXdZZWFyLCBuZXdNb250aCAtIDEsIDEpO1xuICAgIHRoaXMucHJldmlvdXNNb250aC5zZXQobmV3UHJldmlvdXNNb250aCk7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFycygpO1xuICB9XG5cbiAgZ2V0TW9udGhOYW1lKGRhdGU6IERhdGUpOiBzdHJpbmcge1xuICAgIGNvbnN0IG1vbnRoTmFtZXMgPSB0aGlzLmxvY2FsZS5tb250aE5hbWVzIHx8IHRoaXMuZGVmYXVsdE1vbnRoTmFtZXM7XG4gICAgcmV0dXJuIGAke21vbnRoTmFtZXNbdGhpcy5kYXRlQWRhcHRlci5nZXRNb250aChkYXRlKV19ICR7dGhpcy5kYXRlQWRhcHRlci5nZXRZZWFyKGRhdGUpfWA7XG4gIH1cblxuICBnZXREYXlOYW1lcygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMubG9jYWxlLmRheU5hbWVzU2hvcnQgfHwgdGhpcy5kZWZhdWx0RGF5TmFtZXNTaG9ydDtcbiAgfVxuXG4gIHNlbGVjdFByZXNldFJhbmdlKHByZXNldDogUHJlc2V0Q29uZmlnKTogdm9pZCB7XG4gICAgaWYgKCFwcmVzZXQuZ2V0VmFsdWUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1ByZXNldENvbmZpZyBtdXN0IGhhdmUgZ2V0VmFsdWUoKSBmdW5jdGlvbicpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHJhbmdlID0gcHJlc2V0LmdldFZhbHVlKCk7XG4gICAgdGhpcy5zdGFydERhdGUgPSByYW5nZS5zdGFydDtcbiAgICB0aGlzLmVuZERhdGUgPSByYW5nZS5lbmQ7XG4gICAgdGhpcy51cGRhdGVEYXRlUmFuZ2VUZXh0KCk7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFycygpO1xuICAgIGlmICh0aGlzLmNsb3NlT25QcmVzZXRTZWxlY3Rpb24pIHtcbiAgICAgIHRoaXMuc2hvd0RhdGVQaWNrZXIuc2V0KGZhbHNlKTtcbiAgICB9XG4gICAgdGhpcy5lbWl0U2VsZWN0aW9uKCk7XG4gIH1cblxuICBjbGVhcigpOiB2b2lkIHtcbiAgICB0aGlzLnN0YXJ0RGF0ZSA9ICcnO1xuICAgIHRoaXMuZW5kRGF0ZSA9ICcnO1xuICAgIHRoaXMuZGF0ZVJhbmdlVGV4dC5zZXQoJycpO1xuICAgIHRoaXMuc2hvd0RhdGVQaWNrZXIuc2V0KGZhbHNlKTtcbiAgICB0aGlzLnNlbGVjdGluZ1N0YXJ0RGF0ZS5zZXQodHJ1ZSk7XG4gICAgXG4gICAgaWYgKHRoaXMubXVsdGlSYW5nZSkge1xuICAgICAgdGhpcy5zZWxlY3RlZFJhbmdlcy5zZXQoW10pO1xuICAgICAgdGhpcy5jdXJyZW50UmFuZ2VJbmRleC5zZXQoLTEpO1xuICAgICAgdGhpcy5lbWl0TXVsdGlDaGFuZ2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5lbWl0Q2hhbmdlKCk7XG4gICAgfVxuICAgIFxuICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFycygpO1xuICB9XG4gIFxuICByZW1vdmVSYW5nZShpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLm11bHRpUmFuZ2UpIHJldHVybjtcbiAgICBcbiAgICBjb25zdCBjdXJyZW50UmFuZ2VzID0gWy4uLnRoaXMuc2VsZWN0ZWRSYW5nZXMoKV07XG4gICAgY3VycmVudFJhbmdlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIHRoaXMuc2VsZWN0ZWRSYW5nZXMuc2V0KGN1cnJlbnRSYW5nZXMpO1xuICAgIFxuICAgIHRoaXMudXBkYXRlTXVsdGlSYW5nZVRleHQoKTtcbiAgICB0aGlzLmVtaXRNdWx0aUNoYW5nZSgpO1xuICAgIHRoaXMuZW1pdE11bHRpU2VsZWN0aW9uKCk7XG4gICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFycygpO1xuICB9XG4gIFxuICBwcml2YXRlIHVwZGF0ZU11bHRpUmFuZ2VUZXh0KCk6IHZvaWQge1xuICAgIGNvbnN0IGNvdW50ID0gdGhpcy5zZWxlY3RlZFJhbmdlcygpLmxlbmd0aDtcbiAgICBpZiAoY291bnQgPT09IDApIHtcbiAgICAgIHRoaXMuZGF0ZVJhbmdlVGV4dC5zZXQoJycpO1xuICAgIH0gZWxzZSBpZiAoY291bnQgPT09IDEpIHtcbiAgICAgIHRoaXMuZGF0ZVJhbmdlVGV4dC5zZXQoJzEgcmFuZ2Ugc2VsZWN0ZWQnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kYXRlUmFuZ2VUZXh0LnNldChgJHtjb3VudH0gcmFuZ2VzIHNlbGVjdGVkYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBlbWl0Q2hhbmdlKCk6IHZvaWQge1xuICAgIHRoaXMuZGF0ZVJhbmdlQ2hhbmdlLmVtaXQoe1xuICAgICAgc3RhcnREYXRlOiB0aGlzLnN0YXJ0RGF0ZSxcbiAgICAgIGVuZERhdGU6IHRoaXMuZW5kRGF0ZSxcbiAgICAgIHJhbmdlVGV4dDogdGhpcy5kYXRlUmFuZ2VUZXh0KClcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZW1pdFNlbGVjdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLmRhdGVSYW5nZVNlbGVjdGVkLmVtaXQoe1xuICAgICAgc3RhcnREYXRlOiB0aGlzLnN0YXJ0RGF0ZSxcbiAgICAgIGVuZERhdGU6IHRoaXMuZW5kRGF0ZSxcbiAgICAgIHJhbmdlVGV4dDogdGhpcy5kYXRlUmFuZ2VUZXh0KClcbiAgICB9KTtcbiAgfVxuICBcbiAgcHJpdmF0ZSBlbWl0TXVsdGlDaGFuZ2UoKTogdm9pZCB7XG4gICAgdGhpcy5tdWx0aURhdGVSYW5nZUNoYW5nZS5lbWl0KHtcbiAgICAgIHJhbmdlczogdGhpcy5zZWxlY3RlZFJhbmdlcygpXG4gICAgfSk7XG4gIH1cbiAgXG4gIHByaXZhdGUgZW1pdE11bHRpU2VsZWN0aW9uKCk6IHZvaWQge1xuICAgIHRoaXMubXVsdGlEYXRlUmFuZ2VTZWxlY3RlZC5lbWl0KHtcbiAgICAgIHJhbmdlczogdGhpcy5zZWxlY3RlZFJhbmdlcygpXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGdldERhdGVSYW5nZVZhbHVlKCk6IERhdGVSYW5nZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXJ0RGF0ZTogdGhpcy5zdGFydERhdGUsXG4gICAgICBlbmREYXRlOiB0aGlzLmVuZERhdGUsXG4gICAgICByYW5nZVRleHQ6IHRoaXMuZGF0ZVJhbmdlVGV4dCgpXG4gICAgfTtcbiAgfVxuXG4gIC8vIENvbnRyb2xWYWx1ZUFjY2Vzc29yIGltcGxlbWVudGF0aW9uXG4gIHdyaXRlVmFsdWUodmFsdWU6IERhdGVSYW5nZSB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIHRoaXMuc3RhcnREYXRlID0gdmFsdWUuc3RhcnREYXRlIHx8ICcnO1xuICAgICAgdGhpcy5lbmREYXRlID0gdmFsdWUuZW5kRGF0ZSB8fCAnJztcbiAgICAgIGlmICh0aGlzLnN0YXJ0RGF0ZSAmJiB0aGlzLmVuZERhdGUpIHtcbiAgICAgICAgdGhpcy51cGRhdGVEYXRlUmFuZ2VUZXh0KCk7XG4gICAgICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcnMoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zdGFydERhdGUgPSAnJztcbiAgICAgIHRoaXMuZW5kRGF0ZSA9ICcnO1xuICAgICAgdGhpcy5kYXRlUmFuZ2VUZXh0LnNldCgnJyk7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogKHZhbHVlOiBEYXRlUmFuZ2UgfCBudWxsKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5vbkNoYW5nZSA9IGZuO1xuICB9XG5cbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICB9XG5cbiAgc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5pc0Rpc2FibGVkLnNldChpc0Rpc2FibGVkKTtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImRhdGVwaWNrZXItd3JhcHBlclwiIFxuICBbc3R5bGUuLS1pbnB1dC1ib3JkZXItaG92ZXJdPVwiaW5wdXRCb3JkZXJDb2xvckhvdmVyXCJcbiAgW3N0eWxlLi0taW5wdXQtYm9yZGVyLWZvY3VzXT1cImlucHV0Qm9yZGVyQ29sb3JGb2N1c1wiPlxuICA8aW5wdXQgXG4gICAgdHlwZT1cInRleHRcIiBcbiAgICBjbGFzcz1cImRhdGVwaWNrZXItaW5wdXRcIiBcbiAgICBbdmFsdWVdPVwiZGF0ZVJhbmdlVGV4dCgpXCIgXG4gICAgKGNsaWNrKT1cInRvZ2dsZURhdGVQaWNrZXIoKVwiIFxuICAgIFtwbGFjZWhvbGRlcl09XCJwbGFjZWhvbGRlclwiXG4gICAgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWQoKVwiXG4gICAgW25nU3R5bGVdPVwie1xuICAgICAgJ2JhY2tncm91bmQtY29sb3InOiBpbnB1dEJhY2tncm91bmRDb2xvcixcbiAgICAgICdjb2xvcic6IGlucHV0VGV4dENvbG9yLFxuICAgICAgJ2JvcmRlci1jb2xvcic6IGlucHV0Qm9yZGVyQ29sb3IsXG4gICAgICAncGFkZGluZyc6IGlucHV0UGFkZGluZ1xuICAgIH1cIlxuICAgIHJlYWRvbmx5PlxuXG4gIEBpZiAoc2hvd0RhdGVQaWNrZXIoKSkge1xuICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItZHJvcGRvd25cIj5cbiAgICBAaWYgKHNob3dQcmVzZXRzKSB7XG4gICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLXByZXNldHNcIj5cbiAgICAgIEBmb3IgKHByZXNldCBvZiBwcmVzZXRzOyB0cmFjayBwcmVzZXQubGFiZWwpIHtcbiAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJzZWxlY3RQcmVzZXRSYW5nZShwcmVzZXQpXCI+e3sgcHJlc2V0LmxhYmVsIH19PC9idXR0b24+XG4gICAgICB9XG4gICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0bi1jbG9zZS1jYWxlbmRhclwiIChjbGljayk9XCJjbG9zZURhdGVQaWNrZXIoKVwiIHRpdGxlPVwiQ2xvc2VcIj5cbiAgICAgICAgw5dcbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICAgIH1cblxuICAgIEBpZiAoIXNob3dQcmVzZXRzKSB7XG4gICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLWhlYWRlci1vbmx5LWNsb3NlXCI+XG4gICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0bi1jbG9zZS1jYWxlbmRhclwiIChjbGljayk9XCJjbG9zZURhdGVQaWNrZXIoKVwiIHRpdGxlPVwiQ2xvc2VcIj5cbiAgICAgICAgw5dcbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICAgIH1cblxuICAgIDwhLS0gQ2FsZW5kYXJzIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1jYWxlbmRhcnNcIj5cbiAgICAgIDwhLS0gUHJldmlvdXMgbW9udGggY2FsZW5kYXIgLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItY2FsZW5kYXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLWhlYWRlclwiPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJjaGFuZ2VNb250aCgtMSlcIj5cbiAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgZmlsbD1cImN1cnJlbnRDb2xvclwiIHZpZXdCb3g9XCIwIDAgMTYgMTZcIj5cbiAgICAgICAgICAgICAgPHBhdGggZmlsbC1ydWxlPVwiZXZlbm9kZFwiIGQ9XCJNMTEuMzU0IDEuNjQ2YS41LjUgMCAwIDEgMCAuNzA4TDUuNzA3IDhsNS42NDcgNS42NDZhLjUuNSAwIDAgMS0uNzA4LjcwOGwtNi02YS41LjUgMCAwIDEgMC0uNzA4bDYtNmEuNS41IDAgMCAxIC43MDggMHpcIi8+XG4gICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8c3Bhbj57eyBwcmV2aW91c01vbnRoTmFtZSgpIH19PC9zcGFuPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIHN0eWxlPVwidmlzaWJpbGl0eTogaGlkZGVuO1wiPlxuICAgICAgICAgICAgPHN2ZyB3aWR0aD1cIjE2XCIgaGVpZ2h0PVwiMTZcIiBmaWxsPVwiY3VycmVudENvbG9yXCIgdmlld0JveD1cIjAgMCAxNiAxNlwiPlxuICAgICAgICAgICAgICA8cGF0aCBmaWxsLXJ1bGU9XCJldmVub2RkXCIgZD1cIk00LjY0NiAxLjY0NmEuNS41IDAgMCAxIC43MDggMGw2IDZhLjUuNSAwIDAgMSAwIC43MDhsLTYgNmEuNS41IDAgMCAxLS43MDgtLjcwOEwxMC4yOTMgOCA0LjY0NiAyLjM1NGEuNS41IDAgMCAxIDAtLjcwOHpcIi8+XG4gICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci13ZWVrZGF5c1wiPlxuICAgICAgICAgIEBmb3IgKGRheU5hbWUgb2Ygd2Vla0RheU5hbWVzKCk7IHRyYWNrICRpbmRleCkge1xuICAgICAgICAgICAgPHNwYW4+e3sgZGF5TmFtZSB9fTwvc3Bhbj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItZGF5c1wiPlxuICAgICAgICAgIEBmb3IgKGRheU9iaiBvZiBwcmV2aW91c01vbnRoRGF5cygpOyB0cmFjayBkYXlPYmouZGF0ZSB8fCAkaW5kZXgpIHtcbiAgICAgICAgICAgIDxidXR0b24gXG4gICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICBjbGFzcz1cImRhdGUtcGlja2VyLWRheVwiIFxuICAgICAgICAgICAgICBbY2xhc3MuZW1wdHldPVwiIWRheU9iai5pc0N1cnJlbnRNb250aFwiXG4gICAgICAgICAgICAgIFtjbGFzcy5zZWxlY3RlZF09XCJkYXlPYmouaXNTdGFydCB8fCBkYXlPYmouaXNFbmRcIlxuICAgICAgICAgICAgICBbY2xhc3MuaW4tcmFuZ2VdPVwiZGF5T2JqLmluUmFuZ2UgJiYgIWRheU9iai5pc1N0YXJ0ICYmICFkYXlPYmouaXNFbmRcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0RGF5KGRheU9iailcIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWRheU9iai5pc0N1cnJlbnRNb250aFwiPlxuICAgICAgICAgICAgICB7eyBkYXlPYmouZGF5IH19XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDwhLS0gQ3VycmVudCBtb250aCBjYWxlbmRhciAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1jYWxlbmRhclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItaGVhZGVyXCI+XG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgc3R5bGU9XCJ2aXNpYmlsaXR5OiBoaWRkZW47XCI+XG4gICAgICAgICAgICA8c3ZnIHdpZHRoPVwiMTZcIiBoZWlnaHQ9XCIxNlwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIiB2aWV3Qm94PVwiMCAwIDE2IDE2XCI+XG4gICAgICAgICAgICAgIDxwYXRoIGZpbGwtcnVsZT1cImV2ZW5vZGRcIiBkPVwiTTExLjM1NCAxLjY0NmEuNS41IDAgMCAxIDAgLjcwOEw1LjcwNyA4bDUuNjQ3IDUuNjQ2YS41LjUgMCAwIDEtLjcwOC43MDhsLTYtNmEuNS41IDAgMCAxIDAtLjcwOGw2LTZhLjUuNSAwIDAgMSAuNzA4IDB6XCIvPlxuICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPHNwYW4+e3sgY3VycmVudE1vbnRoTmFtZSgpIH19PC9zcGFuPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJjaGFuZ2VNb250aCgxKVwiPlxuICAgICAgICAgICAgPHN2ZyB3aWR0aD1cIjE2XCIgaGVpZ2h0PVwiMTZcIiBmaWxsPVwiY3VycmVudENvbG9yXCIgdmlld0JveD1cIjAgMCAxNiAxNlwiPlxuICAgICAgICAgICAgICA8cGF0aCBmaWxsLXJ1bGU9XCJldmVub2RkXCIgZD1cIk00LjY0NiAxLjY0NmEuNS41IDAgMCAxIC43MDggMGw2IDZhLjUuNSAwIDAgMSAwIC43MDhsLTYgNmEuNS41IDAgMCAxLS43MDgtLjcwOEwxMC4yOTMgOCA0LjY0NiAyLjM1NGEuNS41IDAgMCAxIDAtLjcwOHpcIi8+XG4gICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci13ZWVrZGF5c1wiPlxuICAgICAgICAgIEBmb3IgKGRheU5hbWUgb2Ygd2Vla0RheU5hbWVzKCk7IHRyYWNrICRpbmRleCkge1xuICAgICAgICAgICAgPHNwYW4+e3sgZGF5TmFtZSB9fTwvc3Bhbj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItZGF5c1wiPlxuICAgICAgICAgIEBmb3IgKGRheU9iaiBvZiBjdXJyZW50TW9udGhEYXlzKCk7IHRyYWNrIGRheU9iai5kYXRlIHx8ICRpbmRleCkge1xuICAgICAgICAgICAgPGJ1dHRvbiBcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiZGF0ZS1waWNrZXItZGF5XCIgXG4gICAgICAgICAgICAgIFtjbGFzcy5lbXB0eV09XCIhZGF5T2JqLmlzQ3VycmVudE1vbnRoXCJcbiAgICAgICAgICAgICAgW2NsYXNzLnNlbGVjdGVkXT1cImRheU9iai5pc1N0YXJ0IHx8IGRheU9iai5pc0VuZFwiXG4gICAgICAgICAgICAgIFtjbGFzcy5pbi1yYW5nZV09XCJkYXlPYmouaW5SYW5nZSAmJiAhZGF5T2JqLmlzU3RhcnQgJiYgIWRheU9iai5pc0VuZFwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3REYXkoZGF5T2JqKVwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhZGF5T2JqLmlzQ3VycmVudE1vbnRoXCI+XG4gICAgICAgICAgICAgIHt7IGRheU9iai5kYXkgfX1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0gTXVsdGktUmFuZ2UgTGlzdCAtLT5cbiAgICBAaWYgKG11bHRpUmFuZ2UgJiYgc2VsZWN0ZWRSYW5nZXMoKS5sZW5ndGggPiAwKSB7XG4gICAgPGRpdiBjbGFzcz1cIm11bHRpLXJhbmdlLWxpc3RcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJtdWx0aS1yYW5nZS1oZWFkZXJcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJtdWx0aS1yYW5nZS10aXRsZVwiPlNlbGVjdGVkIFJhbmdlcyAoe3sgc2VsZWN0ZWRSYW5nZXMoKS5sZW5ndGggfX0pPC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwibXVsdGktcmFuZ2UtaXRlbXNcIj5cbiAgICAgICAgQGZvciAocmFuZ2Ugb2Ygc2VsZWN0ZWRSYW5nZXMoKTsgdHJhY2sgJGluZGV4KSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJtdWx0aS1yYW5nZS1pdGVtXCI+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJtdWx0aS1yYW5nZS10ZXh0XCI+e3sgcmFuZ2UucmFuZ2VUZXh0IH19PC9zcGFuPlxuICAgICAgICAgIDxidXR0b24gXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCIgXG4gICAgICAgICAgICBjbGFzcz1cImJ0bi1yZW1vdmUtcmFuZ2VcIiBcbiAgICAgICAgICAgIChjbGljayk9XCJyZW1vdmVSYW5nZSgkaW5kZXgpXCJcbiAgICAgICAgICAgIHRpdGxlPVwiUmVtb3ZlIHRoaXMgcmFuZ2VcIj5cbiAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIxNFwiIGhlaWdodD1cIjE0XCIgZmlsbD1cImN1cnJlbnRDb2xvclwiIHZpZXdCb3g9XCIwIDAgMTYgMTZcIj5cbiAgICAgICAgICAgICAgPHBhdGggZD1cIk0yLjE0NiAyLjg1NGEuNS41IDAgMSAxIC43MDgtLjcwOEw4IDcuMjkzbDUuMTQ2LTUuMTQ3YS41LjUgMCAwIDEgLjcwOC43MDhMOC43MDcgOGw1LjE0NyA1LjE0NmEuNS41IDAgMCAxLS43MDguNzA4TDggOC43MDdsLTUuMTQ2IDUuMTQ3YS41LjUgMCAwIDEtLjcwOC0uNzA4TDcuMjkzIDggMi4xNDYgMi44NTRaXCIvPlxuICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICB9XG5cbiAgICA8IS0tIEZvb3RlciB3aXRoIGNsZWFyIGJ1dHRvbiAtLT5cbiAgICBAaWYgKHNob3dDbGVhckJ1dHRvbiB8fCBtdWx0aVJhbmdlKSB7XG4gICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLWZvb3RlclwiPlxuICAgICAgQGlmIChtdWx0aVJhbmdlKSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJtdWx0aS1yYW5nZS1mb290ZXItYWN0aW9uc1wiPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuLWNsZWFyXCIgKGNsaWNrKT1cImNsZWFyKClcIiB0aXRsZT1cIkNsZWFyIGFsbCByYW5nZXNcIj5cbiAgICAgICAgICAgIENsZWFyIEFsbFxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuLWRvbmVcIiAoY2xpY2spPVwiY2xvc2VEYXRlUGlja2VyKClcIiB0aXRsZT1cIkRvbmUgc2VsZWN0aW5nXCI+XG4gICAgICAgICAgICBEb25lXG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgfVxuICAgICAgQGlmICghbXVsdGlSYW5nZSAmJiBzaG93Q2xlYXJCdXR0b24pIHtcbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4tY2xlYXJcIiAoY2xpY2spPVwiY2xlYXIoKVwiIHRpdGxlPVwiQ2xlYXIgc2VsZWN0aW9uXCI+XG4gICAgICAgICAgQ2xlYXJcbiAgICAgICAgPC9idXR0b24+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gICAgfVxuICA8L2Rpdj5cbiAgfVxuPC9kaXY+XG4iXX0=