angular-select-dropdown
Version:
A highly customizable and flexible dropdown select component for Angular applications. Ideal for creating dynamic select menus with search, filtering.
184 lines • 34.9 kB
JavaScript
import { ChangeDetectionStrategy, Component, EventEmitter, forwardRef, HostBinding, Input, Output, ViewEncapsulation } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "../directives/click-outside.directive";
export class AngularSelectDropdownComponent {
/**
* List of items to populate the dropdown.
* This setter updates the internal store of items and triggers an update.
* @param items The array of items to be displayed in the dropdown.
*/
set items(items) {
this._items = items;
this.updateItems(items);
}
get items() {
return this._items;
}
constructor(cdRef) {
this.cdRef = cdRef;
/**
* Handler function to extract the label for each item.
* @param item The item from the list.
* @returns The label (name or value) of the item.
*/
this.labelHandler = (item) => item['name'] || item;
/**
* Defines the key used to sort the dropdown items.
* @param sortKeyName The key used to sort the items, default is 'value'.
* @default 'value'
*/
this.sortKeyName = 'value';
/**
* Determines whether the dropdown allows clearing the selection.
* @param isClearable If true, the dropdown will show a clear button.
* @default false
*/
this.isClearable = false;
/**
* Determines whether the dropdown is disabled.
* @param disabled If true, the dropdown is disabled and cannot be interacted with.
* @default false
*/
this.disabled = false;
/**
* Determines whether the dropdown menu should close when the selected item is cleared.
* @param closeMenuOnClear If true, the dropdown will close when the selection is cleared.
* @default true
*/
this.closeMenuOnClear = true;
/**
* Placeholder text displayed when no item is selected.
* @param placeholder The placeholder text.
* @default ''
*/
this.placeholder = '';
/**
* Message displayed when no items match the search query.
* @param notFoundMessage The message to display when no items are found.
* @default 'Nothing found'
*/
this.notFoundMessage = 'Nothing found';
/**
* Event emitted when an item is selected.
* @param selectItem The selected item is emitted as an event.
*/
this.selectItem = new EventEmitter();
this.hostClasses = 'angular-select-dropdown';
this._items = [];
this.data = '';
this.isDropdownOpen = false;
this.itemsStore = [];
this.selectedItem = {
value: null,
name: ''
};
this.onTouched = () => { };
this.onChange = () => { };
}
ngOnDestroy() {
this.isDropdownOpen = false;
}
registerOnChange(onChange) {
this.onChange = onChange;
}
registerOnTouched(onTouched) {
this.onTouched = onTouched;
}
writeValue(obj) {
this.data = obj;
this.updateItems(this.items);
}
updateData(data) {
this.onChange(data);
this.onTouched();
}
updateItems(items) {
if (items && items.length) {
this.itemsStore = items.map((item) => ({
value: item[this.sortKeyName] ?? this.labelHandler(item),
name: this.labelHandler(item),
disabled: !!item?.['disabled']
}));
}
else {
this.itemsStore = [];
}
this.updateSelectedItem();
this.cdRef.markForCheck();
}
updateSelectedItem(item) {
const selectedItem = this.itemsStore.find(item => item?.value == this.data);
this.selectedItem = {
value: item?.value ?? (selectedItem?.value ?? null),
name: item?.name ?? (selectedItem?.name ?? '')
};
}
trackByValue(index, item) {
return item.value;
}
closeDropdownMenu() {
this.isDropdownOpen = false;
}
onClickRemove(event) {
event.stopImmediatePropagation();
if (this.selectedItem.value && this.selectedItem.name) {
this.updateSelectedItem();
this.updateData(null);
this.selectItem.emit();
if (this.closeMenuOnClear) {
this.closeDropdownMenu();
}
}
}
onSelectItem(item) {
this.updateData(item.value);
this.updateSelectedItem(item);
this.closeDropdownMenu();
this.selectItem.emit(item.value);
}
onSelectClick() {
this.isDropdownOpen = !this.isDropdownOpen;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AngularSelectDropdownComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AngularSelectDropdownComponent, selector: "angular-select-dropdown", inputs: { labelHandler: "labelHandler", sortKeyName: "sortKeyName", items: "items", isClearable: "isClearable", disabled: "disabled", closeMenuOnClear: "closeMenuOnClear", placeholder: "placeholder", notFoundMessage: "notFoundMessage" }, outputs: { selectItem: "selectItem" }, host: { properties: { "class": "this.hostClasses" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AngularSelectDropdownComponent),
multi: true
}
], ngImport: i0, template: "<div\n class=\"angular-select-dropdown-wrapper\"\n [excludeElements]=\"['.angular-select-dropdown-menu']\"\n [class.angular-select-dropdown-wrapper_disabled]=\"disabled\"\n (clickOutside)=\"closeDropdownMenu()\"\n (click)=\"onSelectClick()\"\n>\n <div\n class=\"angular-select-dropdown__text\"\n [class.angular-select-dropdown__text_placeholder]=\"!selectedItem.name && placeholder\"\n [title]=\"selectedItem.name\"\n >\n {{selectedItem.name || placeholder}}\n </div>\n\n <div class=\"angular-select-dropdown-actions\">\n <div\n *ngIf=\"isClearable\"\n class=\"angular-select-dropdown-actions__close\"\n (click)=\"onClickRemove($event)\"\n ></div>\n <div\n class=\"angular-select-dropdown-actions__arrow\"\n [class.angular-select-dropdown-actions__arrow_rotate]=\"isDropdownOpen\"\n ></div>\n </div>\n</div>\n\n<div\n *ngIf=\"isDropdownOpen\"\n class=\"angular-select-dropdown-menu\"\n>\n <div class=\"angular-select-dropdown-menu__wrapper\">\n <div\n *ngIf=\"itemsStore.length; else itemsListEmpty\"\n class=\"angular-select-dropdown-menu__items\"\n >\n <div\n *ngFor=\"let item of itemsStore; let i = index; trackBy: trackByValue\"\n class=\"angular-select-dropdown-menu__item\"\n [class.angular-select-dropdown-menu__item_active]=\"item.value === selectedItem.value\"\n [title]=\"item.name\"\n (click)=\"onSelectItem(item)\"\n >\n {{item.name}}\n </div>\n </div>\n\n <ng-template #itemsListEmpty>\n <div\n class=\"angular-select-dropdown-menu__not-found\"\n >\n {{notFoundMessage}}\n </div>\n </ng-template>\n </div>\n</div>\n", styles: [":host,.angular-select-dropdown{display:block;position:relative;width:100%}.angular-select-dropdown-wrapper{display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:10px 10px 10px 15px;border:1px solid rgba(0,0,0,.1019607843);border-radius:.625rem}.angular-select-dropdown-wrapper:hover .angular-select-dropdown-actions__arrow{background-image:url(\"data:image/svg+xml,%3Csvg viewBox%3D%220 0 24 24%22 fill%3D%22none%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cg%3E %3Cpath d%3D%22M7 10L12 15%22 stroke%3D%22%23333%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3Cpath d%3D%22M12 15L17 10%22 stroke%3D%22%23333%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3C%2Fg%3E%3C%2Fsvg%3E\")}.angular-select-dropdown-wrapper_disabled{pointer-events:none;opacity:.5}.angular-select-dropdown__text{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;color:#1b1f3b;font-family:inherit;width:100%}.angular-select-dropdown__text_placeholder{color:#1b1f3ba6}.angular-select-dropdown-actions{display:flex;align-items:center}.angular-select-dropdown-actions__close,.angular-select-dropdown-actions__arrow{width:20px;height:20px;background-repeat:no-repeat}.angular-select-dropdown-actions__close{background-image:url(\"data:image/svg+xml,%3Csvg viewBox%3D%220 0 24 24%22 fill%3D%22none%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cg%3E %3Cpath d%3D%22M8 8L16 16%22 stroke%3D%22%23808080%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3Cpath d%3D%22M16 8L8 16%22 stroke%3D%22%23808080%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3C%2Fg%3E%3C%2Fsvg%3E\")}.angular-select-dropdown-actions__close:hover{background-image:url(\"data:image/svg+xml,%3Csvg viewBox%3D%220 0 24 24%22 fill%3D%22none%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cg%3E %3Cpath d%3D%22M8 8L16 16%22 stroke%3D%22%23333%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3Cpath d%3D%22M16 8L8 16%22 stroke%3D%22%23333%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3C%2Fg%3E%3C%2Fsvg%3E\")}.angular-select-dropdown-actions__arrow{transition:.4s;background-image:url(\"data:image/svg+xml,%3Csvg viewBox%3D%220 0 24 24%22 fill%3D%22none%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cg%3E %3Cpath d%3D%22M7 10L12 15%22 stroke%3D%22%23808080%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3Cpath d%3D%22M12 15L17 10%22 stroke%3D%22%23808080%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3C%2Fg%3E%3C%2Fsvg%3E\")}.angular-select-dropdown-actions__arrow_rotate{transform:rotate(180deg)}.angular-select-dropdown-menu{position:absolute;width:100%;left:0;top:45px;border:1px solid rgba(0,0,0,.1019607843);border-radius:.625rem}.angular-select-dropdown-menu__wrapper{padding:4px}.angular-select-dropdown-menu__items{padding:1px;max-height:200px;overflow-y:auto;overflow-x:hidden;box-sizing:border-box}.angular-select-dropdown-menu__items::-webkit-scrollbar{width:4px}.angular-select-dropdown-menu__items::-webkit-scrollbar-thumb{background:#888;border-radius:.625rem;cursor:pointer}.angular-select-dropdown-menu__items::-webkit-scrollbar-thumb:hover{background:#555}.angular-select-dropdown-menu__item{padding:10px;cursor:pointer;border-radius:.625rem;margin-bottom:2px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;font-family:inherit;color:#1b1f3b}.angular-select-dropdown-menu__item_active,.angular-select-dropdown-menu__item:hover{background-color:#0000000a}.angular-select-dropdown-menu__item:last-child{margin-bottom:0}.angular-select-dropdown-menu__not-found{padding:10px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;font-family:inherit;color:#1b1f3b66}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.ClickOutsideDirective, selector: "[clickOutside]", inputs: ["excludeElements"], outputs: ["clickOutside"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AngularSelectDropdownComponent, decorators: [{
type: Component,
args: [{ selector: 'angular-select-dropdown', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AngularSelectDropdownComponent),
multi: true
}
], template: "<div\n class=\"angular-select-dropdown-wrapper\"\n [excludeElements]=\"['.angular-select-dropdown-menu']\"\n [class.angular-select-dropdown-wrapper_disabled]=\"disabled\"\n (clickOutside)=\"closeDropdownMenu()\"\n (click)=\"onSelectClick()\"\n>\n <div\n class=\"angular-select-dropdown__text\"\n [class.angular-select-dropdown__text_placeholder]=\"!selectedItem.name && placeholder\"\n [title]=\"selectedItem.name\"\n >\n {{selectedItem.name || placeholder}}\n </div>\n\n <div class=\"angular-select-dropdown-actions\">\n <div\n *ngIf=\"isClearable\"\n class=\"angular-select-dropdown-actions__close\"\n (click)=\"onClickRemove($event)\"\n ></div>\n <div\n class=\"angular-select-dropdown-actions__arrow\"\n [class.angular-select-dropdown-actions__arrow_rotate]=\"isDropdownOpen\"\n ></div>\n </div>\n</div>\n\n<div\n *ngIf=\"isDropdownOpen\"\n class=\"angular-select-dropdown-menu\"\n>\n <div class=\"angular-select-dropdown-menu__wrapper\">\n <div\n *ngIf=\"itemsStore.length; else itemsListEmpty\"\n class=\"angular-select-dropdown-menu__items\"\n >\n <div\n *ngFor=\"let item of itemsStore; let i = index; trackBy: trackByValue\"\n class=\"angular-select-dropdown-menu__item\"\n [class.angular-select-dropdown-menu__item_active]=\"item.value === selectedItem.value\"\n [title]=\"item.name\"\n (click)=\"onSelectItem(item)\"\n >\n {{item.name}}\n </div>\n </div>\n\n <ng-template #itemsListEmpty>\n <div\n class=\"angular-select-dropdown-menu__not-found\"\n >\n {{notFoundMessage}}\n </div>\n </ng-template>\n </div>\n</div>\n", styles: [":host,.angular-select-dropdown{display:block;position:relative;width:100%}.angular-select-dropdown-wrapper{display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:10px 10px 10px 15px;border:1px solid rgba(0,0,0,.1019607843);border-radius:.625rem}.angular-select-dropdown-wrapper:hover .angular-select-dropdown-actions__arrow{background-image:url(\"data:image/svg+xml,%3Csvg viewBox%3D%220 0 24 24%22 fill%3D%22none%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cg%3E %3Cpath d%3D%22M7 10L12 15%22 stroke%3D%22%23333%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3Cpath d%3D%22M12 15L17 10%22 stroke%3D%22%23333%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3C%2Fg%3E%3C%2Fsvg%3E\")}.angular-select-dropdown-wrapper_disabled{pointer-events:none;opacity:.5}.angular-select-dropdown__text{text-overflow:ellipsis;white-space:nowrap;overflow:hidden;color:#1b1f3b;font-family:inherit;width:100%}.angular-select-dropdown__text_placeholder{color:#1b1f3ba6}.angular-select-dropdown-actions{display:flex;align-items:center}.angular-select-dropdown-actions__close,.angular-select-dropdown-actions__arrow{width:20px;height:20px;background-repeat:no-repeat}.angular-select-dropdown-actions__close{background-image:url(\"data:image/svg+xml,%3Csvg viewBox%3D%220 0 24 24%22 fill%3D%22none%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cg%3E %3Cpath d%3D%22M8 8L16 16%22 stroke%3D%22%23808080%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3Cpath d%3D%22M16 8L8 16%22 stroke%3D%22%23808080%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3C%2Fg%3E%3C%2Fsvg%3E\")}.angular-select-dropdown-actions__close:hover{background-image:url(\"data:image/svg+xml,%3Csvg viewBox%3D%220 0 24 24%22 fill%3D%22none%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cg%3E %3Cpath d%3D%22M8 8L16 16%22 stroke%3D%22%23333%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3Cpath d%3D%22M16 8L8 16%22 stroke%3D%22%23333%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3C%2Fg%3E%3C%2Fsvg%3E\")}.angular-select-dropdown-actions__arrow{transition:.4s;background-image:url(\"data:image/svg+xml,%3Csvg viewBox%3D%220 0 24 24%22 fill%3D%22none%22 xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E %3Cg%3E %3Cpath d%3D%22M7 10L12 15%22 stroke%3D%22%23808080%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3Cpath d%3D%22M12 15L17 10%22 stroke%3D%22%23808080%22 stroke-width%3D%222%22 stroke-linecap%3D%22round%22 stroke-linejoin%3D%22round%22 %3E%3C%2Fpath%3E %3C%2Fg%3E%3C%2Fsvg%3E\")}.angular-select-dropdown-actions__arrow_rotate{transform:rotate(180deg)}.angular-select-dropdown-menu{position:absolute;width:100%;left:0;top:45px;border:1px solid rgba(0,0,0,.1019607843);border-radius:.625rem}.angular-select-dropdown-menu__wrapper{padding:4px}.angular-select-dropdown-menu__items{padding:1px;max-height:200px;overflow-y:auto;overflow-x:hidden;box-sizing:border-box}.angular-select-dropdown-menu__items::-webkit-scrollbar{width:4px}.angular-select-dropdown-menu__items::-webkit-scrollbar-thumb{background:#888;border-radius:.625rem;cursor:pointer}.angular-select-dropdown-menu__items::-webkit-scrollbar-thumb:hover{background:#555}.angular-select-dropdown-menu__item{padding:10px;cursor:pointer;border-radius:.625rem;margin-bottom:2px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;font-family:inherit;color:#1b1f3b}.angular-select-dropdown-menu__item_active,.angular-select-dropdown-menu__item:hover{background-color:#0000000a}.angular-select-dropdown-menu__item:last-child{margin-bottom:0}.angular-select-dropdown-menu__not-found{padding:10px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;font-family:inherit;color:#1b1f3b66}\n"] }]
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { labelHandler: [{
type: Input
}], sortKeyName: [{
type: Input
}], items: [{
type: Input
}], isClearable: [{
type: Input
}], disabled: [{
type: Input
}], closeMenuOnClear: [{
type: Input
}], placeholder: [{
type: Input
}], notFoundMessage: [{
type: Input
}], selectItem: [{
type: Output
}], hostClasses: [{
type: HostBinding,
args: ['class']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5ndWxhci1zZWxlY3QtZHJvcGRvd24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci1zZWxlY3QtZHJvcGRvd24vc3JjL2xpYi9jb21wb25lbnRzL2FuZ3VsYXItc2VsZWN0LWRyb3Bkb3duLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItc2VsZWN0LWRyb3Bkb3duL3NyYy9saWIvY29tcG9uZW50cy9hbmd1bGFyLXNlbGVjdC1kcm9wZG93bi5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osVUFBVSxFQUNWLFdBQVcsRUFDWCxLQUFLLEVBRUwsTUFBTSxFQUNOLGlCQUFpQixFQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXdCLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7QUF1QnpFLE1BQU0sT0FBTyw4QkFBOEI7SUFlekM7Ozs7T0FJRztJQUNILElBQWEsS0FBSyxDQUFDLEtBQVU7UUFDM0IsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDcEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBK0NELElBQUksS0FBSztRQUNQLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBVUQsWUFDVSxLQUF3QjtRQUF4QixVQUFLLEdBQUwsS0FBSyxDQUFtQjtRQWxGbEM7Ozs7V0FJRztRQUNNLGlCQUFZLEdBQXFCLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBRSxJQUE4QixDQUFDLE1BQU0sQ0FBQyxJQUFJLElBQUksQ0FBQztRQUVwRzs7OztXQUlHO1FBQ00sZ0JBQVcsR0FBVyxPQUFPLENBQUM7UUFZdkM7Ozs7V0FJRztRQUNNLGdCQUFXLEdB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QUdsQix1QkFBdUIsQ0FBQyxNQUFNLGlCQUNoQyxpQkFBaUIsQ0FBQyxJQUFJLGFBQzFCO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLCtCQUErQixDQUFDOzRCQUM3RCxLQUFLLEVBQUUsSUFBSTt5QkFDWjtxQkFDRjt3R0FRUSxZQUFZO3NCQUFwQixLQUFLO2dCQU9HLFdBQVc7c0JBQW5CLEtBQUs7Z0JBT08sS0FBSztzQkFBakIsS0FBSztnQkFVRyxXQUFXO3NCQUFuQixLQUFLO2dCQU9HLFFBQVE7c0JBQWhCLEtBQUs7Z0JBT0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQU9HLFdBQVc7c0JBQW5CLEtBQUs7Z0JBT0csZUFBZTtzQkFBdkIsS0FBSztnQkFNSSxVQUFVO3NCQUFuQixNQUFNO2dCQUVlLFdBQVc7c0JBQWhDLFdBQVc7dUJBQUMsT0FBTyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIGZvcndhcmRSZWYsXG4gIEhvc3RCaW5kaW5nLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPdXRwdXQsXG4gIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBBbmd1bGFyU2VsZWN0RHJvcGRvd24gfSBmcm9tICcuLi9tb2RlbHMnO1xuXG5pbnRlcmZhY2UgU2VsZWN0ZWRJdGVtIHtcbiAgdmFsdWU6IGFueTtcbiAgbmFtZTogc3RyaW5nO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhbmd1bGFyLXNlbGVjdC1kcm9wZG93bicsXG4gIHRlbXBsYXRlVXJsOiAnYW5ndWxhci1zZWxlY3QtZHJvcGRvd24uY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsgJ2FuZ3VsYXItc2VsZWN0LWRyb3Bkb3duLmNvbXBvbmVudC5zY3NzJyBdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBBbmd1bGFyU2VsZWN0RHJvcGRvd25Db21wb25lbnQpLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9XG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgQW5ndWxhclNlbGVjdERyb3Bkb3duQ29tcG9uZW50PFQ+IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE9uRGVzdHJveSB7XG4gIC8qKlxuICAgKiBIYW5kbGVyIGZ1bmN0aW9uIHRvIGV4dHJhY3QgdGhlIGxhYmVsIGZvciBlYWNoIGl0ZW0uXG4gICAqIEBwYXJhbSBpdGVtIFRoZSBpdGVtIGZyb20gdGhlIGxpc3QuXG4gICAqIEByZXR1cm5zIFRoZSBsYWJlbCAobmFtZSBvciB2YWx1ZSkgb2YgdGhlIGl0ZW0uXG4gICAqL1xuICBASW5wdXQoKSBsYWJlbEhhbmRsZXI6IChpdGVtOiBUKSA9PiBhbnkgPSAoaXRlbSkgPT4gKGl0ZW0gYXMgQW5ndWxhclNlbGVjdERyb3Bkb3duKVsnbmFtZSddIHx8IGl0ZW07XG5cbiAgLyoqXG4gICAqIERlZmluZXMgdGhlIGtleSB1c2VkIHRvIHNvcnQgdGhlIGRyb3Bkb3duIGl0ZW1zLlxuICAgKiBAcGFyYW0gc29ydEtleU5hbWUgVGhlIGtleSB1c2VkIHRvIHNvcnQgdGhlIGl0ZW1zLCBkZWZhdWx0IGlzICd2YWx1ZScuXG4gICAqIEBkZWZhdWx0ICd2YWx1ZSdcbiAgICovXG4gIEBJbnB1dCgpIHNvcnRLZXlOYW1lOiBzdHJpbmcgPSAndmFsdWUnO1xuXG4gIC8qKlxuICAgKiBMaXN0IG9mIGl0ZW1zIHRvIHBvcHVsYXRlIHRoZSBkcm9wZG93bi5cbiAgICogVGhpcyBzZXR0ZXIgdXBkYXRlcyB0aGUgaW50ZXJuYWwgc3RvcmUgb2YgaXRlbXMgYW5kIHRyaWdnZXJzIGFuIHVwZGF0ZS5cbiAgICogQHBhcmFtIGl0ZW1zIFRoZSBhcnJheSBvZiBpdGVtcyB0byBiZSBkaXNwbGF5ZWQgaW4gdGhlIGRyb3Bkb3duLlxuICAgKi9cbiAgQElucHV0KCkgc2V0IGl0ZW1zKGl0ZW1zOiBUW10pIHtcbiAgICB0aGlzLl9pdGVtcyA9IGl0ZW1zO1xuICAgIHRoaXMudXBkYXRlSXRlbXMoaXRlbXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgd2hldGhlciB0aGUgZHJvcGRvd24gYWxsb3dzIGNsZWFyaW5nIHRoZSBzZWxlY3Rpb24uXG4gICAqIEBwYXJhbSBpc0NsZWFyYWJsZSBJZiB0cnVlLCB0aGUgZHJvcGRvd24gd2lsbCBzaG93IGEgY2xlYXIgYnV0dG9uLlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgQElucHV0KCkgaXNDbGVhcmFibGU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBkcm9wZG93biBpcyBkaXNhYmxlZC5cbiAgICogQHBhcmFtIGRpc2FibGVkIElmIHRydWUsIHRoZSBkcm9wZG93biBpcyBkaXNhYmxlZCBhbmQgY2Fubm90IGJlIGludGVyYWN0ZWQgd2l0aC5cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIEBJbnB1dCgpIGRpc2FibGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgd2hldGhlciB0aGUgZHJvcGRvd24gbWVudSBzaG91bGQgY2xvc2Ugd2hlbiB0aGUgc2VsZWN0ZWQgaXRlbSBpcyBjbGVhcmVkLlxuICAgKiBAcGFyYW0gY2xvc2VNZW51T25DbGVhciBJZiB0cnVlLCB0aGUgZHJvcGRvd24gd2lsbCBjbG9zZSB3aGVuIHRoZSBzZWxlY3Rpb24gaXMgY2xlYXJlZC5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgQElucHV0KCkgY2xvc2VNZW51T25DbGVhcjogYm9vbGVhbiA9IHRydWU7XG5cbiAgLyoqXG4gICAqIFBsYWNlaG9sZGVyIHRleHQgZGlzcGxheWVkIHdoZW4gbm8gaXRlbSBpcyBzZWxlY3RlZC5cbiAgICogQHBhcmFtIHBsYWNlaG9sZGVyIFRoZSBwbGFjZWhvbGRlciB0ZXh0LlxuICAgKiBAZGVmYXVsdCAnJ1xuICAgKi9cbiAgQElucHV0KCkgcGxhY2Vob2xkZXI6IHN0cmluZyA9ICcnO1xuXG4gIC8qKlxuICAgKiBNZXNzYWdlIGRpc3BsYXllZCB3aGVuIG5vIGl0ZW1zIG1hdGNoIHRoZSBzZWFyY2ggcXVlcnkuXG4gICAqIEBwYXJhbSBub3RGb3VuZE1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gZGlzcGxheSB3aGVuIG5vIGl0ZW1zIGFyZSBmb3VuZC5cbiAgICogQGRlZmF1bHQgJ05vdGhpbmcgZm91bmQnXG4gICAqL1xuICBASW5wdXQoKSBub3RGb3VuZE1lc3NhZ2U6IHN0cmluZyA9ICdOb3RoaW5nIGZvdW5kJztcblxuICAvKipcbiAgICogRXZlbnQgZW1pdHRlZCB3aGVuIGFuIGl0ZW0gaXMgc2VsZWN0ZWQuXG4gICAqIEBwYXJhbSBzZWxlY3RJdGVtIFRoZSBzZWxlY3RlZCBpdGVtIGlzIGVtaXR0ZWQgYXMgYW4gZXZlbnQuXG4gICAqL1xuICBAT3V0cHV0KCkgc2VsZWN0SXRlbTogRXZlbnRFbWl0dGVyPFQ+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBIb3N0QmluZGluZygnY2xhc3MnKSBob3N0Q2xhc3NlcyA9ICdhbmd1bGFyLXNlbGVjdC1kcm9wZG93bic7XG5cbiAgcHJpdmF0ZSBfaXRlbXM6IFRbXSA9IFtdO1xuXG4gIGdldCBpdGVtcygpOiBUW10ge1xuICAgIHJldHVybiB0aGlzLl9pdGVtcztcbiAgfVxuXG4gIGRhdGE6IChudW1iZXIgfCBzdHJpbmcpIHwgKG51bWJlciB8IHN0cmluZylbXSA9ICcnO1xuICBpc0Ryb3Bkb3duT3BlbjogYm9vbGVhbiA9IGZhbHNlO1xuICBpdGVtc1N0b3JlOiBBbmd1bGFyU2VsZWN0RHJvcGRvd25bXSA9IFtdO1xuICBzZWxlY3RlZEl0ZW06IFNlbGVjdGVkSXRlbSA9IHtcbiAgICB2YWx1ZTogbnVsbCxcbiAgICBuYW1lOiAnJ1xuICB9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY2RSZWY6IENoYW5nZURldGVjdG9yUmVmXG4gICkge31cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLmlzRHJvcGRvd25PcGVuID0gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIG9uVG91Y2hlZCA9ICgpID0+IHt9O1xuXG4gIHByaXZhdGUgb25DaGFuZ2U6ICh2YWx1ZTogbnVtYmVyIHwgc3RyaW5nIHwgbnVsbCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuXG4gIHJlZ2lzdGVyT25DaGFuZ2Uob25DaGFuZ2U6ICh2YWx1ZTogbnVtYmVyIHwgc3RyaW5nIHwgbnVsbCkgPT4gdm9pZCkge1xuICAgIHRoaXMub25DaGFuZ2UgPSBvbkNoYW5nZTtcbiAgfVxuXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKG9uVG91Y2hlZDogKCkgPT4gdm9pZCkge1xuICAgIHRoaXMub25Ub3VjaGVkID0gb25Ub3VjaGVkO1xuICB9XG5cbiAgd3JpdGVWYWx1ZShvYmo6IG51bWJlciB8IHN0cmluZykge1xuICAgIHRoaXMuZGF0YSA9IG9iajtcbiAgICB0aGlzLnVwZGF0ZUl0ZW1zKHRoaXMuaXRlbXMpO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVEYXRhKGRhdGE6IG51bWJlciB8IHN0cmluZyB8IG51bGwpIHtcbiAgICB0aGlzLm9uQ2hhbmdlKGRhdGEpO1xuICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZUl0ZW1zKGl0ZW1zOiBUW10pIHtcbiAgICBpZiAoaXRlbXMgJiYgaXRlbXMubGVuZ3RoKSB7XG4gICAgICB0aGlzLml0ZW1zU3RvcmUgPSBpdGVtcy5tYXAoKGl0ZW06IGFueSkgPT4gKHtcbiAgICAgICAgdmFsdWU6IGl0ZW1bdGhpcy5zb3J0S2V5TmFtZSBhcyBrZXlvZiBUXSA/PyB0aGlzLmxhYmVsSGFuZGxlcihpdGVtKSxcbiAgICAgICAgbmFtZTogdGhpcy5sYWJlbEhhbmRsZXIoaXRlbSksXG4gICAgICAgIGRpc2FibGVkOiAhIWl0ZW0/LlsnZGlzYWJsZWQnXVxuICAgICAgfSkpIGFzIEFuZ3VsYXJTZWxlY3REcm9wZG93bltdO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLml0ZW1zU3RvcmUgPSBbXTtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZVNlbGVjdGVkSXRlbSgpO1xuICAgIHRoaXMuY2RSZWYubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVNlbGVjdGVkSXRlbShpdGVtPzogQW5ndWxhclNlbGVjdERyb3Bkb3duKSB7XG4gICAgY29uc3Qgc2VsZWN0ZWRJdGVtID0gdGhpcy5pdGVtc1N0b3JlLmZpbmQoaXRlbSA9PiBpdGVtPy52YWx1ZSA9PSB0aGlzLmRhdGEpO1xuXG4gICAgdGhpcy5zZWxlY3RlZEl0ZW0gPSB7XG4gICAgICB2YWx1ZTogaXRlbT8udmFsdWUgPz8gKHNlbGVjdGVkSXRlbT8udmFsdWUgPz8gbnVsbCksXG4gICAgICBuYW1lOiBpdGVtPy5uYW1lID8/IChzZWxlY3RlZEl0ZW0/Lm5hbWUgPz8gJycpXG4gICAgfTtcbiAgfVxuXG4gIHRyYWNrQnlWYWx1ZShpbmRleDogbnVtYmVyLCBpdGVtOiBBbmd1bGFyU2VsZWN0RHJvcGRvd24pIHtcbiAgICByZXR1cm4gaXRlbS52YWx1ZTtcbiAgfVxuXG4gIGNsb3NlRHJvcGRvd25NZW51KCkge1xuICAgIHRoaXMuaXNEcm9wZG93bk9wZW4gPSBmYWxzZTtcbiAgfVxuXG4gIG9uQ2xpY2tSZW1vdmUoZXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICBldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcblxuICAgIGlmICh0aGlzLnNlbGVjdGVkSXRlbS52YWx1ZSAmJiB0aGlzLnNlbGVjdGVkSXRlbS5uYW1lKSB7XG4gICAgICB0aGlzLnVwZGF0ZVNlbGVjdGVkSXRlbSgpO1xuICAgICAgdGhpcy51cGRhdGVEYXRhKG51bGwpO1xuICAgICAgdGhpcy5zZWxlY3RJdGVtLmVtaXQoKTtcblxuICAgICAgaWYgKHRoaXMuY2xvc2VNZW51T25DbGVhcikge1xuICAgICAgICB0aGlzLmNsb3NlRHJvcGRvd25NZW51KCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgb25TZWxlY3RJdGVtKGl0ZW06IEFuZ3VsYXJTZWxlY3REcm9wZG93bikge1xuICAgIHRoaXMudXBkYXRlRGF0YShpdGVtLnZhbHVlKTtcbiAgICB0aGlzLnVwZGF0ZVNlbGVjdGVkSXRlbShpdGVtKTtcbiAgICB0aGlzLmNsb3NlRHJvcGRvd25NZW51KCk7XG5cbiAgICB0aGlzLnNlbGVjdEl0ZW0uZW1pdChpdGVtLnZhbHVlKTtcbiAgfVxuXG4gIG9uU2VsZWN0Q2xpY2soKSB7XG4gICAgdGhpcy5pc0Ryb3Bkb3duT3BlbiA9ICF0aGlzLmlzRHJvcGRvd25PcGVuO1xuICB9XG59XG4iLCI8ZGl2XG4gIGNsYXNzPVwiYW5ndWxhci1zZWxlY3QtZHJvcGRvd24td3JhcHBlclwiXG4gIFtleGNsdWRlRWxlbWVudHNdPVwiWycuYW5ndWxhci1zZWxlY3QtZHJvcGRvd24tbWVudSddXCJcbiAgW2NsYXNzLmFuZ3VsYXItc2VsZWN0LWRyb3Bkb3duLXdyYXBwZXJfZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAoY2xpY2tPdXRzaWRlKT1cImNsb3NlRHJvcGRvd25NZW51KClcIlxuICAoY2xpY2spPVwib25TZWxlY3RDbGljaygpXCJcbj5cbiAgPGRpdlxuICAgIGNsYXNzPVwiYW5ndWxhci1zZWxlY3QtZHJvcGRvd25fX3RleHRcIlxuICAgIFtjbGFzcy5hbmd1bGFyLXNlbGVjdC1kcm9wZG93bl9fdGV4dF9wbGFjZWhvbGRlcl09XCIhc2VsZWN0ZWRJdGVtLm5hbWUgJiYgcGxhY2Vob2xkZXJcIlxuICAgIFt0aXRsZV09XCJzZWxlY3RlZEl0ZW0ubmFtZVwiXG4gID5cbiAgICB7e3NlbGVjdGVkSXRlbS5uYW1lIHx8IHBsYWNlaG9sZGVyfX1cbiAgPC9kaXY+XG5cbiAgPGRpdiBjbGFzcz1cImFuZ3VsYXItc2VsZWN0LWRyb3Bkb3duLWFjdGlvbnNcIj5cbiAgICA8ZGl2XG4gICAgICAqbmdJZj1cImlzQ2xlYXJhYmxlXCJcbiAgICAgIGNsYXNzPVwiYW5ndWxhci1zZWxlY3QtZHJvcGRvd24tYWN0aW9uc19fY2xvc2VcIlxuICAgICAgKGNsaWNrKT1cIm9uQ2xpY2tSZW1vdmUoJGV2ZW50KVwiXG4gICAgPjwvZGl2PlxuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwiYW5ndWxhci1zZWxlY3QtZHJvcGRvd24tYWN0aW9uc19fYXJyb3dcIlxuICAgICAgW2NsYXNzLmFuZ3VsYXItc2VsZWN0LWRyb3Bkb3duLWFjdGlvbnNfX2Fycm93X3JvdGF0ZV09XCJpc0Ryb3Bkb3duT3BlblwiXG4gICAgPjwvZGl2PlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48ZGl2XG4gICpuZ0lmPVwiaXNEcm9wZG93bk9wZW5cIlxuICBjbGFzcz1cImFuZ3VsYXItc2VsZWN0LWRyb3Bkb3duLW1lbnVcIlxuPlxuICA8ZGl2IGNsYXNzPVwiYW5ndWxhci1zZWxlY3QtZHJvcGRvd24tbWVudV9fd3JhcHBlclwiPlxuICAgIDxkaXZcbiAgICAgICpuZ0lmPVwiaXRlbXNTdG9yZS5sZW5ndGg7IGVsc2UgaXRlbXNMaXN0RW1wdHlcIlxuICAgICAgY2xhc3M9XCJhbmd1bGFyLXNlbGVjdC1kcm9wZG93bi1tZW51X19pdGVtc1wiXG4gICAgPlxuICAgICAgPGRpdlxuICAgICAgICAqbmdGb3I9XCJsZXQgaXRlbSBvZiBpdGVtc1N0b3JlOyBsZXQgaSA9IGluZGV4OyB0cmFja0J5OiB0cmFja0J5VmFsdWVcIlxuICAgICAgICBjbGFzcz1cImFuZ3VsYXItc2VsZWN0LWRyb3Bkb3duLW1lbnVfX2l0ZW1cIlxuICAgICAgICBbY2xhc3MuYW5ndWxhci1zZWxlY3QtZHJvcGRvd24tbWVudV9faXRlbV9hY3RpdmVdPVwiaXRlbS52YWx1ZSA9PT0gc2VsZWN0ZWRJdGVtLnZhbHVlXCJcbiAgICAgICAgW3RpdGxlXT1cIml0ZW0ubmFtZVwiXG4gICAgICAgIChjbGljayk9XCJvblNlbGVjdEl0ZW0oaXRlbSlcIlxuICAgICAgPlxuICAgICAgICB7e2l0ZW0ubmFtZX19XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuICAgIDxuZy10ZW1wbGF0ZSAjaXRlbXNMaXN0RW1wdHk+XG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwiYW5ndWxhci1zZWxlY3QtZHJvcGRvd24tbWVudV9fbm90LWZvdW5kXCJcbiAgICAgID5cbiAgICAgICAge3tub3RGb3VuZE1lc3NhZ2V9fVxuICAgICAgPC9kaXY+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==