design-angular-kit
Version:
Un toolkit Angular conforme alle linee guida di design per i servizi web della PA
112 lines • 24.2 kB
JavaScript
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { debounceTime, distinctUntilChanged, map, Observable, of, switchMap } from 'rxjs';
import { AsyncPipe, NgTemplateOutlet } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';
import { ItIconComponent } from '../../utils/icon/icon.component';
import { ItMarkMatchingTextPipe } from '../../../pipes/mark-matching-text.pipe';
import { ItAbstractFormComponent } from '../../../abstracts/abstract-form.component';
import { inputToBoolean } from '../../../utils/coercion';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
export class ItAutocompleteComponent extends ItAbstractFormComponent {
constructor() {
super(...arguments);
/**
* Time span [ms] has passed without another source emission, to delay data filtering.
* Useful when the user is typing multiple letters
* @default 300 [ms]
*/
this.debounceTime = 300;
/**
* The input placeholder
*/
this.placeholder = '';
/**
* The input label even get labelWaria icon
*/
this.labelWaria = undefined;
/**
* Show the label
*/
this.forceShowLabel = true;
/**
* Fired when the Autocomplete Item has been selected
*/
this.autocompleteSelectedEvent = new EventEmitter();
this.showAutocompletion = false;
/** Observable da cui vengono emessi i risultati dell'auto completamento */
this.autocompleteResults$ = new Observable();
}
ngOnInit() {
super.ngOnInit();
this.autocompleteResults$ = this.getAutocompleteResults$();
}
/**
* Create the autocomplete list
*/
getAutocompleteResults$() {
return this.control.valueChanges.pipe(debounceTime(this.debounceTime), // Delay filter data after time span has passed without another source emission, useful when the user is typing multiple letters
distinctUntilChanged(), // Only if searchValue is distinct in comparison to the last value
switchMap(searchedValue => {
if (!this.autocompleteData) {
return of({
searchedValue,
relatedEntries: [],
});
}
const autoCompleteData$ = Array.isArray(this.autocompleteData) ? of(this.autocompleteData) : this.autocompleteData(searchedValue);
return autoCompleteData$.pipe(map(autocompleteData => {
if (!searchedValue || typeof searchedValue === 'number') {
return { searchedValue, relatedEntries: [] };
}
const lowercaseValue = searchedValue.toLowerCase();
const relatedEntries = autocompleteData.filter(item => item.value?.toLowerCase().includes(lowercaseValue));
return { searchedValue, relatedEntries };
}));
}));
}
onEntryClick(entry, event) {
// Se non è stato definito un link associato all'elemento dell'autocomplete, probabilmente il desiderata
// non è effettuare la navigazione al default '#', pertanto in tal caso meglio annullare la navigazione.
if (!entry.link) {
event.preventDefault();
}
this.autocompleteSelectedEvent.next(entry);
this.control.setValue(entry.value);
this.showAutocompletion = false;
}
autocompleteItemTrackByValueFn(index, item) {
return item.value;
}
onKeyDown() {
this.showAutocompletion = true;
}
get isActiveLabel() {
const value = this.control.value;
return this.forceShowLabel && (!!value || !!this.placeholder);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: ItAutocompleteComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.6", type: ItAutocompleteComponent, isStandalone: true, selector: "it-autocomplete", inputs: { autocompleteData: "autocompleteData", big: ["big", "big", inputToBoolean], debounceTime: "debounceTime", placeholder: "placeholder", labelWaria: "labelWaria", forceShowLabel: ["forceShowLabel", "forceShowLabel", inputToBoolean] }, outputs: { autocompleteSelectedEvent: "autocompleteSelectedEvent" }, usesInheritance: true, ngImport: i0, template: "<div class=\"form-group\" [class.autocomplete-wrapper-big]=\"big\">\n @if (label) {\n <label [for]=\"id\" [class.visually-hidden]=\"!isActiveLabel\" [class.active]=\"isActiveLabel\">\n {{ label }}\n </label>\n }\n\n <input\n [id]=\"id\"\n type=\"search\"\n class=\"autocomplete form-control\"\n [placeholder]=\"placeholder\"\n [formControl]=\"control\"\n [class.is-invalid]=\"isInvalid\"\n [class.is-valid]=\"isValid\"\n (blur)=\"markAsTouched()\"\n (keydown)=\"onKeyDown()\" />\n\n <span class=\"autocomplete-icon\" aria-hidden=\"true\">\n <it-icon [labelWaria]=\"labelWaria\" name=\"search\" size=\"sm\"></it-icon>\n </span>\n\n @if (autocompleteResults$ | async; as autocomplete) {\n <ul class=\"autocomplete-list\" [class.autocomplete-list-show]=\"autocomplete.relatedEntries?.length && showAutocompletion\">\n @for (entry of autocomplete.relatedEntries; track autocompleteItemTrackByValueFn($index, entry)) {\n <li>\n <a [href]=\"entry.link\" (click)=\"onEntryClick(entry, $event)\">\n @if (entry.avatarSrcPath) {\n <div class=\"avatar size-sm\">\n <img [src]=\"entry.avatarSrcPath\" [alt]=\"entry.avatarAltText\" />\n </div>\n }\n @if (entry.icon) {\n <it-icon [name]=\"entry.icon\" size=\"sm\"></it-icon>\n }\n <span class=\"autocomplete-list-text\">\n <span [innerHTML]=\"entry.value | itMarkMatchingText: autocomplete.searchedValue\"></span>\n @if (entry.label) {\n <em>{{ entry.label }}</em>\n }\n </span>\n </a>\n </li>\n }\n </ul>\n }\n\n @if (isInvalid) {\n <div class=\"form-feedback just-validate-error-label\" [id]=\"id + '-error'\">\n <div #customError>\n <ng-content select=\"[error]\"></ng-content>\n </div>\n @if (!customError.hasChildNodes()) {\n {{ invalidMessage | async }}\n }\n </div>\n }\n</div>\n", dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: ItIconComponent, selector: "it-icon", inputs: ["name", "size", "color", "padded", "svgClass", "title", "labelWaria"] }, { kind: "pipe", type: ItMarkMatchingTextPipe, name: "itMarkMatchingText" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: ItAutocompleteComponent, decorators: [{
type: Component,
args: [{ standalone: true, selector: 'it-autocomplete', imports: [AsyncPipe, ItIconComponent, ItMarkMatchingTextPipe, NgTemplateOutlet, ReactiveFormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"form-group\" [class.autocomplete-wrapper-big]=\"big\">\n @if (label) {\n <label [for]=\"id\" [class.visually-hidden]=\"!isActiveLabel\" [class.active]=\"isActiveLabel\">\n {{ label }}\n </label>\n }\n\n <input\n [id]=\"id\"\n type=\"search\"\n class=\"autocomplete form-control\"\n [placeholder]=\"placeholder\"\n [formControl]=\"control\"\n [class.is-invalid]=\"isInvalid\"\n [class.is-valid]=\"isValid\"\n (blur)=\"markAsTouched()\"\n (keydown)=\"onKeyDown()\" />\n\n <span class=\"autocomplete-icon\" aria-hidden=\"true\">\n <it-icon [labelWaria]=\"labelWaria\" name=\"search\" size=\"sm\"></it-icon>\n </span>\n\n @if (autocompleteResults$ | async; as autocomplete) {\n <ul class=\"autocomplete-list\" [class.autocomplete-list-show]=\"autocomplete.relatedEntries?.length && showAutocompletion\">\n @for (entry of autocomplete.relatedEntries; track autocompleteItemTrackByValueFn($index, entry)) {\n <li>\n <a [href]=\"entry.link\" (click)=\"onEntryClick(entry, $event)\">\n @if (entry.avatarSrcPath) {\n <div class=\"avatar size-sm\">\n <img [src]=\"entry.avatarSrcPath\" [alt]=\"entry.avatarAltText\" />\n </div>\n }\n @if (entry.icon) {\n <it-icon [name]=\"entry.icon\" size=\"sm\"></it-icon>\n }\n <span class=\"autocomplete-list-text\">\n <span [innerHTML]=\"entry.value | itMarkMatchingText: autocomplete.searchedValue\"></span>\n @if (entry.label) {\n <em>{{ entry.label }}</em>\n }\n </span>\n </a>\n </li>\n }\n </ul>\n }\n\n @if (isInvalid) {\n <div class=\"form-feedback just-validate-error-label\" [id]=\"id + '-error'\">\n <div #customError>\n <ng-content select=\"[error]\"></ng-content>\n </div>\n @if (!customError.hasChildNodes()) {\n {{ invalidMessage | async }}\n }\n </div>\n }\n</div>\n" }]
}], propDecorators: { autocompleteData: [{
type: Input,
args: [{ required: true }]
}], big: [{
type: Input,
args: [{ transform: inputToBoolean }]
}], debounceTime: [{
type: Input
}], placeholder: [{
type: Input
}], labelWaria: [{
type: Input
}], forceShowLabel: [{
type: Input,
args: [{ transform: inputToBoolean }]
}], autocompleteSelectedEvent: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0b2NvbXBsZXRlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Rlc2lnbi1hbmd1bGFyLWtpdC9zcmMvbGliL2NvbXBvbmVudHMvZm9ybS9hdXRvY29tcGxldGUvYXV0b2NvbXBsZXRlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Rlc2lnbi1hbmd1bGFyLWtpdC9zcmMvbGliL2NvbXBvbmVudHMvZm9ybS9hdXRvY29tcGxldGUvYXV0b2NvbXBsZXRlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDeEcsT0FBTyxFQUFFLFlBQVksRUFBRSxvQkFBb0IsRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDMUYsT0FBTyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzlELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNsRSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUNoRixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQztBQUVyRixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7OztBQVN6RCxNQUFNLE9BQU8sdUJBQXdCLFNBQVEsdUJBQWtEO0lBUC9GOztRQW9CRTs7OztXQUlHO1FBQ00saUJBQVksR0FBRyxHQUFHLENBQUM7UUFFNUI7O1dBRUc7UUFDTSxnQkFBVyxHQUFHLEVBQUUsQ0FB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SyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDaEUsQ0FBQzs4R0EvR1UsdUJBQXVCO2tHQUF2Qix1QkFBdUIsdUhBV2QsY0FBYyw0SUFzQmQsY0FBYyx5SENsRHBDLHEvREEwREEsdUNENUNZLFNBQVMsOENBQUUsZUFBZSwrSEFBRSxzQkFBc0IsMERBQW9CLG1CQUFtQjs7MkZBR3hGLHVCQUF1QjtrQkFQbkMsU0FBUztpQ0FDSSxJQUFJLFlBQ04saUJBQWlCLFdBRWxCLENBQUMsU0FBUyxFQUFFLGVBQWUsRUFBRSxzQkFBc0IsRUFBRSxnQkFBZ0IsRUFBRSxtQkFBbUIsQ0FBQyxtQkFDbkYsdUJBQXVCLENBQUMsTUFBTTs4QkFRcEIsZ0JBQWdCO3NCQUExQyxLQUFLO3VCQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRTtnQkFLYSxHQUFHO3NCQUF4QyxLQUFLO3VCQUFDLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRTtnQkFPM0IsWUFBWTtzQkFBcEIsS0FBSztnQkFLRyxXQUFXO3NCQUFuQixLQUFLO2dCQUtHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBS2dDLGNBQWM7c0JBQW5ELEtBQUs7dUJBQUMsRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFO2dCQUsxQix5QkFBeUI7c0JBQWxDLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIElucHV0LCBPbkluaXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgbWFwLCBPYnNlcnZhYmxlLCBvZiwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBBc3luY1BpcGUsIE5nVGVtcGxhdGVPdXRsZXQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEl0SWNvbkNvbXBvbmVudCB9IGZyb20gJy4uLy4uL3V0aWxzL2ljb24vaWNvbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgSXRNYXJrTWF0Y2hpbmdUZXh0UGlwZSB9IGZyb20gJy4uLy4uLy4uL3BpcGVzL21hcmstbWF0Y2hpbmctdGV4dC5waXBlJztcbmltcG9ydCB7IEl0QWJzdHJhY3RGb3JtQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vLi4vYWJzdHJhY3RzL2Fic3RyYWN0LWZvcm0uY29tcG9uZW50JztcbmltcG9ydCB7IEF1dG9jb21wbGV0ZUl0ZW0gfSBmcm9tICcuLi8uLi8uLi9pbnRlcmZhY2VzL2Zvcm0nO1xuaW1wb3J0IHsgaW5wdXRUb0Jvb2xlYW4gfSBmcm9tICcuLi8uLi8uLi91dGlscy9jb2VyY2lvbic7XG5cbkBDb21wb25lbnQoe1xuICBzdGFuZGFsb25lOiB0cnVlLFxuICBzZWxlY3RvcjogJ2l0LWF1dG9jb21wbGV0ZScsXG4gIHRlbXBsYXRlVXJsOiAnLi9hdXRvY29tcGxldGUuY29tcG9uZW50Lmh0bWwnLFxuICBpbXBvcnRzOiBbQXN5bmNQaXBlLCBJdEljb25Db21wb25lbnQsIEl0TWFya01hdGNoaW5nVGV4dFBpcGUsIE5nVGVtcGxhdGVPdXRsZXQsIFJlYWN0aXZlRm9ybXNNb2R1bGVdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgSXRBdXRvY29tcGxldGVDb21wb25lbnQgZXh0ZW5kcyBJdEFic3RyYWN0Rm9ybUNvbXBvbmVudDxzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkPiBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgdGhlIGxpc3Qgb2Ygc2VhcmNoYWJsZSBlbGVtZW50cyBvbiB3aGljaCB0byBiYXNlIHRoZSBpbnB1dCBhdXRvY29tcGxldGUgc3lzdGVtXG4gICAqIElmIHlvdSBuZWVkIHRvIHJldHJpZXZlIGl0ZW1zIHZpYSBBUEksIGNhbiBwYXNzIGEgZnVuY3Rpb24gb2YgT2JzZXJ2YWJsZVxuICAgKiBAZGVmYXVsdCB1bmRlZmluZWRcbiAgICovXG4gIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pIGF1dG9jb21wbGV0ZURhdGEhOiBBcnJheTxBdXRvY29tcGxldGVJdGVtPiB8ICgoc2VhcmNoPzogc3RyaW5nIHwgbnVsbCkgPT4gT2JzZXJ2YWJsZTxBcnJheTxBdXRvY29tcGxldGVJdGVtPj4pO1xuXG4gIC8qKlxuICAgKiBUbyBnZXQgYSBsYXJnZSB2ZXJzaW9uIG9mIEF1dG9jb21wbGV0ZVxuICAgKi9cbiAgQElucHV0KHsgdHJhbnNmb3JtOiBpbnB1dFRvQm9vbGVhbiB9KSBiaWc/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaW1lIHNwYW4gW21zXSBoYXMgcGFzc2VkIHdpdGhvdXQgYW5vdGhlciBzb3VyY2UgZW1pc3Npb24sIHRvIGRlbGF5IGRhdGEgZmlsdGVyaW5nLlxuICAgKiBVc2VmdWwgd2hlbiB0aGUgdXNlciBpcyB0eXBpbmcgbXVsdGlwbGUgbGV0dGVyc1xuICAgKiBAZGVmYXVsdCAzMDAgW21zXVxuICAgKi9cbiAgQElucHV0KCkgZGVib3VuY2VUaW1lID0gMzAwO1xuXG4gIC8qKlxuICAgKiBUaGUgaW5wdXQgcGxhY2Vob2xkZXJcbiAgICovXG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyID0gJyc7XG5cbiAgLyoqXG4gICAqIFRoZSBpbnB1dCBsYWJlbCBldmVuIGdldCBsYWJlbFdhcmlhIGljb25cbiAgICovXG4gIEBJbnB1dCgpIGxhYmVsV2FyaWE6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogU2hvdyB0aGUgbGFiZWxcbiAgICovXG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogaW5wdXRUb0Jvb2xlYW4gfSkgZm9yY2VTaG93TGFiZWw6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBGaXJlZCB3aGVuIHRoZSBBdXRvY29tcGxldGUgSXRlbSBoYXMgYmVlbiBzZWxlY3RlZFxuICAgKi9cbiAgQE91dHB1dCgpIGF1dG9jb21wbGV0ZVNlbGVjdGVkRXZlbnQ6IEV2ZW50RW1pdHRlcjxBdXRvY29tcGxldGVJdGVtPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBwcm90ZWN0ZWQgc2hvd0F1dG9jb21wbGV0aW9uID0gZmFsc2U7XG5cbiAgLyoqIE9ic2VydmFibGUgZGEgY3VpIHZlbmdvbm8gZW1lc3NpIGkgcmlzdWx0YXRpIGRlbGwnYXV0byBjb21wbGV0YW1lbnRvICovXG4gIHByb3RlY3RlZCBhdXRvY29tcGxldGVSZXN1bHRzJDogT2JzZXJ2YWJsZTx7XG4gICAgc2VhcmNoZWRWYWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkIHwgbnVsbDtcbiAgICByZWxhdGVkRW50cmllczogQXJyYXk8QXV0b2NvbXBsZXRlSXRlbT47XG4gIH0+ID0gbmV3IE9ic2VydmFibGUoKTtcblxuICBvdmVycmlkZSBuZ09uSW5pdCgpIHtcbiAgICBzdXBlci5uZ09uSW5pdCgpO1xuICAgIHRoaXMuYXV0b2NvbXBsZXRlUmVzdWx0cyQgPSB0aGlzLmdldEF1dG9jb21wbGV0ZVJlc3VsdHMkKCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIHRoZSBhdXRvY29tcGxldGUgbGlzdFxuICAgKi9cbiAgcHJpdmF0ZSBnZXRBdXRvY29tcGxldGVSZXN1bHRzJCgpOiBPYnNlcnZhYmxlPHtcbiAgICBzZWFyY2hlZFZhbHVlOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkO1xuICAgIHJlbGF0ZWRFbnRyaWVzOiBBcnJheTxBdXRvY29tcGxldGVJdGVtPjtcbiAgfT4ge1xuICAgIHJldHVybiB0aGlzLmNvbnRyb2wudmFsdWVDaGFuZ2VzLnBpcGUoXG4gICAgICBkZWJvdW5jZVRpbWUodGhpcy5kZWJvdW5jZVRpbWUpLCAvLyBEZWxheSBmaWx0ZXIgZGF0YSBhZnRlciB0aW1lIHNwYW4gaGFzIHBhc3NlZCB3aXRob3V0IGFub3RoZXIgc291cmNlIGVtaXNzaW9uLCB1c2VmdWwgd2hlbiB0aGUgdXNlciBpcyB0eXBpbmcgbXVsdGlwbGUgbGV0dGVyc1xuICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSwgLy8gT25seSBpZiBzZWFyY2hWYWx1ZSBpcyBkaXN0aW5jdCBpbiBjb21wYXJpc29uIHRvIHRoZSBsYXN0IHZhbHVlXG4gICAgICBzd2l0Y2hNYXAoc2VhcmNoZWRWYWx1ZSA9PiB7XG4gICAgICAgIGlmICghdGhpcy5hdXRvY29tcGxldGVEYXRhKSB7XG4gICAgICAgICAgcmV0dXJuIG9mKHtcbiAgICAgICAgICAgIHNlYXJjaGVkVmFsdWUsXG4gICAgICAgICAgICByZWxhdGVkRW50cmllczogPEFycmF5PEF1dG9jb21wbGV0ZUl0ZW0+PltdLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYXV0b0NvbXBsZXRlRGF0YSQgPSBBcnJheS5pc0FycmF5KHRoaXMuYXV0b2NvbXBsZXRlRGF0YSkgPyBvZih0aGlzLmF1dG9jb21wbGV0ZURhdGEpIDogdGhpcy5hdXRvY29tcGxldGVEYXRhKHNlYXJjaGVkVmFsdWUpO1xuICAgICAgICByZXR1cm4gYXV0b0NvbXBsZXRlRGF0YSQucGlwZShcbiAgICAgICAgICBtYXAoYXV0b2NvbXBsZXRlRGF0YSA9PiB7XG4gICAgICAgICAgICBpZiAoIXNlYXJjaGVkVmFsdWUgfHwgdHlwZW9mIHNlYXJjaGVkVmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgIHJldHVybiB7IHNlYXJjaGVkVmFsdWUsIHJlbGF0ZWRFbnRyaWVzOiBbXSB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBsb3dlcmNhc2VWYWx1ZSA9IHNlYXJjaGVkVmFsdWUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRFbnRyaWVzID0gYXV0b2NvbXBsZXRlRGF0YS5maWx0ZXIoaXRlbSA9PiBpdGVtLnZhbHVlPy50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKGxvd2VyY2FzZVZhbHVlKSk7XG5cbiAgICAgICAgICAgIHJldHVybiB7IHNlYXJjaGVkVmFsdWUsIHJlbGF0ZWRFbnRyaWVzIH07XG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvbkVudHJ5Q2xpY2soZW50cnk6IEF1dG9jb21wbGV0ZUl0ZW0sIGV2ZW50OiBFdmVudCkge1xuICAgIC8vIFNlIG5vbiDDqCBzdGF0byBkZWZpbml0byB1biBsaW5rIGFzc29jaWF0byBhbGwnZWxlbWVudG8gZGVsbCdhdXRvY29tcGxldGUsIHByb2JhYmlsbWVudGUgaWwgZGVzaWRlcmF0YVxuICAgIC8vIG5vbiDDqCBlZmZldHR1YXJlIGxhIG5hdmlnYXppb25lIGFsIGRlZmF1bHQgJyMnLCBwZXJ0YW50byBpbiB0YWwgY2FzbyBtZWdsaW8gYW5udWxsYXJlIGxhIG5hdmlnYXppb25lLlxuICAgIGlmICghZW50cnkubGluaykge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICB0aGlzLmF1dG9jb21wbGV0ZVNlbGVjdGVkRXZlbnQubmV4dChlbnRyeSk7XG4gICAgdGhpcy5jb250cm9sLnNldFZhbHVlKGVudHJ5LnZhbHVlKTtcbiAgICB0aGlzLnNob3dBdXRvY29tcGxldGlvbiA9IGZhbHNlO1xuICB9XG5cbiAgcHJvdGVjdGVkIGF1dG9jb21wbGV0ZUl0ZW1UcmFja0J5VmFsdWVGbihpbmRleDogbnVtYmVyLCBpdGVtOiBBdXRvY29tcGxldGVJdGVtKSB7XG4gICAgcmV0dXJuIGl0ZW0udmFsdWU7XG4gIH1cblxuICBwcm90ZWN0ZWQgb25LZXlEb3duKCkge1xuICAgIHRoaXMuc2hvd0F1dG9jb21wbGV0aW9uID0gdHJ1ZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQgaXNBY3RpdmVMYWJlbCgpOiBib29sZWFuIHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuY29udHJvbC52YWx1ZTtcbiAgICByZXR1cm4gdGhpcy5mb3JjZVNob3dMYWJlbCAmJiAoISF2YWx1ZSB8fCAhIXRoaXMucGxhY2Vob2xkZXIpO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiIFtjbGFzcy5hdXRvY29tcGxldGUtd3JhcHBlci1iaWddPVwiYmlnXCI+XG4gIEBpZiAobGFiZWwpIHtcbiAgICA8bGFiZWwgW2Zvcl09XCJpZFwiIFtjbGFzcy52aXN1YWxseS1oaWRkZW5dPVwiIWlzQWN0aXZlTGFiZWxcIiBbY2xhc3MuYWN0aXZlXT1cImlzQWN0aXZlTGFiZWxcIj5cbiAgICAgIHt7IGxhYmVsIH19XG4gICAgPC9sYWJlbD5cbiAgfVxuXG4gIDxpbnB1dFxuICAgIFtpZF09XCJpZFwiXG4gICAgdHlwZT1cInNlYXJjaFwiXG4gICAgY2xhc3M9XCJhdXRvY29tcGxldGUgZm9ybS1jb250cm9sXCJcbiAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICAgIFtmb3JtQ29udHJvbF09XCJjb250cm9sXCJcbiAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJpc0ludmFsaWRcIlxuICAgIFtjbGFzcy5pcy12YWxpZF09XCJpc1ZhbGlkXCJcbiAgICAoYmx1cik9XCJtYXJrQXNUb3VjaGVkKClcIlxuICAgIChrZXlkb3duKT1cIm9uS2V5RG93bigpXCIgLz5cblxuICA8c3BhbiBjbGFzcz1cImF1dG9jb21wbGV0ZS1pY29uXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+XG4gICAgPGl0LWljb24gW2xhYmVsV2FyaWFdPVwibGFiZWxXYXJpYVwiIG5hbWU9XCJzZWFyY2hcIiBzaXplPVwic21cIj48L2l0LWljb24+XG4gIDwvc3Bhbj5cblxuICBAaWYgKGF1dG9jb21wbGV0ZVJlc3VsdHMkIHwgYXN5bmM7IGFzIGF1dG9jb21wbGV0ZSkge1xuICAgIDx1bCBjbGFzcz1cImF1dG9jb21wbGV0ZS1saXN0XCIgW2NsYXNzLmF1dG9jb21wbGV0ZS1saXN0LXNob3ddPVwiYXV0b2NvbXBsZXRlLnJlbGF0ZWRFbnRyaWVzPy5sZW5ndGggJiYgc2hvd0F1dG9jb21wbGV0aW9uXCI+XG4gICAgICBAZm9yIChlbnRyeSBvZiBhdXRvY29tcGxldGUucmVsYXRlZEVudHJpZXM7IHRyYWNrIGF1dG9jb21wbGV0ZUl0ZW1UcmFja0J5VmFsdWVGbigkaW5kZXgsIGVudHJ5KSkge1xuICAgICAgICA8bGk+XG4gICAgICAgICAgPGEgW2hyZWZdPVwiZW50cnkubGlua1wiIChjbGljayk9XCJvbkVudHJ5Q2xpY2soZW50cnksICRldmVudClcIj5cbiAgICAgICAgICAgIEBpZiAoZW50cnkuYXZhdGFyU3JjUGF0aCkge1xuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYXZhdGFyIHNpemUtc21cIj5cbiAgICAgICAgICAgICAgICA8aW1nIFtzcmNdPVwiZW50cnkuYXZhdGFyU3JjUGF0aFwiIFthbHRdPVwiZW50cnkuYXZhdGFyQWx0VGV4dFwiIC8+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgQGlmIChlbnRyeS5pY29uKSB7XG4gICAgICAgICAgICAgIDxpdC1pY29uIFtuYW1lXT1cImVudHJ5Lmljb25cIiBzaXplPVwic21cIj48L2l0LWljb24+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImF1dG9jb21wbGV0ZS1saXN0LXRleHRcIj5cbiAgICAgICAgICAgICAgPHNwYW4gW2lubmVySFRNTF09XCJlbnRyeS52YWx1ZSB8IGl0TWFya01hdGNoaW5nVGV4dDogYXV0b2NvbXBsZXRlLnNlYXJjaGVkVmFsdWVcIj48L3NwYW4+XG4gICAgICAgICAgICAgIEBpZiAoZW50cnkubGFiZWwpIHtcbiAgICAgICAgICAgICAgICA8ZW0+e3sgZW50cnkubGFiZWwgfX08L2VtPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPC9hPlxuICAgICAgICA8L2xpPlxuICAgICAgfVxuICAgIDwvdWw+XG4gIH1cblxuICBAaWYgKGlzSW52YWxpZCkge1xuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWZlZWRiYWNrIGp1c3QtdmFsaWRhdGUtZXJyb3ItbGFiZWxcIiBbaWRdPVwiaWQgKyAnLWVycm9yJ1wiPlxuICAgICAgPGRpdiAjY3VzdG9tRXJyb3I+XG4gICAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIltlcnJvcl1cIj48L25nLWNvbnRlbnQ+XG4gICAgICA8L2Rpdj5cbiAgICAgIEBpZiAoIWN1c3RvbUVycm9yLmhhc0NoaWxkTm9kZXMoKSkge1xuICAgICAgICB7eyBpbnZhbGlkTWVzc2FnZSB8IGFzeW5jIH19XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIH1cbjwvZGl2PlxuIl19