@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
170 lines • 20.5 kB
JavaScript
import { DOWN_ARROW, END, ESCAPE, HOME, LEFT_ARROW, RIGHT_ARROW, UP_ARROW } from '@angular/cdk/keycodes';
import { Directive, EventEmitter, HostListener, inject, Input, Output } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { MenuNavigationService } from './menu-navigation.service';
import * as i0 from "@angular/core";
export class MenuNavigationDirective {
constructor() {
this._menuNavigationService = inject(MenuNavigationService);
/** Define the position of the toggle button relative to the menu */
this.toggleButtonPosition = 'top';
/** Emit when the menu is no longer focused */
this.navigatedOut = new EventEmitter();
/** Determine if the menu currently has focus */
this._isFocused = false;
/** Unsubscribe from all observables on destroy */
this._onDestroy = new Subject();
}
/** Get the index of the currently active item */
get activeIndex() {
return this.menuItems.indexOf(this._menuNavigationService.active$.value);
}
// get the list of menu items
get menuItems() {
return this._menuNavigationService.menuItems;
}
ngOnInit() {
if (this.toggleButton) {
this.toggleButton.keyEnter.pipe(takeUntil(this._onDestroy))
.subscribe(() => this.focusFirst());
}
}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
focusFirst() {
this.moveFirst();
}
onFocusIn() {
this._isFocused = true;
}
onFocusOut() {
this._isFocused = false;
}
keydownHandler(event) {
// Only handle events when focus in within the list of menu items
if (this._isFocused === false) {
return;
}
let handled = false;
switch (event.which) {
case UP_ARROW:
this.movePrevious(event);
handled = true;
break;
case DOWN_ARROW:
this.moveNext(event);
handled = true;
break;
case LEFT_ARROW:
if (this.toggleButtonPosition === 'left') {
this.moveToToggleButton(event);
handled = true;
}
break;
case RIGHT_ARROW:
if (this.toggleButtonPosition === 'right') {
this.moveToToggleButton(event);
handled = true;
}
break;
case HOME:
this.moveFirst();
handled = true;
break;
case END:
this.moveLast();
handled = true;
break;
case ESCAPE:
this.moveToToggleButton(event);
handled = true;
break;
}
if (handled) {
event.preventDefault();
event.stopPropagation();
}
}
moveNext(event) {
// Do nothing if there's no active menu item registered
if (this.activeIndex < 0) {
return;
}
const nextIndex = this.activeIndex + 1;
if (nextIndex < this.menuItems.length) {
// Activate the next menu item
// (uxMenuNavigationItem subscribes to this and applies focus if it matches)
this._menuNavigationService.active$.next(this.menuItems[nextIndex]);
}
else {
// Check if focus went out of bounds in the direction of the origin toggle button
if (this.toggleButtonPosition === 'bottom') {
this.moveToToggleButton(event);
}
}
}
movePrevious(event) {
// Do nothing if there's no active menu item registered
if (this.activeIndex < 0) {
return;
}
const nextIndex = this.activeIndex - 1;
if (nextIndex >= 0) {
// Activate the previous menu item
// (uxMenuNavigationItem subscribes to this and applies focus if it matches)
this._menuNavigationService.active$.next(this.menuItems[nextIndex]);
}
else {
// Check if focus went out of bounds in the direction of the origin toggle button
if (this.toggleButtonPosition === 'top') {
this.moveToToggleButton(event);
}
}
}
moveFirst() {
if (this.menuItems.length > 0) {
this._menuNavigationService.active$.next(this.menuItems[0]);
}
}
moveLast() {
if (this.menuItems.length > 0) {
this._menuNavigationService.active$.next(this.menuItems[this.menuItems.length - 1]);
}
}
moveToToggleButton(event) {
if (this.toggleButton) {
this.toggleButton.focus('keyboard');
this.toggleButton.menuOpen = false;
}
this.navigatedOut.emit(event);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: MenuNavigationDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.12", type: MenuNavigationDirective, selector: "[uxMenuNavigation]", inputs: { toggleButton: "toggleButton", toggleButtonPosition: "toggleButtonPosition" }, outputs: { navigatedOut: "navigatedOut" }, host: { listeners: { "focusin": "onFocusIn()", "focusout": "onFocusOut()", "keydown": "keydownHandler($event)" } }, providers: [MenuNavigationService], exportAs: ["uxMenuNavigation"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: MenuNavigationDirective, decorators: [{
type: Directive,
args: [{
selector: '[uxMenuNavigation]',
exportAs: 'uxMenuNavigation',
providers: [MenuNavigationService]
}]
}], propDecorators: { toggleButton: [{
type: Input
}], toggleButtonPosition: [{
type: Input
}], navigatedOut: [{
type: Output
}], onFocusIn: [{
type: HostListener,
args: ['focusin']
}], onFocusOut: [{
type: HostListener,
args: ['focusout']
}], keydownHandler: [{
type: HostListener,
args: ['keydown', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVudS1uYXZpZ2F0aW9uLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9kaXJlY3RpdmVzL21lbnUtbmF2aWdhdGlvbi9tZW51LW5hdmlnYXRpb24uZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN6RyxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBcUIsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hILE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRzNDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDOztBQU9sRSxNQUFNLE9BQU8sdUJBQXVCO0lBTHBDO1FBTXFCLDJCQUFzQixHQUFHLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBS3hFLG9FQUFvRTtRQUMzRCx5QkFBb0IsR0FBd0MsS0FBSyxDQUFDO1FBRTNFLDhDQUE4QztRQUNwQyxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFpQixDQUFDO1FBWTNELGdEQUFnRDtRQUN4QyxlQUFVLEdBQVksS0FBSyxDQUFDO1FBRXBDLGtEQUFrRDtRQUNqQyxlQUFVLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztLQXdKckQ7SUF0S0csaURBQWlEO0lBQ2pELElBQUksV0FBVztRQUNYLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM3RSxDQUFDO0lBRUQsNkJB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LENBQUM7SUFFTyxRQUFRO1FBQ1osSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM1QixJQUFJLENBQUMsc0JBQXNCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEYsQ0FBQztJQUNMLENBQUM7SUFFTyxrQkFBa0IsQ0FBQyxLQUFvQjtRQUMzQyxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNwQixJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNwQyxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7UUFDdkMsQ0FBQztRQUVELElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2xDLENBQUM7K0dBakxRLHVCQUF1QjttR0FBdkIsdUJBQXVCLG9TQUZyQixDQUFDLHFCQUFxQixDQUFDOzs0RkFFekIsdUJBQXVCO2tCQUxuQyxTQUFTO21CQUFDO29CQUNQLFFBQVEsRUFBRSxvQkFBb0I7b0JBQzlCLFFBQVEsRUFBRSxrQkFBa0I7b0JBQzVCLFNBQVMsRUFBRSxDQUFDLHFCQUFxQixDQUFDO2lCQUNyQzs4QkFLWSxZQUFZO3NCQUFwQixLQUFLO2dCQUdHLG9CQUFvQjtzQkFBNUIsS0FBSztnQkFHSSxZQUFZO3NCQUFyQixNQUFNO2dCQW1DUCxTQUFTO3NCQURSLFlBQVk7dUJBQUMsU0FBUztnQkFNdkIsVUFBVTtzQkFEVCxZQUFZO3VCQUFDLFVBQVU7Z0JBTXhCLGNBQWM7c0JBRGIsWUFBWTt1QkFBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBET1dOX0FSUk9XLCBFTkQsIEVTQ0FQRSwgSE9NRSwgTEVGVF9BUlJPVywgUklHSFRfQVJST1csIFVQX0FSUk9XIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2tleWNvZGVzJztcbmltcG9ydCB7IERpcmVjdGl2ZSwgRXZlbnRFbWl0dGVyLCBIb3N0TGlzdGVuZXIsIGluamVjdCwgSW5wdXQsIE9uRGVzdHJveSwgT25Jbml0LCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IE1lbnVOYXZpZ2F0aW9uSXRlbURpcmVjdGl2ZSB9IGZyb20gJy4vbWVudS1uYXZpZ2F0aW9uLWl0ZW0uZGlyZWN0aXZlJztcbmltcG9ydCB7IE1lbnVOYXZpZ2F0aW9uVG9nZ2xlRGlyZWN0aXZlIH0gZnJvbSAnLi9tZW51LW5hdmlnYXRpb24tdG9nZ2xlLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBNZW51TmF2aWdhdGlvblNlcnZpY2UgfSBmcm9tICcuL21lbnUtbmF2aWdhdGlvbi5zZXJ2aWNlJztcblxuQERpcmVjdGl2ZSh7XG4gICAgc2VsZWN0b3I6ICdbdXhNZW51TmF2aWdhdGlvbl0nLFxuICAgIGV4cG9ydEFzOiAndXhNZW51TmF2aWdhdGlvbicsXG4gICAgcHJvdmlkZXJzOiBbTWVudU5hdmlnYXRpb25TZXJ2aWNlXVxufSlcbmV4cG9ydCBjbGFzcyBNZW51TmF2aWdhdGlvbkRpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9tZW51TmF2aWdhdGlvblNlcnZpY2UgPSBpbmplY3QoTWVudU5hdmlnYXRpb25TZXJ2aWNlKTtcblxuICAgIC8qKiBEZWZpbmUgdGhlIG1lbnUgdG9nZ2xlIGJ1dHRvbiAqL1xuICAgIEBJbnB1dCgpIHRvZ2dsZUJ1dHRvbjogTWVudU5hdmlnYXRpb25Ub2dnbGVEaXJlY3RpdmU7XG5cbiAgICAvKiogRGVmaW5lIHRoZSBwb3NpdGlvbiBvZiB0aGUgdG9nZ2xlIGJ1dHRvbiByZWxhdGl2ZSB0byB0aGUgbWVudSAqL1xuICAgIEBJbnB1dCgpIHRvZ2dsZUJ1dHRvblBvc2l0aW9uOiAndG9wJyB8ICdyaWdodCcgfCAnYm90dG9tJyB8ICdsZWZ0JyA9ICd0b3AnO1xuXG4gICAgLyoqIEVtaXQgd2hlbiB0aGUgbWVudSBpcyBubyBsb25nZXIgZm9jdXNlZCAqL1xuICAgIEBPdXRwdXQoKSBuYXZpZ2F0ZWRPdXQgPSBuZXcgRXZlbnRFbWl0dGVyPEtleWJvYXJkRXZlbnQ+KCk7XG5cbiAgICAvKiogR2V0IHRoZSBpbmRleCBvZiB0aGUgY3VycmVudGx5IGFjdGl2ZSBpdGVtICovXG4gICAgZ2V0IGFjdGl2ZUluZGV4KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lbnVJdGVtcy5pbmRleE9mKHRoaXMuX21lbnVOYXZpZ2F0aW9uU2VydmljZS5hY3RpdmUkLnZhbHVlKTtcbiAgICB9XG5cbiAgICAvLyBnZXQgdGhlIGxpc3Qgb2YgbWVudSBpdGVtc1xuICAgIGdldCBtZW51SXRlbXMoKTogUmVhZG9ubHlBcnJheTxNZW51TmF2aWdhdGlvbkl0ZW1EaXJlY3RpdmU+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21lbnVOYXZpZ2F0aW9uU2VydmljZS5tZW51SXRlbXM7XG4gICAgfVxuXG4gICAgLyoqIERldGVybWluZSBpZiB0aGUgbWVudSBjdXJyZW50bHkgaGFzIGZvY3VzICovXG4gICAgcHJpdmF0ZSBfaXNGb2N1c2VkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogVW5zdWJzY3JpYmUgZnJvbSBhbGwgb2JzZXJ2YWJsZXMgb24gZGVzdHJveSAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX29uRGVzdHJveSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMudG9nZ2xlQnV0dG9uKSB7XG4gICAgICAgICAgICB0aGlzLnRvZ2dsZUJ1dHRvbi5rZXlFbnRlci5waXBlKHRha2VVbnRpbCh0aGlzLl9vbkRlc3Ryb3kpKVxuICAgICAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5mb2N1c0ZpcnN0KCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX29uRGVzdHJveS5uZXh0KCk7XG4gICAgICAgIHRoaXMuX29uRGVzdHJveS5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIGZvY3VzRmlyc3QoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubW92ZUZpcnN0KCk7XG4gICAgfVxuXG4gICAgQEhvc3RMaXN0ZW5lcignZm9jdXNpbicpXG4gICAgb25Gb2N1c0luKCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9pc0ZvY3VzZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIEBIb3N0TGlzdGVuZXIoJ2ZvY3Vzb3V0JylcbiAgICBvbkZvY3VzT3V0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9pc0ZvY3VzZWQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBASG9zdExpc3RlbmVyKCdrZXlkb3duJywgWyckZXZlbnQnXSlcbiAgICBrZXlkb3duSGFuZGxlcihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuXG4gICAgICAgIC8vIE9ubHkgaGFuZGxlIGV2ZW50cyB3aGVuIGZvY3VzIGluIHdpdGhpbiB0aGUgbGlzdCBvZiBtZW51IGl0ZW1zXG4gICAgICAgIGlmICh0aGlzLl9pc0ZvY3VzZWQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgaGFuZGxlZCA9IGZhbHNlO1xuXG4gICAgICAgIHN3aXRjaCAoZXZlbnQud2hpY2gpIHtcblxuICAgICAgICAgICAgY2FzZSBVUF9BUlJPVzpcbiAgICAgICAgICAgICAgICB0aGlzLm1vdmVQcmV2aW91cyhldmVudCk7XG4gICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgRE9XTl9BUlJPVzpcbiAgICAgICAgICAgICAgICB0aGlzLm1vdmVOZXh0KGV2ZW50KTtcbiAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSBMRUZUX0FSUk9XOlxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnRvZ2dsZUJ1dHRvblBvc2l0aW9uID09PSAnbGVmdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tb3ZlVG9Ub2dnbGVCdXR0b24oZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgUklHSFRfQVJST1c6XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudG9nZ2xlQnV0dG9uUG9zaXRpb24gPT09ICdyaWdodCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tb3ZlVG9Ub2dnbGVCdXR0b24oZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgSE9NRTpcbiAgICAgICAgICAgICAgICB0aGlzLm1vdmVGaXJzdCgpO1xuICAgICAgICAgICAgICAgIGhhbmRsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlIEVORDpcbiAgICAgICAgICAgICAgICB0aGlzLm1vdmVMYXN0KCk7XG4gICAgICAgICAgICAgICAgaGFuZGxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgRVNDQVBFOlxuICAgICAgICAgICAgICAgIHRoaXMubW92ZVRvVG9nZ2xlQnV0dG9uKGV2ZW50KTtcbiAgICAgICAgICAgICAgICBoYW5kbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChoYW5kbGVkKSB7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG1vdmVOZXh0KGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG5cbiAgICAgICAgLy8gRG8gbm90aGluZyBpZiB0aGVyZSdzIG5vIGFjdGl2ZSBtZW51IGl0ZW0gcmVnaXN0ZXJlZFxuICAgICAgICBpZiAodGhpcy5hY3RpdmVJbmRleCA8IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG5leHRJbmRleCA9IHRoaXMuYWN0aXZlSW5kZXggKyAxO1xuICAgICAgICBpZiAobmV4dEluZGV4IDwgdGhpcy5tZW51SXRlbXMubGVuZ3RoKSB7XG5cbiAgICAgICAgICAgIC8vIEFjdGl2YXRlIHRoZSBuZXh0IG1lbnUgaXRlbVxuICAgICAgICAgICAgLy8gKHV4TWVudU5hdmlnYXRpb25JdGVtIHN1YnNjcmliZXMgdG8gdGhpcyBhbmQgYXBwbGllcyBmb2N1cyBpZiBpdCBtYXRjaGVzKVxuICAgICAgICAgICAgdGhpcy5fbWVudU5hdmlnYXRpb25TZXJ2aWNlLmFjdGl2ZSQubmV4dCh0aGlzLm1lbnVJdGVtc1tuZXh0SW5kZXhdKTtcblxuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiBmb2N1cyB3ZW50IG91dCBvZiBib3VuZHMgaW4gdGhlIGRpcmVjdGlvbiBvZiB0aGUgb3JpZ2luIHRvZ2dsZSBidXR0b25cbiAgICAgICAgICAgIGlmICh0aGlzLnRvZ2dsZUJ1dHRvblBvc2l0aW9uID09PSAnYm90dG9tJykge1xuICAgICAgICAgICAgICAgIHRoaXMubW92ZVRvVG9nZ2xlQnV0dG9uKGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgbW92ZVByZXZpb3VzKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG5cbiAgICAgICAgLy8gRG8gbm90aGluZyBpZiB0aGVyZSdzIG5vIGFjdGl2ZSBtZW51IGl0ZW0gcmVnaXN0ZXJlZFxuICAgICAgICBpZiAodGhpcy5hY3RpdmVJbmRleCA8IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG5leHRJbmRleCA9IHRoaXMuYWN0aXZlSW5kZXggLSAxO1xuICAgICAgICBpZiAobmV4dEluZGV4ID49IDApIHtcblxuICAgICAgICAgICAgLy8gQWN0aXZhdGUgdGhlIHByZXZpb3VzIG1lbnUgaXRlbVxuICAgICAgICAgICAgLy8gKHV4TWVudU5hdmlnYXRpb25JdGVtIHN1YnNjcmliZXMgdG8gdGhpcyBhbmQgYXBwbGllcyBmb2N1cyBpZiBpdCBtYXRjaGVzKVxuICAgICAgICAgICAgdGhpcy5fbWVudU5hdmlnYXRpb25TZXJ2aWNlLmFjdGl2ZSQubmV4dCh0aGlzLm1lbnVJdGVtc1tuZXh0SW5kZXhdKTtcblxuICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiBmb2N1cyB3ZW50IG91dCBvZiBib3VuZHMgaW4gdGhlIGRpcmVjdGlvbiBvZiB0aGUgb3JpZ2luIHRvZ2dsZSBidXR0b25cbiAgICAgICAgICAgIGlmICh0aGlzLnRvZ2dsZUJ1dHRvblBvc2l0aW9uID09PSAndG9wJykge1xuICAgICAgICAgICAgICAgIHRoaXMubW92ZVRvVG9nZ2xlQnV0dG9uKGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgbW92ZUZpcnN0KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZW51SXRlbXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5fbWVudU5hdmlnYXRpb25TZXJ2aWNlLmFjdGl2ZSQubmV4dCh0aGlzLm1lbnVJdGVtc1swXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG1vdmVMYXN0KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5tZW51SXRlbXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5fbWVudU5hdmlnYXRpb25TZXJ2aWNlLmFjdGl2ZSQubmV4dCh0aGlzLm1lbnVJdGVtc1t0aGlzLm1lbnVJdGVtcy5sZW5ndGggLSAxXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG1vdmVUb1RvZ2dsZUJ1dHRvbihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy50b2dnbGVCdXR0b24pIHtcbiAgICAgICAgICAgIHRoaXMudG9nZ2xlQnV0dG9uLmZvY3VzKCdrZXlib2FyZCcpO1xuICAgICAgICAgICAgdGhpcy50b2dnbGVCdXR0b24ubWVudU9wZW4gPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubmF2aWdhdGVkT3V0LmVtaXQoZXZlbnQpO1xuICAgIH1cbn0iXX0=