@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.
- package/README.md +36 -9
- package/{dist/dual-datepicker.component.d.ts → dual-datepicker.component.d.ts} +15 -0
- package/esm2022/dual-datepicker.component.mjs +691 -0
- package/fesm2022/oneluiz-dual-datepicker.mjs +1096 -0
- package/fesm2022/oneluiz-dual-datepicker.mjs.map +1 -0
- package/package.json +19 -23
- package/.angular/cache/18.2.21/demo/angular-compiler.db +0 -0
- package/.angular/cache/18.2.21/demo/angular-compiler.db-lock +0 -0
- package/.nojekyll +0 -0
- package/CHANGELOG.md +0 -254
- package/GITHUB_PAGES.md +0 -82
- package/MIGRATION_V3.md +0 -210
- package/angular.json +0 -75
- package/dist/LICENSE +0 -21
- package/dist/README.md +0 -925
- package/dist/esm2022/dual-datepicker.component.mjs +0 -448
- package/dist/fesm2022/oneluiz-dual-datepicker.mjs +0 -853
- package/dist/fesm2022/oneluiz-dual-datepicker.mjs.map +0 -1
- package/ng-package.json +0 -7
- /package/{dist/date-adapter.d.ts → date-adapter.d.ts} +0 -0
- /package/{dist/esm2022 → esm2022}/date-adapter.mjs +0 -0
- /package/{dist/esm2022 → esm2022}/native-date-adapter.mjs +0 -0
- /package/{dist/esm2022 → esm2022}/oneluiz-dual-datepicker.mjs +0 -0
- /package/{dist/esm2022 → esm2022}/preset-utils.mjs +0 -0
- /package/{dist/esm2022 → esm2022}/public-api.mjs +0 -0
- /package/{dist/index.d.ts → index.d.ts} +0 -0
- /package/{dist/native-date-adapter.d.ts → native-date-adapter.d.ts} +0 -0
- /package/{dist/preset-utils.d.ts → preset-utils.d.ts} +0 -0
- /package/{dist/public-api.d.ts → public-api.d.ts} +0 -0
|
@@ -0,0 +1,691 @@
|
|
|
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
|
+
// Keyboard navigation
|
|
46
|
+
focusedDay = signal(null); // monthIndex: 0 = previous, 1 = current
|
|
47
|
+
// Computed values
|
|
48
|
+
currentMonthName = computed(() => this.getMonthName(this.currentMonth()));
|
|
49
|
+
previousMonthName = computed(() => this.getMonthName(this.previousMonth()));
|
|
50
|
+
weekDayNames = computed(() => this.getDayNames());
|
|
51
|
+
defaultMonthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
52
|
+
defaultMonthNamesShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
53
|
+
defaultDayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
54
|
+
defaultDayNamesShort = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
|
|
55
|
+
// ControlValueAccessor callbacks
|
|
56
|
+
onChange = () => { };
|
|
57
|
+
onTouched = () => { };
|
|
58
|
+
constructor(elementRef) {
|
|
59
|
+
this.elementRef = elementRef;
|
|
60
|
+
// Effect to emit changes when dates change
|
|
61
|
+
effect(() => {
|
|
62
|
+
const range = this.dateRangeText();
|
|
63
|
+
if (this.startDate || this.endDate) {
|
|
64
|
+
this.onChange(this.getDateRangeValue());
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
onClickOutside(event) {
|
|
69
|
+
if (this.showDatePicker() && this.closeOnClickOutside) {
|
|
70
|
+
const clickedInside = this.elementRef.nativeElement.contains(event.target);
|
|
71
|
+
if (!clickedInside) {
|
|
72
|
+
this.closeDatePicker();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
handleKeyboardNavigation(event) {
|
|
77
|
+
if (!this.showDatePicker()) {
|
|
78
|
+
// When picker is closed, allow Enter/Space to open it
|
|
79
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
80
|
+
const target = event.target;
|
|
81
|
+
if (target.classList.contains('datepicker-input')) {
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
this.toggleDatePicker();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// When picker is open
|
|
89
|
+
switch (event.key) {
|
|
90
|
+
case 'Escape':
|
|
91
|
+
event.preventDefault();
|
|
92
|
+
this.closeDatePicker();
|
|
93
|
+
break;
|
|
94
|
+
case 'ArrowUp':
|
|
95
|
+
event.preventDefault();
|
|
96
|
+
this.moveFocusVertical(-1);
|
|
97
|
+
break;
|
|
98
|
+
case 'ArrowDown':
|
|
99
|
+
event.preventDefault();
|
|
100
|
+
this.moveFocusVertical(1);
|
|
101
|
+
break;
|
|
102
|
+
case 'ArrowLeft':
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
this.moveFocusHorizontal(-1);
|
|
105
|
+
break;
|
|
106
|
+
case 'ArrowRight':
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
this.moveFocusHorizontal(1);
|
|
109
|
+
break;
|
|
110
|
+
case 'Enter':
|
|
111
|
+
case ' ':
|
|
112
|
+
event.preventDefault();
|
|
113
|
+
this.selectFocusedDay();
|
|
114
|
+
break;
|
|
115
|
+
case 'Home':
|
|
116
|
+
event.preventDefault();
|
|
117
|
+
this.moveFocusToFirstDay();
|
|
118
|
+
break;
|
|
119
|
+
case 'End':
|
|
120
|
+
event.preventDefault();
|
|
121
|
+
this.moveFocusToLastDay();
|
|
122
|
+
break;
|
|
123
|
+
case 'PageUp':
|
|
124
|
+
event.preventDefault();
|
|
125
|
+
if (event.shiftKey) {
|
|
126
|
+
this.moveFocusYear(-1);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.changeMonth(-1);
|
|
130
|
+
this.adjustFocusAfterMonthChange();
|
|
131
|
+
}
|
|
132
|
+
break;
|
|
133
|
+
case 'PageDown':
|
|
134
|
+
event.preventDefault();
|
|
135
|
+
if (event.shiftKey) {
|
|
136
|
+
this.moveFocusYear(1);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
this.changeMonth(1);
|
|
140
|
+
this.adjustFocusAfterMonthChange();
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Keyboard navigation methods
|
|
146
|
+
initializeFocus() {
|
|
147
|
+
// Set initial focus to start date, end date, or first available day
|
|
148
|
+
if (this.startDate) {
|
|
149
|
+
const startMonth = this.isDateInMonth(this.startDate, this.previousMonth()) ? 0 : 1;
|
|
150
|
+
this.focusedDay.set({ date: this.startDate, monthIndex: startMonth });
|
|
151
|
+
}
|
|
152
|
+
else if (this.endDate) {
|
|
153
|
+
const endMonth = this.isDateInMonth(this.endDate, this.previousMonth()) ? 0 : 1;
|
|
154
|
+
this.focusedDay.set({ date: this.endDate, monthIndex: endMonth });
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
// Focus first day of current month
|
|
158
|
+
const currentMonthDays = this.currentMonthDays();
|
|
159
|
+
const firstDay = currentMonthDays.find(day => day.isCurrentMonth);
|
|
160
|
+
if (firstDay) {
|
|
161
|
+
this.focusedDay.set({ date: firstDay.date, monthIndex: 1 });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
isDateInMonth(dateStr, monthDate) {
|
|
166
|
+
const date = this.dateAdapter.parse(dateStr);
|
|
167
|
+
if (!date)
|
|
168
|
+
return false;
|
|
169
|
+
const year = this.dateAdapter.getYear(date);
|
|
170
|
+
const month = this.dateAdapter.getMonth(date);
|
|
171
|
+
const monthYear = this.dateAdapter.getYear(monthDate);
|
|
172
|
+
const monthMonth = this.dateAdapter.getMonth(monthDate);
|
|
173
|
+
return year === monthYear && month === monthMonth;
|
|
174
|
+
}
|
|
175
|
+
moveFocusHorizontal(direction) {
|
|
176
|
+
const focused = this.focusedDay();
|
|
177
|
+
if (!focused) {
|
|
178
|
+
this.initializeFocus();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const currentDate = this.dateAdapter.parse(focused.date);
|
|
182
|
+
if (!currentDate)
|
|
183
|
+
return;
|
|
184
|
+
const newDate = this.dateAdapter.addDays(currentDate, direction);
|
|
185
|
+
const newDateStr = this.formatDate(newDate);
|
|
186
|
+
// Determine which month the new date belongs to
|
|
187
|
+
const inPrevMonth = this.isDateInMonth(newDateStr, this.previousMonth());
|
|
188
|
+
const inCurrMonth = this.isDateInMonth(newDateStr, this.currentMonth());
|
|
189
|
+
if (inPrevMonth || inCurrMonth) {
|
|
190
|
+
this.focusedDay.set({
|
|
191
|
+
date: newDateStr,
|
|
192
|
+
monthIndex: inPrevMonth ? 0 : 1
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
// Date is outside visible months, navigate month
|
|
197
|
+
if (direction > 0) {
|
|
198
|
+
this.changeMonth(1);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
this.changeMonth(-1);
|
|
202
|
+
}
|
|
203
|
+
this.focusedDay.set({ date: newDateStr, monthIndex: direction > 0 ? 0 : 1 });
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
moveFocusVertical(direction) {
|
|
207
|
+
const focused = this.focusedDay();
|
|
208
|
+
if (!focused) {
|
|
209
|
+
this.initializeFocus();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const currentDate = this.dateAdapter.parse(focused.date);
|
|
213
|
+
if (!currentDate)
|
|
214
|
+
return;
|
|
215
|
+
const newDate = this.dateAdapter.addDays(currentDate, direction * 7); // Move by week
|
|
216
|
+
const newDateStr = this.formatDate(newDate);
|
|
217
|
+
const inPrevMonth = this.isDateInMonth(newDateStr, this.previousMonth());
|
|
218
|
+
const inCurrMonth = this.isDateInMonth(newDateStr, this.currentMonth());
|
|
219
|
+
if (inPrevMonth || inCurrMonth) {
|
|
220
|
+
this.focusedDay.set({
|
|
221
|
+
date: newDateStr,
|
|
222
|
+
monthIndex: inPrevMonth ? 0 : 1
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
// Navigate to month containing the new date
|
|
227
|
+
if (direction > 0) {
|
|
228
|
+
this.changeMonth(1);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
this.changeMonth(-1);
|
|
232
|
+
}
|
|
233
|
+
this.focusedDay.set({ date: newDateStr, monthIndex: direction > 0 ? 0 : 1 });
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
moveFocusToFirstDay() {
|
|
237
|
+
const prevMonthDays = this.previousMonthDays();
|
|
238
|
+
const firstDay = prevMonthDays.find(day => day.isCurrentMonth);
|
|
239
|
+
if (firstDay) {
|
|
240
|
+
this.focusedDay.set({ date: firstDay.date, monthIndex: 0 });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
moveFocusToLastDay() {
|
|
244
|
+
const currMonthDays = this.currentMonthDays();
|
|
245
|
+
const validDays = currMonthDays.filter(day => day.isCurrentMonth);
|
|
246
|
+
const lastDay = validDays[validDays.length - 1];
|
|
247
|
+
if (lastDay) {
|
|
248
|
+
this.focusedDay.set({ date: lastDay.date, monthIndex: 1 });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
moveFocusYear(direction) {
|
|
252
|
+
const focused = this.focusedDay();
|
|
253
|
+
if (!focused) {
|
|
254
|
+
this.initializeFocus();
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const currentDate = this.dateAdapter.parse(focused.date);
|
|
258
|
+
if (!currentDate)
|
|
259
|
+
return;
|
|
260
|
+
const currentYear = this.dateAdapter.getYear(currentDate);
|
|
261
|
+
const currentMonth = this.dateAdapter.getMonth(currentDate);
|
|
262
|
+
const currentDay = this.dateAdapter.getDate(currentDate);
|
|
263
|
+
const newDate = this.dateAdapter.createDate(currentYear + direction, currentMonth, currentDay);
|
|
264
|
+
const newDateStr = this.formatDate(newDate);
|
|
265
|
+
// Update months to show the new year
|
|
266
|
+
this.currentMonth.set(this.dateAdapter.createDate(currentYear + direction, currentMonth, 1));
|
|
267
|
+
this.previousMonth.set(this.dateAdapter.createDate(currentYear + direction, currentMonth - 1, 1));
|
|
268
|
+
this.generateCalendars();
|
|
269
|
+
const inPrevMonth = this.isDateInMonth(newDateStr, this.previousMonth());
|
|
270
|
+
this.focusedDay.set({
|
|
271
|
+
date: newDateStr,
|
|
272
|
+
monthIndex: inPrevMonth ? 0 : 1
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
adjustFocusAfterMonthChange() {
|
|
276
|
+
const focused = this.focusedDay();
|
|
277
|
+
if (!focused)
|
|
278
|
+
return;
|
|
279
|
+
const inPrevMonth = this.isDateInMonth(focused.date, this.previousMonth());
|
|
280
|
+
const inCurrMonth = this.isDateInMonth(focused.date, this.currentMonth());
|
|
281
|
+
if (!inPrevMonth && !inCurrMonth) {
|
|
282
|
+
// Focused day is no longer visible, move to equivalent day in visible months
|
|
283
|
+
this.initializeFocus();
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
// Update month index if needed
|
|
287
|
+
this.focusedDay.set({
|
|
288
|
+
date: focused.date,
|
|
289
|
+
monthIndex: inPrevMonth ? 0 : 1
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
selectFocusedDay() {
|
|
294
|
+
const focused = this.focusedDay();
|
|
295
|
+
if (!focused)
|
|
296
|
+
return;
|
|
297
|
+
const monthDays = focused.monthIndex === 0 ? this.previousMonthDays() : this.currentMonthDays();
|
|
298
|
+
const dayObj = monthDays.find(day => day.date === focused.date && day.isCurrentMonth);
|
|
299
|
+
if (dayObj) {
|
|
300
|
+
this.selectDay(dayObj);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
hasKeyboardFocus(date, monthIndex) {
|
|
304
|
+
const focused = this.focusedDay();
|
|
305
|
+
return focused !== null && focused.date === date && focused.monthIndex === monthIndex;
|
|
306
|
+
}
|
|
307
|
+
ngOnInit() {
|
|
308
|
+
if (this.startDate && this.endDate) {
|
|
309
|
+
this.updateDateRangeText();
|
|
310
|
+
this.generateCalendars();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
ngOnChanges(changes) {
|
|
314
|
+
if (changes['startDate'] || changes['endDate']) {
|
|
315
|
+
if (this.startDate && this.endDate) {
|
|
316
|
+
this.updateDateRangeText();
|
|
317
|
+
this.generateCalendars();
|
|
318
|
+
}
|
|
319
|
+
else if (!this.startDate && !this.endDate) {
|
|
320
|
+
this.dateRangeText.set('');
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
formatDate(date) {
|
|
325
|
+
const year = this.dateAdapter.getYear(date);
|
|
326
|
+
const month = String(this.dateAdapter.getMonth(date) + 1).padStart(2, '0');
|
|
327
|
+
const day = String(this.dateAdapter.getDate(date)).padStart(2, '0');
|
|
328
|
+
return `${year}-${month}-${day}`;
|
|
329
|
+
}
|
|
330
|
+
formatDateDisplay(dateStr) {
|
|
331
|
+
if (!dateStr)
|
|
332
|
+
return '';
|
|
333
|
+
const date = this.dateAdapter.parse(dateStr);
|
|
334
|
+
if (!date)
|
|
335
|
+
return '';
|
|
336
|
+
const monthNames = this.locale.monthNamesShort || this.defaultMonthNamesShort;
|
|
337
|
+
return `${this.dateAdapter.getDate(date)} ${monthNames[this.dateAdapter.getMonth(date)]}`;
|
|
338
|
+
}
|
|
339
|
+
updateDateRangeText() {
|
|
340
|
+
if (this.startDate && this.endDate) {
|
|
341
|
+
const start = this.formatDateDisplay(this.startDate);
|
|
342
|
+
const end = this.formatDateDisplay(this.endDate);
|
|
343
|
+
this.dateRangeText.set(`${start} - ${end}`);
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
this.dateRangeText.set('');
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
toggleDatePicker() {
|
|
350
|
+
this.showDatePicker.update(value => !value);
|
|
351
|
+
if (this.showDatePicker()) {
|
|
352
|
+
this.selectingStartDate.set(true);
|
|
353
|
+
const currentMonthValue = this.currentMonth();
|
|
354
|
+
const year = this.dateAdapter.getYear(currentMonthValue);
|
|
355
|
+
const month = this.dateAdapter.getMonth(currentMonthValue);
|
|
356
|
+
const previousMonthDate = this.dateAdapter.createDate(year, month - 1, 1);
|
|
357
|
+
this.previousMonth.set(previousMonthDate);
|
|
358
|
+
this.generateCalendars();
|
|
359
|
+
// Initialize keyboard focus
|
|
360
|
+
this.initializeFocus();
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
// Clear focus when closing
|
|
364
|
+
this.focusedDay.set(null);
|
|
365
|
+
}
|
|
366
|
+
this.onTouched();
|
|
367
|
+
}
|
|
368
|
+
closeDatePicker() {
|
|
369
|
+
this.showDatePicker.set(false);
|
|
370
|
+
this.focusedDay.set(null);
|
|
371
|
+
this.onTouched();
|
|
372
|
+
}
|
|
373
|
+
generateCalendars() {
|
|
374
|
+
this.previousMonthDays.set(this.generateMonthCalendar(this.previousMonth()));
|
|
375
|
+
this.currentMonthDays.set(this.generateMonthCalendar(this.currentMonth()));
|
|
376
|
+
}
|
|
377
|
+
generateMonthCalendar(date) {
|
|
378
|
+
const year = this.dateAdapter.getYear(date);
|
|
379
|
+
const month = this.dateAdapter.getMonth(date);
|
|
380
|
+
const firstDay = this.dateAdapter.createDate(year, month, 1);
|
|
381
|
+
const lastDay = this.dateAdapter.createDate(year, month + 1, 0);
|
|
382
|
+
const daysInMonth = this.dateAdapter.getDate(lastDay);
|
|
383
|
+
const firstDayOfWeek = this.dateAdapter.getDay(firstDay);
|
|
384
|
+
const monthDays = [];
|
|
385
|
+
for (let i = 0; i < firstDayOfWeek; i++) {
|
|
386
|
+
monthDays.push({ day: null, isCurrentMonth: false });
|
|
387
|
+
}
|
|
388
|
+
for (let day = 1; day <= daysInMonth; day++) {
|
|
389
|
+
const dayDate = this.dateAdapter.createDate(year, month, day);
|
|
390
|
+
const dateStr = this.formatDate(dayDate);
|
|
391
|
+
monthDays.push({
|
|
392
|
+
day: day,
|
|
393
|
+
date: dateStr,
|
|
394
|
+
isCurrentMonth: true,
|
|
395
|
+
isStart: this.startDate === dateStr,
|
|
396
|
+
isEnd: this.endDate === dateStr,
|
|
397
|
+
inRange: this.isInRange(dateStr)
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
return monthDays;
|
|
401
|
+
}
|
|
402
|
+
isInRange(dateStr) {
|
|
403
|
+
if (this.multiRange) {
|
|
404
|
+
// Check if date is in any of the selected ranges
|
|
405
|
+
return this.selectedRanges().some(range => {
|
|
406
|
+
return dateStr >= range.startDate && dateStr <= range.endDate;
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
if (!this.startDate || !this.endDate)
|
|
411
|
+
return false;
|
|
412
|
+
return dateStr >= this.startDate && dateStr <= this.endDate;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
selectDay(dayObj) {
|
|
416
|
+
if (!dayObj.isCurrentMonth || this.isDisabled())
|
|
417
|
+
return;
|
|
418
|
+
if (this.multiRange) {
|
|
419
|
+
// Multi-range mode: add ranges to array
|
|
420
|
+
if (this.selectingStartDate()) {
|
|
421
|
+
this.startDate = dayObj.date;
|
|
422
|
+
this.endDate = '';
|
|
423
|
+
this.dateRangeText.set('');
|
|
424
|
+
this.selectingStartDate.set(false);
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
if (dayObj.date < this.startDate) {
|
|
428
|
+
this.endDate = this.startDate;
|
|
429
|
+
this.startDate = dayObj.date;
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
this.endDate = dayObj.date;
|
|
433
|
+
}
|
|
434
|
+
// Add the new range to the array
|
|
435
|
+
const newRange = {
|
|
436
|
+
startDate: this.startDate,
|
|
437
|
+
endDate: this.endDate,
|
|
438
|
+
rangeText: this.formatDateDisplay(this.startDate) + ' – ' + this.formatDateDisplay(this.endDate)
|
|
439
|
+
};
|
|
440
|
+
const currentRanges = [...this.selectedRanges()];
|
|
441
|
+
currentRanges.push(newRange);
|
|
442
|
+
this.selectedRanges.set(currentRanges);
|
|
443
|
+
// Reset for next range selection
|
|
444
|
+
this.startDate = '';
|
|
445
|
+
this.endDate = '';
|
|
446
|
+
this.selectingStartDate.set(true);
|
|
447
|
+
// Update display text
|
|
448
|
+
this.updateMultiRangeText();
|
|
449
|
+
// Don't close if multiRange, allow adding more ranges
|
|
450
|
+
if (this.closeOnSelection && !this.multiRange) {
|
|
451
|
+
this.showDatePicker.set(false);
|
|
452
|
+
}
|
|
453
|
+
this.emitMultiChange();
|
|
454
|
+
this.emitMultiSelection();
|
|
455
|
+
}
|
|
456
|
+
this.generateCalendars();
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
// Single range mode (original behavior)
|
|
460
|
+
if (this.selectingStartDate()) {
|
|
461
|
+
this.startDate = dayObj.date;
|
|
462
|
+
this.endDate = '';
|
|
463
|
+
this.dateRangeText.set('');
|
|
464
|
+
this.selectingStartDate.set(false);
|
|
465
|
+
this.emitChange();
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
if (dayObj.date < this.startDate) {
|
|
469
|
+
this.endDate = this.startDate;
|
|
470
|
+
this.startDate = dayObj.date;
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
this.endDate = dayObj.date;
|
|
474
|
+
}
|
|
475
|
+
this.updateDateRangeText();
|
|
476
|
+
if (this.closeOnSelection) {
|
|
477
|
+
this.showDatePicker.set(false);
|
|
478
|
+
}
|
|
479
|
+
this.selectingStartDate.set(true);
|
|
480
|
+
this.emitChange();
|
|
481
|
+
this.emitSelection();
|
|
482
|
+
}
|
|
483
|
+
this.generateCalendars();
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
changeMonth(direction) {
|
|
487
|
+
const currentMonthValue = this.currentMonth();
|
|
488
|
+
const year = this.dateAdapter.getYear(currentMonthValue);
|
|
489
|
+
const month = this.dateAdapter.getMonth(currentMonthValue);
|
|
490
|
+
const newCurrentMonth = this.dateAdapter.createDate(year, month + direction, 1);
|
|
491
|
+
this.currentMonth.set(newCurrentMonth);
|
|
492
|
+
const newYear = this.dateAdapter.getYear(newCurrentMonth);
|
|
493
|
+
const newMonth = this.dateAdapter.getMonth(newCurrentMonth);
|
|
494
|
+
const newPreviousMonth = this.dateAdapter.createDate(newYear, newMonth - 1, 1);
|
|
495
|
+
this.previousMonth.set(newPreviousMonth);
|
|
496
|
+
this.generateCalendars();
|
|
497
|
+
}
|
|
498
|
+
getMonthName(date) {
|
|
499
|
+
const monthNames = this.locale.monthNames || this.defaultMonthNames;
|
|
500
|
+
return `${monthNames[this.dateAdapter.getMonth(date)]} ${this.dateAdapter.getYear(date)}`;
|
|
501
|
+
}
|
|
502
|
+
getDayNames() {
|
|
503
|
+
return this.locale.dayNamesShort || this.defaultDayNamesShort;
|
|
504
|
+
}
|
|
505
|
+
selectPresetRange(preset) {
|
|
506
|
+
if (!preset.getValue) {
|
|
507
|
+
console.error('PresetConfig must have getValue() function');
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
const range = preset.getValue();
|
|
511
|
+
this.startDate = range.start;
|
|
512
|
+
this.endDate = range.end;
|
|
513
|
+
this.updateDateRangeText();
|
|
514
|
+
this.generateCalendars();
|
|
515
|
+
if (this.closeOnPresetSelection) {
|
|
516
|
+
this.showDatePicker.set(false);
|
|
517
|
+
}
|
|
518
|
+
this.emitSelection();
|
|
519
|
+
}
|
|
520
|
+
clear() {
|
|
521
|
+
this.startDate = '';
|
|
522
|
+
this.endDate = '';
|
|
523
|
+
this.dateRangeText.set('');
|
|
524
|
+
this.showDatePicker.set(false);
|
|
525
|
+
this.selectingStartDate.set(true);
|
|
526
|
+
if (this.multiRange) {
|
|
527
|
+
this.selectedRanges.set([]);
|
|
528
|
+
this.currentRangeIndex.set(-1);
|
|
529
|
+
this.emitMultiChange();
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
this.emitChange();
|
|
533
|
+
}
|
|
534
|
+
this.onTouched();
|
|
535
|
+
this.generateCalendars();
|
|
536
|
+
}
|
|
537
|
+
removeRange(index) {
|
|
538
|
+
if (!this.multiRange)
|
|
539
|
+
return;
|
|
540
|
+
const currentRanges = [...this.selectedRanges()];
|
|
541
|
+
currentRanges.splice(index, 1);
|
|
542
|
+
this.selectedRanges.set(currentRanges);
|
|
543
|
+
this.updateMultiRangeText();
|
|
544
|
+
this.emitMultiChange();
|
|
545
|
+
this.emitMultiSelection();
|
|
546
|
+
this.generateCalendars();
|
|
547
|
+
}
|
|
548
|
+
updateMultiRangeText() {
|
|
549
|
+
const count = this.selectedRanges().length;
|
|
550
|
+
if (count === 0) {
|
|
551
|
+
this.dateRangeText.set('');
|
|
552
|
+
}
|
|
553
|
+
else if (count === 1) {
|
|
554
|
+
this.dateRangeText.set('1 range selected');
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
this.dateRangeText.set(`${count} ranges selected`);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
emitChange() {
|
|
561
|
+
this.dateRangeChange.emit({
|
|
562
|
+
startDate: this.startDate,
|
|
563
|
+
endDate: this.endDate,
|
|
564
|
+
rangeText: this.dateRangeText()
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
emitSelection() {
|
|
568
|
+
this.dateRangeSelected.emit({
|
|
569
|
+
startDate: this.startDate,
|
|
570
|
+
endDate: this.endDate,
|
|
571
|
+
rangeText: this.dateRangeText()
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
emitMultiChange() {
|
|
575
|
+
this.multiDateRangeChange.emit({
|
|
576
|
+
ranges: this.selectedRanges()
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
emitMultiSelection() {
|
|
580
|
+
this.multiDateRangeSelected.emit({
|
|
581
|
+
ranges: this.selectedRanges()
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
getDateRangeValue() {
|
|
585
|
+
return {
|
|
586
|
+
startDate: this.startDate,
|
|
587
|
+
endDate: this.endDate,
|
|
588
|
+
rangeText: this.dateRangeText()
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
// ControlValueAccessor implementation
|
|
592
|
+
writeValue(value) {
|
|
593
|
+
if (value) {
|
|
594
|
+
this.startDate = value.startDate || '';
|
|
595
|
+
this.endDate = value.endDate || '';
|
|
596
|
+
if (this.startDate && this.endDate) {
|
|
597
|
+
this.updateDateRangeText();
|
|
598
|
+
this.generateCalendars();
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
this.startDate = '';
|
|
603
|
+
this.endDate = '';
|
|
604
|
+
this.dateRangeText.set('');
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
registerOnChange(fn) {
|
|
608
|
+
this.onChange = fn;
|
|
609
|
+
}
|
|
610
|
+
registerOnTouched(fn) {
|
|
611
|
+
this.onTouched = fn;
|
|
612
|
+
}
|
|
613
|
+
setDisabledState(isDisabled) {
|
|
614
|
+
this.isDisabled.set(isDisabled);
|
|
615
|
+
}
|
|
616
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDatepickerComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
617
|
+
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)", "keydown": "handleKeyboardNavigation($event)" } }, providers: [
|
|
618
|
+
{
|
|
619
|
+
provide: NG_VALUE_ACCESSOR,
|
|
620
|
+
useExisting: forwardRef(() => DualDatepickerComponent),
|
|
621
|
+
multi: true
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
provide: DATE_ADAPTER,
|
|
625
|
+
useClass: NativeDateAdapter
|
|
626
|
+
}
|
|
627
|
+
], 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 [attr.aria-label]=\"placeholder\"\n [attr.aria-expanded]=\"showDatePicker()\"\n [attr.aria-haspopup]=\"'dialog'\"\n role=\"combobox\"\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 [class.keyboard-focused]=\"hasKeyboardFocus(dayObj.date, 0)\"\n [attr.tabindex]=\"dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 0) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\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 [class.keyboard-focused]=\"hasKeyboardFocus(dayObj.date, 1)\"\n [attr.tabindex]=\"dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 1) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\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;position:relative}.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-day.keyboard-focused{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.date-picker-day.keyboard-focused:not(.selected){background-color:#eff6ff}.date-picker-day:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.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 }] });
|
|
628
|
+
}
|
|
629
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDatepickerComponent, decorators: [{
|
|
630
|
+
type: Component,
|
|
631
|
+
args: [{ selector: 'ngx-dual-datepicker', standalone: true, imports: [CommonModule, FormsModule, ReactiveFormsModule], providers: [
|
|
632
|
+
{
|
|
633
|
+
provide: NG_VALUE_ACCESSOR,
|
|
634
|
+
useExisting: forwardRef(() => DualDatepickerComponent),
|
|
635
|
+
multi: true
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
provide: DATE_ADAPTER,
|
|
639
|
+
useClass: NativeDateAdapter
|
|
640
|
+
}
|
|
641
|
+
], 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 [attr.aria-label]=\"placeholder\"\n [attr.aria-expanded]=\"showDatePicker()\"\n [attr.aria-haspopup]=\"'dialog'\"\n role=\"combobox\"\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 [class.keyboard-focused]=\"hasKeyboardFocus(dayObj.date, 0)\"\n [attr.tabindex]=\"dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 0) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\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 [class.keyboard-focused]=\"hasKeyboardFocus(dayObj.date, 1)\"\n [attr.tabindex]=\"dayObj.isCurrentMonth && hasKeyboardFocus(dayObj.date, 1) ? 0 : -1\"\n [attr.aria-label]=\"formatDateDisplay(dayObj.date)\"\n [attr.aria-selected]=\"dayObj.isStart || dayObj.isEnd\"\n [attr.aria-current]=\"dayObj.isStart ? 'date' : null\"\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;position:relative}.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-day.keyboard-focused{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.date-picker-day.keyboard-focused:not(.selected){background-color:#eff6ff}.date-picker-day:focus-visible{outline:2px solid #3b82f6;outline-offset:2px;z-index:1}.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"] }]
|
|
642
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { placeholder: [{
|
|
643
|
+
type: Input
|
|
644
|
+
}], startDate: [{
|
|
645
|
+
type: Input
|
|
646
|
+
}], endDate: [{
|
|
647
|
+
type: Input
|
|
648
|
+
}], showPresets: [{
|
|
649
|
+
type: Input
|
|
650
|
+
}], showClearButton: [{
|
|
651
|
+
type: Input
|
|
652
|
+
}], multiRange: [{
|
|
653
|
+
type: Input
|
|
654
|
+
}], closeOnSelection: [{
|
|
655
|
+
type: Input
|
|
656
|
+
}], closeOnPresetSelection: [{
|
|
657
|
+
type: Input
|
|
658
|
+
}], closeOnClickOutside: [{
|
|
659
|
+
type: Input
|
|
660
|
+
}], presets: [{
|
|
661
|
+
type: Input
|
|
662
|
+
}], inputBackgroundColor: [{
|
|
663
|
+
type: Input
|
|
664
|
+
}], inputTextColor: [{
|
|
665
|
+
type: Input
|
|
666
|
+
}], inputBorderColor: [{
|
|
667
|
+
type: Input
|
|
668
|
+
}], inputBorderColorHover: [{
|
|
669
|
+
type: Input
|
|
670
|
+
}], inputBorderColorFocus: [{
|
|
671
|
+
type: Input
|
|
672
|
+
}], inputPadding: [{
|
|
673
|
+
type: Input
|
|
674
|
+
}], locale: [{
|
|
675
|
+
type: Input
|
|
676
|
+
}], dateRangeChange: [{
|
|
677
|
+
type: Output
|
|
678
|
+
}], dateRangeSelected: [{
|
|
679
|
+
type: Output
|
|
680
|
+
}], multiDateRangeChange: [{
|
|
681
|
+
type: Output
|
|
682
|
+
}], multiDateRangeSelected: [{
|
|
683
|
+
type: Output
|
|
684
|
+
}], onClickOutside: [{
|
|
685
|
+
type: HostListener,
|
|
686
|
+
args: ['document:click', ['$event']]
|
|
687
|
+
}], handleKeyboardNavigation: [{
|
|
688
|
+
type: HostListener,
|
|
689
|
+
args: ['keydown', ['$event']]
|
|
690
|
+
}] } });
|
|
691
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHVhbC1kYXRlcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kdWFsLWRhdGVwaWNrZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vc3JjL2R1YWwtZGF0ZXBpY2tlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFvQyxZQUFZLEVBQWMsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqTCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzRyxPQUFPLEVBQWUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7OztBQWdEMUQsTUFBTSxPQUFPLHVCQUF1QjtJQTBEZDtJQXpEWCxXQUFXLEdBQVcsbUJBQW1CLENBQUM7SUFDMUMsU0FBUyxHQUFXLEVBQUUsQ0FBQztJQUN2QixPQUFPLEdBQVcsRUFBRSxDQUFDO0lBQ3JCLFdBQVcsR0FBWSxJQUFJLENBQUM7SUFDNUIsZUFBZSxHQUFZLEtBQUssQ0FBQztJQUNqQyxVQUFVLEdBQVksS0FBSyxDQUFDO0lBQzVCLGdCQUFnQixHQUFZLElBQUksQ0FBQztJQUNqQyxzQkFBc0IsR0FBWSxJQUFJLENBQUM7SUFDdkMsbUJBQW1CLEdBQVksSUFBSSxDQUFDO0lBQ3BDLE9BQU8sR0FBbUIsRUFBRSxDQUFDO0lBQzdCLG9CQUFvQixHQUFXLE1BQU0sQ0FBQztJQUN0QyxjQUFjLEdBQVcsU0FBUyxDQUFDO0lBQ25DLGdCQUFnQixHQUFXLFNBQVMsQ0FBQztJ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LCBFdmVudEVtaXR0ZXIsIE9uSW5pdCwgT25DaGFuZ2VzLCBTaW1wbGVDaGFuZ2VzLCBIb3N0TGlzdGVuZXIsIEVsZW1lbnRSZWYsIGZvcndhcmRSZWYsIHNpZ25hbCwgY29tcHV0ZWQsIGVmZmVjdCwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUsIFJlYWN0aXZlRm9ybXNNb2R1bGUsIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IERhdGVBZGFwdGVyLCBEQVRFX0FEQVBURVIgfSBmcm9tICcuL2RhdGUtYWRhcHRlcic7XG5pbXBvcnQgeyBOYXRpdmVEYXRlQWRhcHRlciB9IGZyb20gJy4vbmF0aXZlLWRhdGUtYWRhcHRlcic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGF0ZVJhbmdlIHtcbiAgc3RhcnREYXRlOiBzdHJpbmc7XG4gIGVuZERhdGU6IHN0cmluZztcbiAgcmFuZ2VUZXh0OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTXVsdGlEYXRlUmFuZ2Uge1xuICByYW5nZXM6IERhdGVSYW5nZVtdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByZXNldFJhbmdlIHtcbiAgc3RhcnQ6IHN0cmluZztcbiAgZW5kOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJlc2V0Q29uZmlnIHtcbiAgbGFiZWw6IHN0cmluZztcbiAgZ2V0VmFsdWU6ICgpID0+IFByZXNldFJhbmdlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExvY2FsZUNvbmZpZyB7XG4gIG1vbnRoTmFtZXM/OiBzdHJpbmdbXTtcbiAgbW9udGhOYW1lc1Nob3J0Pzogc3RyaW5nW107XG4gIGRheU5hbWVzPzogc3RyaW5nW107XG4gIGRheU5hbWVzU2hvcnQ/OiBzdHJpbmdbXTtcbiAgZmlyc3REYXlPZldlZWs/OiBudW1iZXI7IC8vIDAgPSBTdW5kYXksIDEgPSBNb25kYXksIGV0Yy5cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWR1YWwtZGF0ZXBpY2tlcicsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIEZvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2R1YWwtZGF0ZXBpY2tlci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9kdWFsLWRhdGVwaWNrZXIuY29tcG9uZW50LnNjc3MnLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IER1YWxEYXRlcGlja2VyQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfSxcbiAgICB7XG4gICAgICBwcm92aWRlOiBEQVRFX0FEQVBURVIsXG4gICAgICB1c2VDbGFzczogTmF0aXZlRGF0ZUFkYXB0ZXJcbiAgICB9XG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgRHVhbERhdGVwaWNrZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xuICBASW5wdXQoKSBwbGFjZWhvbGRlcjogc3RyaW5nID0gJ1NlbGVjdCBkYXRlIHJhbmdlJztcbiAgQElucHV0KCkgc3RhcnREYXRlOiBzdHJpbmcgPSAnJztcbiAgQElucHV0KCkgZW5kRGF0ZTogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIHNob3dQcmVzZXRzOiBib29sZWFuID0gdHJ1ZTtcbiAgQElucHV0KCkgc2hvd0NsZWFyQnV0dG9uOiBib29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIG11bHRpUmFuZ2U6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgY2xvc2VPblNlbGVjdGlvbjogYm9vbGVhbiA9IHRydWU7XG4gIEBJbnB1dCgpIGNsb3NlT25QcmVzZXRTZWxlY3Rpb246IGJvb2xlYW4gPSB0cnVlO1xuICBASW5wdXQoKSBjbG9zZU9uQ2xpY2tPdXRzaWRlOiBib29sZWFuID0gdHJ1ZTtcbiAgQElucHV0KCkgcHJlc2V0czogUHJlc2V0Q29uZmlnW10gPSBbXTtcbiAgQElucHV0KCkgaW5wdXRCYWNrZ3JvdW5kQ29sb3I6IHN0cmluZyA9ICcjZmZmJztcbiAgQElucHV0KCkgaW5wdXRUZXh0Q29sb3I6IHN0cmluZyA9ICcjNDk1MDU3JztcbiAgQElucHV0KCkgaW5wdXRCb3JkZXJDb2xvcjogc3RyaW5nID0gJyNjZWQ0ZGEnO1xuICBASW5wdXQoKSBpbnB1dEJvcmRlckNvbG9ySG92ZXI6IHN0cmluZyA9ICcjY2VkNGRhJztcbiAgQElucHV0KCkgaW5wdXRCb3JkZXJDb2xvckZvY3VzOiBzdHJpbmcgPSAnIzgwYmRmZic7XG4gIEBJbnB1dCgpIGlucHV0UGFkZGluZzogc3RyaW5nID0gJzAuMzc1cmVtIDAuNzVyZW0nO1xuICBASW5wdXQoKSBsb2NhbGU6IExvY2FsZUNvbmZpZyA9IHt9O1xuXG4gIEBPdXRwdXQoKSBkYXRlUmFuZ2VDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPERhdGVSYW5nZT4oKTtcbiAgQE91dHB1dCgpIGRhdGVSYW5nZVNlbGVjdGVkID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlUmFuZ2U+KCk7XG4gIEBPdXRwdXQoKSBtdWx0aURhdGVSYW5nZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8TXVsdGlEYXRlUmFuZ2U+KCk7XG4gIEBPdXRwdXQoKSBtdWx0aURhdGVSYW5nZVNlbGVjdGVkID0gbmV3IEV2ZW50RW1pdHRlcjxNdWx0aURhdGVSYW5nZT4oKTtcblxuICAvLyBEYXRlIGFkYXB0ZXIgaW5qZWN0aW9uXG4gIHByaXZhdGUgZGF0ZUFkYXB0ZXIgPSBpbmplY3Q8RGF0ZUFkYXB0ZXI+KERBVEVfQURBUFRFUik7XG5cbiAgLy8gU2lnbmFscyBmb3IgcmVhY3RpdmUgc3RhdGVcbiAgc2hvd0RhdGVQaWNrZXIgPSBzaWduYWwoZmFsc2UpO1xuICBkYXRlUmFuZ2VUZXh0ID0gc2lnbmFsKCcnKTtcbiAgc2VsZWN0aW5nU3RhcnREYXRlID0gc2lnbmFsKHRydWUpO1xuICBjdXJyZW50TW9udGggPSBzaWduYWwodGhpcy5kYXRlQWRhcHRlci50b2RheSgpKTtcbiAgcHJldmlvdXNNb250aCA9IHNpZ25hbCh0aGlzLmRhdGVBZGFwdGVyLnRvZGF5KCkpO1xuICBjdXJyZW50TW9udGhEYXlzID0gc2lnbmFsPGFueVtdPihbXSk7XG4gIHByZXZpb3VzTW9udGhEYXlzID0gc2lnbmFsPGFueVtdPihbXSk7XG4gIGlzRGlzYWJsZWQgPSBzaWduYWwoZmFsc2UpO1xuICBcbiAgLy8gTXVsdGktcmFuZ2Ugc3VwcG9ydFxuICBzZWxlY3RlZFJhbmdlcyA9IHNpZ25hbDxEYXRlUmFuZ2VbXT4oW10pO1xuICBjdXJyZW50UmFuZ2VJbmRleCA9IHNpZ25hbDxudW1iZXI+KC0xKTtcblxuICAvLyBLZXlib2FyZCBuYXZpZ2F0aW9uXG4gIGZvY3VzZWREYXkgPSBzaWduYWw8eyBkYXRlOiBzdHJpbmc7IG1vbnRoSW5kZXg6IG51bWJlciB9IHwgbnVsbD4obnVsbCk7IC8vIG1vbnRoSW5kZXg6IDAgPSBwcmV2aW91cywgMSA9IGN1cnJlbnRcbiAgXG4gIC8vIENvbXB1dGVkIHZhbHVlc1xuICBjdXJyZW50TW9udGhOYW1lID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5nZXRNb250aE5hbWUodGhpcy5jdXJyZW50TW9udGgoKSkpO1xuICBwcmV2aW91c01vbnRoTmFtZSA9IGNvbXB1dGVkKCgpID0+IHRoaXMuZ2V0TW9udGhOYW1lKHRoaXMucHJldmlvdXNNb250aCgpKSk7XG4gIHdlZWtEYXlOYW1lcyA9IGNvbXB1dGVkKCgpID0+IHRoaXMuZ2V0RGF5TmFtZXMoKSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkZWZhdWx0TW9udGhOYW1lcyA9IFsnSmFudWFyeScsICdGZWJydWFyeScsICdNYXJjaCcsICdBcHJpbCcsICdNYXknLCAnSnVuZScsICdKdWx5JywgJ0F1Z3VzdCcsICdTZXB0ZW1iZXInLCAnT2N0b2JlcicsICdOb3ZlbWJlcicsICdEZWNlbWJlciddO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHRNb250aE5hbWVzU2hvcnQgPSBbJ0phbicsICdGZWInLCAnTWFyJywgJ0FwcicsICdNYXknLCAnSnVuJywgJ0p1bCcsICdBdWcnLCAnU2VwJywgJ09jdCcsICdOb3YnLCAnRGVjJ107XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdERheU5hbWVzID0gWydTdW5kYXknLCAnTW9uZGF5JywgJ1R1ZXNkYXknLCAnV2VkbmVzZGF5JywgJ1RodXJzZGF5JywgJ0ZyaWRheScsICdTYXR1cmRheSddO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHREYXlOYW1lc1Nob3J0ID0gWydTJywgJ00nLCAnVCcsICdXJywgJ1QnLCAnRicsICdTJ107XG5cbiAgLy8gQ29udHJvbFZhbHVlQWNjZXNzb3IgY2FsbGJhY2tzXG4gIHByaXZhdGUgb25DaGFuZ2U6ICh2YWx1ZTogRGF0ZVJhbmdlIHwgbnVsbCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuICBwcml2YXRlIG9uVG91Y2hlZDogKCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZikge1xuICAgIC8vIEVmZmVjdCB0byBlbWl0IGNoYW5nZXMgd2hlbiBkYXRlcyBjaGFuZ2VcbiAgICBlZmZlY3QoKCkgPT4ge1xuICAgICAgY29uc3QgcmFuZ2UgPSB0aGlzLmRhdGVSYW5nZVRleHQoKTtcbiAgICAgIGlmICh0aGlzLnN0YXJ0RGF0ZSB8fCB0aGlzLmVuZERhdGUpIHtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSh0aGlzLmdldERhdGVSYW5nZVZhbHVlKCkpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6Y2xpY2snLCBbJyRldmVudCddKVxuICBvbkNsaWNrT3V0c2lkZShldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnNob3dEYXRlUGlja2VyKCkgJiYgdGhpcy5jbG9zZU9uQ2xpY2tPdXRzaWRlKSB7XG4gICAgICBjb25zdCBjbGlja2VkSW5zaWRlID0gdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuY29udGFpbnMoZXZlbnQudGFyZ2V0KTtcbiAgICAgIGlmICghY2xpY2tlZEluc2lkZSkge1xuICAgICAgICB0aGlzLmNsb3NlRGF0ZVBpY2tlcigpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2tleWRvd24nLCBbJyRldmVudCddKVxuICBoYW5kbGVLZXlib2FyZE5hdmlnYXRpb24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2hvd0RhdGVQaWNrZXIoKSkge1xuICAgICAgLy8gV2hlbiBwaWNrZXIgaXMgY2xvc2VkLCBhbGxvdyBFbnRlci9TcGFjZSB0byBvcGVuIGl0XG4gICAgICBpZiAoZXZlbnQua2V5ID09PSAnRW50ZXInIHx8IGV2ZW50LmtleSA9PT0gJyAnKSB7XG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgaWYgKHRhcmdldC5jbGFzc0xpc3QuY29udGFpbnMoJ2RhdGVwaWNrZXItaW5wdXQnKSkge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgdGhpcy50b2dnbGVEYXRlUGlja2VyKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBXaGVuIHBpY2tlciBpcyBvcGVuXG4gICAgc3dpdGNoIChldmVudC5rZXkpIHtcbiAgICAgIGNhc2UgJ0VzY2FwZSc6XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMuY2xvc2VEYXRlUGlja2VyKCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdBcnJvd1VwJzpcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGhpcy5tb3ZlRm9jdXNWZXJ0aWNhbCgtMSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdBcnJvd0Rvd24nOlxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLm1vdmVGb2N1c1ZlcnRpY2FsKDEpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnQXJyb3dMZWZ0JzpcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGhpcy5tb3ZlRm9jdXNIb3Jpem9udGFsKC0xKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ0Fycm93UmlnaHQnOlxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLm1vdmVGb2N1c0hvcml6b250YWwoMSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdFbnRlcic6XG4gICAgICBjYXNlICcgJzpcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGhpcy5zZWxlY3RGb2N1c2VkRGF5KCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdIb21lJzpcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGhpcy5tb3ZlRm9jdXNUb0ZpcnN0RGF5KCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdFbmQnOlxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLm1vdmVGb2N1c1RvTGFzdERheSgpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnUGFnZVVwJzpcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKGV2ZW50LnNoaWZ0S2V5KSB7XG4gICAgICAgICAgdGhpcy5tb3ZlRm9jdXNZZWFyKC0xKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmNoYW5nZU1vbnRoKC0xKTtcbiAgICAgICAgICB0aGlzLmFkanVzdEZvY3VzQWZ0ZXJNb250aENoYW5nZSgpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdQYWdlRG93bic6XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGlmIChldmVudC5zaGlmdEtleSkge1xuICAgICAgICAgIHRoaXMubW92ZUZvY3VzWWVhcigxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmNoYW5nZU1vbnRoKDEpO1xuICAgICAgICAgIHRoaXMuYWRqdXN0Rm9jdXNBZnRlck1vbnRoQ2hhbmdlKCk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLy8gS2V5Ym9hcmQgbmF2aWdhdGlvbiBtZXRob2RzXG4gIHByaXZhdGUgaW5pdGlhbGl6ZUZvY3VzKCk6IHZvaWQge1xuICAgIC8vIFNldCBpbml0aWFsIGZvY3VzIHRvIHN0YXJ0IGRhdGUsIGVuZCBkYXRlLCBvciBmaXJzdCBhdmFpbGFibGUgZGF5XG4gICAgaWYgKHRoaXMuc3RhcnREYXRlKSB7XG4gICAgICBjb25zdCBzdGFydE1vbnRoID0gdGhpcy5pc0RhdGVJbk1vbnRoKHRoaXMuc3RhcnREYXRlLCB0aGlzLnByZXZpb3VzTW9udGgoKSkgPyAwIDogMTtcbiAgICAgIHRoaXMuZm9jdXNlZERheS5zZXQoeyBkYXRlOiB0aGlzLnN0YXJ0RGF0ZSwgbW9udGhJbmRleDogc3RhcnRNb250aCB9KTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuZW5kRGF0ZSkge1xuICAgICAgY29uc3QgZW5kTW9udGggPSB0aGlzLmlzRGF0ZUluTW9udGgodGhpcy5lbmREYXRlLCB0aGlzLnByZXZpb3VzTW9udGgoKSkgPyAwIDogMTtcbiAgICAgIHRoaXMuZm9jdXNlZERheS5zZXQoeyBkYXRlOiB0aGlzLmVuZERhdGUsIG1vbnRoSW5kZXg6IGVuZE1vbnRoIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBGb2N1cyBmaXJzdCBkYXkgb2YgY3VycmVudCBtb250aFxuICAgICAgY29uc3QgY3VycmVudE1vbnRoRGF5cyA9IHRoaXMuY3VycmVudE1vbnRoRGF5cygpO1xuICAgICAgY29uc3QgZmlyc3REYXkgPSBjdXJyZW50TW9udGhEYXlzLmZpbmQoZGF5ID0+IGRheS5pc0N1cnJlbnRNb250aCk7XG4gICAgICBpZiAoZmlyc3REYXkpIHtcbiAgICAgICAgdGhpcy5mb2N1c2VkRGF5LnNldCh7IGRhdGU6IGZpcnN0RGF5LmRhdGUsIG1vbnRoSW5kZXg6IDEgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpc0RhdGVJbk1vbnRoKGRhdGVTdHI6IHN0cmluZywgbW9udGhEYXRlOiBEYXRlKTogYm9vbGVhbiB7XG4gICAgY29uc3QgZGF0ZSA9IHRoaXMuZGF0ZUFkYXB0ZXIucGFyc2UoZGF0ZVN0cik7XG4gICAgaWYgKCFkYXRlKSByZXR1cm4gZmFsc2U7XG4gICAgY29uc3QgeWVhciA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0WWVhcihkYXRlKTtcbiAgICBjb25zdCBtb250aCA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0TW9udGgoZGF0ZSk7XG4gICAgY29uc3QgbW9udGhZZWFyID0gdGhpcy5kYXRlQWRhcHRlci5nZXRZZWFyKG1vbnRoRGF0ZSk7XG4gICAgY29uc3QgbW9udGhNb250aCA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0TW9udGgobW9udGhEYXRlKTtcbiAgICByZXR1cm4geWVhciA9PT0gbW9udGhZZWFyICYmIG1vbnRoID09PSBtb250aE1vbnRoO1xuICB9XG5cbiAgcHJpdmF0ZSBtb3ZlRm9jdXNIb3Jpem9udGFsKGRpcmVjdGlvbjogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgZm9jdXNlZCA9IHRoaXMuZm9jdXNlZERheSgpO1xuICAgIGlmICghZm9jdXNlZCkge1xuICAgICAgdGhpcy5pbml0aWFsaXplRm9jdXMoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50RGF0ZSA9IHRoaXMuZGF0ZUFkYXB0ZXIucGFyc2UoZm9jdXNlZC5kYXRlKTtcbiAgICBpZiAoIWN1cnJlbnREYXRlKSByZXR1cm47XG5cbiAgICBjb25zdCBuZXdEYXRlID0gdGhpcy5kYXRlQWRhcHRlci5hZGREYXlzKGN1cnJlbnREYXRlLCBkaXJlY3Rpb24pO1xuICAgIGNvbnN0IG5ld0RhdGVTdHIgPSB0aGlzLmZvcm1hdERhdGUobmV3RGF0ZSk7XG5cbiAgICAvLyBEZXRlcm1pbmUgd2hpY2ggbW9udGggdGhlIG5ldyBkYXRlIGJlbG9uZ3MgdG9cbiAgICBjb25zdCBpblByZXZNb250aCA9IHRoaXMuaXNEYXRlSW5Nb250aChuZXdEYXRlU3RyLCB0aGlzLnByZXZpb3VzTW9udGgoKSk7XG4gICAgY29uc3QgaW5DdXJyTW9udGggPSB0aGlzLmlzRGF0ZUluTW9udGgobmV3RGF0ZVN0ciwgdGhpcy5jdXJyZW50TW9udGgoKSk7XG5cbiAgICBpZiAoaW5QcmV2TW9udGggfHwgaW5DdXJyTW9udGgpIHtcbiAgICAgIHRoaXMuZm9jdXNlZERheS5zZXQoeyBcbiAgICAgICAgZGF0ZTogbmV3RGF0ZVN0ciwgXG4gICAgICAgIG1vbnRoSW5kZXg6IGluUHJldk1vbnRoID8gMCA6IDEgXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRGF0ZSBpcyBvdXRzaWRlIHZpc2libGUgbW9udGhzLCBuYXZpZ2F0ZSBtb250aFxuICAgICAgaWYgKGRpcmVjdGlvbiA+IDApIHtcbiAgICAgICAgdGhpcy5jaGFuZ2VNb250aCgxKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY2hhbmdlTW9udGgoLTEpO1xuICAgICAgfVxuICAgICAgdGhpcy5mb2N1c2VkRGF5LnNldCh7IGRhdGU6IG5ld0RhdGVTdHIsIG1vbnRoSW5kZXg6IGRpcmVjdGlvbiA+IDAgPyAwIDogMSB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vdmVGb2N1c1ZlcnRpY2FsKGRpcmVjdGlvbjogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgZm9jdXNlZCA9IHRoaXMuZm9jdXNlZERheSgpO1xuICAgIGlmICghZm9jdXNlZCkge1xuICAgICAgdGhpcy5pbml0aWFsaXplRm9jdXMoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50RGF0ZSA9IHRoaXMuZGF0ZUFkYXB0ZXIucGFyc2UoZm9jdXNlZC5kYXRlKTtcbiAgICBpZiAoIWN1cnJlbnREYXRlKSByZXR1cm47XG5cbiAgICBjb25zdCBuZXdEYXRlID0gdGhpcy5kYXRlQWRhcHRlci5hZGREYXlzKGN1cnJlbnREYXRlLCBkaXJlY3Rpb24gKiA3KTsgLy8gTW92ZSBieSB3ZWVrXG4gICAgY29uc3QgbmV3RGF0ZVN0ciA9IHRoaXMuZm9ybWF0RGF0ZShuZXdEYXRlKTtcblxuICAgIGNvbnN0IGluUHJldk1vbnRoID0gdGhpcy5pc0RhdGVJbk1vbnRoKG5ld0RhdGVTdHIsIHRoaXMucHJldmlvdXNNb250aCgpKTtcbiAgICBjb25zdCBpbkN1cnJNb250aCA9IHRoaXMuaXNEYXRlSW5Nb250aChuZXdEYXRlU3RyLCB0aGlzLmN1cnJlbnRNb250aCgpKTtcblxuICAgIGlmIChpblByZXZNb250aCB8fCBpbkN1cnJNb250aCkge1xuICAgICAgdGhpcy5mb2N1c2VkRGF5LnNldCh7IFxuICAgICAgICBkYXRlOiBuZXdEYXRlU3RyLCBcbiAgICAgICAgbW9udGhJbmRleDogaW5QcmV2TW9udGggPyAwIDogMSBcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBOYXZpZ2F0ZSB0byBtb250aCBjb250YWluaW5nIHRoZSBuZXcgZGF0ZVxuICAgICAgaWYgKGRpcmVjdGlvbiA+IDApIHtcbiAgICAgICAgdGhpcy5jaGFuZ2VNb250aCgxKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY2hhbmdlTW9udGgoLTEpO1xuICAgICAgfVxuICAgICAgdGhpcy5mb2N1c2VkRGF5LnNldCh7IGRhdGU6IG5ld0RhdGVTdHIsIG1vbnRoSW5kZXg6IGRpcmVjdGlvbiA+IDAgPyAwIDogMSB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vdmVGb2N1c1RvRmlyc3REYXkoKTogdm9pZCB7XG4gICAgY29uc3QgcHJldk1vbnRoRGF5cyA9IHRoaXMucHJldmlvdXNNb250aERheXMoKTtcbiAgICBjb25zdCBmaXJzdERheSA9IHByZXZNb250aERheXMuZmluZChkYXkgPT4gZGF5LmlzQ3VycmVudE1vbnRoKTtcbiAgICBpZiAoZmlyc3REYXkpIHtcbiAgICAgIHRoaXMuZm9jdXNlZERheS5zZXQoeyBkYXRlOiBmaXJzdERheS5kYXRlLCBtb250aEluZGV4OiAwIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW92ZUZvY3VzVG9MYXN0RGF5KCk6IHZvaWQge1xuICAgIGNvbnN0IGN1cnJNb250aERheXMgPSB0aGlzLmN1cnJlbnRNb250aERheXMoKTtcbiAgICBjb25zdCB2YWxpZERheXMgPSBjdXJyTW9udGhEYXlzLmZpbHRlcihkYXkgPT4gZGF5LmlzQ3VycmVudE1vbnRoKTtcbiAgICBjb25zdCBsYXN0RGF5ID0gdmFsaWREYXlzW3ZhbGlkRGF5cy5sZW5ndGggLSAxXTtcbiAgICBpZiAobGFzdERheSkge1xuICAgICAgdGhpcy5mb2N1c2VkRGF5LnNldCh7IGRhdGU6IGxhc3REYXkuZGF0ZSwgbW9udGhJbmRleDogMSB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vdmVGb2N1c1llYXIoZGlyZWN0aW9uOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBmb2N1c2VkID0gdGhpcy5mb2N1c2VkRGF5KCk7XG4gICAgaWYgKCFmb2N1c2VkKSB7XG4gICAgICB0aGlzLmluaXRpYWxpemVGb2N1cygpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnREYXRlID0gdGhpcy5kYXRlQWRhcHRlci5wYXJzZShmb2N1c2VkLmRhdGUpO1xuICAgIGlmICghY3VycmVudERhdGUpIHJldHVybjtcblxuICAgIGNvbnN0IGN1cnJlbnRZZWFyID0gdGhpcy5kYXRlQWRhcHRlci5nZXRZZWFyKGN1cnJlbnREYXRlKTtcbiAgICBjb25zdCBjdXJyZW50TW9udGggPSB0aGlzLmRhdGVBZGFwdGVyLmdldE1vbnRoKGN1cnJlbnREYXRlKTtcbiAgICBjb25zdCBjdXJyZW50RGF5ID0gdGhpcy5kYXRlQWRhcHRlci5nZXREYXRlKGN1cnJlbnREYXRlKTtcbiAgICBcbiAgICBjb25zdCBuZXdEYXRlID0gdGhpcy5kYXRlQWRhcHRlci5jcmVhdGVEYXRlKGN1cnJlbnRZZWFyICsgZGlyZWN0aW9uLCBjdXJyZW50TW9udGgsIGN1cnJlbnREYXkpO1xuICAgIGNvbnN0IG5ld0RhdGVTdHIgPSB0aGlzLmZvcm1hdERhdGUobmV3RGF0ZSk7XG5cbiAgICAvLyBVcGRhdGUgbW9udGhzIHRvIHNob3cgdGhlIG5ldyB5ZWFyXG4gICAgdGhpcy5jdXJyZW50TW9udGguc2V0KHRoaXMuZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZShjdXJyZW50WWVhciArIGRpcmVjdGlvbiwgY3VycmVudE1vbnRoLCAxKSk7XG4gICAgdGhpcy5wcmV2aW91c01vbnRoLnNldCh0aGlzLmRhdGVBZGFwdGVyLmNyZWF0ZURhdGUoY3VycmVudFllYXIgKyBkaXJlY3Rpb24sIGN1cnJlbnRNb250aCAtIDEsIDEpKTtcbiAgICB0aGlzLmdlbmVyYXRlQ2FsZW5kYXJzKCk7XG5cbiAgICBjb25zdCBpblByZXZNb250aCA9IHRoaXMuaXNEYXRlSW5Nb250aChuZXdEYXRlU3RyLCB0aGlzLnByZXZpb3VzTW9udGgoKSk7XG4gICAgdGhpcy5mb2N1c2VkRGF5LnNldCh7IFxuICAgICAgZGF0ZTogbmV3RGF0ZVN0ciwgXG4gICAgICBtb250aEluZGV4OiBpblByZXZNb250aCA/IDAgOiAxIFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGp1c3RGb2N1c0FmdGVyTW9udGhDaGFuZ2UoKTogdm9pZCB7XG4gICAgY29uc3QgZm9jdXNlZCA9IHRoaXMuZm9jdXNlZERheSgpO1xuICAgIGlmICghZm9jdXNlZCkgcmV0dXJuO1xuXG4gICAgY29uc3QgaW5QcmV2TW9udGggPSB0aGlzLmlzRGF0ZUluTW9udGgoZm9jdXNlZC5kYXRlLCB0aGlzLnByZXZpb3VzTW9udGgoKSk7XG4gICAgY29uc3QgaW5DdXJyTW9udGggPSB0aGlzLmlzRGF0ZUluTW9udGgoZm9jdXNlZC5kYXRlLCB0aGlzLmN1cnJlbnRNb250aCgpKTtcblxuICAgIGlmICghaW5QcmV2TW9udGggJiYgIWluQ3Vyck1vbnRoKSB7XG4gICAgICAvLyBGb2N1c2VkIGRheSBpcyBubyBsb25nZXIgdmlzaWJsZSwgbW92ZSB0byBlcXVpdmFsZW50IGRheSBpbiB2aXNpYmxlIG1vbnRoc1xuICAgICAgdGhpcy5pbml0aWFsaXplRm9jdXMoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVXBkYXRlIG1vbnRoIGluZGV4IGlmIG5lZWRlZFxuICAgICAgdGhpcy5mb2N1c2VkRGF5LnNldCh7XG4gICAgICAgIGRhdGU6IGZvY3VzZWQuZGF0ZSxcbiAgICAgICAgbW9udGhJbmRleDogaW5QcmV2TW9udGggPyAwIDogMVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzZWxlY3RGb2N1c2VkRGF5KCk6IHZvaWQge1xuICAgIGNvbnN0IGZvY3VzZWQgPSB0aGlzLmZvY3VzZWREYXkoKTtcbiAgICBpZiAoIWZvY3VzZWQpIHJldHVybjtcblxuICAgIGNvbnN0IG1vbnRoRGF5cyA9IGZvY3VzZWQubW9udGhJbmRleCA9PT0gMCA/IHRoaXMucHJldmlvdXNNb250aERheXMoKSA6IHRoaXMuY3VycmVudE1vbnRoRGF5cygpO1xuICAgIGNvbnN0IGRheU9iaiA9IG1vbnRoRGF5cy5maW5kKGRheSA9PiBkYXkuZGF0ZSA9PT0gZm9jdXNlZC5kYXRlICYmIGRheS5pc0N1cnJlbnRNb250aCk7XG4gICAgXG4gICAgaWYgKGRheU9iaikge1xuICAgICAgdGhpcy5zZWxlY3REYXkoZGF5T2JqKTtcbiAgICB9XG4gIH1cblxuICBoYXNLZXlib2FyZEZvY3VzKGRhdGU6IHN0cmluZywgbW9udGhJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgY29uc3QgZm9jdXNlZCA9IHRoaXMuZm9jdXNlZERheSgpO1xuICAgIHJldHVybiBmb2N1c2VkICE9PSBudWxsICYmIGZvY3VzZWQuZGF0ZSA9PT0gZGF0ZSAmJiBmb2N1c2VkLm1vbnRoSW5kZXggPT09IG1vbnRoSW5kZXg7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zdGFydERhdGUgJiYgdGhpcy5lbmREYXRlKSB7XG4gICAgICB0aGlzLnVwZGF0ZURhdGVSYW5nZVRleHQoKTtcbiAgICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcnMoKTtcbiAgICB9XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXNbJ3N0YXJ0RGF0ZSddIHx8IGNoYW5nZXNbJ2VuZERhdGUnXSkge1xuICAgICAgaWYgKHRoaXMuc3RhcnREYXRlICYmIHRoaXMuZW5kRGF0ZSkge1xuICAgICAgICB0aGlzLnVwZGF0ZURhdGVSYW5nZVRleHQoKTtcbiAgICAgICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFycygpO1xuICAgICAgfSBlbHNlIGlmICghdGhpcy5zdGFydERhdGUgJiYgIXRoaXMuZW5kRGF0ZSkge1xuICAgICAgICB0aGlzLmRhdGVSYW5nZVRleHQuc2V0KCcnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmb3JtYXREYXRlKGRhdGU6IERhdGUpOiBzdHJpbmcge1xuICAgIGNvbnN0IHllYXIgPSB0aGlzLmRhdGVBZGFwdGVyLmdldFllYXIoZGF0ZSk7XG4gICAgY29uc3QgbW9udGggPSBTdHJpbmcodGhpcy5kYXRlQWRhcHRlci5nZXRNb250aChkYXRlKSArIDEpLnBhZFN0YXJ0KDIsICcwJyk7XG4gICAgY29uc3QgZGF5ID0gU3RyaW5nKHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0RGF0ZShkYXRlKSkucGFkU3RhcnQoMiwgJzAnKTtcbiAgICByZXR1cm4gYCR7eWVhcn0tJHttb250aH0tJHtkYXl9YDtcbiAgfVxuXG4gIGZvcm1hdERhdGVEaXNwbGF5KGRhdGVTdHI6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKCFkYXRlU3RyKSByZXR1cm4gJyc7XG4gICAgY29uc3QgZGF0ZSA9IHRoaXMuZGF0ZUFkYXB0ZXIucGFyc2UoZGF0ZVN0cik7XG4gICAgaWYgKCFkYXRlKSByZXR1cm4gJyc7XG4gICAgY29uc3QgbW9udGhOYW1lcyA9IHRoaXMubG9jYWxlLm1vbnRoTmFtZXNTaG9ydCB8fCB0aGlzLmRlZmF1bHRNb250aE5hbWVzU2hvcnQ7XG4gICAgcmV0dXJuIGAke3RoaXMuZGF0ZUFkYXB0ZXIuZ2V0RGF0ZShkYXRlKX0gJHttb250aE5hbWVzW3RoaXMuZGF0ZUFkYXB0ZXIuZ2V0TW9udGgoZGF0ZSldfWA7XG4gIH1cblxuICB1cGRhdGVEYXRlUmFuZ2VUZXh0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnN0YXJ0RGF0ZSAmJiB0aGlzLmVuZERhdGUpIHtcbiAgICAgIGNvbnN0IHN0YXJ0ID0gdGhpcy5mb3JtYXREYXRlRGlzcGxheSh0aGlzLnN0YXJ0RGF0ZSk7XG4gICAgICBjb25zdCBlbmQgPSB0aGlzLmZvcm1hdERhdGVEaXNwbGF5KHRoaXMuZW5kRGF0ZSk7XG4gICAgICB0aGlzLmRhdGVSYW5nZVRleHQuc2V0KGAke3N0YXJ0fSAtICR7ZW5kfWApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmRhdGVSYW5nZVRleHQuc2V0KCcnKTtcbiAgICB9XG4gIH1cblxuICB0b2dnbGVEYXRlUGlja2VyKCk6IHZvaWQge1xuICAgIHRoaXMuc2hvd0RhdGVQaWNrZXIudXBkYXRlKHZhbHVlID0+ICF2YWx1ZSk7XG4gICAgaWYgKHRoaXMuc2hvd0RhdGVQaWNrZXIoKSkge1xuICAgICAgdGhpcy5zZWxlY3RpbmdTdGFydERhdGUuc2V0KHRydWUpO1xuICAgICAgY29uc3QgY3VycmVudE1vbnRoVmFsdWUgPSB0aGlzLmN1cnJlbnRNb250aCgpO1xuICAgICAgY29uc3QgeWVhciA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0WWVhcihjdXJyZW50TW9udGhWYWx1ZSk7XG4gICAgICBjb25zdCBtb250aCA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0TW9udGgoY3VycmVudE1vbnRoVmFsdWUpO1xuICAgICAgY29uc3QgcHJldmlvdXNNb250aERhdGUgPSB0aGlzLmRhdGVBZGFwdGVyLmNyZWF0ZURhdGUoeWVhciwgbW9udGggLSAxLCAxKTtcbiAgICAgIHRoaXMucHJldmlvdXNNb250aC5zZXQocHJldmlvdXNNb250aERhdGUpO1xuICAgICAgdGhpcy5nZW5lcmF0ZUNhbGVuZGFycygpO1xuICAgICAgLy8gSW5pdGlhbGl6ZSBrZXlib2FyZCBmb2N1c1xuICAgICAgdGhpcy5pbml0aWFsaXplRm9jdXMoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQ2xlYXIgZm9jdXMgd2hlbiBjbG9zaW5nXG4gICAgICB0aGlzLmZvY3VzZWREYXkuc2V0KG51bGwpO1xuICAgIH1cbiAgICB0aGlzLm9uVG91Y2hlZCgpO1xuICB9XG5cbiAgY2xvc2VEYXRlUGlja2VyKCk6IHZvaWQge1xuICAgIHRoaXMuc2hvd0RhdGVQaWNrZXIuc2V0KGZhbHNlKTtcbiAgICB0aGlzLmZvY3VzZWREYXkuc2V0KG51bGwpO1xuICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gIH1cblxuICBnZW5lcmF0ZUNhbGVuZGFycygpOiB2b2lkIHtcbiAgICB0aGlzLnByZXZpb3VzTW9udGhEYXlzLnNldCh0aGlzLmdlbmVyYXRlTW9udGhDYWxlbmRhcih0aGlzLnByZXZpb3VzTW9udGgoKSkpO1xuICAgIHRoaXMuY3VycmVudE1vbnRoRGF5cy5zZXQodGhpcy5nZW5lcmF0ZU1vbnRoQ2FsZW5kYXIodGhpcy5jdXJyZW50TW9udGgoKSkpO1xuICB9XG5cbiAgZ2VuZXJhdGVNb250aENhbGVuZGFyKGRhdGU6IERhdGUpOiBhbnlbXSB7XG4gICAgY29uc3QgeWVhciA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0WWVhcihkYXRlKTtcbiAgICBjb25zdCBtb250aCA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0TW9udGgoZGF0ZSk7XG4gICAgY29uc3QgZmlyc3REYXkgPSB0aGlzLmRhdGVBZGFwdGVyLmNyZWF0ZURhdGUoeWVhciwgbW9udGgsIDEpO1xuICAgIGNvbnN0IGxhc3REYXkgPSB0aGlzLmRhdGVBZGFwdGVyLmNyZWF0ZURhdGUoeWVhciwgbW9udGggKyAxLCAwKTtcbiAgICBjb25zdCBkYXlzSW5Nb250aCA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0RGF0ZShsYXN0RGF5KTtcbiAgICBjb25zdCBmaXJzdERheU9mV2VlayA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0RGF5KGZpcnN0RGF5KTtcblxuICAgIGNvbnN0IG1vbnRoRGF5cyA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmaXJzdERheU9mV2VlazsgaSsrKSB7XG4gICAgICBtb250aERheXMucHVzaCh7IGRheTogbnVsbCwgaXNDdXJyZW50TW9udGg6IGZhbHNlIH0pO1xuICAgIH1cblxuICAgIGZvciAobGV0IGRheSA9IDE7IGRheSA8PSBkYXlzSW5Nb250aDsgZGF5KyspIHtcbiAgICAgIGNvbnN0IGRheURhdGUgPSB0aGlzLmRhdGVBZGFwdGVyLmNyZWF0ZURhdGUoeWVhciwgbW9udGgsIGRheSk7XG4gICAgICBjb25zdCBkYXRlU3RyID0gdGhpcy5mb3JtYXREYXRlKGRheURhdGUpO1xuICAgICAgbW9udGhEYXlzLnB1c2goe1xuICAgICAgICBkYXk6IGRheSxcbiAgICAgICAgZGF0ZTogZGF0ZVN0cixcbiAgICAgICAgaXNDdXJyZW50TW9udGg6IHRydWUsXG4gICAgICAgIGlzU3RhcnQ6IHRoaXMuc3RhcnREYXRlID09PSBkYXRlU3RyLFxuICAgICAgICBpc0VuZDogdGhpcy5lbmREYXRlID09PSBkYXRlU3RyLFxuICAgICAgICBpblJhbmdlOiB0aGlzLmlzSW5SYW5nZShkYXRlU3RyKVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vbnRoRGF5cztcbiAgfVxuXG4gIGlzSW5SYW5nZShkYXRlU3RyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5tdWx0aVJhbmdlKSB7XG4gICAgICAvLyBDaGVjayBpZiBkYXRlIGlzIGluIGFueSBvZiB0aGUgc2VsZWN0ZWQgcmFuZ2VzXG4gICAgICByZXR1cm4gdGhpcy5zZWxlY3RlZFJhbmdlcygpLnNvbWUocmFuZ2UgPT4ge1xuICAgICAgICByZXR1cm4gZGF0ZVN0ciA+PSByYW5nZS5zdGFydERhdGUgJiYgZGF0ZVN0ciA8PSByYW5nZS5lbmREYXRlO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghdGhpcy5zdGFydERhdGUgfHwgIXRoaXMuZW5kRGF0ZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgcmV0dXJuIGRhdGVTdHIgPj0gdGhpcy5zdGFydERhdGUgJiYgZGF0ZVN0ciA8PSB0aGlzLmVuZERhdGU7XG4gICAgfVxuICB9XG5cbiAgc2VsZWN0RGF5KGRheU9iajogYW55KTogdm9pZCB7XG4gICAgaWYgKCFkYXlPYmouaXNDdXJyZW50TW9udGggfHwgdGhpcy5pc0Rpc2FibGVkKCkpIHJldHVybjtcblxuICAgIGlmICh0aGlzLm11bHRpUmFuZ2UpIHtcbiAgICAgIC8vIE11bHRpLXJhbmdlIG1vZGU6IGFkZCByYW5nZXMgdG8gYXJyYXlcbiAgICAgIGlmICh0aGlzLnNlbGVjdGluZ1N0YXJ0RGF0ZSgpKSB7XG4gICAgICAgIHRoaXMuc3RhcnREYXRlID0gZGF5T2JqLmRhdGU7XG4gICAgICAgIHRoaXMuZW5kRGF0ZSA9ICcnO1xuICAgICAgICB0aGlzLmRhdGVSYW5nZVRleHQuc2V0KCcnKTtcbiAgICAgICAgdGhpcy5zZWxlY3RpbmdTdGFydERhdGUuc2V0KGZhbHNlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChkYXlPYmouZGF0ZSA8IHRoaXMuc3RhcnREYXRlKSB7XG4gICAgICAgICAgdGhpcy5lbmREYXRlID0gdGhpcy5zdGFydERhdGU7XG4gICAgICAgICAgdGhpcy5zdGFydERhdGUgPSBkYXlPYmouZGF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmVuZERhdGUgPSBkYXlPYmouZGF0ZTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gQWRkIHRoZSBuZXcgcmFuZ2UgdG8gdGhlIGFycmF5XG4gICAgICAgIGNvbnN0IG5ld1JhbmdlOiBEYXRlUmFuZ2UgPSB7XG4gICAgICAgICAgc3RhcnREYXRlOiB0aGlzLnN0YXJ0RGF0ZSxcbiAgICAgICAgICBlbmREYXRlOiB0aGlzLmVuZERhdGUsXG4gICAgICAgICAgcmFuZ2VUZXh0OiB0aGlzLmZvcm1hdERhdGVEaXNwbGF5KHRoaXMuc3RhcnREYXRlKSArICcg4oCTICcgKyB0aGlzLmZvcm1hdERhdGVEaXNwbGF5KHRoaXMuZW5kRGF0ZSlcbiAgICAgICAgfTtcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IGN1cnJlbnRSYW5nZXMgPSBbLi4udGhpcy5zZWxlY3RlZFJhbmdlcygpXTtcbiAgICAgICAgY3VycmVudFJhbmdlcy5wdXNoKG5ld1JhbmdlKTtcbiAgICAgICAgdGhpcy5zZWxlY3RlZFJhbmdlcy5zZXQoY3VycmVudFJhbmdlcyk7XG4gICAgICAgIFxuICAgICAgICAvLyBSZXNldCBmb3IgbmV4dCByYW5nZSBzZWxlY3Rpb25cbiAgICAgICAgdGhpcy5zdGFydERhdGUgPSAnJztcbiAgICAgICAgdGhpcy5lbmREYXRlID0gJyc7XG4gICAgICAgIHRoaXMuc2VsZWN0aW5nU3RhcnREYXRlLnNldCh0cnVlKTtcbiAgICAgICAgXG4gICAgICAgIC8vIFVwZGF0ZSBkaXNwbGF5IHRleHRcbiAgICAgICAgdGhpcy51cGRhdGVNdWx0aVJhbmdlVGV4dCgpO1xuICAgICAgICBcbiAgICAgICAgLy8gRG9uJ3QgY2xvc2UgaWYgbXVsdGlSYW5nZSwgYWxsb3cgYWRkaW5nIG1vcmUgcmFuZ2VzXG4gICAgICAgIGlmICh0aGlzLmNsb3NlT25TZWxlY3Rpb24gJiYgIXRoaXMubXVsdGlSYW5nZSkge1xuICAgICAgICAgIHRoaXMuc2hvd0RhdGVQaWNrZXIuc2V0KGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgdGhpcy5lbWl0TXVsdGlDaGFuZ2UoKTtcbiAgICAgICAgdGhpcy5lbWl0TXVsdGlTZWxlY3Rpb24oKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcnMoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gU2luZ2xlIHJhbmdlIG1vZGUgKG9yaWdpbmFsIGJlaGF2aW9yKVxuICAgICAgaWYgKHRoaXMuc2VsZWN0aW5nU3RhcnREYXRlKCkpIHtcbiAgICAgICAgdGhpcy5zdGFydERhdGUgPSBkYXlPYmouZGF0ZTtcbiAgICAgICAgdGhpcy5lbmREYXRlID0gJyc7XG4gICAgICAgIHRoaXMuZGF0ZVJhbmdlVGV4dC5zZXQoJycpO1xuICAgICAgICB0aGlzLnNlbGVjdGluZ1N0YXJ0RGF0ZS5zZXQoZmFsc2UpO1xuICAgICAgICB0aGlzLmVtaXRDaGFuZ2UoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChkYXlPYmouZGF0ZSA8IHRoaXMuc3RhcnREYXRlKSB7XG4gICAgICAgICAgdGhpcy5lbmREYXRlID0gdGhpcy5zdGFydERhdGU7XG4gICAgICAgICAgdGhpcy5zdGFydERhdGUgPSBkYXlPYmouZGF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmVuZERhdGUgPSBkYXlPYmouZGF0ZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZURhdGVSYW5nZVRleHQoKTtcbiAgICAgICAgaWYgKHRoaXMuY2xvc2VPblNlbGVjdGlvbikge1xuICAgICAgICAgIHRoaXMuc2hvd0RhdGVQaWNrZXIuc2V0KGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNlbGVjdGluZ1N0YXJ0RGF0ZS5zZXQodHJ1ZSk7XG4gICAgICAgIHRoaXMuZW1pdENoYW5nZSgpO1xuICAgICAgICB0aGlzLmVtaXRTZWxlY3Rpb24oKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcnMoKTtcbiAgICB9XG4gIH1cblxuICBjaGFuZ2VNb250aChkaXJlY3Rpb246IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGN1cnJlbnRNb250aFZhbHVlID0gdGhpcy5jdXJyZW50TW9udGgoKTtcbiAgICBjb25zdCB5ZWFyID0gdGhpcy5kYXRlQWRhcHRlci5nZXRZZWFyKGN1cnJlbnRNb250aFZhbHVlKTtcbiAgICBjb25zdCBtb250aCA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0TW9udGgoY3VycmVudE1vbnRoVmFsdWUpO1xuICAgIGNvbnN0IG5ld0N1cnJlbnRNb250aCA9IHRoaXMuZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZSh5ZWFyLCBtb250aCArIGRpcmVjdGlvbiwgMSk7XG4gICAgdGhpcy5jdXJyZW50TW9udGguc2V0KG5ld0N1cnJlbnRNb250aCk7XG4gICAgXG4gICAgY29uc3QgbmV3WWVhciA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0WWVhcihuZXdDdXJyZW50TW9udGgpO1xuICAgIGNvbnN0IG5ld01vbnRoID0gdGhpcy5kYXRlQWRhcHRlci5nZXRNb250aChuZXdDdXJyZW50TW9udGgpO1xuICAgIGNvbnN0IG5ld1ByZXZpb3VzTW9udGggPSB0aGlzLmRhdGVBZGFwdGVyLmNyZWF0ZURhdGUobmV3WWVhciwgbmV3TW9udGggLSAxLCAxKTtcbiAgICB0aGlzLnByZXZpb3VzTW9udGguc2V0KG5ld1ByZXZpb3VzTW9udGgpO1xuICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcnMoKTtcbiAgfVxuXG4gIGdldE1vbnRoTmFtZShkYXRlOiBEYXRlKTogc3RyaW5nIHtcbiAgICBjb25zdCBtb250aE5hbWVzID0gdGhpcy5sb2NhbGUubW9udGhOYW1lcyB8fCB0aGlzLmRlZmF1bHRNb250aE5hbWVzO1xuICAgIHJldHVybiBgJHttb250aE5hbWVzW3RoaXMuZGF0ZUFkYXB0ZXIuZ2V0TW9udGgoZGF0ZSldfSAke3RoaXMuZGF0ZUFkYXB0ZXIuZ2V0WWVhcihkYXRlKX1gO1xuICB9XG5cbiAgZ2V0RGF5TmFtZXMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLmxvY2FsZS5kYXlOYW1lc1Nob3J0IHx8IHRoaXMuZGVmYXVsdERheU5hbWVzU2hvcnQ7XG4gIH1cblxuICBzZWxlY3RQcmVzZXRSYW5nZShwcmVzZXQ6IFByZXNldENvbmZpZyk6IHZvaWQge1xuICAgIGlmICghcHJlc2V0LmdldFZhbHVlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdQcmVzZXRDb25maWcgbXVzdCBoYXZlIGdldFZhbHVlKCkgZnVuY3Rpb24nKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCByYW5nZSA9IHByZXNldC5nZXRWYWx1ZSgpO1xuICAgIHRoaXMuc3RhcnREYXRlID0gcmFuZ2Uuc3RhcnQ7XG4gICAgdGhpcy5lbmREYXRlID0gcmFuZ2UuZW5kO1xuICAgIHRoaXMudXBkYXRlRGF0ZVJhbmdlVGV4dCgpO1xuICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcnMoKTtcbiAgICBpZiAodGhpcy5jbG9zZU9uUHJlc2V0U2VsZWN0aW9uKSB7XG4gICAgICB0aGlzLnNob3dEYXRlUGlja2VyLnNldChmYWxzZSk7XG4gICAgfVxuICAgIHRoaXMuZW1pdFNlbGVjdGlvbigpO1xuICB9XG5cbiAgY2xlYXIoKTogdm9pZCB7XG4gICAgdGhpcy5zdGFydERhdGUgPSAnJztcbiAgICB0aGlzLmVuZERhdGUgPSAnJztcbiAgICB0aGlzLmRhdGVSYW5nZVRleHQuc2V0KCcnKTtcbiAgICB0aGlzLnNob3dEYXRlUGlja2VyLnNldChmYWxzZSk7XG4gICAgdGhpcy5zZWxlY3RpbmdTdGFydERhdGUuc2V0KHRydWUpO1xuICAgIFxuICAgIGlmICh0aGlzLm11bHRpUmFuZ2UpIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWRSYW5nZXMuc2V0KFtdKTtcbiAgICAgIHRoaXMuY3VycmVudFJhbmdlSW5kZXguc2V0KC0xKTtcbiAgICAgIHRoaXMuZW1pdE11bHRpQ2hhbmdlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZW1pdENoYW5nZSgpO1xuICAgIH1cbiAgICBcbiAgICB0aGlzLm9uVG91Y2hlZCgpO1xuICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcnMoKTtcbiAgfVxuICBcbiAgcmVtb3ZlUmFuZ2UoaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICghdGhpcy5tdWx0aVJhbmdlKSByZXR1cm47XG4gICAgXG4gICAgY29uc3QgY3VycmVudFJhbmdlcyA9IFsuLi50aGlzLnNlbGVjdGVkUmFuZ2VzKCldO1xuICAgIGN1cnJlbnRSYW5nZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB0aGlzLnNlbGVjdGVkUmFuZ2VzLnNldChjdXJyZW50UmFuZ2VzKTtcbiAgICBcbiAgICB0aGlzLnVwZGF0ZU11bHRpUmFuZ2VUZXh0KCk7XG4gICAgdGhpcy5lbWl0TXVsdGlDaGFuZ2UoKTtcbiAgICB0aGlzLmVtaXRNdWx0aVNlbGVjdGlvbigpO1xuICAgIHRoaXMuZ2VuZXJhdGVDYWxlbmRhcnMoKTtcbiAgfVxuICBcbiAgcHJpdmF0ZSB1cGRhdGVNdWx0aVJhbmdlVGV4dCgpOiB2b2lkIHtcbiAgICBjb25zdCBjb3VudCA9IHRoaXMuc2VsZWN0ZWRSYW5nZXMoKS5sZW5ndGg7XG4gICAgaWYgKGNvdW50ID09PSAwKSB7XG4gICAgICB0aGlzLmRhdGVSYW5nZVRleHQuc2V0KCcnKTtcbiAgICB9IGVsc2UgaWYgKGNvdW50ID09PSAxKSB7XG4gICAgICB0aGlzLmRhdGVSYW5nZVRleHQuc2V0KCcxIHJhbmdlIHNlbGVjdGVkJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGF0ZVJhbmdlVGV4dC5zZXQoYCR7Y291bnR9IHJhbmdlcyBzZWxlY3RlZGApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZW1pdENoYW5nZSgpOiB2b2lkIHtcbiAgICB0aGlzLmRhdGVSYW5nZUNoYW5nZS5lbWl0KHtcbiAgICAgIHN0YXJ0RGF0ZTogdGhpcy5zdGFydERhdGUsXG4gICAgICBlbmREYXRlOiB0aGlzLmVuZERhdGUsXG4gICAgICByYW5nZVRleHQ6IHRoaXMuZGF0ZVJhbmdlVGV4dCgpXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGVtaXRTZWxlY3Rpb24oKTogdm9pZCB7XG4gICAgdGhpcy5kYXRlUmFuZ2VTZWxlY3RlZC5lbWl0KHtcbiAgICAgIHN0YXJ0RGF0ZTogdGhpcy5zdGFydERhdGUsXG4gICAgICBlbmREYXRlOiB0aGlzLmVuZERhdGUsXG4gICAgICByYW5nZVRleHQ6IHRoaXMuZGF0ZVJhbmdlVGV4dCgpXG4gICAgfSk7XG4gIH1cbiAgXG4gIHByaXZhdGUgZW1pdE11bHRpQ2hhbmdlKCk6IHZvaWQge1xuICAgIHRoaXMubXVsdGlEYXRlUmFuZ2VDaGFuZ2UuZW1pdCh7XG4gICAgICByYW5nZXM6IHRoaXMuc2VsZWN0ZWRSYW5nZXMoKVxuICAgIH0pO1xuICB9XG4gIFxuICBwcml2YXRlIGVtaXRNdWx0aVNlbGVjdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLm11bHRpRGF0ZVJhbmdlU2VsZWN0ZWQuZW1pdCh7XG4gICAgICByYW5nZXM6IHRoaXMuc2VsZWN0ZWRSYW5nZXMoKVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREYXRlUmFuZ2VWYWx1ZSgpOiBEYXRlUmFuZ2Uge1xuICAgIHJldHVybiB7XG4gICAgICBzdGFydERhdGU6IHRoaXMuc3RhcnREYXRlLFxuICAgICAgZW5kRGF0ZTogdGhpcy5lbmREYXRlLFxuICAgICAgcmFuZ2VUZXh0OiB0aGlzLmRhdGVSYW5nZVRleHQoKVxuICAgIH07XG4gIH1cblxuICAvLyBDb250cm9sVmFsdWVBY2Nlc3NvciBpbXBsZW1lbnRhdGlvblxuICB3cml0ZVZhbHVlKHZhbHVlOiBEYXRlUmFuZ2UgfCBudWxsKTogdm9pZCB7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICB0aGlzLnN0YXJ0RGF0ZSA9IHZhbHVlLnN0YXJ0RGF0ZSB8fCAnJztcbiAgICAgIHRoaXMuZW5kRGF0ZSA9IHZhbHVlLmVuZERhdGUgfHwgJyc7XG4gICAgICBpZiAodGhpcy5zdGFydERhdGUgJiYgdGhpcy5lbmREYXRlKSB7XG4gICAgICAgIHRoaXMudXBkYXRlRGF0ZVJhbmdlVGV4dCgpO1xuICAgICAgICB0aGlzLmdlbmVyYXRlQ2FsZW5kYXJzKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc3RhcnREYXRlID0gJyc7XG4gICAgICB0aGlzLmVuZERhdGUgPSAnJztcbiAgICAgIHRoaXMuZGF0ZVJhbmdlVGV4dC5zZXQoJycpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46ICh2YWx1ZTogRGF0ZVJhbmdlIHwgbnVsbCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcbiAgfVxuXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcbiAgfVxuXG4gIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaXNEaXNhYmxlZC5zZXQoaXNEaXNhYmxlZCk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJkYXRlcGlja2VyLXdyYXBwZXJcIiBcbiAgW3N0eWxlLi0taW5wdXQtYm9yZGVyLWhvdmVyXT1cImlucHV0Qm9yZGVyQ29sb3JIb3ZlclwiXG4gIFtzdHlsZS4tLWlucHV0LWJvcmRlci1mb2N1c109XCJpbnB1dEJvcmRlckNvbG9yRm9jdXNcIj5cbiAgPGlucHV0IFxuICAgIHR5cGU9XCJ0ZXh0XCIgXG4gICAgY2xhc3M9XCJkYXRlcGlja2VyLWlucHV0XCIgXG4gICAgW3ZhbHVlXT1cImRhdGVSYW5nZVRleHQoKVwiIFxuICAgIChjbGljayk9XCJ0b2dnbGVEYXRlUGlja2VyKClcIiBcbiAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICAgIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkKClcIlxuICAgIFthdHRyLmFyaWEtbGFiZWxdPVwicGxhY2Vob2xkZXJcIlxuICAgIFthdHRyLmFyaWEtZXhwYW5kZWRdPVwic2hvd0RhdGVQaWNrZXIoKVwiXG4gICAgW2F0dHIuYXJpYS1oYXNwb3B1cF09XCInZGlhbG9nJ1wiXG4gICAgcm9sZT1cImNvbWJvYm94XCJcbiAgICBbbmdTdHlsZV09XCJ7XG4gICAgICAnYmFja2dyb3VuZC1jb2xvcic6IGlucHV0QmFja2dyb3VuZENvbG9yLFxuICAgICAgJ2NvbG9yJzogaW5wdXRUZXh0Q29sb3IsXG4gICAgICAnYm9yZGVyLWNvbG9yJzogaW5wdXRCb3JkZXJDb2xvcixcbiAgICAgICdwYWRkaW5nJzogaW5wdXRQYWRkaW5nXG4gICAgfVwiXG4gICAgcmVhZG9ubHk+XG5cbiAgQGlmIChzaG93RGF0ZVBpY2tlcigpKSB7XG4gIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1kcm9wZG93blwiPlxuICAgIEBpZiAoc2hvd1ByZXNldHMpIHtcbiAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItcHJlc2V0c1wiPlxuICAgICAgQGZvciAocHJlc2V0IG9mIHByZXNldHM7IHRyYWNrIHByZXNldC5sYWJlbCkge1xuICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cInNlbGVjdFByZXNldFJhbmdlKHByZXNldClcIj57eyBwcmVzZXQubGFiZWwgfX08L2J1dHRvbj5cbiAgICAgIH1cbiAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuLWNsb3NlLWNhbGVuZGFyXCIgKGNsaWNrKT1cImNsb3NlRGF0ZVBpY2tlcigpXCIgdGl0bGU9XCJDbG9zZVwiPlxuICAgICAgICDDl1xuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gICAgfVxuXG4gICAgQGlmICghc2hvd1ByZXNldHMpIHtcbiAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItaGVhZGVyLW9ubHktY2xvc2VcIj5cbiAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuLWNsb3NlLWNhbGVuZGFyXCIgKGNsaWNrKT1cImNsb3NlRGF0ZVBpY2tlcigpXCIgdGl0bGU9XCJDbG9zZVwiPlxuICAgICAgICDDl1xuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gICAgfVxuXG4gICAgPCEtLSBDYWxlbmRhcnMgLS0+XG4gICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLWNhbGVuZGFyc1wiPlxuICAgICAgPCEtLSBQcmV2aW91cyBtb250aCBjYWxlbmRhciAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1jYWxlbmRhclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItaGVhZGVyXCI+XG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cImNoYW5nZU1vbnRoKC0xKVwiPlxuICAgICAgICAgICAgPHN2ZyB3aWR0aD1cIjE2XCIgaGVpZ2h0PVwiMTZcIiBmaWxsPVwiY3VycmVudENvbG9yXCIgdmlld0JveD1cIjAgMCAxNiAxNlwiPlxuICAgICAgICAgICAgICA8cGF0aCBmaWxsLXJ1bGU9XCJldmVub2RkXCIgZD1cIk0xMS4zNTQgMS42NDZhLjUuNSAwIDAgMSAwIC43MDhMNS43MDcgOGw1LjY0NyA1LjY0NmEuNS41IDAgMCAxLS43MDguNzA4bC02LTZhLjUuNSAwIDAgMSAwLS43MDhsNi02YS41LjUgMCAwIDEgLjcwOCAwelwiLz5cbiAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxzcGFuPnt7IHByZXZpb3VzTW9udGhOYW1lKCkgfX08L3NwYW4+XG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgc3R5bGU9XCJ2aXNpYmlsaXR5OiBoaWRkZW47XCI+XG4gICAgICAgICAgICA8c3ZnIHdpZHRoPVwiMTZcIiBoZWlnaHQ9XCIxNlwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIiB2aWV3Qm94PVwiMCAwIDE2IDE2XCI+XG4gICAgICAgICAgICAgIDxwYXRoIGZpbGwtcnVsZT1cImV2ZW5vZGRcIiBkPVwiTTQuNjQ2IDEuNjQ2YS41LjUgMCAwIDEgLjcwOCAwbDYgNmEuNS41IDAgMCAxIDAgLjcwOGwtNiA2YS41LjUgMCAwIDEtLjcwOC0uNzA4TDEwLjI5MyA4IDQuNjQ2IDIuMzU0YS41LjUgMCAwIDEgMC0uNzA4elwiLz5cbiAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLXdlZWtkYXlzXCI+XG4gICAgICAgICAgQGZvciAoZGF5TmFtZSBvZiB3ZWVrRGF5TmFtZXMoKTsgdHJhY2sgJGluZGV4KSB7XG4gICAgICAgICAgICA8c3Bhbj57eyBkYXlOYW1lIH19PC9zcGFuPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1kYXlzXCI+XG4gICAgICAgICAgQGZvciAoZGF5T2JqIG9mIHByZXZpb3VzTW9udGhEYXlzKCk7IHRyYWNrIGRheU9iai5kYXRlIHx8ICRpbmRleCkge1xuICAgICAgICAgICAgPGJ1dHRvbiBcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiZGF0ZS1waWNrZXItZGF5XCIgXG4gICAgICAgICAgICAgIFtjbGFzcy5lbXB0eV09XCIhZGF5T2JqLmlzQ3VycmVudE1vbnRoXCJcbiAgICAgICAgICAgICAgW2NsYXNzLnNlbGVjdGVkXT1cImRheU9iai5pc1N0YXJ0IHx8IGRheU9iai5pc0VuZFwiXG4gICAgICAgICAgICAgIFtjbGFzcy5pbi1yYW5nZV09XCJkYXlPYmouaW5SYW5nZSAmJiAhZGF5T2JqLmlzU3RhcnQgJiYgIWRheU9iai5pc0VuZFwiXG4gICAgICAgICAgICAgIFtjbGFzcy5rZXlib2FyZC1mb2N1c2VkXT1cImhhc0tleWJvYXJkRm9jdXMoZGF5T2JqLmRhdGUsIDApXCJcbiAgICAgICAgICAgICAgW2F0dHIudGFiaW5kZXhdPVwiZGF5T2JqLmlzQ3VycmVudE1vbnRoICYmIGhhc0tleWJvYXJkRm9jdXMoZGF5T2JqLmRhdGUsIDApID8gMCA6IC0xXCJcbiAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJmb3JtYXREYXRlRGlzcGxheShkYXlPYmouZGF0ZSlcIlxuICAgICAgICAgICAgICBbYXR0ci5hcmlhLXNlbGVjdGVkXT1cImRheU9iai5pc1N0YXJ0IHx8IGRheU9iai5pc0VuZFwiXG4gICAgICAgICAgICAgIFthdHRyLmFyaWEtY3VycmVudF09XCJkYXlPYmouaXNTdGFydCA/ICdkYXRlJyA6IG51bGxcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0RGF5KGRheU9iailcIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWRheU9iai5pc0N1cnJlbnRNb250aFwiPlxuICAgICAgICAgICAgICB7eyBkYXlPYmouZGF5IH19XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDwhLS0gQ3VycmVudCBtb250aCBjYWxlbmRhciAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1jYWxlbmRhclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItaGVhZGVyXCI+XG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgc3R5bGU9XCJ2aXNpYmlsaXR5OiBoaWRkZW47XCI+XG4gICAgICAgICAgICA8c3ZnIHdpZHRoPVwiMTZcIiBoZWlnaHQ9XCIxNlwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIiB2aWV3Qm94PVwiMCAwIDE2IDE2XCI+XG4gICAgICAgICAgICAgIDxwYXRoIGZpbGwtcnVsZT1cImV2ZW5vZGRcIiBkPVwiTTExLjM1NCAxLjY0NmEuNS41IDAgMCAxIDAgLjcwOEw1LjcwNyA4bDUuNjQ3IDUuNjQ2YS41LjUgMCAwIDEtLjcwOC43MDhsLTYtNmEuNS41IDAgMCAxIDAtLjcwOGw2LTZhLjUuNSAwIDAgMSAuNzA4IDB6XCIvPlxuICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPHNwYW4+e3sgY3VycmVudE1vbnRoTmFtZSgpIH19PC9zcGFuPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJjaGFuZ2VNb250aCgxKVwiPlxuICAgICAgICAgICAgPHN2ZyB3aWR0aD1cIjE2XCIgaGVpZ2h0PVwiMTZcIiBmaWxsPVwiY3VycmVudENvbG9yXCIgdmlld0JveD1cIjAgMCAxNiAxNlwiPlxuICAgICAgICAgICAgICA8cGF0aCBmaWxsLXJ1bGU9XCJldmVub2RkXCIgZD1cIk00LjY0NiAxLjY0NmEuNS41IDAgMCAxIC43MDggMGw2IDZhLjUuNSAwIDAgMSAwIC43MDhsLTYgNmEuNS41IDAgMCAxLS43MDgtLjcwOEwxMC4yOTMgOCA0LjY0NiAyLjM1NGEuNS41IDAgMCAxIDAtLjcwOHpcIi8+XG4gICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci13ZWVrZGF5c1wiPlxuICAgICAgICAgIEBmb3IgKGRheU5hbWUgb2Ygd2Vla0RheU5hbWVzKCk7IHRyYWNrICRpbmRleCkge1xuICAgICAgICAgICAgPHNwYW4+e3sgZGF5TmFtZSB9fTwvc3Bhbj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItZGF5c1wiPlxuICAgICAgICAgIEBmb3IgKGRheU9iaiBvZiBjdXJyZW50TW9udGhEYXlzKCk7IHRyYWNrIGRheU9iai5kYXRlIHx8ICRpbmRleCkge1xuICAgICAgICAgICAgPGJ1dHRvbiBcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiZGF0ZS1waWNrZXItZGF5XCIgXG4gICAgICAgICAgICAgIFtjbGFzcy5lbXB0eV09XCIhZGF5T2JqLmlzQ3VycmVudE1vbnRoXCJcbiAgICAgICAgICAgICAgW2NsYXNzLnNlbGVjdGVkXT1cImRheU9iai5pc1N0YXJ0IHx8IGRheU9iai5pc0VuZFwiXG4gICAgICAgICAgICAgIFtjbGFzcy5pbi1yYW5nZV09XCJkYXlPYmouaW5SYW5nZSAmJiAhZGF5T2JqLmlzU3RhcnQgJiYgIWRheU9iai5pc0VuZFwiXG4gICAgICAgICAgICAgIFtjbGFzcy5rZXlib2FyZC1mb2N1c2VkXT1cImhhc0tleWJvYXJkRm9jdXMoZGF5T2JqLmRhdGUsIDEpXCJcbiAgICAgICAgICAgICAgW2F0dHIudGFiaW5kZXhdPVwiZGF5T2JqLmlzQ3VycmVudE1vbnRoICYmIGhhc0tleWJvYXJkRm9jdXMoZGF5T2JqLmRhdGUsIDEpID8gMCA6IC0xXCJcbiAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJmb3JtYXREYXRlRGlzcGxheShkYXlPYmouZGF0ZSlcIlxuICAgICAgICAgICAgICBbYXR0ci5hcmlhLXNlbGVjdGVkXT1cImRheU9iai5pc1N0YXJ0IHx8IGRheU9iai5pc0VuZFwiXG4gICAgICAgICAgICAgIFthdHRyLmFyaWEtY3VycmVudF09XCJkYXlPYmouaXNTdGFydCA/ICdkYXRlJyA6IG51bGxcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0RGF5KGRheU9iailcIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWRheU9iai5pc0N1cnJlbnRNb250aFwiPlxuICAgICAgICAgICAgICB7eyBkYXlPYmouZGF5IH19XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tIE11bHRpLVJhbmdlIExpc3QgLS0+XG4gICAgQGlmIChtdWx0aVJhbmdlICYmIHNlbGVjdGVkUmFuZ2VzKCkubGVuZ3RoID4gMCkge1xuICAgIDxkaXYgY2xhc3M9XCJtdWx0aS1yYW5nZS1saXN0XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwibXVsdGktcmFuZ2UtaGVhZGVyXCI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwibXVsdGktcmFuZ2UtdGl0bGVcIj5TZWxlY3RlZCBSYW5nZXMgKHt7IHNlbGVjdGVkUmFuZ2VzKCkubGVuZ3RoIH19KTwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cIm11bHRpLXJhbmdlLWl0ZW1zXCI+XG4gICAgICAgIEBmb3IgKHJhbmdlIG9mIHNlbGVjdGVkUmFuZ2VzKCk7IHRyYWNrICRpbmRleCkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwibXVsdGktcmFuZ2UtaXRlbVwiPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibXVsdGktcmFuZ2UtdGV4dFwiPnt7IHJhbmdlLnJhbmdlVGV4dCB9fTwvc3Bhbj5cbiAgICAgICAgICA8YnV0dG9uIFxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiIFxuICAgICAgICAgICAgY2xhc3M9XCJidG4tcmVtb3ZlLXJhbmdlXCIgXG4gICAgICAgICAgICAoY2xpY2spPVwicmVtb3ZlUmFuZ2UoJGluZGV4KVwiXG4gICAgICAgICAgICB0aXRsZT1cIlJlbW92ZSB0aGlzIHJhbmdlXCI+XG4gICAgICAgICAgICA8c3ZnIHdpZHRoPVwiMTRcIiBoZWlnaHQ9XCIxNFwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIiB2aWV3Qm94PVwiMCAwIDE2IDE2XCI+XG4gICAgICAgICAgICAgIDxwYXRoIGQ9XCJNMi4xNDYgMi44NTRhLjUuNSAwIDEgMSAuNzA4LS43MDhMOCA3LjI5M2w1LjE0Ni01LjE0N2EuNS41IDAgMCAxIC43MDguNzA4TDguNzA3IDhsNS4xNDcgNS4xNDZhLjUuNSAwIDAgMS0uNzA4LjcwOEw4IDguNzA3bC01LjE0NiA1LjE0N2EuNS41IDAgMCAxLS43MDgtLjcwOEw3LjI5MyA4IDIuMTQ2IDIuODU0WlwiLz5cbiAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gICAgfVxuXG4gICAgPCEtLSBGb290ZXIgd2l0aCBjbGVhciBidXR0b24gLS0+XG4gICAgQGlmIChzaG93Q2xlYXJCdXR0b24gfHwgbXVsdGlSYW5nZSkge1xuICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1mb290ZXJcIj5cbiAgICAgIEBpZiAobXVsdGlSYW5nZSkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwibXVsdGktcmFuZ2UtZm9vdGVyLWFjdGlvbnNcIj5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0bi1jbGVhclwiIChjbGljayk9XCJjbGVhcigpXCIgdGl0bGU9XCJDbGVhciBhbGwgcmFuZ2VzXCI+XG4gICAgICAgICAgICBDbGVhciBBbGxcbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0bi1kb25lXCIgKGNsaWNrKT1cImNsb3NlRGF0ZVBpY2tlcigpXCIgdGl0bGU9XCJEb25lIHNlbGVjdGluZ1wiPlxuICAgICAgICAgICAgRG9uZVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICAgIEBpZiAoIW11bHRpUmFuZ2UgJiYgc2hvd0NsZWFyQnV0dG9uKSB7XG4gICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuLWNsZWFyXCIgKGNsaWNrKT1cImNsZWFyKClcIiB0aXRsZT1cIkNsZWFyIHNlbGVjdGlvblwiPlxuICAgICAgICAgIENsZWFyXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgfVxuICAgIDwvZGl2PlxuICAgIH1cbiAgPC9kaXY+XG4gIH1cbjwvZGl2PlxuIl19
|