UNPKG

carbon-components-angular

Version:
643 lines 66 kB
import { Component, Input, Output, EventEmitter, ViewChild, ViewChildren } from "@angular/core"; import { Observable, isObservable, of } from "rxjs"; import { first } from "rxjs/operators"; import { AbstractDropdownView } from "../abstract-dropdown-view.class"; import { watchFocusJump } from "../dropdowntools"; import * as i0 from "@angular/core"; import * as i1 from "carbon-components-angular/i18n"; import * as i2 from "@angular/common"; import * as i3 from "carbon-components-angular/icon"; /** * ```html * <cds-dropdown-list [items]="listItems"></cds-dropdown-list> * ``` * ```typescript * listItems = [ * { * content: "item one", * selected: false * }, * { * content: "item two", * selected: false, * }, * { * content: "item three", * selected: false * }, * { * content: "item four", * selected: false * } * ]; * ``` */ export class DropdownList { /** * Creates an instance of `DropdownList`. */ constructor(elementRef, i18n, appRef) { this.elementRef = elementRef; this.i18n = i18n; this.appRef = appRef; this.ariaLabel = this.i18n.get().DROPDOWN_LIST.LABEL; /** * Template to bind to items in the `DropdownList` (optional). */ this.listTpl = null; /** * Event to emit selection of a list item within the `DropdownList`. */ this.select = new EventEmitter(); /** * Event to emit scroll event of a list within the `DropdownList`. */ this.scroll = new EventEmitter(); /** * Event to suggest a blur on the view. * Emits _after_ the first/last item has been focused. * ex. * ArrowUp -> focus first item * ArrowUp -> emit event * * When this event fires focus should be placed on some element outside of the list - blurring the list as a result */ this.blurIntent = new EventEmitter(); /** * Defines whether or not the `DropdownList` supports selecting multiple items as opposed to single * item selection. */ this.type = "single"; /** * Defines whether to show title attribute or not */ this.showTitles = true; /** * Defines the rendering size of the `DropdownList` input component. */ this.size = "md"; this.listId = `listbox-${DropdownList.listCount++}`; this.highlightedItem = null; /** * Holds the list of items that will be displayed in the `DropdownList`. * It differs from the the complete set of items when filtering is used (but * it is always a subset of the total items in `DropdownList`). */ this.displayItems = []; /** * Maintains the index for the selected item within the `DropdownList`. */ this.index = -1; /** * Useful representation of the items, should be accessed via `getListItems`. */ this._items = []; } /** * The list items belonging to the `DropdownList`. */ set items(value) { if (isObservable(value)) { if (this._itemsSubscription) { this._itemsSubscription.unsubscribe(); } this._itemsReady = new Observable((observer) => { this._itemsSubscription = value.subscribe(v => { this.updateList(v); observer.next(true); observer.complete(); }); }); this.onItemsReady(null); } else { this.updateList(value); } this._originalItems = value; } get items() { return this._originalItems; } /** * Retrieves array of list items and index of the selected item after view has rendered. * Additionally, any Observables for the `DropdownList` are initialized. */ ngAfterViewInit() { this.index = this.getListItems().findIndex(item => item.selected); this.setupFocusObservable(); setTimeout(() => { this.doEmitSelect(true); }); } /** * Removes any Observables on destruction of the component. */ ngOnDestroy() { if (this.focusJump) { this.focusJump.unsubscribe(); } if (this._itemsSubscription) { this._itemsSubscription.unsubscribe(); } } doEmitSelect(isUpdate = true) { if (this.type === "single") { this.select.emit({ item: this._items.find(item => item.selected), isUpdate: isUpdate }); } else { // abuse javascripts object mutability until we can break the API and switch to // { items: [], isUpdate: true } const selected = this.getSelected() || []; selected["isUpdate"] = isUpdate; this.select.emit(selected); } } getItemId(index) { return `${this.listId}-${index}`; } /** * Updates the displayed list of items and then retrieves the most current properties for the `DropdownList` from the DOM. */ updateList(items) { this._items = items.map(item => Object.assign({}, item)); this.displayItems = this._items; this.updateIndex(); this.setupFocusObservable(); this.doEmitSelect(); } /** * Filters the items being displayed in the DOM list. */ filterBy(query = "") { if (query) { this.displayItems = this.getListItems().filter(item => item.content.toLowerCase().includes(query.toLowerCase())); // Reset index if items were found // Prevent selecting index in list that are undefined. if (this.displayItems) { this.index = 0; } } else { this.displayItems = this.getListItems(); } this.updateIndex(); } /** * Initializes (or re-initializes) the Observable that handles switching focus to an element based on * key input matching the first letter of the item in the list. */ setupFocusObservable() { if (!this.list) { return; } if (this.focusJump) { this.focusJump.unsubscribe(); } let elList = Array.from(this.list.nativeElement.querySelectorAll("li")); this.focusJump = watchFocusJump(this.list.nativeElement, elList) .subscribe(el => { el.focus(); }); } /** * Returns the `ListItem` that is subsequent to the selected item in the `DropdownList`. */ getNextItem() { if (this.index < this.displayItems.length - 1) { this.index++; } return this.displayItems[this.index]; } /** * Returns `true` if the selected item is not the last item in the `DropdownList`. */ hasNextElement() { return this.index < this.displayItems.length - 1 && (!(this.index === this.displayItems.length - 2) || !this.displayItems[this.index + 1].disabled); } /** * Returns the `HTMLElement` for the item that is subsequent to the selected item. */ getNextElement() { // Only return native elements if they are rendered const elemList = this.listElementList ? this.listElementList.toArray() : []; if (!elemList.length) { return null; } /** * Start checking from next index * Continue looping through the list until a non disabeled element is found or * end of list is reached */ for (let i = this.index + 1; i < elemList.length; i++) { // If the values in the list are not disabled if (!this.displayItems[i].disabled) { this.index = i; return elemList[i].nativeElement; } } return elemList[this.index]?.nativeElement; } /** * Returns the `ListItem` that precedes the selected item within `DropdownList`. */ getPrevItem() { if (this.index > 0) { this.index--; } return this.displayItems[this.index]; } /** * Returns `true` if the selected item is not the first in the list. */ hasPrevElement() { return this.index > 0 && (!(this.index === 1) || !this.displayItems[0].disabled); } /** * Returns the `HTMLElement` for the item that precedes the selected item. */ getPrevElement() { // Only return native elements if they are rendered const elemList = this.listElementList ? this.listElementList.toArray() : []; if (!elemList.length) { return null; } /** * Start checking from next index * Continue looping through the list until a non disabeled element is found or * end of list is reached */ for (let i = this.index - 1; i < this.index && i >= 0; i--) { // If the values in the list are not disabled if (!this.displayItems[i].disabled) { this.index = i; return elemList[i].nativeElement; } } return elemList[this.index].nativeElement; } /** * Returns the `ListItem` that is selected within `DropdownList`. */ getCurrentItem() { if (this.index < 0) { return this.displayItems[0]; } return this.displayItems[this.index]; } /** * Returns the `HTMLElement` for the item that is selected within the `DropdownList`. */ getCurrentElement() { if (this.index < 0) { return this.listElementList.first.nativeElement; } return this.listElementList.toArray()[this.index].nativeElement; } /** * Returns the items as an Array */ getListItems() { return this._items; } /** * Returns a list containing the selected item(s) in the `DropdownList`. */ getSelected() { let selected = this.getListItems().filter(item => item.selected); if (selected.length === 0) { return []; } return selected; } /** * Transforms array input list of items to the correct state by updating the selected item(s). */ propagateSelected(value) { // if we get a non-array, log out an error (since it is one) if (!Array.isArray(value)) { console.error(`${this.constructor.name}.propagateSelected expects an Array<ListItem>, got ${JSON.stringify(value)}`); } this.onItemsReady(() => { const selectedNewItems = []; for (let newItem of value) { if (newItem && newItem.selected) { // copy the item let tempNewItem = Object.assign({}, newItem); // deleted selected because it's what we _want_ to change delete tempNewItem.selected; // stringify for compare later tempNewItem = JSON.stringify(tempNewItem); // add to the list of selected items selectedNewItems.push(tempNewItem); } } // loop through the list items and update the `selected` state for matching items in `value` for (let oldItem of this.getListItems()) { // fast path when no items are selected if (selectedNewItems.length === 0) { oldItem.selected = false; continue; } // copy the item let tempOldItem = Object.assign({}, oldItem); // deleted selected because it's what we _want_ to change delete tempOldItem.selected; // stringify for compare tempOldItem = JSON.stringify(tempOldItem); for (let selectedNewItem of selectedNewItems) { // do the compare if (tempOldItem.includes(selectedNewItem)) { oldItem.selected = true; // if we've found a matching item, we can stop looping break; } else { oldItem.selected = false; } } } }); } /** * Initializes focus in the list, effectively a wrapper for `getCurrentElement().focus()` */ initFocus() { if (this.index < 0) { this.updateIndex(); } this.list.nativeElement.focus(); setTimeout(() => { this.highlightedItem = this.getItemId(this.index); }); } updateIndex() { // initialize index on the first selected item or // on the next non disabled item if no items are selected // in case, if all items are disabled, the index value will remain same const selected = this.getSelected(); if (selected.length) { this.index = this.displayItems.indexOf(selected[0]); } else if (this.index < 0 && this.hasNextElement()) { this.getNextElement(); } } /** * Manages the keyboard accessibility for navigation and selection within a `DropdownList`. */ navigateList(event) { if (event.key === "Enter" || event.key === " ") { if (this.listElementList.some(option => option.nativeElement === event.target)) { event.preventDefault(); } if (event.key === "Enter") { this.doClick(event, this.getCurrentItem()); } } else if (event.key === "ArrowDown" || event.key === "ArrowUp") { event.preventDefault(); if (event.key === "ArrowDown") { if (this.hasNextElement()) { this.getNextElement()?.scrollIntoView({ block: "end" }); } else { this.blurIntent.emit("bottom"); } } else if (event.key === "ArrowUp") { if (this.hasPrevElement()) { this.getPrevElement().scrollIntoView({ block: "nearest" }); } else { this.blurIntent.emit("top"); } } setTimeout(() => { this.highlightedItem = this.getItemId(this.index); }); } } /** * Emits the selected item or items after a mouse click event has occurred. */ doClick(event, item) { event.preventDefault(); if (item && !item.disabled) { this.list.nativeElement.focus(); if (this.type === "single") { item.selected = true; // reset the selection for (let otherItem of this.getListItems()) { if (item !== otherItem) { otherItem.selected = false; } } } else { item.selected = !item.selected; } this.index = this.displayItems.indexOf(item); this.highlightedItem = this.getItemId(this.index); this.doEmitSelect(false); this.appRef.tick(); } } onItemFocus(index) { const element = this.listElementList.toArray()[index].nativeElement; element.classList.add("cds--list-box__menu-item--highlighted"); element.tabIndex = 0; } onItemBlur(index) { const element = this.listElementList.toArray()[index].nativeElement; element.classList.remove("cds--list-box__menu-item--highlighted"); element.tabIndex = -1; } /** * Emits the scroll event of the options list */ emitScroll(event) { const atTop = event.srcElement.scrollTop === 0; const atBottom = event.srcElement.scrollHeight - event.srcElement.scrollTop === event.srcElement.clientHeight; const customScrollEvent = { atTop, atBottom, event }; this.scroll.emit(customScrollEvent); } /** * Subscribe the function passed to an internal observable that will resolve once the items are ready */ onItemsReady(subcription) { // this subscription will auto unsubscribe because of the `first()` pipe (this._itemsReady || of(true)).pipe(first()).subscribe(subcription); } reorderSelected(moveFocus = true) { this.displayItems = [...this.getSelected(), ...this.getListItems().filter(item => !item.selected)]; if (moveFocus) { setTimeout(() => { this.updateIndex(); this.highlightedItem = this.getItemId(this.index); }); } } } DropdownList.listCount = 0; DropdownList.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DropdownList, deps: [{ token: i0.ElementRef }, { token: i1.I18n }, { token: i0.ApplicationRef }], target: i0.ɵɵFactoryTarget.Component }); DropdownList.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DropdownList, selector: "cds-dropdown-list, ibm-dropdown-list", inputs: { ariaLabel: "ariaLabel", items: "items", listTpl: "listTpl", type: "type", showTitles: "showTitles" }, outputs: { select: "select", scroll: "scroll", blurIntent: "blurIntent" }, providers: [ { provide: AbstractDropdownView, useExisting: DropdownList } ], viewQueries: [{ propertyName: "list", first: true, predicate: ["list"], descendants: true, static: true }, { propertyName: "listElementList", predicate: ["listItem"], descendants: true }], ngImport: i0, template: ` <ul #list [id]="listId" role="listbox" class="cds--list-box__menu cds--multi-select" (scroll)="emitScroll($event)" (keydown)="navigateList($event)" tabindex="0" [attr.aria-label]="ariaLabel" [attr.aria-activedescendant]="highlightedItem"> <li role="option" *ngFor="let item of displayItems; let i = index" (click)="doClick($event, item)" class="cds--list-box__menu-item" [attr.aria-selected]="item.selected" [id]="getItemId(i)" [attr.tabindex]="highlightedItem === getItemId(i) ? 0 : null" [attr.title]=" showTitles ? item.content : null" [attr.disabled]="item.disabled ? true : null" [ngClass]="{ 'cds--list-box__menu-item--active': item.selected, 'cds--list-box__menu-item--highlighted': highlightedItem === getItemId(i) }"> <div #listItem tabindex="-1" class="cds--list-box__menu-item__option"> <div *ngIf="!listTpl && type === 'multi'" class="cds--form-item cds--checkbox-wrapper"> <label [attr.data-contained-checkbox-state]="item.selected" class="cds--checkbox-label"> <input class="cds--checkbox" type="checkbox" [checked]="item.selected" [disabled]="item.disabled" tabindex="-1"> <span class="cds--checkbox-appearance"></span> <span class="cds--checkbox-label-text">{{item.content}}</span> </label> </div> <ng-container *ngIf="!listTpl && type === 'single'">{{item.content}}</ng-container> <svg *ngIf="!listTpl && type === 'single'" cdsIcon="checkmark" size="16" class="cds--list-box__menu-item__selected-icon"> </svg> <ng-template *ngIf="listTpl" [ngTemplateOutletContext]="{item: item}" [ngTemplateOutlet]="listTpl"> </ng-template> </div> </li> </ul>`, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DropdownList, decorators: [{ type: Component, args: [{ selector: "cds-dropdown-list, ibm-dropdown-list", template: ` <ul #list [id]="listId" role="listbox" class="cds--list-box__menu cds--multi-select" (scroll)="emitScroll($event)" (keydown)="navigateList($event)" tabindex="0" [attr.aria-label]="ariaLabel" [attr.aria-activedescendant]="highlightedItem"> <li role="option" *ngFor="let item of displayItems; let i = index" (click)="doClick($event, item)" class="cds--list-box__menu-item" [attr.aria-selected]="item.selected" [id]="getItemId(i)" [attr.tabindex]="highlightedItem === getItemId(i) ? 0 : null" [attr.title]=" showTitles ? item.content : null" [attr.disabled]="item.disabled ? true : null" [ngClass]="{ 'cds--list-box__menu-item--active': item.selected, 'cds--list-box__menu-item--highlighted': highlightedItem === getItemId(i) }"> <div #listItem tabindex="-1" class="cds--list-box__menu-item__option"> <div *ngIf="!listTpl && type === 'multi'" class="cds--form-item cds--checkbox-wrapper"> <label [attr.data-contained-checkbox-state]="item.selected" class="cds--checkbox-label"> <input class="cds--checkbox" type="checkbox" [checked]="item.selected" [disabled]="item.disabled" tabindex="-1"> <span class="cds--checkbox-appearance"></span> <span class="cds--checkbox-label-text">{{item.content}}</span> </label> </div> <ng-container *ngIf="!listTpl && type === 'single'">{{item.content}}</ng-container> <svg *ngIf="!listTpl && type === 'single'" cdsIcon="checkmark" size="16" class="cds--list-box__menu-item__selected-icon"> </svg> <ng-template *ngIf="listTpl" [ngTemplateOutletContext]="{item: item}" [ngTemplateOutlet]="listTpl"> </ng-template> </div> </li> </ul>`, providers: [ { provide: AbstractDropdownView, useExisting: DropdownList } ] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.I18n }, { type: i0.ApplicationRef }]; }, propDecorators: { ariaLabel: [{ type: Input }], items: [{ type: Input }], listTpl: [{ type: Input }], select: [{ type: Output }], scroll: [{ type: Output }], blurIntent: [{ type: Output }], list: [{ type: ViewChild, args: ["list", { static: true }] }], type: [{ type: Input }], showTitles: [{ type: Input }], listElementList: [{ type: ViewChildren, args: ["listItem"] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcGRvd24tbGlzdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZHJvcGRvd24vbGlzdC9kcm9wZG93bi1saXN0LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ04sU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBRU4sWUFBWSxFQUdaLFNBQVMsRUFFVCxZQUFZLEVBR1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQWdCLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHdkMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFdkUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGtCQUFrQixDQUFDOzs7OztBQUlsRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBc0VILE1BQU0sT0FBTyxZQUFZO0lBMEd4Qjs7T0FFRztJQUNILFlBQW1CLFVBQXNCLEVBQVksSUFBVSxFQUFZLE1BQXNCO1FBQTlFLGVBQVUsR0FBVixVQUFVLENBQVk7UUFBWSxTQUFJLEdBQUosSUFBSSxDQUFNO1FBQVksV0FBTSxHQUFOLE1BQU0sQ0FBZ0I7UUEzR3hGLGNBQVMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUM7UUEwQnpEOztXQUVHO1FBQ00sWUFBTyxHQUE4QixJQUFJLENBQUM7UUFDbkQ7O1dBRUc7UUFDTyxXQUFNLEdBQXNFLElBQUksWUFBWSxFQUFFLENBQUM7UUFDekc7O1dBRUc7UUFDTyxXQUFNLEdBQW9DLElBQUksWUFBWSxFQUFFLENBQUM7UUFDdkU7Ozs7Ozs7O1dBUUc7UUFDTyxlQUFVLEdBQUcsSUFBSSxZQUFZLEVBQW9CLENBQUM7UUFLNUQ7OztX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Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7UUEyREg7b0JBQ1AsU0FBUyxFQUFFO3dCQUNWOzRCQUNDLE9BQU8sRUFBRSxvQkFBb0I7NEJBQzdCLFdBQVcsY0FBYzt5QkFDekI7cUJBQ0Q7aUJBQ0Q7aUpBR1MsU0FBUztzQkFBakIsS0FBSztnQkFJTyxLQUFLO3NCQUFqQixLQUFLO2dCQXlCRyxPQUFPO3NCQUFmLEtBQUs7Z0JBSUksTUFBTTtzQkFBZixNQUFNO2dCQUlHLE1BQU07c0JBQWYsTUFBTTtnQkFVRyxVQUFVO3NCQUFuQixNQUFNO2dCQUk4QixJQUFJO3NCQUF4QyxTQUFTO3VCQUFDLE1BQU0sRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBSzFCLElBQUk7c0JBQVosS0FBSztnQkFLRyxVQUFVO3NCQUFsQixLQUFLO2dCQXFCOEIsZUFBZTtzQkFBbEQsWUFBWTt1QkFBQyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcblx0Q29tcG9uZW50LFxuXHRJbnB1dCxcblx0T3V0cHV0LFxuXHRPbkRlc3Ryb3ksXG5cdEV2ZW50RW1pdHRlcixcblx0VGVtcGxhdGVSZWYsXG5cdEFmdGVyVmlld0luaXQsXG5cdFZpZXdDaGlsZCxcblx0RWxlbWVudFJlZixcblx0Vmlld0NoaWxkcmVuLFxuXHRRdWVyeUxpc3QsXG5cdEFwcGxpY2F0aW9uUmVmXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBpc09ic2VydmFibGUsIFN1YnNjcmlwdGlvbiwgb2YgfSBmcm9tIFwicnhqc1wiO1xuaW1wb3J0IHsgZmlyc3QgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcblxuaW1wb3J0IHsgSTE4biB9IGZyb20gXCJjYXJib24tY29tcG9uZW50cy1hbmd1bGFyL2kxOG5cIjtcbmltcG9ydCB7IEFic3RyYWN0RHJvcGRvd25WaWV3IH0gZnJvbSBcIi4uL2Fic3RyYWN0LWRyb3Bkb3duLXZpZXcuY2xhc3NcIjtcbmltcG9ydCB7IExpc3RJdGVtIH0gZnJvbSBcIi4uL2xpc3QtaXRlbS5pbnRlcmZhY2VcIjtcbmltcG9ydCB7IHdhdGNoRm9jdXNKdW1wIH0gZnJvbSBcIi4uL2Ryb3Bkb3dudG9vbHNcIjtcbmltcG9ydCB7IFNjcm9sbEN1c3RvbUV2ZW50IH0gZnJvbSBcIi4vc2Nyb2xsLWN1c3RvbS1ldmVudC5pbnRlcmZhY2VcIjtcblxuXG4vKipcbiAqIGBgYGh0bWxcbiAqIDxjZHMtZHJvcGRvd24tbGlzdCBbaXRlbXNdPVwibGlzdEl0ZW1zXCI+PC9jZHMtZHJvcGRvd24tbGlzdD5cbiAqIGBgYFxuICogYGBgdHlwZXNjcmlwdFxuICogbGlzdEl0ZW1zID0gW1xuICogXHR7XG4gKiBcdFx0Y29udGVudDogXCJpdGVtIG9uZVwiLFxuICogXHRcdHNlbGVjdGVkOiBmYWxzZVxuICogXHR9LFxuICogXHR7XG4gKiBcdFx0Y29udGVudDogXCJpdGVtIHR3b1wiLFxuICogXHRcdHNlbGVjdGVkOiBmYWxzZSxcbiAqIFx0fSxcbiAqIFx0e1xuICogXHRcdGNvbnRlbnQ6IFwiaXRlbSB0aHJlZVwiLFxuICogXHRcdHNlbGVjdGVkOiBmYWxzZVxuICogXHR9LFxuICogXHR7XG4gKiBcdFx0Y29udGVudDogXCJpdGVtIGZvdXJcIixcbiAqIFx0XHRzZWxlY3RlZDogZmFsc2VcbiAqIFx0fVxuICogXTtcbiAqIGBgYFxuICovXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6IFwiY2RzLWRyb3Bkb3duLWxpc3QsIGlibS1kcm9wZG93bi1saXN0XCIsXG5cdHRlbXBsYXRlOiBgXG5cdFx0PHVsXG5cdFx0XHQjbGlzdFxuXHRcdFx0W2lkXT1cImxpc3RJZFwiXG5cdFx0XHRyb2xlPVwibGlzdGJveFwiXG5cdFx0XHRjbGFzcz1cImNkcy0tbGlzdC1ib3hfX21lbnUgY2RzLS1tdWx0aS1zZWxlY3RcIlxuXHRcdFx0KHNjcm9sbCk9XCJlbWl0U2Nyb2xsKCRldmVudClcIlxuXHRcdFx0KGtleWRvd24pPVwibmF2aWdhdGVMaXN0KCRldmVudClcIlxuXHRcdFx0dGFiaW5kZXg9XCIwXCJcblx0XHRcdFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsXCJcblx0XHRcdFthdHRyLmFyaWEtYWN0aXZlZGVzY2VuZGFudF09XCJoaWdobGlnaHRlZEl0ZW1cIj5cblx0XHRcdDxsaVxuXHRcdFx0XHRyb2xlPVwib3B0aW9uXCJcblx0XHRcdFx0Km5nRm9yPVwibGV0IGl0ZW0gb2YgZGlzcGxheUl0ZW1zOyBsZXQgaSA9IGluZGV4XCJcblx0XHRcdFx0KGNsaWNrKT1cImRvQ2xpY2soJGV2ZW50LCBpdGVtKVwiXG5cdFx0XHRcdGNsYXNzPVwiY2RzLS1saXN0LWJveF9fbWVudS1pdGVtXCJcblx0XHRcdFx0W2F0dHIuYXJpYS1zZWxlY3RlZF09XCJpdGVtLnNlbGVjdGVkXCJcblx0XHRcdFx0W2lkXT1cImdldEl0ZW1JZChpKVwiXG5cdFx0XHRcdFthdHRyLnRhYmluZGV4XT1cImhpZ2hsaWdodGVkSXRlbSA9PT0gZ2V0SXRlbUlkKGkpID8gMCA6IG51bGxcIlxuXHRcdFx0XHRbYXR0ci50aXRsZV09XCIgc2hvd1RpdGxlcyA/IGl0ZW0uY29udGVudCA6IG51bGxcIlxuXHRcdFx0XHRbYXR0ci5kaXNhYmxlZF09XCJpdGVtLmRpc2FibGVkID8gdHJ1ZSA6IG51bGxcIlxuXHRcdFx0XHRbbmdDbGFzc109XCJ7XG5cdFx0XHRcdFx0J2Nkcy0tbGlzdC1ib3hfX21lbnUtaXRlbS0tYWN0aXZlJzogaXRlbS5zZWxlY3RlZCxcblx0XHRcdFx0XHQnY2RzLS1saXN0LWJveF9fbWVudS1pdGVtLS1oaWdobGlnaHRlZCc6IGhpZ2hsaWdodGVkSXRlbSA9PT0gZ2V0SXRlbUlkKGkpXG5cdFx0XHRcdH1cIj5cblx0XHRcdFx0PGRpdlxuXHRcdFx0XHRcdCNsaXN0SXRlbVxuXHRcdFx0XHRcdHRhYmluZGV4PVwiLTFcIlxuXHRcdFx0XHRcdGNsYXNzPVwiY2RzLS1saXN0LWJveF9fbWVudS1pdGVtX19vcHRpb25cIj5cblx0XHRcdFx0XHQ8ZGl2XG5cdFx0XHRcdFx0XHQqbmdJZj1cIiFsaXN0VHBsICYmIHR5cGUgPT09ICdtdWx0aSdcIlxuXHRcdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLWZvcm0taXRlbSBjZHMtLWNoZWNrYm94LXdyYXBwZXJcIj5cblx0XHRcdFx0XHRcdDxsYWJlbFxuXHRcdFx0XHRcdFx0XHRbYXR0ci5kYXRhLWNvbnRhaW5lZC1jaGVja2JveC1zdGF0ZV09XCJpdGVtLnNlbGVjdGVkXCJcblx0XHRcdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLWNoZWNrYm94LWxhYmVsXCI+XG5cdFx0XHRcdFx0XHRcdDxpbnB1dFxuXHRcdFx0XHRcdFx0XHRcdGNsYXNzPVwiY2RzLS1jaGVja2JveFwiXG5cdFx0XHRcdFx0XHRcdFx0dHlwZT1cImNoZWNrYm94XCJcblx0XHRcdFx0XHRcdFx0XHRbY2hlY2tlZF09XCJpdGVtLnNlbGVjdGVkXCJcblx0XHRcdFx0XHRcdFx0XHRbZGlzYWJsZWRdPVwiaXRlbS5kaXNhYmxlZFwiXG5cdFx0XHRcdFx0XHRcdFx0dGFiaW5kZXg9XCItMVwiPlxuXHRcdFx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cImNkcy0tY2hlY2tib3gtYXBwZWFyYW5jZVwiPjwvc3Bhbj5cblx0XHRcdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJjZHMtLWNoZWNrYm94LWxhYmVsLXRleHRcIj57e2l0ZW0uY29udGVudH19PC9zcGFuPlxuXHRcdFx0XHRcdFx0PC9sYWJlbD5cblx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIWxpc3RUcGwgJiYgdHlwZSA9PT0gJ3NpbmdsZSdcIj57e2l0ZW0uY29udGVudH19PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdFx0PHN2Z1xuXHRcdFx0XHRcdFx0Km5nSWY9XCIhbGlzdFRwbCAmJiB0eXBlID09PSAnc2luZ2xlJ1wiXG5cdFx0XHRcdFx0XHRjZHNJY29uPVwiY2hlY2ttYXJrXCJcblx0XHRcdFx0XHRcdHNpemU9XCIxNlwiXG5cdFx0XHRcdFx0XHRjbGFzcz1cImNkcy0tbGlzdC1ib3hfX21lbnUtaXRlbV9fc2VsZWN0ZWQtaWNvblwiPlxuXHRcdFx0XHRcdDwvc3ZnPlxuXHRcdFx0XHRcdDxuZy10ZW1wbGF0ZVxuXHRcdFx0XHRcdFx0Km5nSWY9XCJsaXN0VHBsXCJcblx0XHRcdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7aXRlbTogaXRlbX1cIlxuXHRcdFx0XHRcdFx0W25nVGVtcGxhdGVPdXRsZXRdPVwibGlzdFRwbFwiPlxuXHRcdFx0XHRcdDwvbmctdGVtcGxhdGU+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0PC9saT5cblx0XHQ8L3VsPmAsXG5cdHByb3ZpZGVyczogW1xuXHRcdHtcblx0XHRcdHByb3ZpZGU6IEFic3RyYWN0RHJvcGRvd25WaWV3LFxuXHRcdFx0dXNlRXhpc3Rpbmc6IERyb3Bkb3duTGlzdFxuXHRcdH1cblx0XVxufSlcbmV4cG9ydCBjbGFzcyBEcm9wZG93bkxpc3QgaW1wbGVtZW50cyBBYnN0cmFjdERyb3Bkb3duVmlldywgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcblx0c3RhdGljIGxpc3RDb3VudCA9IDA7XG5cdEBJbnB1dCgpIGFyaWFMYWJlbCA9IHRoaXMuaTE4bi5nZXQoKS5EUk9QRE9XTl9MSVNULkxBQkVMO1xuXHQvKipcblx0ICogVGhlIGxpc3QgaXRlbXMgYmVsb25naW5nIHRvIHRoZSBgRHJvcGRvd25MaXN0YC5cblx0ICovXG5cdEBJbnB1dCgpIHNldCBpdGVtcyh2YWx1ZTogQXJyYXk8TGlzdEl0ZW0+IHwgT2JzZXJ2YWJsZTxBcnJheTxMaXN0SXRlbT4+KSB7XG5cdFx0aWYgKGlzT2JzZXJ2YWJsZSh2YWx1ZSkpIHtcblx0XHRcdGlmICh0aGlzLl9pdGVtc1N1YnNjcmlwdGlvbikge1xuXHRcdFx0XHR0aGlzLl9pdGVtc1N1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5faXRlbXNSZWFkeSA9IG5ldyBPYnNlcnZhYmxlPGJvb2xlYW4+KChvYnNlcnZlcikgPT4ge1xuXHRcdFx0XHR0aGlzLl9pdGVtc1N1YnNjcmlwdGlvbiA9IHZhbHVlLnN1YnNjcmliZSh2ID0+IHtcblx0XHRcdFx0XHR0aGlzLnVwZGF0ZUxpc3Qodik7XG5cdFx0XHRcdFx0b2JzZXJ2ZXIubmV4dCh0cnVlKTtcblx0XHRcdFx0XHRvYnNlcnZlci5jb21wbGV0ZSgpO1xuXHRcdFx0XHR9KTtcblx0XHRcdH0pO1xuXHRcdFx0dGhpcy5vbkl0ZW1zUmVhZHkobnVsbCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMudXBkYXRlTGlzdCh2YWx1ZSk7XG5cdFx0fVxuXHRcdHRoaXMuX29yaWdpbmFsSXRlbXMgPSB2YWx1ZTtcblx0fVxuXG5cdGdldCBpdGVtcygpOiBBcnJheTxMaXN0SXRlbT4gfCBPYnNlcnZhYmxlPEFycmF5PExpc3RJdGVtPj4ge1xuXHRcdHJldHVybiB0aGlzLl9vcmlnaW5hbEl0ZW1zO1xuXHR9XG5cdC8qKlxuXHQgKiBUZW1wbGF0ZSB0byBiaW5kIHRvIGl0ZW1zIGluIHRoZSBgRHJvcGRvd25MaXN0YCAob3B0aW9uYWwpLlxuXHQgKi9cblx0QElucHV0KCkgbGlzdFRwbDogc3RyaW5nIHwgVGVtcGxhdGVSZWY8YW55PiA9IG51bGw7XG5cdC8qKlxuXHQgKiBFdmVudCB0byBlbWl0IHNlbGVjdGlvbiBvZiBhIGxpc3QgaXRlbSB3aXRoaW4gdGhlIGBEcm9wZG93bkxpc3RgLlxuXHQgKi9cblx0QE91dHB1dCgpIHNlbGVjdDogRXZlbnRFbWl0dGVyPHsgaXRlbTogTGlzdEl0ZW0sIGlzVXBkYXRlPzogYm9vbGVhbiB9IHwgTGlzdEl0ZW1bXT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cdC8qKlxuXHQgKiBFdmVudCB0byBlbWl0IHNjcm9sbCBldmVudCBvZiBhIGxpc3Qgd2l0aGluIHRoZSBgRHJvcGRvd25MaXN0YC5cblx0ICovXG5cdEBPdXRwdXQoKSBzY3JvbGw6IEV2ZW50RW1pdHRlcjxTY3JvbGxDdXN0b21FdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cdC8qKlxuXHQgKiBFdmVudCB0byBzdWdnZXN0IGEgYmx1ciBvbiB0aGUgdmlldy5cblx0ICogRW1pdHMgX2FmdGVyXyB0aGUgZmlyc3QvbGFzdCBpdGVtIGhhcyBiZWVuIGZvY3VzZWQuXG5cdCAqIGV4LlxuXHQgKiBBcnJvd1VwIC0+IGZvY3VzIGZpcnN0IGl0ZW1cblx0ICogQXJyb3dVcCAtPiBlbWl0IGV2ZW50XG5cdCAqXG5cdCAqIFdoZW4gdGhpcyBldmVudCBmaXJlcyBmb2N1cyBzaG91bGQgYmUgcGxhY2VkIG9uIHNvbWUgZWxlbWVudCBvdXRzaWRlIG9mIHRoZSBsaXN0IC0gYmx1cnJpbmcgdGhlIGxpc3QgYXMgYSByZXN1bHRcblx0ICovXG5cdEBPdXRwdXQoKSBibHVySW50ZW50ID0gbmV3IEV2ZW50RW1pdHRlcjxcInRvcFwiIHwgXCJib3R0b21cIj4oKTtcblx0LyoqXG5cdCAqIE1haW50YWlucyBhIHJlZmVyZW5jZSB0byB0aGUgdmlldyBET00gZWxlbWVudCBmb3IgdGhlIHVub3JkZXJlZCBsaXN0IG9mIGl0ZW1zIHdpdGhpbiB0aGUgYERyb3Bkb3duTGlzdGAuXG5cdCAqL1xuXHRAVmlld0NoaWxkKFwibGlzdFwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBsaXN0OiBFbGVtZW50UmVmO1xuXHQvKipcblx0ICogRGVmaW5lcyB3aGV0aGVyIG9yIG5vdCB0aGUgYERyb3Bkb3duTGlzdGAgc3VwcG9ydHMgc2VsZWN0aW5nIG11bHRpcGxlIGl0ZW1zIGFzIG9wcG9zZWQgdG8gc2luZ2xlXG5cdCAqIGl0ZW0gc2VsZWN0aW9uLlxuXHQgKi9cblx0QElucHV0KCkgdHlwZTogXCJzaW5nbGVcIiB8IFwibXVsdGlcIiA9IFwic2luZ2xlXCI7XG5cblx0LyoqXG5cdCAqIERlZmluZXMgd2hldGhlciB0byBzaG93IHRpdGxlIGF0dHJpYnV0ZSBvciBub3Rcblx0ICovXG5cdEBJbnB1dCgpIHNob3dUaXRsZXMgPSB0cnVlO1xuXG5cdC8qKlxuXHQgKiBEZWZpbmVzIHRoZSByZW5kZXJpbmcgc2l6ZSBvZiB0aGUgYERyb3Bkb3duTGlzdGAgaW5wdXQgY29tcG9uZW50LlxuXHQgKi9cblx0cHVibGljIHNpemU6IFwic21cIiB8IFwibWRcIiB8IFwibGdcIiA9IFwibWRcIjtcblx0cHVibGljIGxpc3RJZCA9IGBsaXN0Ym94LSR7RHJvcGRvd25MaXN0Lmxpc3RDb3VudCsrfWA7XG5cdHB1YmxpYyBoaWdobGlnaHRlZEl0ZW0gPSBudWxsO1xuXHQvKipcblx0ICogSG9sZHMgdGhlIGxpc3Qgb2YgaXRlbXMgdGhhdCB3aWxsIGJlIGRpc3BsYXllZCBpbiB0aGUgYERyb3Bkb3duTGlzdGAuXG5cdCAqIEl0IGRpZmZlcnMgZnJvbSB0aGUgdGhlIGNvbXBsZXRlIHNldCBvZiBpdGVtcyB3aGVuIGZpbHRlcmluZyBpcyB1c2VkIChidXRcblx0ICogaXQgaXMgYWx3YXlzIGEgc3Vic2V0IG9mIHRoZSB0b3RhbCBpdGVtcyBpbiBgRHJvcGRvd25MaXN0YCkuXG5cdCAqL1xuXHRwdWJsaWMgZGlzcGxheUl0ZW1zOiBBcnJheTxMaXN0SXRlbT4gPSBbXTtcblx0LyoqXG5cdCAqIE1haW50YWlucyB0aGUgaW5kZXggZm9yIHRoZSBzZWxlY3RlZCBpdGVtIHdpdGhpbiB0aGUgYERyb3Bkb3duTGlzdGAuXG5cdCAqL1xuXHRwcm90ZWN0ZWQgaW5kZXggPSAtMTtcblx0LyoqXG5cdCAqIEFuIGFycmF5IGhvbGRpbmcgdGhlIEhUTUwgbGlzdCBlbGVtZW50cyBpbiB0aGUgdmlldy5cblx0ICovXG5cdEBWaWV3Q2hpbGRyZW4oXCJsaXN0SXRlbVwiKSBwcm90ZWN0ZWQgbGlzdEVsZW1lbnRMaXN0OiBRdWVyeUxpc3Q8RWxlbWVudFJlZj47XG5cdC8qKlxuXHQgKiBPYnNlcnZhYmxlIGJvdW5kIHRvIGtleWRvd24gZXZlbnRzIHRvIGNvbnRyb2wgZmlsdGVyaW5nLlxuXHQgKi9cblx0cHJvdGVjdGVkIGZvY3VzSnVtcDtcblx0LyoqXG5cdCAqIFRyYWNrcyB0aGUgY3VycmVudCAoaWYgYW55KSBzdWJzY3JpcHRpb24gdG8gdGhlIGl0ZW1zIG9ic2VydmFibGUgc28gd2UgY2FuIGNsZWFuIHVwIHdoZW4gdGhlIGlucHV0IGlzIHVwZGF0ZWQuXG5cdCAqL1xuXHRwcm90ZWN0ZWQgX2l0ZW1zU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cdC8qKlxuXHQgKiBVc2VkIHRvIHJldGFpbiB0aGUgb3JpZ2luYWwgaXRlbXMgcGFzc2VkIHRvIHRoZSBzZXR0ZXIuXG5cdCAqL1xuXHRwcm90ZWN0ZWQgX29yaWdpbmFsSXRlbXM6IEFycmF5PExpc3RJdGVtPiB8IE9ic2VydmFibGU8QXJyYXk8TGlzdEl0ZW0+Pjtcblx0LyoqXG5cdCAqIFVzZWZ1bCByZXByZXNlbnRhdGlvbiBvZiB0aGUgaXRlbXMsIHNob3VsZCBiZSBhY2Nlc3NlZCB2aWEgYGdldExpc3RJdGVtc2AuXG5cdCAqL1xuXHRwcm90ZWN0ZWQgX2l0ZW1zOiBBcnJheTxMaXN0SXRlbT4gPSBbXTtcblx0LyoqXG5cdCAqIFVzZWQgdG8gd2FpdCBmb3IgaXRlbXMgaW4gY2FzZSB0aGV5IGFyZSBwYXNzZWQgdGhyb3VnaCBhbiBvYnNlcnZhYmxlLlxuXHQgKi9cblx0cHJvdGVjdGVkIF9pdGVtc1JlYWR5OiBPYnNlcnZhYmxlPGJvb2xlYW4+O1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIGBEcm9wZG93bkxpc3RgLlxuXHQgKi9cblx0Y29uc3RydWN0b3IocHVibGljIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsIHByb3RlY3RlZCBpMThuOiBJMThuLCBwcm90ZWN0ZWQgYXBwUmVmOiBBcHBsaWNhdGlvblJlZikge31cblxuXHQvKipcblx0ICogUmV0cmlldmVzIGFycmF5IG9mIGxpc3QgaXRlbXMgYW5kIGluZGV4IG9mIHRoZSBzZWxlY3RlZCBpdGVtIGFmdGVyIHZpZXcgaGFzIHJlbmRlcmVkLlxuXHQgKiBBZGRpdGlvbmFs