@oneluiz/dual-datepicker 3.0.0 → 3.1.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.
@@ -1,448 +0,0 @@
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=