@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.
@@ -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