@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
91 lines • 25.6 kB
JavaScript
import { LEFT_ARROW, RIGHT_ARROW, SPACE } from '@angular/cdk/keycodes';
import { Component, ElementRef, HostListener, inject, Input, ViewChild } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { getIconType } from '../../../../common/index';
import { tick } from '../../../../common/operators/index';
import { PageHeaderService } from '../../page-header.service';
import { PageHeaderNavigationService } from '../navigation.service';
import * as i0 from "@angular/core";
import * as i1 from "../../../../directives/accessibility/focus-indicator/focus-indicator.directive";
import * as i2 from "@angular/common";
import * as i3 from "../../../icon/icon.component";
import * as i4 from "../../../menu/menu/menu.component";
import * as i5 from "../../../menu/menu-trigger/menu-trigger.directive";
import * as i6 from "@angular/router";
import * as i7 from "../navigation-dropdown-item/navigation-dropdown-item.component";
export class PageHeaderNavigationItemComponent {
constructor() {
this.elementRef = inject(ElementRef);
this._pageHeaderService = inject(PageHeaderService);
this._navigationService = inject(PageHeaderNavigationService);
/** Store the secondary state */
this.secondary$ = this._pageHeaderService.secondary$;
/** Update the tabindex based on keyboard input */
this._tabindex = this._navigationService.getTabIndex(this);
/** Unsubscribe when the component is destroyed */
this._onDestroy = new Subject();
}
/** Access the data for this dropdown item */
set item(item) {
this._item = item;
this._iconType = getIconType(item.icon);
}
get item() {
return this._item;
}
ngAfterViewInit() {
this._pageHeaderService.selected$.pipe(tick(), takeUntil(this._onDestroy)).subscribe(selectedItem => {
// Update selected state for this item
this._pageHeaderService.updateItem(this.item, selectedItem);
if (selectedItem && this.isOpen) {
this.isOpen = false;
}
});
}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
focus() {
this.navigationBtn.nativeElement.focus();
}
select() {
// if the item is disabled or has children then do nothing at this stage
if (this.item.disabled || (this.item.children && this._pageHeaderService.secondary$.getValue() === false)) {
return;
}
// if autoselect is enabled the first child should be selected when we click on the parent item (this element).
// We should remove the selected state on all children as the service will perform the selection
// of the first item and handle any routing etc..
if (this._pageHeaderService.secondaryNavigationAutoselect && Array.isArray(this.item.children)) {
this.item.children.forEach(item => item.selected = false);
}
// otherwise select the current item
this._pageHeaderService.select(this.item);
}
onKeydown(event, target) {
if (event.keyCode === LEFT_ARROW || event.keyCode === RIGHT_ARROW) {
this._navigationService.onKeydown(event);
}
if (event.keyCode === SPACE) {
event.preventDefault();
target.click();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: PageHeaderNavigationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: PageHeaderNavigationItemComponent, selector: "ux-page-header-horizontal-navigation-item", inputs: { item: "item" }, host: { listeners: { "keydown": "onKeydown($event,$event.target)" } }, viewQueries: [{ propertyName: "navigationBtn", first: true, predicate: ["navigationBtn"], descendants: true }], ngImport: i0, template: "@if (_item.children && _item.children.length > 0 && (secondary$ | async) === false) {\n <div>\n <button\n #navigationBtn\n type=\"button\"\n [attr.id]=\"_item.id\"\n [tabindex]=\"_tabindex | async\"\n [uxMenuTriggerFor]=\"menu\"\n [disabled]=\"_item.disabled\"\n role=\"menuitem\"\n class=\"horizontal-navigation-button\"\n [class.disabled]=\"_item.disabled\"\n [class.selected]=\"_item.selected\"\n [class.open]=\"isOpen\"\n >\n <ng-container [ngTemplateOutlet]=\"navigationItemContent\"> </ng-container>\n <ux-icon class=\"navigation-item-dropdown-icon\" name=\"down\"></ux-icon>\n </button>\n <ux-menu\n #menu\n menuClass=\"horizontal-navigation-dropdown-menu\"\n (opened)=\"isOpen = true\"\n (closed)=\"isOpen = false\"\n >\n @for (item of _item?.children; track item) {\n <ux-page-header-horizontal-navigation-dropdown-item\n [item]=\"item\"\n >\n </ux-page-header-horizontal-navigation-dropdown-item>\n }\n </ux-menu>\n </div>\n}\n\n@if (!_item.children || _item.children.length === 0 || (secondary$ | async)) {\n @if (_item.routerLink) {\n <a\n uxFocusIndicator\n #navigationBtn\n [tabindex]=\"_tabindex | async\"\n [attr.id]=\"_item.id\"\n role=\"menuitem\"\n class=\"horizontal-navigation-button\"\n [class.disabled]=\"_item.disabled\"\n [class.selected]=\"_item.selected\"\n [routerLink]=\"_item.routerLink\"\n [fragment]=\"_item.routerExtras?.fragment\"\n [queryParams]=\"_item.routerExtras?.queryParams\"\n [queryParamsHandling]=\"_item.routerExtras?.queryParamsHandling\"\n [preserveFragment]=\"_item.routerExtras?.preserveFragment\"\n [skipLocationChange]=\"_item.routerExtras?.skipLocationChange\"\n [replaceUrl]=\"_item.routerExtras?.replaceUrl\"\n [state]=\"_item.routerExtras?.state\"\n >\n <ng-container [ngTemplateOutlet]=\"navigationItemContent\"> </ng-container>\n </a>\n }\n @if (!_item.routerLink) {\n <button\n uxFocusIndicator\n #navigationBtn\n type=\"button\"\n [tabindex]=\"_tabindex | async\"\n [attr.id]=\"_item.id\"\n role=\"menuitem\"\n class=\"horizontal-navigation-button\"\n [class.disabled]=\"_item.disabled\"\n [class.selected]=\"_item.selected\"\n (click)=\"select()\"\n [disabled]=\"_item.disabled\"\n >\n <ng-container [ngTemplateOutlet]=\"navigationItemContent\"> </ng-container>\n </button>\n }\n}\n\n<!-- Support all icon types -->\n<ng-template #navigationItemContent>\n @if (_item.icon) {\n @if (_iconType !== 'component') {\n <i\n class=\"navigation-item-icon\"\n [ngClass]=\"[_iconType, _item.icon]\"\n >\n </i>\n }\n @if (_iconType === 'component') {\n <ux-icon class=\"navigation-item-icon\" [name]=\"_item.icon\">\n </ux-icon>\n }\n }\n\n <span class=\"navigation-item-label\">{{ _item?.title }}</span>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i1.FocusIndicatorDirective, selector: "[uxFocusIndicator]", inputs: ["checkChildren", "mouseFocusIndicator", "touchFocusIndicator", "keyboardFocusIndicator", "programmaticFocusIndicator"], outputs: ["indicator"], exportAs: ["ux-focus-indicator"] }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.IconComponent, selector: "ux-icon", inputs: ["name", "size", "rotate", "flipHorizontal", "flipVertical"] }, { kind: "component", type: i4.MenuComponent, selector: "ux-menu", inputs: ["id", "placement", "alignment", "animate", "menuClass"], outputs: ["opening", "opened", "closing", "closed"] }, { kind: "directive", type: i5.MenuTriggerDirective, selector: "[uxMenuTriggerFor]", inputs: ["uxMenuTriggerFor", "disabled", "uxMenuParent", "closeOnBlur"], outputs: ["closed"], exportAs: ["ux-menu-trigger"] }, { kind: "directive", type: i6.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i7.PageHeaderNavigationDropdownItemComponent, selector: "ux-page-header-horizontal-navigation-dropdown-item", inputs: ["item"], exportAs: ["ux-page-header-horizontal-navigation-dropdown-item"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: PageHeaderNavigationItemComponent, decorators: [{
type: Component,
args: [{ selector: 'ux-page-header-horizontal-navigation-item', template: "@if (_item.children && _item.children.length > 0 && (secondary$ | async) === false) {\n <div>\n <button\n #navigationBtn\n type=\"button\"\n [attr.id]=\"_item.id\"\n [tabindex]=\"_tabindex | async\"\n [uxMenuTriggerFor]=\"menu\"\n [disabled]=\"_item.disabled\"\n role=\"menuitem\"\n class=\"horizontal-navigation-button\"\n [class.disabled]=\"_item.disabled\"\n [class.selected]=\"_item.selected\"\n [class.open]=\"isOpen\"\n >\n <ng-container [ngTemplateOutlet]=\"navigationItemContent\"> </ng-container>\n <ux-icon class=\"navigation-item-dropdown-icon\" name=\"down\"></ux-icon>\n </button>\n <ux-menu\n #menu\n menuClass=\"horizontal-navigation-dropdown-menu\"\n (opened)=\"isOpen = true\"\n (closed)=\"isOpen = false\"\n >\n @for (item of _item?.children; track item) {\n <ux-page-header-horizontal-navigation-dropdown-item\n [item]=\"item\"\n >\n </ux-page-header-horizontal-navigation-dropdown-item>\n }\n </ux-menu>\n </div>\n}\n\n@if (!_item.children || _item.children.length === 0 || (secondary$ | async)) {\n @if (_item.routerLink) {\n <a\n uxFocusIndicator\n #navigationBtn\n [tabindex]=\"_tabindex | async\"\n [attr.id]=\"_item.id\"\n role=\"menuitem\"\n class=\"horizontal-navigation-button\"\n [class.disabled]=\"_item.disabled\"\n [class.selected]=\"_item.selected\"\n [routerLink]=\"_item.routerLink\"\n [fragment]=\"_item.routerExtras?.fragment\"\n [queryParams]=\"_item.routerExtras?.queryParams\"\n [queryParamsHandling]=\"_item.routerExtras?.queryParamsHandling\"\n [preserveFragment]=\"_item.routerExtras?.preserveFragment\"\n [skipLocationChange]=\"_item.routerExtras?.skipLocationChange\"\n [replaceUrl]=\"_item.routerExtras?.replaceUrl\"\n [state]=\"_item.routerExtras?.state\"\n >\n <ng-container [ngTemplateOutlet]=\"navigationItemContent\"> </ng-container>\n </a>\n }\n @if (!_item.routerLink) {\n <button\n uxFocusIndicator\n #navigationBtn\n type=\"button\"\n [tabindex]=\"_tabindex | async\"\n [attr.id]=\"_item.id\"\n role=\"menuitem\"\n class=\"horizontal-navigation-button\"\n [class.disabled]=\"_item.disabled\"\n [class.selected]=\"_item.selected\"\n (click)=\"select()\"\n [disabled]=\"_item.disabled\"\n >\n <ng-container [ngTemplateOutlet]=\"navigationItemContent\"> </ng-container>\n </button>\n }\n}\n\n<!-- Support all icon types -->\n<ng-template #navigationItemContent>\n @if (_item.icon) {\n @if (_iconType !== 'component') {\n <i\n class=\"navigation-item-icon\"\n [ngClass]=\"[_iconType, _item.icon]\"\n >\n </i>\n }\n @if (_iconType === 'component') {\n <ux-icon class=\"navigation-item-icon\" [name]=\"_item.icon\">\n </ux-icon>\n }\n }\n\n <span class=\"navigation-item-label\">{{ _item?.title }}</span>\n</ng-template>\n" }]
}], propDecorators: { item: [{
type: Input
}], navigationBtn: [{
type: ViewChild,
args: ['navigationBtn', { static: false }]
}], onKeydown: [{
type: HostListener,
args: ['keydown', ['$event', '$event.target']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF2aWdhdGlvbi1pdGVtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3BhZ2UtaGVhZGVyL25hdmlnYXRpb24vbmF2aWdhdGlvbi1pdGVtL25hdmlnYXRpb24taXRlbS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9wYWdlLWhlYWRlci9uYXZpZ2F0aW9uL25hdmlnYXRpb24taXRlbS9uYXZpZ2F0aW9uLWl0ZW0uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDdkUsT0FBTyxFQUFpQixTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFhLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN4SCxPQUFPLEVBQStCLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM1RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxFQUFFLFdBQVcsRUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUMxRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUU5RCxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQzs7Ozs7Ozs7O0FBTXBFLE1BQU0sT0FBTyxpQ0FBaUM7SUFKOUM7UUFLYSxlQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRXhCLHVCQUFrQixHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBRS9DLHVCQUFrQixHQUFHLE1BQU0sQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1FB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aUM7a0JBSjdDLFNBQVM7K0JBQ0ksMkNBQTJDOzhCQVd4QyxJQUFJO3NCQUFoQixLQUFLO2dCQXlCeUMsYUFBYTtzQkFBM0QsU0FBUzt1QkFBQyxlQUFlLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQTZDN0MsU0FBUztzQkFEUixZQUFZO3VCQUFDLFNBQVMsRUFBRSxDQUFDLFFBQVEsRUFBRSxlQUFlLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGb2N1c2FibGVPcHRpb24gfSBmcm9tICdAYW5ndWxhci9jZGsvYTExeSc7XG5pbXBvcnQgeyBMRUZUX0FSUk9XLCBSSUdIVF9BUlJPVywgU1BBQ0UgfSBmcm9tICdAYW5ndWxhci9jZGsva2V5Y29kZXMnO1xuaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBIb3N0TGlzdGVuZXIsIGluamVjdCwgSW5wdXQsIE9uRGVzdHJveSwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IGdldEljb25UeXBlLCBJY29uVHlwZSB9IGZyb20gJy4uLy4uLy4uLy4uL2NvbW1vbi9pbmRleCc7XG5pbXBvcnQgeyB0aWNrIH0gZnJvbSAnLi4vLi4vLi4vLi4vY29tbW9uL29wZXJhdG9ycy9pbmRleCc7XG5pbXBvcnQgeyBQYWdlSGVhZGVyU2VydmljZSB9IGZyb20gJy4uLy4uL3BhZ2UtaGVhZGVyLnNlcnZpY2UnO1xuaW1wb3J0IHR5cGUgeyBQYWdlSGVhZGVyTmF2aWdhdGlvbkl0ZW0gfSBmcm9tICcuLi9uYXZpZ2F0aW9uLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBQYWdlSGVhZGVyTmF2aWdhdGlvblNlcnZpY2UgfSBmcm9tICcuLi9uYXZpZ2F0aW9uLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ3V4LXBhZ2UtaGVhZGVyLWhvcml6b250YWwtbmF2aWdhdGlvbi1pdGVtJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vbmF2aWdhdGlvbi1pdGVtLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBQYWdlSGVhZGVyTmF2aWdhdGlvbkl0ZW1Db21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3ksIEZvY3VzYWJsZU9wdGlvbiB7XG4gICAgcmVhZG9ubHkgZWxlbWVudFJlZiA9IGluamVjdChFbGVtZW50UmVmKTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3BhZ2VIZWFkZXJTZXJ2aWNlID0gaW5qZWN0KFBhZ2VIZWFkZXJTZXJ2aWNlKTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX25hdmlnYXRpb25TZXJ2aWNlID0gaW5qZWN0KFBhZ2VIZWFkZXJOYXZpZ2F0aW9uU2VydmljZSk7XG5cbiAgICAvKiogQWNjZXNzIHRoZSBkYXRhIGZvciB0aGlzIGRyb3Bkb3duIGl0ZW0gKi9cbiAgICBASW5wdXQoKSBzZXQgaXRlbShpdGVtOiBQYWdlSGVhZGVyTmF2aWdhdGlvbkl0ZW0pIHtcbiAgICAgICAgdGhpcy5faXRlbSA9IGl0ZW07XG4gICAgICAgIHRoaXMuX2ljb25UeXBlID0gZ2V0SWNvblR5cGUoaXRlbS5pY29uKTtcbiAgICB9XG5cbiAgICBnZXQgaXRlbSgpOiBQYWdlSGVhZGVyTmF2aWdhdGlvbkl0ZW0ge1xuICAgICAgICByZXR1cm4gdGhpcy5faXRlbTtcbiAgICB9XG5cbiAgICAvKiogU3RvcmUgdGhlIHNlY29uZGFyeSBzdGF0ZSAqL1xuICAgIHNlY29uZGFyeSQ6IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPiA9IHRoaXMuX3BhZ2VIZWFkZXJTZXJ2aWNlLnNlY29uZGFyeSQ7XG5cbiAgICAvKiogU3RvcmUgdGhlIG9wZW4gc3RhdGUgb2YgdGhlIGl0ZW0gZHJvcGRvd24gKi9cbiAgICBpc09wZW46IGJvb2xlYW47XG5cbiAgICAvKiogU3RvcmUgdGhlIGl0ZW0gZGF0YSAqL1xuICAgIF9pdGVtOiBQYWdlSGVhZGVyTmF2aWdhdGlvbkl0ZW07XG5cbiAgICAvKiogU3RvcmUgdGhlIGljb24gdHlwZSAqL1xuICAgIF9pY29uVHlwZTogSWNvblR5cGU7XG5cbiAgICAvKiogVXBkYXRlIHRoZSB0YWJpbmRleCBiYXNlZCBvbiBrZXlib2FyZCBpbnB1dCAqL1xuICAgIF90YWJpbmRleDogT2JzZXJ2YWJsZTxudW1iZXI+ID0gdGhpcy5fbmF2aWdhdGlvblNlcnZpY2UuZ2V0VGFiSW5kZXgodGhpcyk7XG5cbiAgICAvKiogQWNjZXNzIHRoZSBuYXZpZ2F0aW9uIGJ1dHRvbiBlbGVtZW50ICovXG4gICAgQFZpZXdDaGlsZCgnbmF2aWdhdGlvbkJ0bicsIHsgc3RhdGljOiBmYWxzZSB9KSBuYXZpZ2F0aW9uQnRuOiBFbGVtZW50UmVmO1xuXG4gICAgLyoqIFVuc3Vic2NyaWJlIHdoZW4gdGhlIGNvbXBvbmVudCBpcyBkZXN0cm95ZWQgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9vbkRlc3Ryb3kgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gICAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9wYWdlSGVhZGVyU2VydmljZS5zZWxlY3RlZCQucGlwZSh0aWNrKCksIHRha2VVbnRpbCh0aGlzLl9vbkRlc3Ryb3kpKS5zdWJzY3JpYmUoc2VsZWN0ZWRJdGVtID0+IHtcblxuICAgICAgICAgICAgLy8gVXBkYXRlIHNlbGVjdGVkIHN0YXRlIGZvciB0aGlzIGl0ZW1cbiAgICAgICAgICAgIHRoaXMuX3BhZ2VIZWFkZXJTZXJ2aWNlLnVwZGF0ZUl0ZW0odGhpcy5pdGVtLCBzZWxlY3RlZEl0ZW0pO1xuXG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWRJdGVtICYmIHRoaXMuaXNPcGVuKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pc09wZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX29uRGVzdHJveS5uZXh0KCk7XG4gICAgICAgIHRoaXMuX29uRGVzdHJveS5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIGZvY3VzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm5hdmlnYXRpb25CdG4ubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgIH1cblxuICAgIHNlbGVjdCgpOiB2b2lkIHtcblxuICAgICAgICAvLyBpZiB0aGUgaXRlbSBpcyBkaXNhYmxlZCBvciBoYXMgY2hpbGRyZW4gdGhlbiBkbyBub3RoaW5nIGF0IHRoaXMgc3RhZ2VcbiAgICAgICAgaWYgKHRoaXMuaXRlbS5kaXNhYmxlZCB8fCAodGhpcy5pdGVtLmNoaWxkcmVuICYmIHRoaXMuX3BhZ2VIZWFkZXJTZXJ2aWNlLnNlY29uZGFyeSQuZ2V0VmFsdWUoKSA9PT0gZmFsc2UpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiBhdXRvc2VsZWN0IGlzIGVuYWJsZWQgdGhlIGZpcnN0IGNoaWxkIHNob3VsZCBiZSBzZWxlY3RlZCB3aGVuIHdlIGNsaWNrIG9uIHRoZSBwYXJlbnQgaXRlbSAodGhpcyBlbGVtZW50KS5cbiAgICAgICAgLy8gV2Ugc2hvdWxkIHJlbW92ZSB0aGUgc2VsZWN0ZWQgc3RhdGUgb24gYWxsIGNoaWxkcmVuIGFzIHRoZSBzZXJ2aWNlIHdpbGwgcGVyZm9ybSB0aGUgc2VsZWN0aW9uXG4gICAgICAgIC8vIG9mIHRoZSBmaXJzdCBpdGVtIGFuZCBoYW5kbGUgYW55IHJvdXRpbmcgZXRjLi5cbiAgICAgICAgaWYgKHRoaXMuX3BhZ2VIZWFkZXJTZXJ2aWNlLnNlY29uZGFyeU5hdmlnYXRpb25BdXRvc2VsZWN0ICYmIEFycmF5LmlzQXJyYXkodGhpcy5pdGVtLmNoaWxkcmVuKSkge1xuICAgICAgICAgICAgdGhpcy5pdGVtLmNoaWxkcmVuLmZvckVhY2goaXRlbSA9PiBpdGVtLnNlbGVjdGVkID0gZmFsc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gb3RoZXJ3aXNlIHNlbGVjdCB0aGUgY3VycmVudCBpdGVtXG4gICAgICAgIHRoaXMuX3BhZ2VIZWFkZXJTZXJ2aWNlLnNlbGVjdCh0aGlzLml0ZW0pO1xuICAgIH1cblxuICAgIEBIb3N0TGlzdGVuZXIoJ2tleWRvd24nLCBbJyRldmVudCcsICckZXZlbnQudGFyZ2V0J10pXG4gICAgb25LZXlkb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50LCB0YXJnZXQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG4gICAgICAgIGlmIChldmVudC5rZXlDb2RlID09PSBMRUZUX0FSUk9XIHx8IGV2ZW50LmtleUNvZGUgPT09IFJJR0hUX0FSUk9XKSB7XG4gICAgICAgICAgICB0aGlzLl9uYXZpZ2F0aW9uU2VydmljZS5vbktleWRvd24oZXZlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGV2ZW50LmtleUNvZGUgPT09IFNQQUNFKSB7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgdGFyZ2V0LmNsaWNrKCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCJAaWYgKF9pdGVtLmNoaWxkcmVuICYmIF9pdGVtLmNoaWxkcmVuLmxlbmd0aCA+IDAgJiYgKHNlY29uZGFyeSQgfCBhc3luYykgPT09IGZhbHNlKSB7XG4gIDxkaXY+XG4gICAgPGJ1dHRvblxuICAgICAgI25hdmlnYXRpb25CdG5cbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgW2F0dHIuaWRdPVwiX2l0ZW0uaWRcIlxuICAgICAgW3RhYmluZGV4XT1cIl90YWJpbmRleCB8IGFzeW5jXCJcbiAgICAgIFt1eE1lbnVUcmlnZ2VyRm9yXT1cIm1lbnVcIlxuICAgICAgW2Rpc2FibGVkXT1cIl9pdGVtLmRpc2FibGVkXCJcbiAgICAgIHJvbGU9XCJtZW51aXRlbVwiXG4gICAgICBjbGFzcz1cImhvcml6b250YWwtbmF2aWdhdGlvbi1idXR0b25cIlxuICAgICAgW2NsYXNzLmRpc2FibGVkXT1cIl9pdGVtLmRpc2FibGVkXCJcbiAgICAgIFtjbGFzcy5zZWxlY3RlZF09XCJfaXRlbS5zZWxlY3RlZFwiXG4gICAgICBbY2xhc3Mub3Blbl09XCJpc09wZW5cIlxuICAgICAgPlxuICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJuYXZpZ2F0aW9uSXRlbUNvbnRlbnRcIj4gPC9uZy1jb250YWluZXI+XG4gICAgICA8dXgtaWNvbiBjbGFzcz1cIm5hdmlnYXRpb24taXRlbS1kcm9wZG93bi1pY29uXCIgbmFtZT1cImRvd25cIj48L3V4LWljb24+XG4gICAgPC9idXR0b24+XG4gICAgPHV4LW1lbnVcbiAgICAgICNtZW51XG4gICAgICBtZW51Q2xhc3M9XCJob3Jpem9udGFsLW5hdmlnYXRpb24tZHJvcGRvd24tbWVudVwiXG4gICAgICAob3BlbmVkKT1cImlzT3BlbiA9IHRydWVcIlxuICAgICAgKGNsb3NlZCk9XCJpc09wZW4gPSBmYWxzZVwiXG4gICAgICA+XG4gICAgICBAZm9yIChpdGVtIG9mIF9pdGVtPy5jaGlsZHJlbjsgdHJhY2sgaXRlbSkge1xuICAgICAgICA8dXgtcGFnZS1oZWFkZXItaG9yaXpvbnRhbC1uYXZpZ2F0aW9uLWRyb3Bkb3duLWl0ZW1cbiAgICAgICAgICBbaXRlbV09XCJpdGVtXCJcbiAgICAgICAgICA+XG4gICAgICAgIDwvdXgtcGFnZS1oZWFkZXItaG9yaXpvbnRhbC1uYXZpZ2F0aW9uLWRyb3Bkb3duLWl0ZW0+XG4gICAgICB9XG4gICAgPC91eC1tZW51PlxuICA8L2Rpdj5cbn1cblxuQGlmICghX2l0ZW0uY2hpbGRyZW4gfHwgX2l0ZW0uY2hpbGRyZW4ubGVuZ3RoID09PSAwIHx8IChzZWNvbmRhcnkkIHwgYXN5bmMpKSB7XG4gIEBpZiAoX2l0ZW0ucm91dGVyTGluaykge1xuICAgIDxhXG4gICAgICB1eEZvY3VzSW5kaWNhdG9yXG4gICAgICAjbmF2aWdhdGlvbkJ0blxuICAgICAgW3RhYmluZGV4XT1cIl90YWJpbmRleCB8IGFzeW5jXCJcbiAgICAgIFthdHRyLmlkXT1cIl9pdGVtLmlkXCJcbiAgICAgIHJvbGU9XCJtZW51aXRlbVwiXG4gICAgICBjbGFzcz1cImhvcml6b250YWwtbmF2aWdhdGlvbi1idXR0b25cIlxuICAgICAgW2NsYXNzLmRpc2FibGVkXT1cIl9pdGVtLmRpc2FibGVkXCJcbiAgICAgIFtjbGFzcy5zZWxlY3RlZF09XCJfaXRlbS5zZWxlY3RlZFwiXG4gICAgICBbcm91dGVyTGlua109XCJfaXRlbS5yb3V0ZXJMaW5rXCJcbiAgICAgIFtmcmFnbWVudF09XCJfaXRlbS5yb3V0ZXJFeHRyYXM/LmZyYWdtZW50XCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJfaXRlbS5yb3V0ZXJFeHRyYXM/LnF1ZXJ5UGFyYW1zXCJcbiAgICAgIFtxdWVyeVBhcmFtc0hhbmRsaW5nXT1cIl9pdGVtLnJvdXRlckV4dHJhcz8ucXVlcnlQYXJhbXNIYW5kbGluZ1wiXG4gICAgICBbcHJlc2VydmVGcmFnbWVudF09XCJfaXRlbS5yb3V0ZXJFeHRyYXM/LnByZXNlcnZlRnJhZ21lbnRcIlxuICAgICAgW3NraXBMb2NhdGlvbkNoYW5nZV09XCJfaXRlbS5yb3V0ZXJFeHRyYXM/LnNraXBMb2NhdGlvbkNoYW5nZVwiXG4gICAgICBbcmVwbGFjZVVybF09XCJfaXRlbS5yb3V0ZXJFeHRyYXM/LnJlcGxhY2VVcmxcIlxuICAgICAgW3N0YXRlXT1cIl9pdGVtLnJvdXRlckV4dHJhcz8uc3RhdGVcIlxuICAgICAgPlxuICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJuYXZpZ2F0aW9uSXRlbUNvbnRlbnRcIj4gPC9uZy1jb250YWluZXI+XG4gICAgPC9hPlxuICB9XG4gIEBpZiAoIV9pdGVtLnJvdXRlckxpbmspIHtcbiAgICA8YnV0dG9uXG4gICAgICB1eEZvY3VzSW5kaWNhdG9yXG4gICAgICAjbmF2aWdhdGlvbkJ0blxuICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICBbdGFiaW5kZXhdPVwiX3RhYmluZGV4IHwgYXN5bmNcIlxuICAgICAgW2F0dHIuaWRdPVwiX2l0ZW0uaWRcIlxuICAgICAgcm9sZT1cIm1lbnVpdGVtXCJcbiAgICAgIGNsYXNzPVwiaG9yaXpvbnRhbC1uYXZpZ2F0aW9uLWJ1dHRvblwiXG4gICAgICBbY2xhc3MuZGlzYWJsZWRdPVwiX2l0ZW0uZGlzYWJsZWRcIlxuICAgICAgW2NsYXNzLnNlbGVjdGVkXT1cIl9pdGVtLnNlbGVjdGVkXCJcbiAgICAgIChjbGljayk9XCJzZWxlY3QoKVwiXG4gICAgICBbZGlzYWJsZWRdPVwiX2l0ZW0uZGlzYWJsZWRcIlxuICAgICAgPlxuICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJuYXZpZ2F0aW9uSXRlbUNvbnRlbnRcIj4gPC9uZy1jb250YWluZXI+XG4gICAgPC9idXR0b24+XG4gIH1cbn1cblxuPCEtLSBTdXBwb3J0IGFsbCBpY29uIHR5cGVzIC0tPlxuPG5nLXRlbXBsYXRlICNuYXZpZ2F0aW9uSXRlbUNvbnRlbnQ+XG4gIEBpZiAoX2l0ZW0uaWNvbikge1xuICAgIEBpZiAoX2ljb25UeXBlICE9PSAnY29tcG9uZW50Jykge1xuICAgICAgPGlcbiAgICAgICAgY2xhc3M9XCJuYXZpZ2F0aW9uLWl0ZW0taWNvblwiXG4gICAgICAgIFtuZ0NsYXNzXT1cIltfaWNvblR5cGUsIF9pdGVtLmljb25dXCJcbiAgICAgICAgPlxuICAgICAgPC9pPlxuICAgIH1cbiAgICBAaWYgKF9pY29uVHlwZSA9PT0gJ2NvbXBvbmVudCcpIHtcbiAgICAgIDx1eC1pY29uIGNsYXNzPVwibmF2aWdhdGlvbi1pdGVtLWljb25cIiBbbmFtZV09XCJfaXRlbS5pY29uXCI+XG4gICAgICA8L3V4LWljb24+XG4gICAgfVxuICB9XG5cbiAgPHNwYW4gY2xhc3M9XCJuYXZpZ2F0aW9uLWl0ZW0tbGFiZWxcIj57eyBfaXRlbT8udGl0bGUgfX08L3NwYW4+XG48L25nLXRlbXBsYXRlPlxuIl19