@oneluiz/dual-datepicker 2.6.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,362 +0,0 @@
1
- import { Component, Input, Output, EventEmitter, HostListener, forwardRef, signal, computed, effect, inject } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import { FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
4
- import { DATE_ADAPTER } from './date-adapter';
5
- import { NativeDateAdapter } from './native-date-adapter';
6
- import * as i0 from "@angular/core";
7
- import * as i1 from "@angular/common";
8
- export class DualDatepickerComponent {
9
- elementRef;
10
- placeholder = 'Select date range';
11
- fechaInicio = '';
12
- fechaFin = '';
13
- showPresets = true;
14
- showClearButton = false;
15
- closeOnSelection = true;
16
- closeOnPresetSelection = true;
17
- closeOnClickOutside = true;
18
- presets = [
19
- { label: 'Last month', daysAgo: 30 },
20
- { label: 'Last 6 months', daysAgo: 180 },
21
- { label: 'Last year', daysAgo: 365 }
22
- ];
23
- inputBackgroundColor = '#fff';
24
- inputTextColor = '#495057';
25
- inputBorderColor = '#ced4da';
26
- inputBorderColorHover = '#ced4da';
27
- inputBorderColorFocus = '#80bdff';
28
- inputPadding = '0.375rem 0.75rem';
29
- locale = {};
30
- dateRangeChange = new EventEmitter();
31
- dateRangeSelected = new EventEmitter();
32
- // Date adapter injection
33
- dateAdapter = inject(DATE_ADAPTER);
34
- // Signals for reactive state
35
- mostrarDatePicker = signal(false);
36
- rangoFechas = signal('');
37
- fechaSeleccionandoInicio = signal(true);
38
- mesActual = signal(this.dateAdapter.today());
39
- mesAnterior = signal(this.dateAdapter.today());
40
- diasMesActual = signal([]);
41
- diasMesAnterior = signal([]);
42
- isDisabled = signal(false);
43
- // Computed values
44
- nombreMesActual = computed(() => this.getNombreMes(this.mesActual()));
45
- nombreMesAnterior = computed(() => this.getNombreMes(this.mesAnterior()));
46
- diasSemana = computed(() => this.getDayNames());
47
- defaultMonthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
48
- defaultMonthNamesShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
49
- defaultDayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
50
- defaultDayNamesShort = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
51
- // ControlValueAccessor callbacks
52
- onChange = () => { };
53
- onTouched = () => { };
54
- constructor(elementRef) {
55
- this.elementRef = elementRef;
56
- // Effect to emit changes when dates change
57
- effect(() => {
58
- const rango = this.rangoFechas();
59
- if (this.fechaInicio || this.fechaFin) {
60
- this.onChange(this.getDateRangeValue());
61
- }
62
- });
63
- }
64
- onClickOutside(event) {
65
- if (this.mostrarDatePicker() && this.closeOnClickOutside) {
66
- const clickedInside = this.elementRef.nativeElement.contains(event.target);
67
- if (!clickedInside) {
68
- this.cerrarDatePicker();
69
- }
70
- }
71
- }
72
- ngOnInit() {
73
- if (this.fechaInicio && this.fechaFin) {
74
- this.actualizarRangoFechasTexto();
75
- this.generarCalendarios();
76
- }
77
- }
78
- ngOnChanges(changes) {
79
- if (changes['fechaInicio'] || changes['fechaFin']) {
80
- if (this.fechaInicio && this.fechaFin) {
81
- this.actualizarRangoFechasTexto();
82
- this.generarCalendarios();
83
- }
84
- else if (!this.fechaInicio && !this.fechaFin) {
85
- this.rangoFechas.set('');
86
- }
87
- }
88
- }
89
- formatearFecha(fecha) {
90
- const year = this.dateAdapter.getYear(fecha);
91
- const month = String(this.dateAdapter.getMonth(fecha) + 1).padStart(2, '0');
92
- const day = String(this.dateAdapter.getDate(fecha)).padStart(2, '0');
93
- return `${year}-${month}-${day}`;
94
- }
95
- formatearFechaDisplay(fechaStr) {
96
- if (!fechaStr)
97
- return '';
98
- const fecha = this.dateAdapter.parse(fechaStr);
99
- if (!fecha)
100
- return '';
101
- const monthNames = this.locale.monthNamesShort || this.defaultMonthNamesShort;
102
- return `${this.dateAdapter.getDate(fecha)} ${monthNames[this.dateAdapter.getMonth(fecha)]}`;
103
- }
104
- actualizarRangoFechasTexto() {
105
- if (this.fechaInicio && this.fechaFin) {
106
- const inicio = this.formatearFechaDisplay(this.fechaInicio);
107
- const fin = this.formatearFechaDisplay(this.fechaFin);
108
- this.rangoFechas.set(`${inicio} - ${fin}`);
109
- }
110
- else {
111
- this.rangoFechas.set('');
112
- }
113
- }
114
- toggleDatePicker() {
115
- this.mostrarDatePicker.update(value => !value);
116
- if (this.mostrarDatePicker()) {
117
- this.fechaSeleccionandoInicio.set(true);
118
- const mesActualValue = this.mesActual();
119
- const año = this.dateAdapter.getYear(mesActualValue);
120
- const mes = this.dateAdapter.getMonth(mesActualValue);
121
- const mesAnteriorDate = this.dateAdapter.createDate(año, mes - 1, 1);
122
- this.mesAnterior.set(mesAnteriorDate);
123
- this.generarCalendarios();
124
- }
125
- this.onTouched();
126
- }
127
- cerrarDatePicker() {
128
- this.mostrarDatePicker.set(false);
129
- this.onTouched();
130
- }
131
- generarCalendarios() {
132
- this.diasMesAnterior.set(this.generarCalendarioMes(this.mesAnterior()));
133
- this.diasMesActual.set(this.generarCalendarioMes(this.mesActual()));
134
- }
135
- generarCalendarioMes(fecha) {
136
- const año = this.dateAdapter.getYear(fecha);
137
- const mes = this.dateAdapter.getMonth(fecha);
138
- const primerDia = this.dateAdapter.createDate(año, mes, 1);
139
- const ultimoDia = this.dateAdapter.createDate(año, mes + 1, 0);
140
- const diasEnMes = this.dateAdapter.getDate(ultimoDia);
141
- const primerDiaSemana = this.dateAdapter.getDay(primerDia);
142
- const diasMes = [];
143
- for (let i = 0; i < primerDiaSemana; i++) {
144
- diasMes.push({ dia: null, esMesActual: false });
145
- }
146
- for (let dia = 1; dia <= diasEnMes; dia++) {
147
- const fechaDia = this.dateAdapter.createDate(año, mes, dia);
148
- const fechaStr = this.formatearFecha(fechaDia);
149
- diasMes.push({
150
- dia: dia,
151
- fecha: fechaStr,
152
- esMesActual: true,
153
- esInicio: this.fechaInicio === fechaStr,
154
- esFin: this.fechaFin === fechaStr,
155
- enRango: this.estaEnRango(fechaStr)
156
- });
157
- }
158
- return diasMes;
159
- }
160
- estaEnRango(fechaStr) {
161
- if (!this.fechaInicio || !this.fechaFin)
162
- return false;
163
- return fechaStr >= this.fechaInicio && fechaStr <= this.fechaFin;
164
- }
165
- seleccionarDia(diaObj) {
166
- if (!diaObj.esMesActual || this.isDisabled())
167
- return;
168
- if (this.fechaSeleccionandoInicio()) {
169
- this.fechaInicio = diaObj.fecha;
170
- this.fechaFin = '';
171
- this.rangoFechas.set('');
172
- this.fechaSeleccionandoInicio.set(false);
173
- this.emitirCambio();
174
- }
175
- else {
176
- if (diaObj.fecha < this.fechaInicio) {
177
- this.fechaFin = this.fechaInicio;
178
- this.fechaInicio = diaObj.fecha;
179
- }
180
- else {
181
- this.fechaFin = diaObj.fecha;
182
- }
183
- this.actualizarRangoFechasTexto();
184
- if (this.closeOnSelection) {
185
- this.mostrarDatePicker.set(false);
186
- }
187
- this.fechaSeleccionandoInicio.set(true);
188
- this.emitirCambio();
189
- this.emitirSeleccion();
190
- }
191
- this.generarCalendarios();
192
- }
193
- cambiarMes(direccion) {
194
- const mesActualValue = this.mesActual();
195
- const año = this.dateAdapter.getYear(mesActualValue);
196
- const mes = this.dateAdapter.getMonth(mesActualValue);
197
- const nuevoMesActual = this.dateAdapter.createDate(año, mes + direccion, 1);
198
- this.mesActual.set(nuevoMesActual);
199
- const añoNuevo = this.dateAdapter.getYear(nuevoMesActual);
200
- const mesNuevo = this.dateAdapter.getMonth(nuevoMesActual);
201
- const mesAnteriorNuevo = this.dateAdapter.createDate(añoNuevo, mesNuevo - 1, 1);
202
- this.mesAnterior.set(mesAnteriorNuevo);
203
- this.generarCalendarios();
204
- }
205
- getNombreMes(fecha) {
206
- const monthNames = this.locale.monthNames || this.defaultMonthNames;
207
- return `${monthNames[this.dateAdapter.getMonth(fecha)]} ${this.dateAdapter.getYear(fecha)}`;
208
- }
209
- getDayNames() {
210
- return this.locale.dayNamesShort || this.defaultDayNamesShort;
211
- }
212
- seleccionarRangoPredefinido(preset) {
213
- let start;
214
- let end;
215
- // New flexible pattern with getValue()
216
- if (preset.getValue) {
217
- const range = preset.getValue();
218
- start = range.start;
219
- end = range.end;
220
- }
221
- // Backward compatibility with daysAgo pattern
222
- else if (preset.daysAgo !== undefined) {
223
- const hoy = this.dateAdapter.today();
224
- const fechaInicio = this.dateAdapter.addDays(hoy, -preset.daysAgo);
225
- start = this.formatearFecha(fechaInicio);
226
- end = this.formatearFecha(hoy);
227
- }
228
- else {
229
- console.error('PresetConfig must have either getValue() or daysAgo');
230
- return;
231
- }
232
- this.fechaInicio = start;
233
- this.fechaFin = end;
234
- this.actualizarRangoFechasTexto();
235
- this.generarCalendarios();
236
- if (this.closeOnPresetSelection) {
237
- this.mostrarDatePicker.set(false);
238
- }
239
- this.emitirSeleccion();
240
- }
241
- limpiar() {
242
- this.fechaInicio = '';
243
- this.fechaFin = '';
244
- this.rangoFechas.set('');
245
- this.mostrarDatePicker.set(false);
246
- this.fechaSeleccionandoInicio.set(true);
247
- this.emitirCambio();
248
- this.onTouched();
249
- }
250
- emitirCambio() {
251
- this.dateRangeChange.emit({
252
- fechaInicio: this.fechaInicio,
253
- fechaFin: this.fechaFin,
254
- rangoTexto: this.rangoFechas()
255
- });
256
- }
257
- emitirSeleccion() {
258
- this.dateRangeSelected.emit({
259
- fechaInicio: this.fechaInicio,
260
- fechaFin: this.fechaFin,
261
- rangoTexto: this.rangoFechas()
262
- });
263
- }
264
- getDateRangeValue() {
265
- return {
266
- fechaInicio: this.fechaInicio,
267
- fechaFin: this.fechaFin,
268
- rangoTexto: this.rangoFechas()
269
- };
270
- }
271
- // ControlValueAccessor implementation
272
- writeValue(value) {
273
- if (value) {
274
- this.fechaInicio = value.fechaInicio || '';
275
- this.fechaFin = value.fechaFin || '';
276
- if (this.fechaInicio && this.fechaFin) {
277
- this.actualizarRangoFechasTexto();
278
- this.generarCalendarios();
279
- }
280
- }
281
- else {
282
- this.fechaInicio = '';
283
- this.fechaFin = '';
284
- this.rangoFechas.set('');
285
- }
286
- }
287
- registerOnChange(fn) {
288
- this.onChange = fn;
289
- }
290
- registerOnTouched(fn) {
291
- this.onTouched = fn;
292
- }
293
- setDisabledState(isDisabled) {
294
- this.isDisabled.set(isDisabled);
295
- }
296
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDatepickerComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
297
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: DualDatepickerComponent, isStandalone: true, selector: "ngx-dual-datepicker", inputs: { placeholder: "placeholder", fechaInicio: "fechaInicio", fechaFin: "fechaFin", showPresets: "showPresets", showClearButton: "showClearButton", 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" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, providers: [
298
- {
299
- provide: NG_VALUE_ACCESSOR,
300
- useExisting: forwardRef(() => DualDatepickerComponent),
301
- multi: true
302
- },
303
- {
304
- provide: DATE_ADAPTER,
305
- useClass: NativeDateAdapter
306
- }
307
- ], 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]=\"rangoFechas()\" \n (click)=\"toggleDatePicker()\" \n [placeholder]=\"placeholder\"\n [disabled]=\"isDisabled()\"\n [ngStyle]=\"{\n 'background-color': inputBackgroundColor,\n 'color': inputTextColor,\n 'border-color': inputBorderColor,\n 'padding': inputPadding\n }\"\n readonly>\n\n @if (mostrarDatePicker()) {\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)=\"seleccionarRangoPredefinido(preset)\">{{ preset.label }}</button>\n }\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"cerrarDatePicker()\" 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)=\"cerrarDatePicker()\" 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)=\"cambiarMes(-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>{{ nombreMesAnterior() }}</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 diasSemana(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (diaObj of diasMesAnterior(); track diaObj.fecha || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!diaObj.esMesActual\"\n [class.selected]=\"diaObj.esInicio || diaObj.esFin\"\n [class.in-range]=\"diaObj.enRango && !diaObj.esInicio && !diaObj.esFin\"\n (click)=\"seleccionarDia(diaObj)\"\n [disabled]=\"!diaObj.esMesActual\">\n {{ diaObj.dia }}\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>{{ nombreMesActual() }}</span>\n <button type=\"button\" (click)=\"cambiarMes(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 diasSemana(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (diaObj of diasMesActual(); track diaObj.fecha || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!diaObj.esMesActual\"\n [class.selected]=\"diaObj.esInicio || diaObj.esFin\"\n [class.in-range]=\"diaObj.enRango && !diaObj.esInicio && !diaObj.esFin\"\n (click)=\"seleccionarDia(diaObj)\"\n [disabled]=\"!diaObj.esMesActual\">\n {{ diaObj.dia }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Footer with clear button -->\n @if (showClearButton) {\n <div class=\"date-picker-footer\">\n <button type=\"button\" class=\"btn-clear\" (click)=\"limpiar()\" title=\"Clear selection\">\n Clear\n </button>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".datepicker-wrapper{position:relative;width:100%}.datepicker-wrapper .datepicker-input{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;cursor:pointer}.datepicker-wrapper .datepicker-input:hover{border-color:var(--input-border-hover, #ced4da)}.datepicker-wrapper .datepicker-input:focus{border-color:var(--input-border-focus, #80bdff);box-shadow:0 0 0 .2rem #007bff40;outline:0}.datepicker-wrapper .datepicker-input::placeholder{color:#6c757d;opacity:1}.datepicker-wrapper .datepicker-input:disabled,.datepicker-wrapper .datepicker-input[readonly]{background-color:#e9ecef;opacity:1}.date-picker-dropdown{position:absolute;top:100%;left:0;margin-top:4px;background:#fff;border:1px solid #e1e4e8;border-radius:8px;box-shadow:0 4px 12px #00000014,0 0 1px #00000014;padding:16px;z-index:1060;min-width:680px}@media (max-width: 768px){.date-picker-dropdown{min-width:100%;left:0;right:0}}.date-picker-header-only-close{display:flex;justify-content:flex-end;margin-bottom:12px}.date-picker-header-only-close .btn-close-calendar{background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;border-radius:6px;cursor:pointer;transition:all .15s ease;font-size:1.5rem;line-height:1}.date-picker-header-only-close .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-header-only-close .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-presets{display:flex;gap:6px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid #e5e7eb;align-items:center}@media (max-width: 768px){.date-picker-presets{flex-wrap:wrap}}.date-picker-presets button{font-size:.75rem;padding:6px 14px;border:none;background-color:#f9fafb;color:#374151;border-radius:6px;transition:all .15s ease;font-weight:500;cursor:pointer;border:1px solid #e5e7eb}.date-picker-presets button:hover{background-color:#f3f4f6;border-color:#d1d5db;transform:translateY(-1px);box-shadow:0 2px 4px #0000000f}.date-picker-presets button:active{transform:translateY(0);box-shadow:none}.date-picker-presets .btn-close-calendar{margin-left:auto;background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;font-size:1.5rem;line-height:1}.date-picker-presets .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-presets .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-calendars{display:flex;gap:32px}@media (max-width: 768px){.date-picker-calendars{flex-direction:column;gap:16px}}.date-picker-calendar{flex:1}.date-picker-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 4px}.date-picker-header span{font-size:.813rem;font-weight:600;color:#111827}.date-picker-header button{padding:4px;color:#6b7280;text-decoration:none;border-radius:6px;transition:all .15s ease;border:none;background:transparent;cursor:pointer}.date-picker-header button:hover{background-color:#f3f4f6;color:#111827}.date-picker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.date-picker-weekdays span{text-align:center;font-size:.625rem;font-weight:600;color:#6b7280;padding:6px}.date-picker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.date-picker-day{aspect-ratio:1;border:none;background:transparent;border-radius:50%;font-size:.75rem;cursor:pointer;transition:all .15s ease;color:#374151;font-weight:400}.date-picker-day:hover:not(:disabled):not(.selected){background-color:#f3f4f6;color:#111827}.date-picker-day.empty{visibility:hidden}.date-picker-day.selected{background-color:#222;color:#fff;font-weight:600}.date-picker-day.in-range{background-color:#f9fafb;border-radius:0}.date-picker-day:disabled{cursor:not-allowed;opacity:.3}.date-picker-footer{padding:12px;border-top:1px solid #e1e4e8;display:flex;justify-content:center;gap:8px}.date-picker-footer .btn-clear{padding:8px 16px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-clear:hover{background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-clear:active{transform:translateY(0);box-shadow:none;background-color:#e9ecef}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
308
- }
309
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DualDatepickerComponent, decorators: [{
310
- type: Component,
311
- args: [{ selector: 'ngx-dual-datepicker', standalone: true, imports: [CommonModule, FormsModule, ReactiveFormsModule], providers: [
312
- {
313
- provide: NG_VALUE_ACCESSOR,
314
- useExisting: forwardRef(() => DualDatepickerComponent),
315
- multi: true
316
- },
317
- {
318
- provide: DATE_ADAPTER,
319
- useClass: NativeDateAdapter
320
- }
321
- ], 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]=\"rangoFechas()\" \n (click)=\"toggleDatePicker()\" \n [placeholder]=\"placeholder\"\n [disabled]=\"isDisabled()\"\n [ngStyle]=\"{\n 'background-color': inputBackgroundColor,\n 'color': inputTextColor,\n 'border-color': inputBorderColor,\n 'padding': inputPadding\n }\"\n readonly>\n\n @if (mostrarDatePicker()) {\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)=\"seleccionarRangoPredefinido(preset)\">{{ preset.label }}</button>\n }\n <button type=\"button\" class=\"btn-close-calendar\" (click)=\"cerrarDatePicker()\" 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)=\"cerrarDatePicker()\" 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)=\"cambiarMes(-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>{{ nombreMesAnterior() }}</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 diasSemana(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (diaObj of diasMesAnterior(); track diaObj.fecha || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!diaObj.esMesActual\"\n [class.selected]=\"diaObj.esInicio || diaObj.esFin\"\n [class.in-range]=\"diaObj.enRango && !diaObj.esInicio && !diaObj.esFin\"\n (click)=\"seleccionarDia(diaObj)\"\n [disabled]=\"!diaObj.esMesActual\">\n {{ diaObj.dia }}\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>{{ nombreMesActual() }}</span>\n <button type=\"button\" (click)=\"cambiarMes(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 diasSemana(); track $index) {\n <span>{{ dayName }}</span>\n }\n </div>\n <div class=\"date-picker-days\">\n @for (diaObj of diasMesActual(); track diaObj.fecha || $index) {\n <button \n type=\"button\"\n class=\"date-picker-day\" \n [class.empty]=\"!diaObj.esMesActual\"\n [class.selected]=\"diaObj.esInicio || diaObj.esFin\"\n [class.in-range]=\"diaObj.enRango && !diaObj.esInicio && !diaObj.esFin\"\n (click)=\"seleccionarDia(diaObj)\"\n [disabled]=\"!diaObj.esMesActual\">\n {{ diaObj.dia }}\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Footer with clear button -->\n @if (showClearButton) {\n <div class=\"date-picker-footer\">\n <button type=\"button\" class=\"btn-clear\" (click)=\"limpiar()\" title=\"Clear selection\">\n Clear\n </button>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".datepicker-wrapper{position:relative;width:100%}.datepicker-wrapper .datepicker-input{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;cursor:pointer}.datepicker-wrapper .datepicker-input:hover{border-color:var(--input-border-hover, #ced4da)}.datepicker-wrapper .datepicker-input:focus{border-color:var(--input-border-focus, #80bdff);box-shadow:0 0 0 .2rem #007bff40;outline:0}.datepicker-wrapper .datepicker-input::placeholder{color:#6c757d;opacity:1}.datepicker-wrapper .datepicker-input:disabled,.datepicker-wrapper .datepicker-input[readonly]{background-color:#e9ecef;opacity:1}.date-picker-dropdown{position:absolute;top:100%;left:0;margin-top:4px;background:#fff;border:1px solid #e1e4e8;border-radius:8px;box-shadow:0 4px 12px #00000014,0 0 1px #00000014;padding:16px;z-index:1060;min-width:680px}@media (max-width: 768px){.date-picker-dropdown{min-width:100%;left:0;right:0}}.date-picker-header-only-close{display:flex;justify-content:flex-end;margin-bottom:12px}.date-picker-header-only-close .btn-close-calendar{background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;border-radius:6px;cursor:pointer;transition:all .15s ease;font-size:1.5rem;line-height:1}.date-picker-header-only-close .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-header-only-close .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-presets{display:flex;gap:6px;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid #e5e7eb;align-items:center}@media (max-width: 768px){.date-picker-presets{flex-wrap:wrap}}.date-picker-presets button{font-size:.75rem;padding:6px 14px;border:none;background-color:#f9fafb;color:#374151;border-radius:6px;transition:all .15s ease;font-weight:500;cursor:pointer;border:1px solid #e5e7eb}.date-picker-presets button:hover{background-color:#f3f4f6;border-color:#d1d5db;transform:translateY(-1px);box-shadow:0 2px 4px #0000000f}.date-picker-presets button:active{transform:translateY(0);box-shadow:none}.date-picker-presets .btn-close-calendar{margin-left:auto;background-color:transparent;border:1px solid transparent;color:#6b7280;padding:6px 10px;font-size:1.5rem;line-height:1}.date-picker-presets .btn-close-calendar:hover{background-color:#fee;border-color:#fcc;color:#dc2626;transform:translateY(-1px);box-shadow:0 2px 4px #dc26261a}.date-picker-presets .btn-close-calendar:active{transform:translateY(0);box-shadow:none}.date-picker-calendars{display:flex;gap:32px}@media (max-width: 768px){.date-picker-calendars{flex-direction:column;gap:16px}}.date-picker-calendar{flex:1}.date-picker-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding:0 4px}.date-picker-header span{font-size:.813rem;font-weight:600;color:#111827}.date-picker-header button{padding:4px;color:#6b7280;text-decoration:none;border-radius:6px;transition:all .15s ease;border:none;background:transparent;cursor:pointer}.date-picker-header button:hover{background-color:#f3f4f6;color:#111827}.date-picker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.date-picker-weekdays span{text-align:center;font-size:.625rem;font-weight:600;color:#6b7280;padding:6px}.date-picker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.date-picker-day{aspect-ratio:1;border:none;background:transparent;border-radius:50%;font-size:.75rem;cursor:pointer;transition:all .15s ease;color:#374151;font-weight:400}.date-picker-day:hover:not(:disabled):not(.selected){background-color:#f3f4f6;color:#111827}.date-picker-day.empty{visibility:hidden}.date-picker-day.selected{background-color:#222;color:#fff;font-weight:600}.date-picker-day.in-range{background-color:#f9fafb;border-radius:0}.date-picker-day:disabled{cursor:not-allowed;opacity:.3}.date-picker-footer{padding:12px;border-top:1px solid #e1e4e8;display:flex;justify-content:center;gap:8px}.date-picker-footer .btn-clear{padding:8px 16px;background-color:#f6f8fa;border:1px solid #d0d7de;border-radius:6px;font-size:.875rem;font-weight:500;color:#24292f;cursor:pointer;transition:all .15s ease}.date-picker-footer .btn-clear:hover{background-color:#f3f4f6;border-color:#8c959f;transform:translateY(-1px);box-shadow:0 2px 4px #0000000d}.date-picker-footer .btn-clear:active{transform:translateY(0);box-shadow:none;background-color:#e9ecef}\n"] }]
322
- }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { placeholder: [{
323
- type: Input
324
- }], fechaInicio: [{
325
- type: Input
326
- }], fechaFin: [{
327
- type: Input
328
- }], showPresets: [{
329
- type: Input
330
- }], showClearButton: [{
331
- type: Input
332
- }], closeOnSelection: [{
333
- type: Input
334
- }], closeOnPresetSelection: [{
335
- type: Input
336
- }], closeOnClickOutside: [{
337
- type: Input
338
- }], presets: [{
339
- type: Input
340
- }], inputBackgroundColor: [{
341
- type: Input
342
- }], inputTextColor: [{
343
- type: Input
344
- }], inputBorderColor: [{
345
- type: Input
346
- }], inputBorderColorHover: [{
347
- type: Input
348
- }], inputBorderColorFocus: [{
349
- type: Input
350
- }], inputPadding: [{
351
- type: Input
352
- }], locale: [{
353
- type: Input
354
- }], dateRangeChange: [{
355
- type: Output
356
- }], dateRangeSelected: [{
357
- type: Output
358
- }], onClickOutside: [{
359
- type: HostListener,
360
- args: ['document:click', ['$event']]
361
- }] } });
362
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHVhbC1kYXRlcGlja2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kdWFsLWRhdGVwaWNrZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vc3JjL2R1YWwtZGF0ZXBpY2tlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFvQyxZQUFZLEVBQWMsVUFBVSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqTCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzRyxPQUFPLEVBQWUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7OztBQThDMUQsTUFBTSxPQUFPLHVCQUF1QjtJQW9EZDtJQW5EWCxXQUFXLEdBQVcsbUJBQW1CLENBQUM7SUFDMUMsV0FBVyxHQUFXLEVBQUUsQ0FBQztJQUN6QixRQUFRLEdBQVcsRUFBRSxDQUFDO0lBQ3RCLFdBQVcsR0FBWSxJQUFJLENBQUM7SUFDNUIsZUFBZSxHQUFZLEtBQUssQ0FBQztJQUNqQyxnQkFBZ0IsR0FBWSxJQUFJLENBQUM7SUFDakMsc0JBQXNCLEdBQVksSUFBSSxDQUFDO0lBQ3ZDLG1CQUFtQixHQUFZLElBQUksQ0FBQztJQUNwQyxPQUFPLEdBQW1CO1FBQ2pDLEVBQUUsS0FBSyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFO1FBQ3BDLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFO1FBQ3hDLEVBQUUsS0FBSyxF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d0IsQ0FBQzs0QkFDdEQsS0FBSyxFQUFFLElBQUk7eUJBQ1o7d0JBQ0Q7NEJBQ0UsT0FBTyxFQUFFLFlBQVk7NEJBQ3JCLFFBQVEsRUFBRSxpQkFBaUI7eUJBQzVCO3FCQUNGOytFQUdRLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBQ0csc0JBQXNCO3NCQUE5QixLQUFLO2dCQUNHLG1CQUFtQjtzQkFBM0IsS0FBSztnQkFDRyxPQUFPO3NCQUFmLEtBQUs7Z0JBS0csb0JBQW9CO3NCQUE1QixLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUNHLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFDRyxxQkFBcUI7c0JBQTdCLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUs7Z0JBRUksZUFBZTtzQkFBeEIsTUFBTTtnQkFDRyxpQkFBaUI7c0JBQTFCLE1BQU07Z0JBd0NQLGNBQWM7c0JBRGIsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBPbkluaXQsIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlcywgSG9zdExpc3RlbmVyLCBFbGVtZW50UmVmLCBmb3J3YXJkUmVmLCBzaWduYWwsIGNvbXB1dGVkLCBlZmZlY3QsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlLCBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBEYXRlQWRhcHRlciwgREFURV9BREFQVEVSIH0gZnJvbSAnLi9kYXRlLWFkYXB0ZXInO1xuaW1wb3J0IHsgTmF0aXZlRGF0ZUFkYXB0ZXIgfSBmcm9tICcuL25hdGl2ZS1kYXRlLWFkYXB0ZXInO1xuXG5leHBvcnQgaW50ZXJmYWNlIERhdGVSYW5nZSB7XG4gIGZlY2hhSW5pY2lvOiBzdHJpbmc7XG4gIGZlY2hhRmluOiBzdHJpbmc7XG4gIHJhbmdvVGV4dG86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcmVzZXRSYW5nZSB7XG4gIHN0YXJ0OiBzdHJpbmc7XG4gIGVuZDogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByZXNldENvbmZpZyB7XG4gIGxhYmVsOiBzdHJpbmc7XG4gIC8qKiBAZGVwcmVjYXRlZCBVc2UgZ2V0VmFsdWUoKSBpbnN0ZWFkIGZvciBtb3JlIGZsZXhpYmlsaXR5ICovXG4gIGRheXNBZ28/OiBudW1iZXI7XG4gIGdldFZhbHVlPzogKCkgPT4gUHJlc2V0UmFuZ2U7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9jYWxlQ29uZmlnIHtcbiAgbW9udGhOYW1lcz86IHN0cmluZ1tdO1xuICBtb250aE5hbWVzU2hvcnQ/OiBzdHJpbmdbXTtcbiAgZGF5TmFtZXM/OiBzdHJpbmdbXTtcbiAgZGF5TmFtZXNTaG9ydD86IHN0cmluZ1tdO1xuICBmaXJzdERheU9mV2Vlaz86IG51bWJlcjsgLy8gMCA9IFN1bmRheSwgMSA9IE1vbmRheSwgZXRjLlxufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZHVhbC1kYXRlcGlja2VyJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRm9ybXNNb2R1bGUsIFJlYWN0aXZlRm9ybXNNb2R1bGVdLFxuICB0ZW1wbGF0ZVVybDogJy4vZHVhbC1kYXRlcGlja2VyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL2R1YWwtZGF0ZXBpY2tlci5jb21wb25lbnQuc2NzcycsXG4gIHByb3ZpZGVyczogW1xuICAgIHtcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gRHVhbERhdGVwaWNrZXJDb21wb25lbnQpLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9LFxuICAgIHtcbiAgICAgIHByb3ZpZGU6IERBVEVfQURBUFRFUixcbiAgICAgIHVzZUNsYXNzOiBOYXRpdmVEYXRlQWRhcHRlclxuICAgIH1cbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBEdWFsRGF0ZXBpY2tlckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBDb250cm9sVmFsdWVBY2Nlc3NvciB7XG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyOiBzdHJpbmcgPSAnU2VsZWN0IGRhdGUgcmFuZ2UnO1xuICBASW5wdXQoKSBmZWNoYUluaWNpbzogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIGZlY2hhRmluOiBzdHJpbmcgPSAnJztcbiAgQElucHV0KCkgc2hvd1ByZXNldHM6IGJvb2xlYW4gPSB0cnVlO1xuICBASW5wdXQoKSBzaG93Q2xlYXJCdXR0b246IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgY2xvc2VPblNlbGVjdGlvbjogYm9vbGVhbiA9IHRydWU7XG4gIEBJbnB1dCgpIGNsb3NlT25QcmVzZXRTZWxlY3Rpb246IGJvb2xlYW4gPSB0cnVlO1xuICBASW5wdXQoKSBjbG9zZU9uQ2xpY2tPdXRzaWRlOiBib29sZWFuID0gdHJ1ZTtcbiAgQElucHV0KCkgcHJlc2V0czogUHJlc2V0Q29uZmlnW10gPSBbXG4gICAgeyBsYWJlbDogJ0xhc3QgbW9udGgnLCBkYXlzQWdvOiAzMCB9LFxuICAgIHsgbGFiZWw6ICdMYXN0IDYgbW9udGhzJywgZGF5c0FnbzogMTgwIH0sXG4gICAgeyBsYWJlbDogJ0xhc3QgeWVhcicsIGRheXNBZ286IDM2NSB9XG4gIF07XG4gIEBJbnB1dCgpIGlucHV0QmFja2dyb3VuZENvbG9yOiBzdHJpbmcgPSAnI2ZmZic7XG4gIEBJbnB1dCgpIGlucHV0VGV4dENvbG9yOiBzdHJpbmcgPSAnIzQ5NTA1Nyc7XG4gIEBJbnB1dCgpIGlucHV0Qm9yZGVyQ29sb3I6IHN0cmluZyA9ICcjY2VkNGRhJztcbiAgQElucHV0KCkgaW5wdXRCb3JkZXJDb2xvckhvdmVyOiBzdHJpbmcgPSAnI2NlZDRkYSc7XG4gIEBJbnB1dCgpIGlucHV0Qm9yZGVyQ29sb3JGb2N1czogc3RyaW5nID0gJyM4MGJkZmYnO1xuICBASW5wdXQoKSBpbnB1dFBhZGRpbmc6IHN0cmluZyA9ICcwLjM3NXJlbSAwLjc1cmVtJztcbiAgQElucHV0KCkgbG9jYWxlOiBMb2NhbGVDb25maWcgPSB7fTtcblxuICBAT3V0cHV0KCkgZGF0ZVJhbmdlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlUmFuZ2U+KCk7XG4gIEBPdXRwdXQoKSBkYXRlUmFuZ2VTZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXI8RGF0ZVJhbmdlPigpO1xuXG4gIC8vIERhdGUgYWRhcHRlciBpbmplY3Rpb25cbiAgcHJpdmF0ZSBkYXRlQWRhcHRlciA9IGluamVjdDxEYXRlQWRhcHRlcj4oREFURV9BREFQVEVSKTtcblxuICAvLyBTaWduYWxzIGZvciByZWFjdGl2ZSBzdGF0ZVxuICBtb3N0cmFyRGF0ZVBpY2tlciA9IHNpZ25hbChmYWxzZSk7XG4gIHJhbmdvRmVjaGFzID0gc2lnbmFsKCcnKTtcbiAgZmVjaGFTZWxlY2Npb25hbmRvSW5pY2lvID0gc2lnbmFsKHRydWUpO1xuICBtZXNBY3R1YWwgPSBzaWduYWwodGhpcy5kYXRlQWRhcHRlci50b2RheSgpKTtcbiAgbWVzQW50ZXJpb3IgPSBzaWduYWwodGhpcy5kYXRlQWRhcHRlci50b2RheSgpKTtcbiAgZGlhc01lc0FjdHVhbCA9IHNpZ25hbDxhbnlbXT4oW10pO1xuICBkaWFzTWVzQW50ZXJpb3IgPSBzaWduYWw8YW55W10+KFtdKTtcbiAgaXNEaXNhYmxlZCA9IHNpZ25hbChmYWxzZSk7XG5cbiAgLy8gQ29tcHV0ZWQgdmFsdWVzXG4gIG5vbWJyZU1lc0FjdHVhbCA9IGNvbXB1dGVkKCgpID0+IHRoaXMuZ2V0Tm9tYnJlTWVzKHRoaXMubWVzQWN0dWFsKCkpKTtcbiAgbm9tYnJlTWVzQW50ZXJpb3IgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmdldE5vbWJyZU1lcyh0aGlzLm1lc0FudGVyaW9yKCkpKTtcbiAgZGlhc1NlbWFuYSA9IGNvbXB1dGVkKCgpID0+IHRoaXMuZ2V0RGF5TmFtZXMoKSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkZWZhdWx0TW9udGhOYW1lcyA9IFsnSmFudWFyeScsICdGZWJydWFyeScsICdNYXJjaCcsICdBcHJpbCcsICdNYXknLCAnSnVuZScsICdKdWx5JywgJ0F1Z3VzdCcsICdTZXB0ZW1iZXInLCAnT2N0b2JlcicsICdOb3ZlbWJlcicsICdEZWNlbWJlciddO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHRNb250aE5hbWVzU2hvcnQgPSBbJ0phbicsICdGZWInLCAnTWFyJywgJ0FwcicsICdNYXknLCAnSnVuJywgJ0p1bCcsICdBdWcnLCAnU2VwJywgJ09jdCcsICdOb3YnLCAnRGVjJ107XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdERheU5hbWVzID0gWydTdW5kYXknLCAnTW9uZGF5JywgJ1R1ZXNkYXknLCAnV2VkbmVzZGF5JywgJ1RodXJzZGF5JywgJ0ZyaWRheScsICdTYXR1cmRheSddO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHREYXlOYW1lc1Nob3J0ID0gWydTJywgJ00nLCAnVCcsICdXJywgJ1QnLCAnRicsICdTJ107XG5cbiAgLy8gQ29udHJvbFZhbHVlQWNjZXNzb3IgY2FsbGJhY2tzXG4gIHByaXZhdGUgb25DaGFuZ2U6ICh2YWx1ZTogRGF0ZVJhbmdlIHwgbnVsbCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuICBwcml2YXRlIG9uVG91Y2hlZDogKCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZikge1xuICAgIC8vIEVmZmVjdCB0byBlbWl0IGNoYW5nZXMgd2hlbiBkYXRlcyBjaGFuZ2VcbiAgICBlZmZlY3QoKCkgPT4ge1xuICAgICAgY29uc3QgcmFuZ28gPSB0aGlzLnJhbmdvRmVjaGFzKCk7XG4gICAgICBpZiAodGhpcy5mZWNoYUluaWNpbyB8fCB0aGlzLmZlY2hhRmluKSB7XG4gICAgICAgIHRoaXMub25DaGFuZ2UodGhpcy5nZXREYXRlUmFuZ2VWYWx1ZSgpKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmNsaWNrJywgWyckZXZlbnQnXSlcbiAgb25DbGlja091dHNpZGUoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5tb3N0cmFyRGF0ZVBpY2tlcigpICYmIHRoaXMuY2xvc2VPbkNsaWNrT3V0c2lkZSkge1xuICAgICAgY29uc3QgY2xpY2tlZEluc2lkZSA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKGV2ZW50LnRhcmdldCk7XG4gICAgICBpZiAoIWNsaWNrZWRJbnNpZGUpIHtcbiAgICAgICAgdGhpcy5jZXJyYXJEYXRlUGlja2VyKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZmVjaGFJbmljaW8gJiYgdGhpcy5mZWNoYUZpbikge1xuICAgICAgdGhpcy5hY3R1YWxpemFyUmFuZ29GZWNoYXNUZXh0bygpO1xuICAgICAgdGhpcy5nZW5lcmFyQ2FsZW5kYXJpb3MoKTtcbiAgICB9XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXNbJ2ZlY2hhSW5pY2lvJ10gfHwgY2hhbmdlc1snZmVjaGFGaW4nXSkge1xuICAgICAgaWYgKHRoaXMuZmVjaGFJbmljaW8gJiYgdGhpcy5mZWNoYUZpbikge1xuICAgICAgICB0aGlzLmFjdHVhbGl6YXJSYW5nb0ZlY2hhc1RleHRvKCk7XG4gICAgICAgIHRoaXMuZ2VuZXJhckNhbGVuZGFyaW9zKCk7XG4gICAgICB9IGVsc2UgaWYgKCF0aGlzLmZlY2hhSW5pY2lvICYmICF0aGlzLmZlY2hhRmluKSB7XG4gICAgICAgIHRoaXMucmFuZ29GZWNoYXMuc2V0KCcnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmb3JtYXRlYXJGZWNoYShmZWNoYTogRGF0ZSk6IHN0cmluZyB7XG4gICAgY29uc3QgeWVhciA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0WWVhcihmZWNoYSk7XG4gICAgY29uc3QgbW9udGggPSBTdHJpbmcodGhpcy5kYXRlQWRhcHRlci5nZXRNb250aChmZWNoYSkgKyAxKS5wYWRTdGFydCgyLCAnMCcpO1xuICAgIGNvbnN0IGRheSA9IFN0cmluZyh0aGlzLmRhdGVBZGFwdGVyLmdldERhdGUoZmVjaGEpKS5wYWRTdGFydCgyLCAnMCcpO1xuICAgIHJldHVybiBgJHt5ZWFyfS0ke21vbnRofS0ke2RheX1gO1xuICB9XG5cbiAgZm9ybWF0ZWFyRmVjaGFEaXNwbGF5KGZlY2hhU3RyOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICghZmVjaGFTdHIpIHJldHVybiAnJztcbiAgICBjb25zdCBmZWNoYSA9IHRoaXMuZGF0ZUFkYXB0ZXIucGFyc2UoZmVjaGFTdHIpO1xuICAgIGlmICghZmVjaGEpIHJldHVybiAnJztcbiAgICBjb25zdCBtb250aE5hbWVzID0gdGhpcy5sb2NhbGUubW9udGhOYW1lc1Nob3J0IHx8IHRoaXMuZGVmYXVsdE1vbnRoTmFtZXNTaG9ydDtcbiAgICByZXR1cm4gYCR7dGhpcy5kYXRlQWRhcHRlci5nZXREYXRlKGZlY2hhKX0gJHttb250aE5hbWVzW3RoaXMuZGF0ZUFkYXB0ZXIuZ2V0TW9udGgoZmVjaGEpXX1gO1xuICB9XG5cbiAgYWN0dWFsaXphclJhbmdvRmVjaGFzVGV4dG8oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZmVjaGFJbmljaW8gJiYgdGhpcy5mZWNoYUZpbikge1xuICAgICAgY29uc3QgaW5pY2lvID0gdGhpcy5mb3JtYXRlYXJGZWNoYURpc3BsYXkodGhpcy5mZWNoYUluaWNpbyk7XG4gICAgICBjb25zdCBmaW4gPSB0aGlzLmZvcm1hdGVhckZlY2hhRGlzcGxheSh0aGlzLmZlY2hhRmluKTtcbiAgICAgIHRoaXMucmFuZ29GZWNoYXMuc2V0KGAke2luaWNpb30gLSAke2Zpbn1gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yYW5nb0ZlY2hhcy5zZXQoJycpO1xuICAgIH1cbiAgfVxuXG4gIHRvZ2dsZURhdGVQaWNrZXIoKTogdm9pZCB7XG4gICAgdGhpcy5tb3N0cmFyRGF0ZVBpY2tlci51cGRhdGUodmFsdWUgPT4gIXZhbHVlKTtcbiAgICBpZiAodGhpcy5tb3N0cmFyRGF0ZVBpY2tlcigpKSB7XG4gICAgICB0aGlzLmZlY2hhU2VsZWNjaW9uYW5kb0luaWNpby5zZXQodHJ1ZSk7XG4gICAgICBjb25zdCBtZXNBY3R1YWxWYWx1ZSA9IHRoaXMubWVzQWN0dWFsKCk7XG4gICAgICBjb25zdCBhw7FvID0gdGhpcy5kYXRlQWRhcHRlci5nZXRZZWFyKG1lc0FjdHVhbFZhbHVlKTtcbiAgICAgIGNvbnN0IG1lcyA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0TW9udGgobWVzQWN0dWFsVmFsdWUpO1xuICAgICAgY29uc3QgbWVzQW50ZXJpb3JEYXRlID0gdGhpcy5kYXRlQWRhcHRlci5jcmVhdGVEYXRlKGHDsW8sIG1lcyAtIDEsIDEpO1xuICAgICAgdGhpcy5tZXNBbnRlcmlvci5zZXQobWVzQW50ZXJpb3JEYXRlKTtcbiAgICAgIHRoaXMuZ2VuZXJhckNhbGVuZGFyaW9zKCk7XG4gICAgfVxuICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gIH1cblxuICBjZXJyYXJEYXRlUGlja2VyKCk6IHZvaWQge1xuICAgIHRoaXMubW9zdHJhckRhdGVQaWNrZXIuc2V0KGZhbHNlKTtcbiAgICB0aGlzLm9uVG91Y2hlZCgpO1xuICB9XG5cbiAgZ2VuZXJhckNhbGVuZGFyaW9zKCk6IHZvaWQge1xuICAgIHRoaXMuZGlhc01lc0FudGVyaW9yLnNldCh0aGlzLmdlbmVyYXJDYWxlbmRhcmlvTWVzKHRoaXMubWVzQW50ZXJpb3IoKSkpO1xuICAgIHRoaXMuZGlhc01lc0FjdHVhbC5zZXQodGhpcy5nZW5lcmFyQ2FsZW5kYXJpb01lcyh0aGlzLm1lc0FjdHVhbCgpKSk7XG4gIH1cblxuICBnZW5lcmFyQ2FsZW5kYXJpb01lcyhmZWNoYTogRGF0ZSk6IGFueVtdIHtcbiAgICBjb25zdCBhw7FvID0gdGhpcy5kYXRlQWRhcHRlci5nZXRZZWFyKGZlY2hhKTtcbiAgICBjb25zdCBtZXMgPSB0aGlzLmRhdGVBZGFwdGVyLmdldE1vbnRoKGZlY2hhKTtcbiAgICBjb25zdCBwcmltZXJEaWEgPSB0aGlzLmRhdGVBZGFwdGVyLmNyZWF0ZURhdGUoYcOxbywgbWVzLCAxKTtcbiAgICBjb25zdCB1bHRpbW9EaWEgPSB0aGlzLmRhdGVBZGFwdGVyLmNyZWF0ZURhdGUoYcOxbywgbWVzICsgMSwgMCk7XG4gICAgY29uc3QgZGlhc0VuTWVzID0gdGhpcy5kYXRlQWRhcHRlci5nZXREYXRlKHVsdGltb0RpYSk7XG4gICAgY29uc3QgcHJpbWVyRGlhU2VtYW5hID0gdGhpcy5kYXRlQWRhcHRlci5nZXREYXkocHJpbWVyRGlhKTtcblxuICAgIGNvbnN0IGRpYXNNZXMgPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcHJpbWVyRGlhU2VtYW5hOyBpKyspIHtcbiAgICAgIGRpYXNNZXMucHVzaCh7IGRpYTogbnVsbCwgZXNNZXNBY3R1YWw6IGZhbHNlIH0pO1xuICAgIH1cblxuICAgIGZvciAobGV0IGRpYSA9IDE7IGRpYSA8PSBkaWFzRW5NZXM7IGRpYSsrKSB7XG4gICAgICBjb25zdCBmZWNoYURpYSA9IHRoaXMuZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZShhw7FvLCBtZXMsIGRpYSk7XG4gICAgICBjb25zdCBmZWNoYVN0ciA9IHRoaXMuZm9ybWF0ZWFyRmVjaGEoZmVjaGFEaWEpO1xuICAgICAgZGlhc01lcy5wdXNoKHtcbiAgICAgICAgZGlhOiBkaWEsXG4gICAgICAgIGZlY2hhOiBmZWNoYVN0cixcbiAgICAgICAgZXNNZXNBY3R1YWw6IHRydWUsXG4gICAgICAgIGVzSW5pY2lvOiB0aGlzLmZlY2hhSW5pY2lvID09PSBmZWNoYVN0cixcbiAgICAgICAgZXNGaW46IHRoaXMuZmVjaGFGaW4gPT09IGZlY2hhU3RyLFxuICAgICAgICBlblJhbmdvOiB0aGlzLmVzdGFFblJhbmdvKGZlY2hhU3RyKVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRpYXNNZXM7XG4gIH1cblxuICBlc3RhRW5SYW5nbyhmZWNoYVN0cjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKCF0aGlzLmZlY2hhSW5pY2lvIHx8ICF0aGlzLmZlY2hhRmluKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIGZlY2hhU3RyID49IHRoaXMuZmVjaGFJbmljaW8gJiYgZmVjaGFTdHIgPD0gdGhpcy5mZWNoYUZpbjtcbiAgfVxuXG4gIHNlbGVjY2lvbmFyRGlhKGRpYU9iajogYW55KTogdm9pZCB7XG4gICAgaWYgKCFkaWFPYmouZXNNZXNBY3R1YWwgfHwgdGhpcy5pc0Rpc2FibGVkKCkpIHJldHVybjtcblxuICAgIGlmICh0aGlzLmZlY2hhU2VsZWNjaW9uYW5kb0luaWNpbygpKSB7XG4gICAgICB0aGlzLmZlY2hhSW5pY2lvID0gZGlhT2JqLmZlY2hhO1xuICAgICAgdGhpcy5mZWNoYUZpbiA9ICcnO1xuICAgICAgdGhpcy5yYW5nb0ZlY2hhcy5zZXQoJycpO1xuICAgICAgdGhpcy5mZWNoYVNlbGVjY2lvbmFuZG9JbmljaW8uc2V0KGZhbHNlKTtcbiAgICAgIHRoaXMuZW1pdGlyQ2FtYmlvKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChkaWFPYmouZmVjaGEgPCB0aGlzLmZlY2hhSW5pY2lvKSB7XG4gICAgICAgIHRoaXMuZmVjaGFGaW4gPSB0aGlzLmZlY2hhSW5pY2lvO1xuICAgICAgICB0aGlzLmZlY2hhSW5pY2lvID0gZGlhT2JqLmZlY2hhO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5mZWNoYUZpbiA9IGRpYU9iai5mZWNoYTtcbiAgICAgIH1cbiAgICAgIHRoaXMuYWN0dWFsaXphclJhbmdvRmVjaGFzVGV4dG8oKTtcbiAgICAgIGlmICh0aGlzLmNsb3NlT25TZWxlY3Rpb24pIHtcbiAgICAgICAgdGhpcy5tb3N0cmFyRGF0ZVBpY2tlci5zZXQoZmFsc2UpO1xuICAgICAgfVxuICAgICAgdGhpcy5mZWNoYVNlbGVjY2lvbmFuZG9JbmljaW8uc2V0KHRydWUpO1xuICAgICAgdGhpcy5lbWl0aXJDYW1iaW8oKTtcbiAgICAgIHRoaXMuZW1pdGlyU2VsZWNjaW9uKCk7XG4gICAgfVxuICAgIHRoaXMuZ2VuZXJhckNhbGVuZGFyaW9zKCk7XG4gIH1cblxuICBjYW1iaWFyTWVzKGRpcmVjY2lvbjogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgbWVzQWN0dWFsVmFsdWUgPSB0aGlzLm1lc0FjdHVhbCgpO1xuICAgIGNvbnN0IGHDsW8gPSB0aGlzLmRhdGVBZGFwdGVyLmdldFllYXIobWVzQWN0dWFsVmFsdWUpO1xuICAgIGNvbnN0IG1lcyA9IHRoaXMuZGF0ZUFkYXB0ZXIuZ2V0TW9udGgobWVzQWN0dWFsVmFsdWUpO1xuICAgIGNvbnN0IG51ZXZvTWVzQWN0dWFsID0gdGhpcy5kYXRlQWRhcHRlci5jcmVhdGVEYXRlKGHDsW8sIG1lcyArIGRpcmVjY2lvbiwgMSk7XG4gICAgdGhpcy5tZXNBY3R1YWwuc2V0KG51ZXZvTWVzQWN0dWFsKTtcbiAgICBcbiAgICBjb25zdCBhw7FvTnVldm8gPSB0aGlzLmRhdGVBZGFwdGVyLmdldFllYXIobnVldm9NZXNBY3R1YWwpO1xuICAgIGNvbnN0IG1lc051ZXZvID0gdGhpcy5kYXRlQWRhcHRlci5nZXRNb250aChudWV2b01lc0FjdHVhbCk7XG4gICAgY29uc3QgbWVzQW50ZXJpb3JOdWV2byA9IHRoaXMuZGF0ZUFkYXB0ZXIuY3JlYXRlRGF0ZShhw7FvTnVldm8sIG1lc051ZXZvIC0gMSwgMSk7XG4gICAgdGhpcy5tZXNBbnRlcmlvci5zZXQobWVzQW50ZXJpb3JOdWV2byk7XG4gICAgdGhpcy5nZW5lcmFyQ2FsZW5kYXJpb3MoKTtcbiAgfVxuXG4gIGdldE5vbWJyZU1lcyhmZWNoYTogRGF0ZSk6IHN0cmluZyB7XG4gICAgY29uc3QgbW9udGhOYW1lcyA9IHRoaXMubG9jYWxlLm1vbnRoTmFtZXMgfHwgdGhpcy5kZWZhdWx0TW9udGhOYW1lcztcbiAgICByZXR1cm4gYCR7bW9udGhOYW1lc1t0aGlzLmRhdGVBZGFwdGVyLmdldE1vbnRoKGZlY2hhKV19ICR7dGhpcy5kYXRlQWRhcHRlci5nZXRZZWFyKGZlY2hhKX1gO1xuICB9XG5cbiAgZ2V0RGF5TmFtZXMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLmxvY2FsZS5kYXlOYW1lc1Nob3J0IHx8IHRoaXMuZGVmYXVsdERheU5hbWVzU2hvcnQ7XG4gIH1cblxuICBzZWxlY2Npb25hclJhbmdvUHJlZGVmaW5pZG8ocHJlc2V0OiBQcmVzZXRDb25maWcpOiB2b2lkIHtcbiAgICBsZXQgc3RhcnQ6IHN0cmluZztcbiAgICBsZXQgZW5kOiBzdHJpbmc7XG5cbiAgICAvLyBOZXcgZmxleGlibGUgcGF0dGVybiB3aXRoIGdldFZhbHVlKClcbiAgICBpZiAocHJlc2V0LmdldFZhbHVlKSB7XG4gICAgICBjb25zdCByYW5nZSA9IHByZXNldC5nZXRWYWx1ZSgpO1xuICAgICAgc3RhcnQgPSByYW5nZS5zdGFydDtcbiAgICAgIGVuZCA9IHJhbmdlLmVuZDtcbiAgICB9XG4gICAgLy8gQmFja3dhcmQgY29tcGF0aWJpbGl0eSB3aXRoIGRheXNBZ28gcGF0dGVyblxuICAgIGVsc2UgaWYgKHByZXNldC5kYXlzQWdvICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IGhveSA9IHRoaXMuZGF0ZUFkYXB0ZXIudG9kYXkoKTtcbiAgICAgIGNvbnN0IGZlY2hhSW5pY2lvID0gdGhpcy5kYXRlQWRhcHRlci5hZGREYXlzKGhveSwgLXByZXNldC5kYXlzQWdvKTtcbiAgICAgIHN0YXJ0ID0gdGhpcy5mb3JtYXRlYXJGZWNoYShmZWNoYUluaWNpbyk7XG4gICAgICBlbmQgPSB0aGlzLmZvcm1hdGVhckZlY2hhKGhveSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgY29uc29sZS5lcnJvcignUHJlc2V0Q29uZmlnIG11c3QgaGF2ZSBlaXRoZXIgZ2V0VmFsdWUoKSBvciBkYXlzQWdvJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5mZWNoYUluaWNpbyA9IHN0YXJ0O1xuICAgIHRoaXMuZmVjaGFGaW4gPSBlbmQ7XG4gICAgdGhpcy5hY3R1YWxpemFyUmFuZ29GZWNoYXNUZXh0bygpO1xuICAgIHRoaXMuZ2VuZXJhckNhbGVuZGFyaW9zKCk7XG4gICAgaWYgKHRoaXMuY2xvc2VPblByZXNldFNlbGVjdGlvbikge1xuICAgICAgdGhpcy5tb3N0cmFyRGF0ZVBpY2tlci5zZXQoZmFsc2UpO1xuICAgIH1cbiAgICB0aGlzLmVtaXRpclNlbGVjY2lvbigpO1xuICB9XG5cbiAgbGltcGlhcigpOiB2b2lkIHtcbiAgICB0aGlzLmZlY2hhSW5pY2lvID0gJyc7XG4gICAgdGhpcy5mZWNoYUZpbiA9ICcnO1xuICAgIHRoaXMucmFuZ29GZWNoYXMuc2V0KCcnKTtcbiAgICB0aGlzLm1vc3RyYXJEYXRlUGlja2VyLnNldChmYWxzZSk7XG4gICAgdGhpcy5mZWNoYVNlbGVjY2lvbmFuZG9JbmljaW8uc2V0KHRydWUpO1xuICAgIHRoaXMuZW1pdGlyQ2FtYmlvKCk7XG4gICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgfVxuXG4gIHByaXZhdGUgZW1pdGlyQ2FtYmlvKCk6IHZvaWQge1xuICAgIHRoaXMuZGF0ZVJhbmdlQ2hhbmdlLmVtaXQoe1xuICAgICAgZmVjaGFJbmljaW86IHRoaXMuZmVjaGFJbmljaW8sXG4gICAgICBmZWNoYUZpbjogdGhpcy5mZWNoYUZpbixcbiAgICAgIHJhbmdvVGV4dG86IHRoaXMucmFuZ29GZWNoYXMoKVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBlbWl0aXJTZWxlY2Npb24oKTogdm9pZCB7XG4gICAgdGhpcy5kYXRlUmFuZ2VTZWxlY3RlZC5lbWl0KHtcbiAgICAgIGZlY2hhSW5pY2lvOiB0aGlzLmZlY2hhSW5pY2lvLFxuICAgICAgZmVjaGFGaW46IHRoaXMuZmVjaGFGaW4sXG4gICAgICByYW5nb1RleHRvOiB0aGlzLnJhbmdvRmVjaGFzKClcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RGF0ZVJhbmdlVmFsdWUoKTogRGF0ZVJhbmdlIHtcbiAgICByZXR1cm4ge1xuICAgICAgZmVjaGFJbmljaW86IHRoaXMuZmVjaGFJbmljaW8sXG4gICAgICBmZWNoYUZpbjogdGhpcy5mZWNoYUZpbixcbiAgICAgIHJhbmdvVGV4dG86IHRoaXMucmFuZ29GZWNoYXMoKVxuICAgIH07XG4gIH1cblxuICAvLyBDb250cm9sVmFsdWVBY2Nlc3NvciBpbXBsZW1lbnRhdGlvblxuICB3cml0ZVZhbHVlKHZhbHVlOiBEYXRlUmFuZ2UgfCBudWxsKTogdm9pZCB7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICB0aGlzLmZlY2hhSW5pY2lvID0gdmFsdWUuZmVjaGFJbmljaW8gfHwgJyc7XG4gICAgICB0aGlzLmZlY2hhRmluID0gdmFsdWUuZmVjaGFGaW4gfHwgJyc7XG4gICAgICBpZiAodGhpcy5mZWNoYUluaWNpbyAmJiB0aGlzLmZlY2hhRmluKSB7XG4gICAgICAgIHRoaXMuYWN0dWFsaXphclJhbmdvRmVjaGFzVGV4dG8oKTtcbiAgICAgICAgdGhpcy5nZW5lcmFyQ2FsZW5kYXJpb3MoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5mZWNoYUluaWNpbyA9ICcnO1xuICAgICAgdGhpcy5mZWNoYUZpbiA9ICcnO1xuICAgICAgdGhpcy5yYW5nb0ZlY2hhcy5zZXQoJycpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46ICh2YWx1ZTogRGF0ZVJhbmdlIHwgbnVsbCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcbiAgfVxuXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcbiAgfVxuXG4gIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaXNEaXNhYmxlZC5zZXQoaXNEaXNhYmxlZCk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJkYXRlcGlja2VyLXdyYXBwZXJcIiBcbiAgW3N0eWxlLi0taW5wdXQtYm9yZGVyLWhvdmVyXT1cImlucHV0Qm9yZGVyQ29sb3JIb3ZlclwiXG4gIFtzdHlsZS4tLWlucHV0LWJvcmRlci1mb2N1c109XCJpbnB1dEJvcmRlckNvbG9yRm9jdXNcIj5cbiAgPGlucHV0IFxuICAgIHR5cGU9XCJ0ZXh0XCIgXG4gICAgY2xhc3M9XCJkYXRlcGlja2VyLWlucHV0XCIgXG4gICAgW3ZhbHVlXT1cInJhbmdvRmVjaGFzKClcIiBcbiAgICAoY2xpY2spPVwidG9nZ2xlRGF0ZVBpY2tlcigpXCIgXG4gICAgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyXCJcbiAgICBbZGlzYWJsZWRdPVwiaXNEaXNhYmxlZCgpXCJcbiAgICBbbmdTdHlsZV09XCJ7XG4gICAgICAnYmFja2dyb3VuZC1jb2xvcic6IGlucHV0QmFja2dyb3VuZENvbG9yLFxuICAgICAgJ2NvbG9yJzogaW5wdXRUZXh0Q29sb3IsXG4gICAgICAnYm9yZGVyLWNvbG9yJzogaW5wdXRCb3JkZXJDb2xvcixcbiAgICAgICdwYWRkaW5nJzogaW5wdXRQYWRkaW5nXG4gICAgfVwiXG4gICAgcmVhZG9ubHk+XG5cbiAgQGlmIChtb3N0cmFyRGF0ZVBpY2tlcigpKSB7XG4gIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1kcm9wZG93blwiPlxuICAgIEBpZiAoc2hvd1ByZXNldHMpIHtcbiAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItcHJlc2V0c1wiPlxuICAgICAgQGZvciAocHJlc2V0IG9mIHByZXNldHM7IHRyYWNrIHByZXNldC5sYWJlbCkge1xuICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cInNlbGVjY2lvbmFyUmFuZ29QcmVkZWZpbmlkbyhwcmVzZXQpXCI+e3sgcHJlc2V0LmxhYmVsIH19PC9idXR0b24+XG4gICAgICB9XG4gICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0bi1jbG9zZS1jYWxlbmRhclwiIChjbGljayk9XCJjZXJyYXJEYXRlUGlja2VyKClcIiB0aXRsZT1cIkNsb3NlXCI+XG4gICAgICAgIMOXXG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgICB9XG5cbiAgICBAaWYgKCFzaG93UHJlc2V0cykge1xuICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1oZWFkZXItb25seS1jbG9zZVwiPlxuICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4tY2xvc2UtY2FsZW5kYXJcIiAoY2xpY2spPVwiY2VycmFyRGF0ZVBpY2tlcigpXCIgdGl0bGU9XCJDbG9zZVwiPlxuICAgICAgICDDl1xuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gICAgfVxuXG4gICAgPCEtLSBDYWxlbmRhcnMgLS0+XG4gICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLWNhbGVuZGFyc1wiPlxuICAgICAgPCEtLSBQcmV2aW91cyBtb250aCBjYWxlbmRhciAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1jYWxlbmRhclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItaGVhZGVyXCI+XG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cImNhbWJpYXJNZXMoLTEpXCI+XG4gICAgICAgICAgICA8c3ZnIHdpZHRoPVwiMTZcIiBoZWlnaHQ9XCIxNlwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIiB2aWV3Qm94PVwiMCAwIDE2IDE2XCI+XG4gICAgICAgICAgICAgIDxwYXRoIGZpbGwtcnVsZT1cImV2ZW5vZGRcIiBkPVwiTTExLjM1NCAxLjY0NmEuNS41IDAgMCAxIDAgLjcwOEw1LjcwNyA4bDUuNjQ3IDUuNjQ2YS41LjUgMCAwIDEtLjcwOC43MDhsLTYtNmEuNS41IDAgMCAxIDAtLjcwOGw2LTZhLjUuNSAwIDAgMSAuNzA4IDB6XCIvPlxuICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPHNwYW4+e3sgbm9tYnJlTWVzQW50ZXJpb3IoKSB9fTwvc3Bhbj5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBzdHlsZT1cInZpc2liaWxpdHk6IGhpZGRlbjtcIj5cbiAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgZmlsbD1cImN1cnJlbnRDb2xvclwiIHZpZXdCb3g9XCIwIDAgMTYgMTZcIj5cbiAgICAgICAgICAgICAgPHBhdGggZmlsbC1ydWxlPVwiZXZlbm9kZFwiIGQ9XCJNNC42NDYgMS42NDZhLjUuNSAwIDAgMSAuNzA4IDBsNiA2YS41LjUgMCAwIDEgMCAuNzA4bC02IDZhLjUuNSAwIDAgMS0uNzA4LS43MDhMMTAuMjkzIDggNC42NDYgMi4zNTRhLjUuNSAwIDAgMSAwLS43MDh6XCIvPlxuICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGF0ZS1waWNrZXItd2Vla2RheXNcIj5cbiAgICAgICAgICBAZm9yIChkYXlOYW1lIG9mIGRpYXNTZW1hbmEoKTsgdHJhY2sgJGluZGV4KSB7XG4gICAgICAgICAgICA8c3Bhbj57eyBkYXlOYW1lIH19PC9zcGFuPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1kYXlzXCI+XG4gICAgICAgICAgQGZvciAoZGlhT2JqIG9mIGRpYXNNZXNBbnRlcmlvcigpOyB0cmFjayBkaWFPYmouZmVjaGEgfHwgJGluZGV4KSB7XG4gICAgICAgICAgICA8YnV0dG9uIFxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJkYXRlLXBpY2tlci1kYXlcIiBcbiAgICAgICAgICAgICAgW2NsYXNzLmVtcHR5XT1cIiFkaWFPYmouZXNNZXNBY3R1YWxcIlxuICAgICAgICAgICAgICBbY2xhc3Muc2VsZWN0ZWRdPVwiZGlhT2JqLmVzSW5pY2lvIHx8IGRpYU9iai5lc0ZpblwiXG4gICAgICAgICAgICAgIFtjbGFzcy5pbi1yYW5nZV09XCJkaWFPYmouZW5SYW5nbyAmJiAhZGlhT2JqLmVzSW5pY2lvICYmICFkaWFPYmouZXNGaW5cIlxuICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWNjaW9uYXJEaWEoZGlhT2JqKVwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhZGlhT2JqLmVzTWVzQWN0dWFsXCI+XG4gICAgICAgICAgICAgIHt7IGRpYU9iai5kaWEgfX1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPCEtLSBDdXJyZW50IG1vbnRoIGNhbGVuZGFyIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLWNhbGVuZGFyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci1oZWFkZXJcIj5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBzdHlsZT1cInZpc2liaWxpdHk6IGhpZGRlbjtcIj5cbiAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgZmlsbD1cImN1cnJlbnRDb2xvclwiIHZpZXdCb3g9XCIwIDAgMTYgMTZcIj5cbiAgICAgICAgICAgICAgPHBhdGggZmlsbC1ydWxlPVwiZXZlbm9kZFwiIGQ9XCJNMTEuMzU0IDEuNjQ2YS41LjUgMCAwIDEgMCAuNzA4TDUuNzA3IDhsNS42NDcgNS42NDZhLjUuNSAwIDAgMS0uNzA4LjcwOGwtNi02YS41LjUgMCAwIDEgMC0uNzA4bDYtNmEuNS41IDAgMCAxIC43MDggMHpcIi8+XG4gICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8c3Bhbj57eyBub21icmVNZXNBY3R1YWwoKSB9fTwvc3Bhbj5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwiY2FtYmlhck1lcygxKVwiPlxuICAgICAgICAgICAgPHN2ZyB3aWR0aD1cIjE2XCIgaGVpZ2h0PVwiMTZcIiBmaWxsPVwiY3VycmVudENvbG9yXCIgdmlld0JveD1cIjAgMCAxNiAxNlwiPlxuICAgICAgICAgICAgICA8cGF0aCBmaWxsLXJ1bGU9XCJldmVub2RkXCIgZD1cIk00LjY0NiAxLjY0NmEuNS41IDAgMCAxIC43MDggMGw2IDZhLjUuNSAwIDAgMSAwIC43MDhsLTYgNmEuNS41IDAgMCAxLS43MDgtLjcwOEwxMC4yOTMgOCA0LjY0NiAyLjM1NGEuNS41IDAgMCAxIDAtLjcwOHpcIi8+XG4gICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLXBpY2tlci13ZWVrZGF5c1wiPlxuICAgICAgICAgIEBmb3IgKGRheU5hbWUgb2YgZGlhc1NlbWFuYSgpOyB0cmFjayAkaW5kZXgpIHtcbiAgICAgICAgICAgIDxzcGFuPnt7IGRheU5hbWUgfX08L3NwYW4+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLWRheXNcIj5cbiAgICAgICAgICBAZm9yIChkaWFPYmogb2YgZGlhc01lc0FjdHVhbCgpOyB0cmFjayBkaWFPYmouZmVjaGEgfHwgJGluZGV4KSB7XG4gICAgICAgICAgICA8YnV0dG9uIFxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJkYXRlLXBpY2tlci1kYXlcIiBcbiAgICAgICAgICAgICAgW2NsYXNzLmVtcHR5XT1cIiFkaWFPYmouZXNNZXNBY3R1YWxcIlxuICAgICAgICAgICAgICBbY2xhc3Muc2VsZWN0ZWRdPVwiZGlhT2JqLmVzSW5pY2lvIHx8IGRpYU9iai5lc0ZpblwiXG4gICAgICAgICAgICAgIFtjbGFzcy5pbi1yYW5nZV09XCJkaWFPYmouZW5SYW5nbyAmJiAhZGlhT2JqLmVzSW5pY2lvICYmICFkaWFPYmouZXNGaW5cIlxuICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWNjaW9uYXJEaWEoZGlhT2JqKVwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhZGlhT2JqLmVzTWVzQWN0dWFsXCI+XG4gICAgICAgICAgICAgIHt7IGRpYU9iai5kaWEgfX1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0gRm9vdGVyIHdpdGggY2xlYXIgYnV0dG9uIC0tPlxuICAgIEBpZiAoc2hvd0NsZWFyQnV0dG9uKSB7XG4gICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLWZvb3RlclwiPlxuICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4tY2xlYXJcIiAoY2xpY2spPVwibGltcGlhcigpXCIgdGl0bGU9XCJDbGVhciBzZWxlY3Rpb25cIj5cbiAgICAgICAgQ2xlYXJcbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICAgIH1cbiAgPC9kaXY+XG4gIH1cbjwvZGl2PlxuIl19