valtech-components 2.0.382 → 2.0.384

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,385 +1,281 @@
1
1
  import { CommonModule } from '@angular/common';
2
- import { ChangeDetectorRef, Component, inject, Input, ViewChild, } from '@angular/core';
2
+ import { Component, inject, Input, ViewChild, signal, computed } from '@angular/core';
3
3
  import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4
4
  import { IonicModule } from '@ionic/angular';
5
- import { IconService } from '../../../services/icons.service';
6
5
  import { LangService } from '../../../services/lang-provider/lang-provider.service';
7
6
  import { applyDefaultValueToControl } from '../../../shared/utils/form-defaults';
8
7
  import { replaceSpecialChars } from '../../../shared/utils/text';
9
- import { SearchbarComponent } from '../searchbar/searchbar.component';
10
8
  import * as i0 from "@angular/core";
11
9
  import * as i1 from "@angular/common";
12
10
  import * as i2 from "@ionic/angular";
13
11
  import * as i3 from "@angular/forms";
14
- /**
15
- * val-select-search
16
- *
17
- * A searchable select/dropdown input with modal and filtering, integrated with Angular forms.
18
- *
19
- * @example
20
- * <val-select-search [props]="{ control: myControl, label: 'Choose', options: [{ id: '1', name: 'Option 1' }] }"></val-select-search>
21
- *
22
- * @input props: InputMetadata - Configuration for the select input (form control, label, options, etc.)
23
- */
24
12
  export class SelectSearchComponent {
25
13
  constructor() {
26
14
  this.labelProperty = 'name';
27
15
  this.valueProperty = 'id';
28
- this.multiple = false;
16
+ this.placeholder = '';
29
17
  this.langService = inject(LangService);
30
- this.icon = inject(IconService);
31
- this.changeDetector = inject(ChangeDetectorRef);
32
- this.searchTerm = '';
33
- this.filteredItems = [];
34
- this.selectedItems = [];
35
- this.displayValue = '';
36
- this.previousOptions = [];
37
- this.isProcessingChanges = false;
38
- this.label = this.langService.getText('_global', 'select', 'Seleccionar');
18
+ // Signals for reactive state management
19
+ this.isOpen = signal(false);
20
+ this.searchTerm = signal('');
21
+ this.selectedValue = signal(null);
22
+ // Computed signals
23
+ this.displayValue = computed(() => {
24
+ const value = this.selectedValue();
25
+ if (!value)
26
+ return '';
27
+ const option = this.getOptionByValue(value);
28
+ return option ? option[this.labelProperty] : '';
29
+ });
30
+ this.filteredOptions = computed(() => {
31
+ const options = this.props?.options || [];
32
+ const search = this.searchTerm().toLowerCase();
33
+ if (!search) {
34
+ return options;
35
+ }
36
+ return options.filter(option => {
37
+ const label = option[this.labelProperty]
38
+ ? replaceSpecialChars(String(option[this.labelProperty]).toLowerCase())
39
+ : '';
40
+ const value = option[this.valueProperty]
41
+ ? replaceSpecialChars(String(option[this.valueProperty]).toLowerCase())
42
+ : '';
43
+ const searchTerm = replaceSpecialChars(search);
44
+ return label.includes(searchTerm) || value.includes(searchTerm);
45
+ });
46
+ });
39
47
  this.placeholder = this.langService.getText('_global', 'selectOption', 'Seleccione una opción');
48
+ // Close dropdown when clicking outside
49
+ document.addEventListener('click', this.handleClickOutside.bind(this));
40
50
  }
41
51
  ngOnInit() {
42
52
  this.applyDefaultValue();
43
- this.initializeItems();
44
- this.syncControlValueWithSelectedItems();
45
- this.updateDisplayValue();
46
- this.subscribeToValueChanges();
53
+ this.syncSelectedValue();
47
54
  }
48
55
  ngOnDestroy() {
49
- // Limpiar suscripciones para evitar memory leaks
50
- if (this.valueChangesSubscription) {
51
- this.valueChangesSubscription.unsubscribe();
52
- }
56
+ document.removeEventListener('click', this.handleClickOutside.bind(this));
53
57
  }
54
- ngOnChanges(changes) {
55
- // Evitar bucles infinitos
56
- if (this.isProcessingChanges) {
57
- return;
58
- }
59
- // Cuando cambia props o props.options
60
- if (changes['props']) {
61
- try {
62
- this.isProcessingChanges = true;
63
- // Desuscribirse del antiguo control si existe
64
- if (this.valueChangesSubscription) {
65
- this.valueChangesSubscription.unsubscribe();
66
- }
67
- if (this.props?.options) {
68
- // Verificar si las opciones han cambiado realmente
69
- const optionsChanged = !this.areOptionsEqual(this.previousOptions, this.props.options);
70
- if (optionsChanged) {
71
- this.previousOptions = [...this.props.options];
72
- this.initializeItems();
73
- }
58
+ // Component methods
59
+ toggleDropdown(event) {
60
+ event.stopPropagation();
61
+ this.isOpen.update(value => !value);
62
+ if (this.isOpen()) {
63
+ // Focus search bar when opening if available
64
+ setTimeout(() => {
65
+ const searchbar = this.dropdownRef?.nativeElement?.querySelector('ion-searchbar');
66
+ if (searchbar) {
67
+ searchbar.setFocus();
74
68
  }
75
- // Sincronizar con el nuevo control si existe
76
- this.syncControlValueWithSelectedItems();
77
- this.updateDisplayValue();
78
- // Suscribirse al nuevo control
79
- this.subscribeToValueChanges();
80
- }
81
- finally {
82
- this.isProcessingChanges = false;
83
- }
84
- }
85
- }
86
- ionViewWillEnter() {
87
- if (this.isProcessingChanges) {
88
- return;
89
- }
90
- try {
91
- this.isProcessingChanges = true;
92
- this.initializeItems();
93
- this.syncControlValueWithSelectedItems();
94
- this.updateDisplayValue();
95
- this.subscribeToValueChanges();
96
- }
97
- finally {
98
- this.isProcessingChanges = false;
99
- }
100
- }
101
- // Suscribirse a cambios en el FormControl
102
- subscribeToValueChanges() {
103
- if (!this.props?.control)
104
- return;
105
- this.valueChangesSubscription = this.props.control.valueChanges.subscribe(value => {
106
- if (this.isProcessingChanges)
107
- return;
108
- try {
109
- this.isProcessingChanges = true;
110
- this.syncControlValueWithSelectedItems();
111
- this.updateDisplayValue();
112
- }
113
- finally {
114
- this.isProcessingChanges = false;
115
- }
116
- });
117
- }
118
- // Compara si dos arrays de opciones son iguales
119
- areOptionsEqual(prevOptions, newOptions) {
120
- // PERF: Use reference equality first for fast path
121
- if (prevOptions === newOptions)
122
- return true;
123
- if (!prevOptions || !newOptions)
124
- return prevOptions === newOptions;
125
- if (prevOptions.length !== newOptions.length)
126
- return false;
127
- // Only compare valueProperty for equality
128
- for (let i = 0; i < prevOptions.length; i++) {
129
- if (prevOptions[i][this.valueProperty] !== newOptions[i][this.valueProperty]) {
130
- return false;
131
- }
132
- }
133
- return true;
134
- }
135
- initializeItems() {
136
- // PERF: Avoid unnecessary array copies
137
- this.filteredItems = this.props?.options || [];
138
- }
139
- syncControlValueWithSelectedItems() {
140
- if (!this.props?.control) {
141
- this.selectedItems = [];
142
- return;
143
- }
144
- const controlValue = this.props.control.value;
145
- if (controlValue === null || controlValue === undefined) {
146
- this.selectedItems = [];
147
- return;
148
- }
149
- // PERF: Use a Map for faster lookup if options are large
150
- if (this.props.options && this.props.options.length > 0) {
151
- const map = new Map(this.props.options.map(opt => [opt[this.valueProperty], opt]));
152
- const selectedOption = map.get(controlValue);
153
- this.selectedItems = selectedOption ? [selectedOption] : [];
154
- }
155
- else {
156
- this.selectedItems = [];
157
- }
158
- }
159
- applyDefaultValue() {
160
- applyDefaultValueToControl(this.props);
161
- }
162
- onFilter(event) {
163
- // If no search term, show all options
164
- if (!event || event.trim() === '') {
165
- this.filteredItems = this.props?.options ? [...this.props.options] : [];
166
- this.changeDetector.detectChanges();
167
- return;
69
+ }, 100);
168
70
  }
169
- // If no options, nothing to filter
170
- if (!this.props?.options || this.props.options.length === 0) {
171
- this.filteredItems = [];
172
- this.changeDetector.detectChanges();
173
- return;
174
- }
175
- // PERF: Avoid repeated replaceSpecialChars and toLowerCase for each option
176
- const search = replaceSpecialChars(event.toLowerCase());
177
- this.filteredItems = this.props.options.filter(element => {
178
- // Only use labelProperty and valueProperty for filtering (faster)
179
- const label = element[this.labelProperty]
180
- ? replaceSpecialChars(String(element[this.labelProperty]).toLowerCase())
181
- : '';
182
- const value = element[this.valueProperty]
183
- ? replaceSpecialChars(String(element[this.valueProperty]).toLowerCase())
184
- : '';
185
- return label.includes(search) || value.includes(search);
186
- });
187
- this.changeDetector.detectChanges();
188
71
  }
189
- onFocus() {
190
- console.log('onFocus');
72
+ onSearch(event) {
73
+ this.searchTerm.set(event.detail.value || '');
191
74
  }
192
- onBlur() {
193
- console.log('onBlur');
194
- }
195
- openModal() {
196
- if (this.modal) {
197
- this.modal.present();
75
+ selectOption(option) {
76
+ const value = option[this.valueProperty];
77
+ this.selectedValue.set(value);
78
+ this.isOpen.set(false);
79
+ this.searchTerm.set('');
80
+ // Update form control
81
+ if (this.props?.control) {
82
+ this.props.control.setValue(value);
83
+ this.props.control.markAsDirty();
84
+ this.props.control.markAsTouched();
198
85
  }
199
86
  }
200
- preventDefaultBehavior(event) {
201
- event.preventDefault();
202
- event.stopPropagation();
203
- this.openModal();
87
+ isSelected(option) {
88
+ return this.selectedValue() === option[this.valueProperty];
204
89
  }
205
- cancelModal() {
206
- // Reset filter and show all options when closing modal
207
- this.searchTerm = '';
208
- this.filteredItems = this.props?.options ? [...this.props.options] : [];
209
- this.changeDetector.detectChanges();
210
- if (this.modal) {
211
- this.modal.dismiss();
212
- }
90
+ trackByFn(_index, option) {
91
+ return option[this.valueProperty];
213
92
  }
214
- selectItem(item) {
215
- if (this.multiple) {
216
- const index = this.selectedItems.findIndex(selectedItem => selectedItem[this.valueProperty] === item[this.valueProperty]);
217
- if (index === -1) {
218
- this.selectedItems.push(item);
219
- }
220
- else {
221
- this.selectedItems.splice(index, 1);
222
- }
223
- }
224
- else {
225
- this.selectedItems = [item];
226
- this.cancelModal();
93
+ handleClickOutside(event) {
94
+ if (this.isOpen() &&
95
+ !this.mainInputRef?.nativeElement?.contains(event.target) &&
96
+ !this.dropdownRef?.nativeElement?.contains(event.target)) {
97
+ this.isOpen.set(false);
98
+ this.searchTerm.set('');
227
99
  }
228
- this.updateDisplayValue();
229
- this.applyChanges();
230
100
  }
231
- isItemSelected(item) {
232
- return this.selectedItems.some(selectedItem => selectedItem[this.valueProperty] === item[this.valueProperty]);
233
- }
234
- updateDisplayValue() {
235
- if (this.selectedItems.length === 0) {
236
- this.displayValue = '';
237
- return;
238
- }
239
- if (this.multiple) {
240
- if (this.selectedItems.length === 1) {
241
- this.displayValue = this.selectedItems[0][this.labelProperty];
242
- }
243
- else {
244
- this.displayValue = `${this.selectedItems.length} elementos seleccionados`;
245
- }
246
- }
247
- else {
248
- this.displayValue = this.selectedItems[0][this.labelProperty];
249
- }
101
+ getOptionByValue(value) {
102
+ return this.props?.options?.find(option => option[this.valueProperty] === value);
250
103
  }
251
- applyChanges() {
252
- if (!this.props?.control) {
253
- return;
254
- }
255
- try {
256
- this.isProcessingChanges = true;
257
- if (this.selectedItems.length > 0) {
258
- this.props.control.setValue(this.selectedItems[0][this.valueProperty]);
259
- }
260
- else {
261
- this.props.control.setValue(null);
262
- }
263
- this.props.control.markAsDirty();
264
- this.props.control.updateValueAndValidity();
265
- }
266
- finally {
267
- this.isProcessingChanges = false;
104
+ applyDefaultValue() {
105
+ if (this.props) {
106
+ applyDefaultValueToControl(this.props);
268
107
  }
269
108
  }
270
- // Método público para reiniciar el componente
271
- reset() {
272
- this.selectedItems = [];
273
- this.displayValue = '';
274
- if (this.props?.control) {
275
- this.props.control.setValue(null);
109
+ syncSelectedValue() {
110
+ if (this.props?.control?.value) {
111
+ this.selectedValue.set(this.props.control.value);
276
112
  }
277
- this.changeDetector.detectChanges();
278
113
  }
279
114
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
280
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SelectSearchComponent, isStandalone: true, selector: "val-select-search", inputs: { label: "label", labelProperty: "labelProperty", valueProperty: "valueProperty", multiple: "multiple", placeholder: "placeholder", props: "props" }, viewQueries: [{ propertyName: "modal", first: true, predicate: ["modal"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
281
- <ion-input
282
- type="text"
283
- [value]="displayValue"
284
- [placeholder]="props?.placeholder || placeholder"
285
- readonly
286
- (mousedown)="preventDefaultBehavior($event)"
287
- />
115
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SelectSearchComponent, isStandalone: true, selector: "val-select-search", inputs: { props: "props", labelProperty: "labelProperty", valueProperty: "valueProperty", placeholder: "placeholder" }, viewQueries: [{ propertyName: "dropdownRef", first: true, predicate: ["dropdown"], descendants: true }, { propertyName: "mainInputRef", first: true, predicate: ["mainInput"], descendants: true }], ngImport: i0, template: `
116
+ <div class="select-container" (click)="toggleDropdown($event)">
117
+ <!-- Main input display -->
118
+ <ion-input
119
+ #mainInput
120
+ type="text"
121
+ [value]="displayValue()"
122
+ [placeholder]="props?.placeholder || placeholder"
123
+ readonly
124
+ class="main-input"
125
+ [class.is-open]="isOpen()"
126
+ />
127
+
128
+ <!-- Dropdown icon -->
129
+ <ion-icon
130
+ name="chevron-down-outline"
131
+ class="dropdown-icon"
132
+ [class.rotated]="isOpen()"
133
+ ></ion-icon>
134
+
135
+ <!-- Hidden input for form control -->
136
+ <ion-input
137
+ style="position: absolute; opacity: 0; pointer-events: none;"
138
+ [formControl]="props?.control"
139
+ type="hidden"
140
+ />
141
+ </div>
288
142
 
289
- <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
290
-
291
- <ion-modal
292
- #modal
293
- [initialBreakpoint]="1"
294
- [breakpoints]="[0, 0.5, 0.75, 1]"
295
- (didDismiss)="cancelModal()"
143
+ <!-- Dropdown overlay -->
144
+ <div
145
+ class="dropdown-overlay"
146
+ [class.visible]="isOpen()"
147
+ #dropdown
296
148
  >
297
- <ng-template>
298
- <ion-header>
299
- <ion-toolbar>
300
- <ion-title>{{ label }}</ion-title>
301
- <ion-buttons slot="end">
302
- <ion-button (click)="cancelModal()">Cerrar</ion-button>
303
- </ion-buttons>
304
- </ion-toolbar>
305
- <ion-toolbar>
306
- <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()" />
307
- </ion-toolbar>
308
- </ion-header>
309
- <ion-content>
310
- <ion-list>
311
- <ion-item *ngFor="let item of filteredItems" button (click)="selectItem(item)" detail="false">
312
- <ion-label>{{ item[labelProperty] }}</ion-label>
313
- <ion-icon *ngIf="isItemSelected(item)" name="checkmark-outline" slot="end" color="primary"></ion-icon>
314
- </ion-item>
315
- <ion-item *ngIf="filteredItems.length === 0" lines="none">
316
- <ion-label color="dark">No se encontraron resultados</ion-label>
317
- </ion-item>
318
- </ion-list>
319
- </ion-content>
320
- </ng-template>
321
- </ion-modal>
322
- `, isInline: true, styles: ["ion-header{padding:8px 8px 0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: IonicModule }, { kind: "component", type: i2.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2.IonInput, selector: "ion-input", inputs: ["autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "spellcheck", "step", "type", "value"] }, { kind: "component", type: i2.IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i2.IonModal, selector: "ion-modal" }, { kind: "directive", type: i2.TextValueAccessor, selector: "ion-input:not([type=number]),ion-textarea,ion-searchbar" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: SearchbarComponent, selector: "val-searchbar", inputs: ["disabled"], outputs: ["filterEvent", "focusEvent", "blurEvent"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }
149
+ <!-- Search bar -->
150
+ <div class="search-container" *ngIf="props?.options && props.options.length > 5">
151
+ <ion-searchbar
152
+ #searchbar
153
+ [placeholder]="'Buscar'"
154
+ (ionInput)="onSearch($event)"
155
+ [value]="searchTerm()"
156
+ show-clear-button="focus"
157
+ [debounce]="200"
158
+ ></ion-searchbar>
159
+ </div>
160
+
161
+ <!-- Options list -->
162
+ <div class="options-container">
163
+ <ion-list class="options-list">
164
+ <ion-item
165
+ *ngFor="let option of filteredOptions(); trackBy: trackByFn"
166
+ button
167
+ (click)="selectOption(option)"
168
+ class="option-item"
169
+ >
170
+ <ion-label>{{ option[labelProperty] }}</ion-label>
171
+ <ion-icon
172
+ *ngIf="isSelected(option)"
173
+ name="checkmark-outline"
174
+ slot="end"
175
+ color="primary"
176
+ ></ion-icon>
177
+ </ion-item>
178
+
179
+ <!-- No results message -->
180
+ <ion-item *ngIf="filteredOptions().length === 0" class="no-results">
181
+ <ion-label color="medium">
182
+ {{ searchTerm() ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
183
+ </ion-label>
184
+ </ion-item>
185
+ </ion-list>
186
+ </div>
187
+ </div>
188
+ `, isInline: true, styles: [":host{display:block;position:relative;width:100%}.select-container{position:relative;display:flex;align-items:center;cursor:pointer}.select-container .main-input{flex:1;cursor:pointer}.select-container .main-input.is-open{--border-color: var(--ion-color-primary)}.select-container .dropdown-icon{position:absolute;right:12px;font-size:16px;color:var(--ion-color-medium);transition:transform .2s ease;pointer-events:none;z-index:2}.select-container .dropdown-icon.rotated{transform:rotate(180deg)}.dropdown-overlay{position:absolute;top:100%;left:0;right:0;background:var(--ion-background-color);border:1px solid var(--ion-color-light);border-radius:8px;box-shadow:0 4px 16px #0000001a;z-index:1000;max-height:300px;opacity:0;transform:translateY(-8px);pointer-events:none;transition:all .2s ease}.dropdown-overlay.visible{opacity:1;transform:translateY(4px);pointer-events:all}.search-container{padding:12px;border-bottom:1px solid var(--ion-color-light)}.search-container ion-searchbar{--background: var(--ion-color-light);--border-radius: 8px;--box-shadow: none;--padding-start: 12px;--padding-end: 12px;height:40px}.options-container{max-height:240px;overflow-y:auto}.options-container .options-list{padding:0}.options-container .option-item{--padding-start: 16px;--padding-end: 16px;--min-height: 48px;cursor:pointer}.options-container .option-item:hover{--background: var(--ion-color-light)}.options-container .option-item ion-label{font-size:16px;line-height:1.4}.options-container .option-item ion-icon{font-size:20px}.options-container .no-results{--padding-start: 16px;--padding-end: 16px;--min-height: 48px;text-align:center}.options-container .no-results ion-label{font-style:italic;font-size:14px}@media (max-width: 768px){.dropdown-overlay{max-height:250px}.options-container{max-height:200px}}@media (prefers-color-scheme: dark){.dropdown-overlay{box-shadow:0 4px 16px #0000004d}}.option-item:focus-within{--background: var(--ion-color-primary-tint);outline:2px solid var(--ion-color-primary);outline-offset:-2px}.option-item{transition:background-color .15s ease}.dropdown-icon{transition:transform .2s cubic-bezier(.4,0,.2,1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: IonicModule }, { kind: "component", type: i2.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2.IonInput, selector: "ion-input", inputs: ["autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "spellcheck", "step", "type", "value"] }, { kind: "component", type: i2.IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i2.IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocapitalize", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "maxlength", "minlength", "mode", "name", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] }, { kind: "directive", type: i2.TextValueAccessor, selector: "ion-input:not([type=number]),ion-textarea,ion-searchbar" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }
323
189
  }
324
190
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectSearchComponent, decorators: [{
325
191
  type: Component,
326
- args: [{ selector: 'val-select-search', standalone: true, imports: [CommonModule, IonicModule, FormsModule, SearchbarComponent, ReactiveFormsModule], template: `
327
- <ion-input
328
- type="text"
329
- [value]="displayValue"
330
- [placeholder]="props?.placeholder || placeholder"
331
- readonly
332
- (mousedown)="preventDefaultBehavior($event)"
333
- />
334
-
335
- <ion-input style="position: absolute;" [formControl]="props.control" type="hidden"></ion-input>
192
+ args: [{ selector: 'val-select-search', standalone: true, imports: [CommonModule, IonicModule, FormsModule, ReactiveFormsModule], template: `
193
+ <div class="select-container" (click)="toggleDropdown($event)">
194
+ <!-- Main input display -->
195
+ <ion-input
196
+ #mainInput
197
+ type="text"
198
+ [value]="displayValue()"
199
+ [placeholder]="props?.placeholder || placeholder"
200
+ readonly
201
+ class="main-input"
202
+ [class.is-open]="isOpen()"
203
+ />
204
+
205
+ <!-- Dropdown icon -->
206
+ <ion-icon
207
+ name="chevron-down-outline"
208
+ class="dropdown-icon"
209
+ [class.rotated]="isOpen()"
210
+ ></ion-icon>
211
+
212
+ <!-- Hidden input for form control -->
213
+ <ion-input
214
+ style="position: absolute; opacity: 0; pointer-events: none;"
215
+ [formControl]="props?.control"
216
+ type="hidden"
217
+ />
218
+ </div>
336
219
 
337
- <ion-modal
338
- #modal
339
- [initialBreakpoint]="1"
340
- [breakpoints]="[0, 0.5, 0.75, 1]"
341
- (didDismiss)="cancelModal()"
220
+ <!-- Dropdown overlay -->
221
+ <div
222
+ class="dropdown-overlay"
223
+ [class.visible]="isOpen()"
224
+ #dropdown
342
225
  >
343
- <ng-template>
344
- <ion-header>
345
- <ion-toolbar>
346
- <ion-title>{{ label }}</ion-title>
347
- <ion-buttons slot="end">
348
- <ion-button (click)="cancelModal()">Cerrar</ion-button>
349
- </ion-buttons>
350
- </ion-toolbar>
351
- <ion-toolbar>
352
- <val-searchbar (filterEvent)="onFilter($event)" (focusEvent)="onFocus()" (blurEvent)="onBlur()" />
353
- </ion-toolbar>
354
- </ion-header>
355
- <ion-content>
356
- <ion-list>
357
- <ion-item *ngFor="let item of filteredItems" button (click)="selectItem(item)" detail="false">
358
- <ion-label>{{ item[labelProperty] }}</ion-label>
359
- <ion-icon *ngIf="isItemSelected(item)" name="checkmark-outline" slot="end" color="primary"></ion-icon>
360
- </ion-item>
361
- <ion-item *ngIf="filteredItems.length === 0" lines="none">
362
- <ion-label color="dark">No se encontraron resultados</ion-label>
363
- </ion-item>
364
- </ion-list>
365
- </ion-content>
366
- </ng-template>
367
- </ion-modal>
368
- `, styles: ["ion-header{padding:8px 8px 0}\n"] }]
369
- }], ctorParameters: () => [], propDecorators: { modal: [{
226
+ <!-- Search bar -->
227
+ <div class="search-container" *ngIf="props?.options && props.options.length > 5">
228
+ <ion-searchbar
229
+ #searchbar
230
+ [placeholder]="'Buscar'"
231
+ (ionInput)="onSearch($event)"
232
+ [value]="searchTerm()"
233
+ show-clear-button="focus"
234
+ [debounce]="200"
235
+ ></ion-searchbar>
236
+ </div>
237
+
238
+ <!-- Options list -->
239
+ <div class="options-container">
240
+ <ion-list class="options-list">
241
+ <ion-item
242
+ *ngFor="let option of filteredOptions(); trackBy: trackByFn"
243
+ button
244
+ (click)="selectOption(option)"
245
+ class="option-item"
246
+ >
247
+ <ion-label>{{ option[labelProperty] }}</ion-label>
248
+ <ion-icon
249
+ *ngIf="isSelected(option)"
250
+ name="checkmark-outline"
251
+ slot="end"
252
+ color="primary"
253
+ ></ion-icon>
254
+ </ion-item>
255
+
256
+ <!-- No results message -->
257
+ <ion-item *ngIf="filteredOptions().length === 0" class="no-results">
258
+ <ion-label color="medium">
259
+ {{ searchTerm() ? 'No se encontraron resultados' : 'No hay opciones disponibles' }}
260
+ </ion-label>
261
+ </ion-item>
262
+ </ion-list>
263
+ </div>
264
+ </div>
265
+ `, styles: [":host{display:block;position:relative;width:100%}.select-container{position:relative;display:flex;align-items:center;cursor:pointer}.select-container .main-input{flex:1;cursor:pointer}.select-container .main-input.is-open{--border-color: var(--ion-color-primary)}.select-container .dropdown-icon{position:absolute;right:12px;font-size:16px;color:var(--ion-color-medium);transition:transform .2s ease;pointer-events:none;z-index:2}.select-container .dropdown-icon.rotated{transform:rotate(180deg)}.dropdown-overlay{position:absolute;top:100%;left:0;right:0;background:var(--ion-background-color);border:1px solid var(--ion-color-light);border-radius:8px;box-shadow:0 4px 16px #0000001a;z-index:1000;max-height:300px;opacity:0;transform:translateY(-8px);pointer-events:none;transition:all .2s ease}.dropdown-overlay.visible{opacity:1;transform:translateY(4px);pointer-events:all}.search-container{padding:12px;border-bottom:1px solid var(--ion-color-light)}.search-container ion-searchbar{--background: var(--ion-color-light);--border-radius: 8px;--box-shadow: none;--padding-start: 12px;--padding-end: 12px;height:40px}.options-container{max-height:240px;overflow-y:auto}.options-container .options-list{padding:0}.options-container .option-item{--padding-start: 16px;--padding-end: 16px;--min-height: 48px;cursor:pointer}.options-container .option-item:hover{--background: var(--ion-color-light)}.options-container .option-item ion-label{font-size:16px;line-height:1.4}.options-container .option-item ion-icon{font-size:20px}.options-container .no-results{--padding-start: 16px;--padding-end: 16px;--min-height: 48px;text-align:center}.options-container .no-results ion-label{font-style:italic;font-size:14px}@media (max-width: 768px){.dropdown-overlay{max-height:250px}.options-container{max-height:200px}}@media (prefers-color-scheme: dark){.dropdown-overlay{box-shadow:0 4px 16px #0000004d}}.option-item:focus-within{--background: var(--ion-color-primary-tint);outline:2px solid var(--ion-color-primary);outline-offset:-2px}.option-item{transition:background-color .15s ease}.dropdown-icon{transition:transform .2s cubic-bezier(.4,0,.2,1)}\n"] }]
266
+ }], ctorParameters: () => [], propDecorators: { dropdownRef: [{
370
267
  type: ViewChild,
371
- args: ['modal']
372
- }], label: [{
268
+ args: ['dropdown']
269
+ }], mainInputRef: [{
270
+ type: ViewChild,
271
+ args: ['mainInput']
272
+ }], props: [{
373
273
  type: Input
374
274
  }], labelProperty: [{
375
275
  type: Input
376
276
  }], valueProperty: [{
377
277
  type: Input
378
- }], multiple: [{
379
- type: Input
380
278
  }], placeholder: [{
381
279
  type: Input
382
- }], props: [{
383
- type: Input
384
280
  }] } });
385
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LXNlYXJjaC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy92YWx0ZWNoLWNvbXBvbmVudHMvc3JjL2xpYi9jb21wb25lbnRzL21vbGVjdWxlcy9zZWxlY3Qtc2VhcmNoL3NlbGVjdC1zZWFyY2guY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxNQUFNLEVBQ04sS0FBSyxFQUlMLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsV0FBVyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFdBQVcsRUFBWSxNQUFNLGdCQUFnQixDQUFDO0FBRXZELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUM5RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdURBQXVELENBQUM7QUFDcEYsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDakYsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFakUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7Ozs7O0FBeUR0RTs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLE9BQU8scUJBQXFCO0lBV2hDO1FBUFMsa0JBQWEsR0FBVyxNQUFNLENBQUM7UUFDL0Isa0JBQWEsR0FBVyxJQUFJLENBQUM7UUFDN0IsYUFBUSxHQUFZLEtBQUssQ0FBQztRQUczQixnQkFBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQWdCMUMsU0FBSSxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNuQixtQkFBYyxHQUFHLE1B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Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFnQkcsS0FBSztzQkFBYixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIGluamVjdCxcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBTaW1wbGVDaGFuZ2VzLFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUsIFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBJb25pY01vZHVsZSwgSW9uTW9kYWwgfSBmcm9tICdAaW9uaWMvYW5ndWxhcic7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEljb25TZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvaWNvbnMuc2VydmljZSc7XG5pbXBvcnQgeyBMYW5nU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2xhbmctcHJvdmlkZXIvbGFuZy1wcm92aWRlci5zZXJ2aWNlJztcbmltcG9ydCB7IGFwcGx5RGVmYXVsdFZhbHVlVG9Db250cm9sIH0gZnJvbSAnLi4vLi4vLi4vc2hhcmVkL3V0aWxzL2Zvcm0tZGVmYXVsdHMnO1xuaW1wb3J0IHsgcmVwbGFjZVNwZWNpYWxDaGFycyB9IGZyb20gJy4uLy4uLy4uL3NoYXJlZC91dGlscy90ZXh0JztcbmltcG9ydCB7IElucHV0TWV0YWRhdGEsIElucHV0T3B0aW9uIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IHsgU2VhcmNoYmFyQ29tcG9uZW50IH0gZnJvbSAnLi4vc2VhcmNoYmFyL3NlYXJjaGJhci5jb21wb25lbnQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWwtc2VsZWN0LXNlYXJjaCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIElvbmljTW9kdWxlLCBGb3Jtc01vZHVsZSwgU2VhcmNoYmFyQ29tcG9uZW50LCBSZWFjdGl2ZUZvcm1zTW9kdWxlXSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8aW9uLWlucHV0XG4gICAgICB0eXBlPVwidGV4dFwiXG4gICAgICBbdmFsdWVdPVwiZGlzcGxheVZhbHVlXCJcbiAgICAgIFtwbGFjZWhvbGRlcl09XCJwcm9wcz8ucGxhY2Vob2xkZXIgfHwgcGxhY2Vob2xkZXJcIlxuICAgICAgcmVhZG9ubHlcbiAgICAgIChtb3VzZWRvd24pPVwicHJldmVudERlZmF1bHRCZWhhdmlvcigkZXZlbnQpXCJcbiAgICAvPlxuXG4gICAgPGlvbi1pbnB1dCBzdHlsZT1cInBvc2l0aW9uOiBhYnNvbHV0ZTtcIiBbZm9ybUNvbnRyb2xdPVwicHJvcHMuY29udHJvbFwiIHR5cGU9XCJoaWRkZW5cIj48L2lvbi1pbnB1dD5cblxuICAgIDxpb24tbW9kYWxcbiAgICAgICNtb2RhbFxuICAgICAgW2luaXRpYWxCcmVha3BvaW50XT1cIjFcIlxuICAgICAgW2JyZWFrcG9pbnRzXT1cIlswLCAwLjUsIDAuNzUsIDFdXCJcbiAgICAgIChkaWREaXNtaXNzKT1cImNhbmNlbE1vZGFsKClcIlxuICAgID5cbiAgICAgIDxuZy10ZW1wbGF0ZT5cbiAgICAgICAgPGlvbi1oZWFkZXI+XG4gICAgICAgICAgPGlvbi10b29sYmFyPlxuICAgICAgICAgICAgPGlvbi10aXRsZT57eyBsYWJlbCB9fTwvaW9uLXRpdGxlPlxuICAgICAgICAgICAgPGlvbi1idXR0b25zIHNsb3Q9XCJlbmRcIj5cbiAgICAgICAgICAgICAgPGlvbi1idXR0b24gKGNsaWNrKT1cImNhbmNlbE1vZGFsKClcIj5DZXJyYXI8L2lvbi1idXR0b24+XG4gICAgICAgICAgICA8L2lvbi1idXR0b25zPlxuICAgICAgICAgIDwvaW9uLXRvb2xiYXI+XG4gICAgICAgICAgPGlvbi10b29sYmFyPlxuICAgICAgICAgICAgPHZhbC1zZWFyY2hiYXIgKGZpbHRlckV2ZW50KT1cIm9uRmlsdGVyKCRldmVudClcIiAoZm9jdXNFdmVudCk9XCJvbkZvY3VzKClcIiAoYmx1ckV2ZW50KT1cIm9uQmx1cigpXCIgLz5cbiAgICAgICAgICA8L2lvbi10b29sYmFyPlxuICAgICAgICA8L2lvbi1oZWFkZXI+XG4gICAgICAgIDxpb24tY29udGVudD5cbiAgICAgICAgICA8aW9uLWxpc3Q+XG4gICAgICAgICAgICA8aW9uLWl0ZW0gKm5nRm9yPVwibGV0IGl0ZW0gb2YgZmlsdGVyZWRJdGVtc1wiIGJ1dHRvbiAoY2xpY2spPVwic2VsZWN0SXRlbShpdGVtKVwiIGRldGFpbD1cImZhbHNlXCI+XG4gICAgICAgICAgICAgIDxpb24tbGFiZWw+e3sgaXRlbVtsYWJlbFByb3BlcnR5XSB9fTwvaW9uLWxhYmVsPlxuICAgICAgICAgICAgICA8aW9uLWljb24gKm5nSWY9XCJpc0l0ZW1TZWxlY3RlZChpdGVtKVwiIG5hbWU9XCJjaGVja21hcmstb3V0bGluZVwiIHNsb3Q9XCJlbmRcIiBjb2xvcj1cInByaW1hcnlcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgPC9pb24taXRlbT5cbiAgICAgICAgICAgIDxpb24taXRlbSAqbmdJZj1cImZpbHRlcmVkSXRlbXMubGVuZ3RoID09PSAwXCIgbGluZXM9XCJub25lXCI+XG4gICAgICAgICAgICAgIDxpb24tbGFiZWwgY29sb3I9XCJkYXJrXCI+Tm8gc2UgZW5jb250cmFyb24gcmVzdWx0YWRvczwvaW9uLWxhYmVsPlxuICAgICAgICAgICAgPC9pb24taXRlbT5cbiAgICAgICAgICA8L2lvbi1saXN0PlxuICAgICAgICA8L2lvbi1jb250ZW50PlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L2lvbi1tb2RhbD5cbiAgYCxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgaW9uLWhlYWRlciB7XG4gICAgICAgIHBhZGRpbmc6IDhweCA4cHggMHB4IDhweDtcbiAgICAgIH1cbiAgICBgLFxuICBdLFxufSlcbi8qKlxuICogdmFsLXNlbGVjdC1zZWFyY2hcbiAqXG4gKiBBIHNlYXJjaGFibGUgc2VsZWN0L2Ryb3Bkb3duIGlucHV0IHdpdGggbW9kYWwgYW5kIGZpbHRlcmluZywgaW50ZWdyYXRlZCB3aXRoIEFuZ3VsYXIgZm9ybXMuXG4gKlxuICogQGV4YW1wbGVcbiAqIDx2YWwtc2VsZWN0LXNlYXJjaCBbcHJvcHNdPVwieyBjb250cm9sOiBteUNvbnRyb2wsIGxhYmVsOiAnQ2hvb3NlJywgb3B0aW9uczogW3sgaWQ6ICcxJywgbmFtZTogJ09wdGlvbiAxJyB9XSB9XCI+PC92YWwtc2VsZWN0LXNlYXJjaD5cbiAqXG4gKiBAaW5wdXQgcHJvcHM6IElucHV0TWV0YWRhdGEgLSBDb25maWd1cmF0aW9uIGZvciB0aGUgc2VsZWN0IGlucHV0IChmb3JtIGNvbnRyb2wsIGxhYmVsLCBvcHRpb25zLCBldGMuKVxuICovXG5leHBvcnQgY2xhc3MgU2VsZWN0U2VhcmNoQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuICBAVmlld0NoaWxkKCdtb2RhbCcpIG1vZGFsITogSW9uTW9kYWw7XG5cbiAgQElucHV0KCkgbGFiZWw6IHN0cmluZztcbiAgQElucHV0KCkgbGFiZWxQcm9wZXJ0eTogc3RyaW5nID0gJ25hbWUnO1xuICBASW5wdXQoKSB2YWx1ZVByb3BlcnR5OiBzdHJpbmcgPSAnaWQnO1xuICBASW5wdXQoKSBtdWx0aXBsZTogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBwbGFjZWhvbGRlcjogc3RyaW5nO1xuXG4gIHByaXZhdGUgbGFuZ1NlcnZpY2UgPSBpbmplY3QoTGFuZ1NlcnZpY2UpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubGFiZWwgPSB0aGlzLmxhbmdTZXJ2aWNlLmdldFRleHQoJ19nbG9iYWwnLCAnc2VsZWN0JywgJ1NlbGVjY2lvbmFyJyk7XG4gICAgdGhpcy5wbGFjZWhvbGRlciA9IHRoaXMubGFuZ1NlcnZpY2UuZ2V0VGV4dCgnX2dsb2JhbCcsICdzZWxlY3RPcHRpb24nLCAnU2VsZWNjaW9uZSB1bmEgb3BjacOzbicpO1xuICB9XG4gIC8qKlxuICAgKiBJbnB1dCBjb25maWd1cmF0aW9uIG9iamVjdC5cbiAgICogQHR5cGUge0lucHV0TWV0YWRhdGF9XG4gICAqIEBwcm9wZXJ0eSBjb250cm9sIC0gVGhlIEFuZ3VsYXIgRm9ybUNvbnRyb2wgZm9yIHRoZSBzZWxlY3QgaW5wdXQuXG4gICAqIEBwcm9wZXJ0eSBsYWJlbCAtIFRoZSBsYWJlbCBmb3IgdGhlIHNlbGVjdC5cbiAgICogQHByb3BlcnR5IG9wdGlvbnMgLSBUaGUgYXZhaWxhYmxlIG9wdGlvbnMgZm9yIHRoZSBzZWxlY3QuXG4gICAqIEBwcm9wZXJ0eSBwbGFjZWhvbGRlciAtIFRoZSBwbGFjZWhvbGRlciB0ZXh0LlxuICAgKi9cbiAgQElucHV0KCkgcHJvcHM6IElucHV0TWV0YWRhdGE7XG5cbiAgaWNvbiA9IGluamVjdChJY29uU2VydmljZSk7XG4gIHByaXZhdGUgY2hhbmdlRGV0ZWN0b3IgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuXG4gIHNlYXJjaFRlcm06IHN0cmluZyA9ICcnO1xuICBmaWx0ZXJlZEl0ZW1zOiBJbnB1dE9wdGlvbltdID0gW107XG4gIHNlbGVjdGVkSXRlbXM6IElucHV0T3B0aW9uW10gPSBbXTtcbiAgZGlzcGxheVZhbHVlOiBzdHJpbmcgPSAnJztcblxuICBwcml2YXRlIHByZXZpb3VzT3B0aW9uczogYW55W10gPSBbXTtcbiAgcHJpdmF0ZSBpc1Byb2Nlc3NpbmdDaGFuZ2VzID0gZmFsc2U7XG4gIHByaXZhdGUgdmFsdWVDaGFuZ2VzU3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uO1xuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuYXBwbHlEZWZhdWx0VmFsdWUoKTtcbiAgICB0aGlzLmluaXRpYWxpemVJdGVtcygpO1xuICAgIHRoaXMuc3luY0NvbnRyb2xWYWx1ZVdpdGhTZWxlY3RlZEl0ZW1zKCk7XG4gICAgdGhpcy51cGRhdGVEaXNwbGF5VmFsdWUoKTtcbiAgICB0aGlzLnN1YnNjcmliZVRvVmFsdWVDaGFuZ2VzKCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICAvLyBMaW1waWFyIHN1c2NyaXBjaW9uZXMgcGFyYSBldml0YXIgbWVtb3J5IGxlYWtzXG4gICAgaWYgKHRoaXMudmFsdWVDaGFuZ2VzU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLnZhbHVlQ2hhbmdlc1N1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICAvLyBFdml0YXIgYnVjbGVzIGluZmluaXRvc1xuICAgIGlmICh0aGlzLmlzUHJvY2Vzc2luZ0NoYW5nZXMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDdWFuZG8gY2FtYmlhIHByb3BzIG8gcHJvcHMub3B0aW9uc1xuICAgIGlmIChjaGFuZ2VzWydwcm9wcyddKSB7XG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLmlzUHJvY2Vzc2luZ0NoYW5nZXMgPSB0cnVlO1xuXG4gICAgICAgIC8vIERlc3VzY3JpYmlyc2UgZGVsIGFudGlndW8gY29udHJvbCBzaSBleGlzdGVcbiAgICAgICAgaWYgKHRoaXMudmFsdWVDaGFuZ2VzU3Vic2NyaXB0aW9uKSB7XG4gICAgICAgICAgdGhpcy52YWx1ZUNoYW5nZXNTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnByb3BzPy5vcHRpb25zKSB7XG4gICAgICAgICAgLy8gVmVyaWZpY2FyIHNpIGxhcyBvcGNpb25lcyBoYW4gY2FtYmlhZG8gcmVhbG1lbnRlXG4gICAgICAgICAgY29uc3Qgb3B0aW9uc0NoYW5nZWQgPSAhdGhpcy5hcmVPcHRpb25zRXF1YWwodGhpcy5wcmV2aW91c09wdGlvbnMsIHRoaXMucHJvcHMub3B0aW9ucyk7XG5cbiAgICAgICAgICBpZiAob3B0aW9uc0NoYW5nZWQpIHtcbiAgICAgICAgICAgIHRoaXMucHJldmlvdXNPcHRpb25zID0gWy4uLnRoaXMucHJvcHMub3B0aW9uc107XG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemVJdGVtcygpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNpbmNyb25pemFyIGNvbiBlbCBudWV2byBjb250cm9sIHNpIGV4aXN0ZVxuICAgICAgICB0aGlzLnN5bmNDb250cm9sVmFsdWVXaXRoU2VsZWN0ZWRJdGVtcygpO1xuICAgICAgICB0aGlzLnVwZGF0ZURpc3BsYXlWYWx1ZSgpO1xuXG4gICAgICAgIC8vIFN1c2NyaWJpcnNlIGFsIG51ZXZvIGNvbnRyb2xcbiAgICAgICAgdGhpcy5zdWJzY3JpYmVUb1ZhbHVlQ2hhbmdlcygpO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgdGhpcy5pc1Byb2Nlc3NpbmdDaGFuZ2VzID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaW9uVmlld1dpbGxFbnRlcigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc1Byb2Nlc3NpbmdDaGFuZ2VzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuaXNQcm9jZXNzaW5nQ2hhbmdlcyA9IHRydWU7XG4gICAgICB0aGlzLmluaXRpYWxpemVJdGVtcygpO1xuICAgICAgdGhpcy5zeW5jQ29udHJvbFZhbHVlV2l0aFNlbGVjdGVkSXRlbXMoKTtcbiAgICAgIHRoaXMudXBkYXRlRGlzcGxheVZhbHVlKCk7XG4gICAgICB0aGlzLnN1YnNjcmliZVRvVmFsdWVDaGFuZ2VzKCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuaXNQcm9jZXNzaW5nQ2hhbmdlcyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8vIFN1c2NyaWJpcnNlIGEgY2FtYmlvcyBlbiBlbCBGb3JtQ29udHJvbFxuICBwcml2YXRlIHN1YnNjcmliZVRvVmFsdWVDaGFuZ2VzKCkge1xuICAgIGlmICghdGhpcy5wcm9wcz8uY29udHJvbCkgcmV0dXJuO1xuXG4gICAgdGhpcy52YWx1ZUNoYW5nZXNTdWJzY3JpcHRpb24gPSB0aGlzLnByb3BzLmNvbnRyb2wudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSh2YWx1ZSA9PiB7XG4gICAgICBpZiAodGhpcy5pc1Byb2Nlc3NpbmdDaGFuZ2VzKSByZXR1cm47XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuaXNQcm9jZXNzaW5nQ2hhbmdlcyA9IHRydWU7XG4gICAgICAgIHRoaXMuc3luY0NvbnRyb2xWYWx1ZVdpdGhTZWxlY3RlZEl0ZW1zKCk7XG4gICAgICAgIHRoaXMudXBkYXRlRGlzcGxheVZhbHVlKCk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB0aGlzLmlzUHJvY2Vzc2luZ0NoYW5nZXMgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIENvbXBhcmEgc2kgZG9zIGFycmF5cyBkZSBvcGNpb25lcyBzb24gaWd1YWxlc1xuICBwcml2YXRlIGFyZU9wdGlvbnNFcXVhbChwcmV2T3B0aW9uczogYW55W10sIG5ld09wdGlvbnM6IGFueVtdKTogYm9vbGVhbiB7XG4gICAgLy8gUEVSRjogVXNlIHJlZmVyZW5jZSBlcXVhbGl0eSBmaXJzdCBmb3IgZmFzdCBwYXRoXG4gICAgaWYgKHByZXZPcHRpb25zID09PSBuZXdPcHRpb25zKSByZXR1cm4gdHJ1ZTtcbiAgICBpZiAoIXByZXZPcHRpb25zIHx8ICFuZXdPcHRpb25zKSByZXR1cm4gcHJldk9wdGlvbnMgPT09IG5ld09wdGlvbnM7XG4gICAgaWYgKHByZXZPcHRpb25zLmxlbmd0aCAhPT0gbmV3T3B0aW9ucy5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICAvLyBPbmx5IGNvbXBhcmUgdmFsdWVQcm9wZXJ0eSBmb3IgZXF1YWxpdHlcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHByZXZPcHRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocHJldk9wdGlvbnNbaV1bdGhpcy52YWx1ZVByb3BlcnR5XSAhPT0gbmV3T3B0aW9uc1tpXVt0aGlzLnZhbHVlUHJvcGVydHldKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcml2YXRlIGluaXRpYWxpemVJdGVtcygpOiB2b2lkIHtcbiAgICAvLyBQRVJGOiBBdm9pZCB1bm5lY2Vzc2FyeSBhcnJheSBjb3BpZXNcbiAgICB0aGlzLmZpbHRlcmVkSXRlbXMgPSB0aGlzLnByb3BzPy5vcHRpb25zIHx8IFtdO1xuICB9XG5cbiAgcHJpdmF0ZSBzeW5jQ29udHJvbFZhbHVlV2l0aFNlbGVjdGVkSXRlbXMoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnByb3BzPy5jb250cm9sKSB7XG4gICAgICB0aGlzLnNlbGVjdGVkSXRlbXMgPSBbXTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgY29udHJvbFZhbHVlID0gdGhpcy5wcm9wcy5jb250cm9sLnZhbHVlO1xuICAgIGlmIChjb250cm9sVmFsdWUgPT09IG51bGwgfHwgY29udHJvbFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWRJdGVtcyA9IFtdO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBQRVJGOiBVc2UgYSBNYXAgZm9yIGZhc3RlciBsb29rdXAgaWYgb3B0aW9ucyBhcmUgbGFyZ2VcbiAgICBpZiAodGhpcy5wcm9wcy5vcHRpb25zICYmIHRoaXMucHJvcHMub3B0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBtYXAgPSBuZXcgTWFwKHRoaXMucHJvcHMub3B0aW9ucy5tYXAob3B0ID0+IFtvcHRbdGhpcy52YWx1ZVByb3BlcnR5XSwgb3B0XSkpO1xuICAgICAgY29uc3Qgc2VsZWN0ZWRPcHRpb24gPSBtYXAuZ2V0KGNvbnRyb2xWYWx1ZSk7XG4gICAgICB0aGlzLnNlbGVjdGVkSXRlbXMgPSBzZWxlY3RlZE9wdGlvbiA/IFtzZWxlY3RlZE9wdGlvbl0gOiBbXTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zZWxlY3RlZEl0ZW1zID0gW107XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhcHBseURlZmF1bHRWYWx1ZSgpOiB2b2lkIHtcbiAgICBhcHBseURlZmF1bHRWYWx1ZVRvQ29udHJvbCh0aGlzLnByb3BzKTtcbiAgfVxuXG4gIG9uRmlsdGVyKGV2ZW50KSB7XG4gICAgLy8gSWYgbm8gc2VhcmNoIHRlcm0sIHNob3cgYWxsIG9wdGlvbnNcbiAgICBpZiAoIWV2ZW50IHx8IGV2ZW50LnRyaW0oKSA9PT0gJycpIHtcbiAgICAgIHRoaXMuZmlsdGVyZWRJdGVtcyA9IHRoaXMucHJvcHM/Lm9wdGlvbnMgPyBbLi4udGhpcy5wcm9wcy5vcHRpb25zXSA6IFtdO1xuICAgICAgdGhpcy5jaGFuZ2VEZXRlY3Rvci5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSWYgbm8gb3B0aW9ucywgbm90aGluZyB0byBmaWx0ZXJcbiAgICBpZiAoIXRoaXMucHJvcHM/Lm9wdGlvbnMgfHwgdGhpcy5wcm9wcy5vcHRpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5maWx0ZXJlZEl0ZW1zID0gW107XG4gICAgICB0aGlzLmNoYW5nZURldGVjdG9yLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBQRVJGOiBBdm9pZCByZXBlYXRlZCByZXBsYWNlU3BlY2lhbENoYXJzIGFuZCB0b0xvd2VyQ2FzZSBmb3IgZWFjaCBvcHRpb25cbiAgICBjb25zdCBzZWFyY2ggPSByZXBsYWNlU3BlY2lhbENoYXJzKGV2ZW50LnRvTG93ZXJDYXNlKCkpO1xuICAgIHRoaXMuZmlsdGVyZWRJdGVtcyA9IHRoaXMucHJvcHMub3B0aW9ucy5maWx0ZXIoZWxlbWVudCA9PiB7XG4gICAgICAvLyBPbmx5IHVzZSBsYWJlbFByb3BlcnR5IGFuZCB2YWx1ZVByb3BlcnR5IGZvciBmaWx0ZXJpbmcgKGZhc3RlcilcbiAgICAgIGNvbnN0IGxhYmVsID0gZWxlbWVudFt0aGlzLmxhYmVsUHJvcGVydHldXG4gICAgICAgID8gcmVwbGFjZVNwZWNpYWxDaGFycyhTdHJpbmcoZWxlbWVudFt0aGlzLmxhYmVsUHJvcGVydHldKS50b0xvd2VyQ2FzZSgpKVxuICAgICAgICA6ICcnO1xuICAgICAgY29uc3QgdmFsdWUgPSBlbGVtZW50W3RoaXMudmFsdWVQcm9wZXJ0eV1cbiAgICAgICAgPyByZXBsYWNlU3BlY2lhbENoYXJzKFN0cmluZyhlbGVtZW50W3RoaXMudmFsdWVQcm9wZXJ0eV0pLnRvTG93ZXJDYXNlKCkpXG4gICAgICAgIDogJyc7XG4gICAgICByZXR1cm4gbGFiZWwuaW5jbHVkZXMoc2VhcmNoKSB8fCB2YWx1ZS5pbmNsdWRlcyhzZWFyY2gpO1xuICAgIH0pO1xuICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3IuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgb25Gb2N1cygpIHtcbiAgICBjb25zb2xlLmxvZygnb25Gb2N1cycpO1xuICB9XG5cbiAgb25CbHVyKCkge1xuICAgIGNvbnNvbGUubG9nKCdvbkJsdXInKTtcbiAgfVxuXG4gIG9wZW5Nb2RhbCgpIHtcbiAgICBpZiAodGhpcy5tb2RhbCkge1xuICAgICAgdGhpcy5tb2RhbC5wcmVzZW50KCk7XG4gICAgfVxuICB9XG5cbiAgcHJldmVudERlZmF1bHRCZWhhdmlvcihldmVudDogTW91c2VFdmVudCkge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgdGhpcy5vcGVuTW9kYWwoKTtcbiAgfVxuXG4gIGNhbmNlbE1vZGFsKCkge1xuICAgIC8vIFJlc2V0IGZpbHRlciBhbmQgc2hvdyBhbGwgb3B0aW9ucyB3aGVuIGNsb3NpbmcgbW9kYWxcbiAgICB0aGlzLnNlYXJjaFRlcm0gPSAnJztcbiAgICB0aGlzLmZpbHRlcmVkSXRlbXMgPSB0aGlzLnByb3BzPy5vcHRpb25zID8gWy4uLnRoaXMucHJvcHMub3B0aW9uc10gOiBbXTtcbiAgICB0aGlzLmNoYW5nZURldGVjdG9yLmRldGVjdENoYW5nZXMoKTtcbiAgICBpZiAodGhpcy5tb2RhbCkge1xuICAgICAgdGhpcy5tb2RhbC5kaXNtaXNzKCk7XG4gICAgfVxuICB9XG5cbiAgc2VsZWN0SXRlbShpdGVtOiBhbnkpIHtcbiAgICBpZiAodGhpcy5tdWx0aXBsZSkge1xuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnNlbGVjdGVkSXRlbXMuZmluZEluZGV4KFxuICAgICAgICBzZWxlY3RlZEl0ZW0gPT4gc2VsZWN0ZWRJdGVtW3RoaXMudmFsdWVQcm9wZXJ0eV0gPT09IGl0ZW1bdGhpcy52YWx1ZVByb3BlcnR5XVxuICAgICAgKTtcblxuICAgICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICB0aGlzLnNlbGVjdGVkSXRlbXMucHVzaChpdGVtKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRJdGVtcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnNlbGVjdGVkSXRlbXMgPSBbaXRlbV07XG4gICAgICB0aGlzLmNhbmNlbE1vZGFsKCk7XG4gICAgfVxuXG4gICAgdGhpcy51cGRhdGVEaXNwbGF5VmFsdWUoKTtcbiAgICB0aGlzLmFwcGx5Q2hhbmdlcygpO1xuICB9XG5cbiAgaXNJdGVtU2VsZWN0ZWQoaXRlbTogYW55KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRJdGVtcy5zb21lKHNlbGVjdGVkSXRlbSA9PiBzZWxlY3RlZEl0ZW1bdGhpcy52YWx1ZVByb3BlcnR5XSA9PT0gaXRlbVt0aGlzLnZhbHVlUHJvcGVydHldKTtcbiAgfVxuXG4gIHVwZGF0ZURpc3BsYXlWYWx1ZSgpIHtcbiAgICBpZiAodGhpcy5zZWxlY3RlZEl0ZW1zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5kaXNwbGF5VmFsdWUgPSAnJztcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5tdWx0aXBsZSkge1xuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRJdGVtcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgdGhpcy5kaXNwbGF5VmFsdWUgPSB0aGlzLnNlbGVjdGVkSXRlbXNbMF1bdGhpcy5sYWJlbFByb3BlcnR5XTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuZGlzcGxheVZhbHVlID0gYCR7dGhpcy5zZWxlY3RlZEl0ZW1zLmxlbmd0aH0gZWxlbWVudG9zIHNlbGVjY2lvbmFkb3NgO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmRpc3BsYXlWYWx1ZSA9IHRoaXMuc2VsZWN0ZWRJdGVtc1swXVt0aGlzLmxhYmVsUHJvcGVydHldO1xuICAgIH1cbiAgfVxuXG4gIGFwcGx5Q2hhbmdlcygpIHtcbiAgICBpZiAoIXRoaXMucHJvcHM/LmNvbnRyb2wpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgdGhpcy5pc1Byb2Nlc3NpbmdDaGFuZ2VzID0gdHJ1ZTtcblxuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRJdGVtcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHRoaXMucHJvcHMuY29udHJvbC5zZXRWYWx1ZSh0aGlzLnNlbGVjdGVkSXRlbXNbMF1bdGhpcy52YWx1ZVByb3BlcnR5XSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnByb3BzLmNvbnRyb2wuc2V0VmFsdWUobnVsbCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMucHJvcHMuY29udHJvbC5tYXJrQXNEaXJ0eSgpO1xuICAgICAgdGhpcy5wcm9wcy5jb250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5pc1Byb2Nlc3NpbmdDaGFuZ2VzID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLy8gTcOpdG9kbyBww7pibGljbyBwYXJhIHJlaW5pY2lhciBlbCBjb21wb25lbnRlXG4gIHJlc2V0KCkge1xuICAgIHRoaXMuc2VsZWN0ZWRJdGVtcyA9IFtdO1xuICAgIHRoaXMuZGlzcGxheVZhbHVlID0gJyc7XG4gICAgaWYgKHRoaXMucHJvcHM/LmNvbnRyb2wpIHtcbiAgICAgIHRoaXMucHJvcHMuY29udHJvbC5zZXRWYWx1ZShudWxsKTtcbiAgICB9XG4gICAgdGhpcy5jaGFuZ2VEZXRlY3Rvci5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cbn1cbiJdfQ==
281
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LXNlYXJjaC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy92YWx0ZWNoLWNvbXBvbmVudHMvc3JjL2xpYi9jb21wb25lbnRzL21vbGVjdWxlcy9zZWxlY3Qtc2VhcmNoL3NlbGVjdC1zZWFyY2guY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQ0wsU0FBUyxFQUVULE1BQU0sRUFDTixLQUFLLEVBR0wsU0FBUyxFQUNULE1BQU0sRUFDTixRQUFRLEVBQ1QsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdURBQXVELENBQUM7QUFDcEYsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDakYsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7Ozs7O0FBbUZqRSxNQUFNLE9BQU8scUJBQXFCO0lBNkNoQztRQXhDUyxrQkFBYSxHQUFXLE1BQU0sQ0FBQztRQUMvQixrQkFBYSxHQUFXLElBQUksQ0FBQztRQUM3QixnQkFBVyxHQUFXLEVBQUUsQ0FBQztRQUUxQixnQkFBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUUxQyx3Q0FBd0M7UUFDeEMsV0FBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2QixlQUFVLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3hCLGtCQUFhLEdBQUcsTUFBTSxDQUFnQixJQUFJLENBQUMsQ0FBQztRQUU1QyxtQkFBbUI7UUFDbkIs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O2tCQWhGakMsU0FBUzsrQkFDRSxtQkFBbUIsY0FDakIsSUFBSSxXQUNQLENBQUMsWUFBWSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsbUJBQW1CLENBQUMsWUFDNUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5RVQ7d0RBSXNCLFdBQVc7c0JBQWpDLFNBQVM7dUJBQUMsVUFBVTtnQkFDRyxZQUFZO3NCQUFuQyxTQUFTO3VCQUFDLFdBQVc7Z0JBRWIsS0FBSztzQkFBYixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgaW5qZWN0LFxuICBJbnB1dCxcbiAgT25Jbml0LFxuICBPbkRlc3Ryb3ksXG4gIFZpZXdDaGlsZCxcbiAgc2lnbmFsLFxuICBjb21wdXRlZFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgSW9uaWNNb2R1bGUgfSBmcm9tICdAaW9uaWMvYW5ndWxhcic7XG5pbXBvcnQgeyBMYW5nU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2xhbmctcHJvdmlkZXIvbGFuZy1wcm92aWRlci5zZXJ2aWNlJztcbmltcG9ydCB7IGFwcGx5RGVmYXVsdFZhbHVlVG9Db250cm9sIH0gZnJvbSAnLi4vLi4vLi4vc2hhcmVkL3V0aWxzL2Zvcm0tZGVmYXVsdHMnO1xuaW1wb3J0IHsgcmVwbGFjZVNwZWNpYWxDaGFycyB9IGZyb20gJy4uLy4uLy4uL3NoYXJlZC91dGlscy90ZXh0JztcbmltcG9ydCB7IElucHV0TWV0YWRhdGEsIElucHV0T3B0aW9uIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWwtc2VsZWN0LXNlYXJjaCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIElvbmljTW9kdWxlLCBGb3Jtc01vZHVsZSwgUmVhY3RpdmVGb3Jtc01vZHVsZV0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cInNlbGVjdC1jb250YWluZXJcIiAoY2xpY2spPVwidG9nZ2xlRHJvcGRvd24oJGV2ZW50KVwiPlxuICAgICAgPCEtLSBNYWluIGlucHV0IGRpc3BsYXkgLS0+XG4gICAgICA8aW9uLWlucHV0XG4gICAgICAgICNtYWluSW5wdXRcbiAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICBbdmFsdWVdPVwiZGlzcGxheVZhbHVlKClcIlxuICAgICAgICBbcGxhY2Vob2xkZXJdPVwicHJvcHM/LnBsYWNlaG9sZGVyIHx8IHBsYWNlaG9sZGVyXCJcbiAgICAgICAgcmVhZG9ubHlcbiAgICAgICAgY2xhc3M9XCJtYWluLWlucHV0XCJcbiAgICAgICAgW2NsYXNzLmlzLW9wZW5dPVwiaXNPcGVuKClcIlxuICAgICAgLz5cbiAgICAgIFxuICAgICAgPCEtLSBEcm9wZG93biBpY29uIC0tPlxuICAgICAgPGlvbi1pY29uIFxuICAgICAgICBuYW1lPVwiY2hldnJvbi1kb3duLW91dGxpbmVcIiBcbiAgICAgICAgY2xhc3M9XCJkcm9wZG93bi1pY29uXCIgXG4gICAgICAgIFtjbGFzcy5yb3RhdGVkXT1cImlzT3BlbigpXCJcbiAgICAgID48L2lvbi1pY29uPlxuICAgICAgXG4gICAgICA8IS0tIEhpZGRlbiBpbnB1dCBmb3IgZm9ybSBjb250cm9sIC0tPlxuICAgICAgPGlvbi1pbnB1dCBcbiAgICAgICAgc3R5bGU9XCJwb3NpdGlvbjogYWJzb2x1dGU7IG9wYWNpdHk6IDA7IHBvaW50ZXItZXZlbnRzOiBub25lO1wiIFxuICAgICAgICBbZm9ybUNvbnRyb2xdPVwicHJvcHM/LmNvbnRyb2xcIiBcbiAgICAgICAgdHlwZT1cImhpZGRlblwiXG4gICAgICAvPlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLSBEcm9wZG93biBvdmVybGF5IC0tPlxuICAgIDxkaXYgXG4gICAgICBjbGFzcz1cImRyb3Bkb3duLW92ZXJsYXlcIiBcbiAgICAgIFtjbGFzcy52aXNpYmxlXT1cImlzT3BlbigpXCJcbiAgICAgICNkcm9wZG93blxuICAgID5cbiAgICAgIDwhLS0gU2VhcmNoIGJhciAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJzZWFyY2gtY29udGFpbmVyXCIgKm5nSWY9XCJwcm9wcz8ub3B0aW9ucyAmJiBwcm9wcy5vcHRpb25zLmxlbmd0aCA+IDVcIj5cbiAgICAgICAgPGlvbi1zZWFyY2hiYXJcbiAgICAgICAgICAjc2VhcmNoYmFyXG4gICAgICAgICAgW3BsYWNlaG9sZGVyXT1cIidCdXNjYXInXCJcbiAgICAgICAgICAoaW9uSW5wdXQpPVwib25TZWFyY2goJGV2ZW50KVwiXG4gICAgICAgICAgW3ZhbHVlXT1cInNlYXJjaFRlcm0oKVwiXG4gICAgICAgICAgc2hvdy1jbGVhci1idXR0b249XCJmb2N1c1wiXG4gICAgICAgICAgW2RlYm91bmNlXT1cIjIwMFwiXG4gICAgICAgID48L2lvbi1zZWFyY2hiYXI+XG4gICAgICA8L2Rpdj5cbiAgICAgIFxuICAgICAgPCEtLSBPcHRpb25zIGxpc3QgLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwib3B0aW9ucy1jb250YWluZXJcIj5cbiAgICAgICAgPGlvbi1saXN0IGNsYXNzPVwib3B0aW9ucy1saXN0XCI+XG4gICAgICAgICAgPGlvbi1pdGVtIFxuICAgICAgICAgICAgKm5nRm9yPVwibGV0IG9wdGlvbiBvZiBmaWx0ZXJlZE9wdGlvbnMoKTsgdHJhY2tCeTogdHJhY2tCeUZuXCIgXG4gICAgICAgICAgICBidXR0b24gXG4gICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0T3B0aW9uKG9wdGlvbilcIlxuICAgICAgICAgICAgY2xhc3M9XCJvcHRpb24taXRlbVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPGlvbi1sYWJlbD57eyBvcHRpb25bbGFiZWxQcm9wZXJ0eV0gfX08L2lvbi1sYWJlbD5cbiAgICAgICAgICAgIDxpb24taWNvbiBcbiAgICAgICAgICAgICAgKm5nSWY9XCJpc1NlbGVjdGVkKG9wdGlvbilcIiBcbiAgICAgICAgICAgICAgbmFtZT1cImNoZWNrbWFyay1vdXRsaW5lXCIgXG4gICAgICAgICAgICAgIHNsb3Q9XCJlbmRcIiBcbiAgICAgICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgICAgICAgID48L2lvbi1pY29uPlxuICAgICAgICAgIDwvaW9uLWl0ZW0+XG4gICAgICAgICAgXG4gICAgICAgICAgPCEtLSBObyByZXN1bHRzIG1lc3NhZ2UgLS0+XG4gICAgICAgICAgPGlvbi1pdGVtICpuZ0lmPVwiZmlsdGVyZWRPcHRpb25zKCkubGVuZ3RoID09PSAwXCIgY2xhc3M9XCJuby1yZXN1bHRzXCI+XG4gICAgICAgICAgICA8aW9uLWxhYmVsIGNvbG9yPVwibWVkaXVtXCI+XG4gICAgICAgICAgICAgIHt7IHNlYXJjaFRlcm0oKSA/ICdObyBzZSBlbmNvbnRyYXJvbiByZXN1bHRhZG9zJyA6ICdObyBoYXkgb3BjaW9uZXMgZGlzcG9uaWJsZXMnIH19XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L2lvbi1pdGVtPlxuICAgICAgICA8L2lvbi1saXN0PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIGAsXG4gIHN0eWxlVXJsczogWycuL3NlbGVjdC1zZWFyY2guY29tcG9uZW50LnNjc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBTZWxlY3RTZWFyY2hDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIEBWaWV3Q2hpbGQoJ2Ryb3Bkb3duJykgZHJvcGRvd25SZWYhOiBFbGVtZW50UmVmO1xuICBAVmlld0NoaWxkKCdtYWluSW5wdXQnKSBtYWluSW5wdXRSZWYhOiBFbGVtZW50UmVmO1xuXG4gIEBJbnB1dCgpIHByb3BzITogSW5wdXRNZXRhZGF0YTtcbiAgQElucHV0KCkgbGFiZWxQcm9wZXJ0eTogc3RyaW5nID0gJ25hbWUnO1xuICBASW5wdXQoKSB2YWx1ZVByb3BlcnR5OiBzdHJpbmcgPSAnaWQnO1xuICBASW5wdXQoKSBwbGFjZWhvbGRlcjogc3RyaW5nID0gJyc7XG5cbiAgcHJpdmF0ZSBsYW5nU2VydmljZSA9IGluamVjdChMYW5nU2VydmljZSk7XG4gIFxuICAvLyBTaWduYWxzIGZvciByZWFjdGl2ZSBzdGF0ZSBtYW5hZ2VtZW50XG4gIGlzT3BlbiA9IHNpZ25hbChmYWxzZSk7XG4gIHNlYXJjaFRlcm0gPSBzaWduYWwoJycpO1xuICBzZWxlY3RlZFZhbHVlID0gc2lnbmFsPHN0cmluZyB8IG51bGw+KG51bGwpO1xuICBcbiAgLy8gQ29tcHV0ZWQgc2lnbmFsc1xuICBkaXNwbGF5VmFsdWUgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLnNlbGVjdGVkVmFsdWUoKTtcbiAgICBpZiAoIXZhbHVlKSByZXR1cm4gJyc7XG4gICAgXG4gICAgY29uc3Qgb3B0aW9uID0gdGhpcy5nZXRPcHRpb25CeVZhbHVlKHZhbHVlKTtcbiAgICByZXR1cm4gb3B0aW9uID8gb3B0aW9uW3RoaXMubGFiZWxQcm9wZXJ0eV0gOiAnJztcbiAgfSk7XG5cbiAgZmlsdGVyZWRPcHRpb25zID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLnByb3BzPy5vcHRpb25zIHx8IFtdO1xuICAgIGNvbnN0IHNlYXJjaCA9IHRoaXMuc2VhcmNoVGVybSgpLnRvTG93ZXJDYXNlKCk7XG4gICAgXG4gICAgaWYgKCFzZWFyY2gpIHtcbiAgICAgIHJldHVybiBvcHRpb25zO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gb3B0aW9ucy5maWx0ZXIob3B0aW9uID0+IHtcbiAgICAgIGNvbnN0IGxhYmVsID0gb3B0aW9uW3RoaXMubGFiZWxQcm9wZXJ0eV1cbiAgICAgICAgPyByZXBsYWNlU3BlY2lhbENoYXJzKFN0cmluZyhvcHRpb25bdGhpcy5sYWJlbFByb3BlcnR5XSkudG9Mb3dlckNhc2UoKSlcbiAgICAgICAgOiAnJztcbiAgICAgIGNvbnN0IHZhbHVlID0gb3B0aW9uW3RoaXMudmFsdWVQcm9wZXJ0eV1cbiAgICAgICAgPyByZXBsYWNlU3BlY2lhbENoYXJzKFN0cmluZyhvcHRpb25bdGhpcy52YWx1ZVByb3BlcnR5XSkudG9Mb3dlckNhc2UoKSlcbiAgICAgICAgOiAnJztcbiAgICAgIGNvbnN0IHNlYXJjaFRlcm0gPSByZXBsYWNlU3BlY2lhbENoYXJzKHNlYXJjaCk7XG4gICAgICByZXR1cm4gbGFiZWwuaW5jbHVkZXMoc2VhcmNoVGVybSkgfHwgdmFsdWUuaW5jbHVkZXMoc2VhcmNoVGVybSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGxhY2Vob2xkZXIgPSB0aGlzLmxhbmdTZXJ2aWNlLmdldFRleHQoJ19nbG9iYWwnLCAnc2VsZWN0T3B0aW9uJywgJ1NlbGVjY2lvbmUgdW5hIG9wY2nDs24nKTtcbiAgICBcbiAgICAvLyBDbG9zZSBkcm9wZG93biB3aGVuIGNsaWNraW5nIG91dHNpZGVcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuaGFuZGxlQ2xpY2tPdXRzaWRlLmJpbmQodGhpcykpO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5hcHBseURlZmF1bHRWYWx1ZSgpO1xuICAgIHRoaXMuc3luY1NlbGVjdGVkVmFsdWUoKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5oYW5kbGVDbGlja091dHNpZGUuYmluZCh0aGlzKSk7XG4gIH1cblxuICAvLyBDb21wb25lbnQgbWV0aG9kc1xuICB0b2dnbGVEcm9wZG93bihldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLmlzT3Blbi51cGRhdGUodmFsdWUgPT4gIXZhbHVlKTtcbiAgICBcbiAgICBpZiAodGhpcy5pc09wZW4oKSkge1xuICAgICAgLy8gRm9jdXMgc2VhcmNoIGJhciB3aGVuIG9wZW5pbmcgaWYgYXZhaWxhYmxlXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgY29uc3Qgc2VhcmNoYmFyID0gdGhpcy5kcm9wZG93blJlZj8ubmF0aXZlRWxlbWVudD8ucXVlcnlTZWxlY3RvcignaW9uLXNlYXJjaGJhcicpO1xuICAgICAgICBpZiAoc2VhcmNoYmFyKSB7XG4gICAgICAgICAgc2VhcmNoYmFyLnNldEZvY3VzKCk7XG4gICAgICAgIH1cbiAgICAgIH0sIDEwMCk7XG4gICAgfVxuICB9XG5cbiAgb25TZWFyY2goZXZlbnQ6IGFueSk6IHZvaWQge1xuICAgIHRoaXMuc2VhcmNoVGVybS5zZXQoZXZlbnQuZGV0YWlsLnZhbHVlIHx8ICcnKTtcbiAgfVxuXG4gIHNlbGVjdE9wdGlvbihvcHRpb246IElucHV0T3B0aW9uKTogdm9pZCB7XG4gICAgY29uc3QgdmFsdWUgPSBvcHRpb25bdGhpcy52YWx1ZVByb3BlcnR5XTtcbiAgICB0aGlzLnNlbGVjdGVkVmFsdWUuc2V0KHZhbHVlKTtcbiAgICB0aGlzLmlzT3Blbi5zZXQoZmFsc2UpO1xuICAgIHRoaXMuc2VhcmNoVGVybS5zZXQoJycpO1xuICAgIFxuICAgIC8vIFVwZGF0ZSBmb3JtIGNvbnRyb2xcbiAgICBpZiAodGhpcy5wcm9wcz8uY29udHJvbCkge1xuICAgICAgdGhpcy5wcm9wcy5jb250cm9sLnNldFZhbHVlKHZhbHVlKTtcbiAgICAgIHRoaXMucHJvcHMuY29udHJvbC5tYXJrQXNEaXJ0eSgpO1xuICAgICAgdGhpcy5wcm9wcy5jb250cm9sLm1hcmtBc1RvdWNoZWQoKTtcbiAgICB9XG4gIH1cblxuICBpc1NlbGVjdGVkKG9wdGlvbjogSW5wdXRPcHRpb24pOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZFZhbHVlKCkgPT09IG9wdGlvblt0aGlzLnZhbHVlUHJvcGVydHldO1xuICB9XG5cbiAgdHJhY2tCeUZuKF9pbmRleDogbnVtYmVyLCBvcHRpb246IElucHV0T3B0aW9uKTogYW55IHtcbiAgICByZXR1cm4gb3B0aW9uW3RoaXMudmFsdWVQcm9wZXJ0eV07XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUNsaWNrT3V0c2lkZShldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc09wZW4oKSAmJiBcbiAgICAgICAgIXRoaXMubWFpbklucHV0UmVmPy5uYXRpdmVFbGVtZW50Py5jb250YWlucyhldmVudC50YXJnZXQpICYmXG4gICAgICAgICF0aGlzLmRyb3Bkb3duUmVmPy5uYXRpdmVFbGVtZW50Py5jb250YWlucyhldmVudC50YXJnZXQpKSB7XG4gICAgICB0aGlzLmlzT3Blbi5zZXQoZmFsc2UpO1xuICAgICAgdGhpcy5zZWFyY2hUZXJtLnNldCgnJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRPcHRpb25CeVZhbHVlKHZhbHVlOiBzdHJpbmcpOiBJbnB1dE9wdGlvbiB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMucHJvcHM/Lm9wdGlvbnM/LmZpbmQob3B0aW9uID0+IG9wdGlvblt0aGlzLnZhbHVlUHJvcGVydHldID09PSB2YWx1ZSk7XG4gIH1cblxuICBwcml2YXRlIGFwcGx5RGVmYXVsdFZhbHVlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnByb3BzKSB7XG4gICAgICBhcHBseURlZmF1bHRWYWx1ZVRvQ29udHJvbCh0aGlzLnByb3BzKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHN5bmNTZWxlY3RlZFZhbHVlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnByb3BzPy5jb250cm9sPy52YWx1ZSkge1xuICAgICAgdGhpcy5zZWxlY3RlZFZhbHVlLnNldCh0aGlzLnByb3BzLmNvbnRyb2wudmFsdWUpO1xuICAgIH1cbiAgfVxufVxuIl19