UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

208 lines 30.9 kB
import { Platform } from '@angular/cdk/platform'; import { ChangeDetectorRef, Directive, ElementRef, EventEmitter, HostListener, inject, Input, Output, Renderer2 } from '@angular/core'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { tick } from '../../../common/index'; import { FocusIndicatorOriginService } from '../focus-indicator/focus-indicator-origin/focus-indicator-origin.service'; import { FocusIndicatorService } from '../focus-indicator/focus-indicator.service'; import { ManagedFocusContainerService } from '../managed-focus-container/managed-focus-container.service'; import { TabbableListService } from './tabbable-list.service'; import * as i0 from "@angular/core"; let nextId = 0; let uniqueKey = 0; export class TabbableListItemDirective { /** Provide a unique key to help identify items when used in a virtual list */ set key(key) { // store the previous key const previousKey = this._key; // check if the key has changed eg. via cell reuse const didChangeRef = previousKey && key !== previousKey; // update the current key this._key = key; // if this element was the previously tabbable item then update the reference if (didChangeRef && this.isTabbable()) { // allow the virtual scroll to update this._changeDetector.detectChanges(); // this item should no longer be tabbable this._tabbableList.focusKeyManager.updateActiveItem(-1); // store the focus origin before we blur const origin = this._focusOrigin; // blur this item this._elementRef.nativeElement.blur(); // update the reference this._tabbableList.itemReferenceChange(previousKey, origin); } } get key() { return this._key || this._defaultKey; } get tabindex() { return this._tabbableList.isItemActive(this) ? 0 : -1; } constructor() { /** Access the service to programmatically control focus indicators */ this.focusIndicatorService = inject(FocusIndicatorService); /** Access the tabbable list service */ this._tabbableList = inject(TabbableListService); /** Access the tabbable item element */ this._elementRef = inject(ElementRef); /** Access the service responsible for handling focus in child elements */ this._managedFocusContainerService = inject(ManagedFocusContainerService); /** Access the service which can provide us with browser identification */ this._platform = inject(Platform); /** Access the change detector to ensure tabindex gets updated as expects */ this._changeDetector = inject(ChangeDetectorRef); /** Access the focus origin if one is provided */ this._focusOriginService = inject(FocusIndicatorOriginService); /** Access the renderer to make manual dom manipulations */ this._renderer = inject(Renderer2); this.rank = 0; /** Indicate if this item is disabled */ this.disabled = false; /** Indicate if the item is expanded if used as a hierarchical item. */ this.expanded = false; /** Emit when the expanded state changes. */ this.expandedChange = new EventEmitter(); /** Emit when the element receives focus via the tabbable list. */ this.activated = new EventEmitter(); /** Give each tabbable item a unique id */ this.id = nextId++; /** Each item in the list needs to be initialised by the service. When the item QueryList changes this is used to identify which items previously existed and which are new */ this.initialized = false; /** Store a list of all child tabbable items */ this.children = []; /** Emit whenever the expanded state changes */ this.keyboardExpanded$ = new Subject(); /** Automatically unsubscribe from all observables */ this._onDestroy = new Subject(); /** Store a default key to use if one is not provided */ this._defaultKey = `tabbable-list-key-${uniqueKey++}`; /** Determine if this element has a focus indicator visible */ this._focusOrigin = null; // create the focus indicator this._focusIndicator = this.focusIndicatorService.monitor(this._elementRef.nativeElement); // store the most current focus origin this._focusIndicator.origin$.pipe(takeUntil(this._onDestroy)) .subscribe(origin => this._focusOrigin = origin); // watch for changes to tabindexes this._tabbableList.onTabIndexChange.pipe(takeUntil(this._onDestroy)) .subscribe(() => this.setTabIndex()); this.keyboardExpanded$.pipe(tick(), takeUntil(this._onDestroy)).subscribe(expanded => { // Emit event which may alter the DOM this.expandedChange.emit(expanded); // Activate the appropriate item if (expanded) { if (this.children.length > 0) { this._tabbableList.activate(this.children[0]); } } else { this._tabbableList.activate(this); } }); } onInit() { this.initialized = true; // Watch for focus within the container element and manage tabindex of descendants this._managedFocusContainerService.register(this._elementRef.nativeElement, this); // ensure the tab index is initially set this.setTabIndex(); } ngOnDestroy() { // check if this is the currently focused item - if so we need to make another item tabbable if (this.tabindex === 0) { this._tabbableList.setFirstItemTabbable(); } this._onDestroy.next(); this._onDestroy.complete(); this._focusIndicator.destroy(); this._managedFocusContainerService.unregister(this._elementRef.nativeElement, this); } focus() { // check if there are currently any items that are tabbable const hasTabbableItem = this._tabbableList.hasTabbableItem(); // determine the focus origin const origin = hasTabbableItem ? this._focusOriginService.getOrigin() || 'keyboard' : 'keyboard'; // apply focus to the element this.focusWithOrigin(origin, !this._tabbableList.shouldScrollInView); // ensure the focus key manager updates the active item correctly this._tabbableList.activate(this, hasTabbableItem); // emit the focus event this.activated.emit(origin); } onFocus() { // if this item is not currently focused in the focusKeyManager set it as the active item if (!this._tabbableList.isItemActive(this)) { this._tabbableList.activate(this, true); } // also inform the service that an item within the list is now focused this._tabbableList.isFocused = true; } onBlur() { // if this is the current active item and it is blurred then update the isFocused state if (this._tabbableList.isItemActive(this)) { this._tabbableList.isFocused = false; } } onKeydown(event) { this._tabbableList.onKeydown(this, event); } getFocused() { return this._elementRef.nativeElement === document.activeElement; } /** We can programmatically focus an element but may want a different origin than 'programmatic' */ focusWithOrigin(origin, preventScroll = true) { if (origin) { const scrollTop = this._tabbableList.containerRef.scrollTop; // focus the item with a given origin this._focusIndicator.focus(origin, { preventScroll }); // IE and Firefox don't support prevent scroll if (preventScroll && !this._platform.WEBKIT) { this._tabbableList.containerRef.scrollTop = scrollTop; } } } isTabbable() { return this.tabindex === 0; } setTabIndex() { // update the tabindex attribute this._renderer.setAttribute(this._elementRef.nativeElement, 'tabindex', this.tabindex.toString()); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TabbableListItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.12", type: TabbableListItemDirective, selector: "[uxTabbableListItem]", inputs: { parent: "parent", rank: "rank", disabled: "disabled", expanded: "expanded", key: "key" }, outputs: { expandedChange: "expandedChange", activated: "activated" }, host: { listeners: { "focus": "onFocus()", "click": "onFocus()", "blur": "onBlur()", "keydown": "onKeydown($event)" } }, exportAs: ["ux-tabbable-list-item"], ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: TabbableListItemDirective, decorators: [{ type: Directive, args: [{ selector: '[uxTabbableListItem]', exportAs: 'ux-tabbable-list-item' }] }], ctorParameters: () => [], propDecorators: { parent: [{ type: Input }], rank: [{ type: Input }], disabled: [{ type: Input }], expanded: [{ type: Input }], key: [{ type: Input }], expandedChange: [{ type: Output }], activated: [{ type: Output }], onFocus: [{ type: HostListener, args: ['focus'] }, { type: HostListener, args: ['click'] }], onBlur: [{ type: HostListener, args: ['blur'] }], onKeydown: [{ type: HostListener, args: ['keydown', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFiYmFibGUtbGlzdC1pdGVtLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9kaXJlY3RpdmVzL2FjY2Vzc2liaWxpdHkvdGFiYmFibGUtbGlzdC90YWJiYWJsZS1saXN0LWl0ZW0uZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQWEsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNsSixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFN0MsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sMEVBQTBFLENBQUM7QUFDdkgsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDbkYsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sNERBQTRELENBQUM7QUFDMUcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7O0FBRTlELElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztBQUNmLElBQUksU0FBUyxHQUFHLENBQUMsQ0FBQztBQU1sQixNQUFNLE9BQU8seUJBQXlCO0lBOEJsQyw4RUFBOEU7SUFFOUUsSUFBYSxHQUFHLENBQUMsR0FBUTtRQUVyQix5QkFBeUI7UUFDekIsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztRQUU5QixrREFBa0Q7UUFDbEQsTUFBTSxZQUFZLEdBQUcsV0FBVyxJQUFJLEdBQUcs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QUFJLENBQUMsUUFBUSxLQUFLLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRU8sV0FBVztRQUNmLGdDQUFnQztRQUNoQyxJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ3RHLENBQUM7K0dBdk9RLHlCQUF5QjttR0FBekIseUJBQXlCOzs0RkFBekIseUJBQXlCO2tCQUpyQyxTQUFTO21CQUFDO29CQUNQLFFBQVEsRUFBRSxzQkFBc0I7b0JBQ2hDLFFBQVEsRUFBRSx1QkFBdUI7aUJBQ3BDO3dEQXFCWSxNQUFNO3NCQUFkLEtBQUs7Z0JBRUcsSUFBSTtzQkFBWixLQUFLO2dCQUdHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBR0csUUFBUTtzQkFBaEIsS0FBSztnQkFJTyxHQUFHO3NCQUFmLEtBQUs7Z0JBcUNJLGNBQWM7c0JBQXZCLE1BQU07Z0JBR0csU0FBUztzQkFBbEIsTUFBTTtnQkE0R1AsT0FBTztzQkFGTixZQUFZO3VCQUFDLE9BQU87O3NCQUNwQixZQUFZO3VCQUFDLE9BQU87Z0JBWXJCLE1BQU07c0JBREwsWUFBWTt1QkFBQyxNQUFNO2dCQVNwQixTQUFTO3NCQURSLFlBQVk7dUJBQUMsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRm9jdXNhYmxlT3B0aW9uLCBGb2N1c09yaWdpbiB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9hMTF5JztcbmltcG9ydCB7IFBsYXRmb3JtIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3BsYXRmb3JtJztcbmltcG9ydCB7IENoYW5nZURldGVjdG9yUmVmLCBEaXJlY3RpdmUsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgSG9zdExpc3RlbmVyLCBpbmplY3QsIElucHV0LCBPbkRlc3Ryb3ksIE91dHB1dCwgUmVuZGVyZXIyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyB0aWNrIH0gZnJvbSAnLi4vLi4vLi4vY29tbW9uL2luZGV4JztcbmltcG9ydCB7IEZvY3VzSW5kaWNhdG9yIH0gZnJvbSAnLi4vZm9jdXMtaW5kaWNhdG9yL2ZvY3VzLWluZGljYXRvcic7XG5pbXBvcnQgeyBGb2N1c0luZGljYXRvck9yaWdpblNlcnZpY2UgfSBmcm9tICcuLi9mb2N1cy1pbmRpY2F0b3IvZm9jdXMtaW5kaWNhdG9yLW9yaWdpbi9mb2N1cy1pbmRpY2F0b3Itb3JpZ2luLnNlcnZpY2UnO1xuaW1wb3J0IHsgRm9jdXNJbmRpY2F0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vZm9jdXMtaW5kaWNhdG9yL2ZvY3VzLWluZGljYXRvci5zZXJ2aWNlJztcbmltcG9ydCB7IE1hbmFnZWRGb2N1c0NvbnRhaW5lclNlcnZpY2UgfSBmcm9tICcuLi9tYW5hZ2VkLWZvY3VzLWNvbnRhaW5lci9tYW5hZ2VkLWZvY3VzLWNvbnRhaW5lci5zZXJ2aWNlJztcbmltcG9ydCB7IFRhYmJhYmxlTGlzdFNlcnZpY2UgfSBmcm9tICcuL3RhYmJhYmxlLWxpc3Quc2VydmljZSc7XG5cbmxldCBuZXh0SWQgPSAwO1xubGV0IHVuaXF1ZUtleSA9IDA7XG5cbkBEaXJlY3RpdmUoe1xuICAgIHNlbGVjdG9yOiAnW3V4VGFiYmFibGVMaXN0SXRlbV0nLFxuICAgIGV4cG9ydEFzOiAndXgtdGFiYmFibGUtbGlzdC1pdGVtJ1xufSlcbmV4cG9ydCBjbGFzcyBUYWJiYWJsZUxpc3RJdGVtRGlyZWN0aXZlIGltcGxlbWVudHMgRm9jdXNhYmxlT3B0aW9uLCBPbkRlc3Ryb3kge1xuICAgIC8qKiBBY2Nlc3MgdGhlIHNlcnZpY2UgdG8gcHJvZ3JhbW1hdGljYWxseSBjb250cm9sIGZvY3VzIGluZGljYXRvcnMgKi9cbiAgICByZWFkb25seSBmb2N1c0luZGljYXRvclNlcnZpY2UgPSBpbmplY3QoRm9jdXNJbmRpY2F0b3JTZXJ2aWNlKTtcbiAgICAvKiogQWNjZXNzIHRoZSB0YWJiYWJsZSBsaXN0IHNlcnZpY2UgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IF90YWJiYWJsZUxpc3QgPSBpbmplY3QoVGFiYmFibGVMaXN0U2VydmljZSk7XG4gICAgLyoqIEFjY2VzcyB0aGUgdGFiYmFibGUgaXRlbSBlbGVtZW50ICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBfZWxlbWVudFJlZiA9IGluamVjdChFbGVtZW50UmVmKTtcbiAgICAvKiogQWNjZXNzIHRoZSBzZXJ2aWNlIHJlc3BvbnNpYmxlIGZvciBoYW5kbGluZyBmb2N1cyBpbiBjaGlsZCBlbGVtZW50cyAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX21hbmFnZWRGb2N1c0NvbnRhaW5lclNlcnZpY2UgPSBpbmplY3QoTWFuYWdlZEZvY3VzQ29udGFpbmVyU2VydmljZSk7XG4gICAgLyoqIEFjY2VzcyB0aGUgc2VydmljZSB3aGljaCBjYW4gcHJvdmlkZSB1cyB3aXRoIGJyb3dzZXIgaWRlbnRpZmljYXRpb24gKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9wbGF0Zm9ybSA9IGluamVjdChQbGF0Zm9ybSk7XG4gICAgLyoqIEFjY2VzcyB0aGUgY2hhbmdlIGRldGVjdG9yIHRvIGVuc3VyZSB0YWJpbmRleCBnZXRzIHVwZGF0ZWQgYXMgZXhwZWN0cyAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NoYW5nZURldGVjdG9yID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcbiAgICAvKiogQWNjZXNzIHRoZSBmb2N1cyBvcmlnaW4gaWYgb25lIGlzIHByb3ZpZGVkICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBfZm9jdXNPcmlnaW5TZXJ2aWNlID0gaW5qZWN0KEZvY3VzSW5kaWNhdG9yT3JpZ2luU2VydmljZSk7XG4gICAgLyoqIEFjY2VzcyB0aGUgcmVuZGVyZXIgdG8gbWFrZSBtYW51YWwgZG9tIG1hbmlwdWxhdGlvbnMgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9yZW5kZXJlciA9IGluamVjdChSZW5kZXJlcjIpO1xuXG5cbiAgICAvKiogSW5kaWNhdGUgdGhlIHBhcmVudCB0YWJiYWJsZSBsaXN0IGl0ZW0gaWYgb25lIGlzIHByZXNlbnQuICovXG4gICAgQElucHV0KCkgcGFyZW50OiBUYWJiYWJsZUxpc3RJdGVtRGlyZWN0aXZlO1xuXG4gICAgQElucHV0KCkgcmFuazogbnVtYmVyID0gMDtcblxuICAgIC8qKiBJbmRpY2F0ZSBpZiB0aGlzIGl0ZW0gaXMgZGlzYWJsZWQgKi9cbiAgICBASW5wdXQoKSBkaXNhYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgLyoqIEluZGljYXRlIGlmIHRoZSBpdGVtIGlzIGV4cGFuZGVkIGlmIHVzZWQgYXMgYSBoaWVyYXJjaGljYWwgaXRlbS4gKi9cbiAgICBASW5wdXQoKSBleHBhbmRlZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgLyoqIFByb3ZpZGUgYSB1bmlxdWUga2V5IHRvIGhlbHAgaWRlbnRpZnkgaXRlbXMgd2hlbiB1c2VkIGluIGEgdmlydHVhbCBsaXN0ICovXG4gICAgIFxuICAgIEBJbnB1dCgpIHNldCBrZXkoa2V5OiBhbnkpIHtcblxuICAgICAgICAvLyBzdG9yZSB0aGUgcHJldmlvdXMga2V5XG4gICAgICAgIGNvbnN0IHByZXZpb3VzS2V5ID0gdGhpcy5fa2V5O1xuXG4gICAgICAgIC8vIGNoZWNrIGlmIHRoZSBrZXkgaGFzIGNoYW5nZWQgZWcuIHZpYSBjZWxsIHJldXNlXG4gICAgICAgIGNvbnN0IGRpZENoYW5nZVJlZiA9IHByZXZpb3VzS2V5ICYmIGtleSAhPT0gcHJldmlvdXNLZXk7XG5cbiAgICAgICAgLy8gdXBkYXRlIHRoZSBjdXJyZW50IGtleVxuICAgICAgICB0aGlzLl9rZXkgPSBrZXk7XG5cbiAgICAgICAgLy8gaWYgdGhpcyBlbGVtZW50IHdhcyB0aGUgcHJldmlvdXNseSB0YWJiYWJsZSBpdGVtIHRoZW4gdXBkYXRlIHRoZSByZWZlcmVuY2VcbiAgICAgICAgaWYgKGRpZENoYW5nZVJlZiAmJiB0aGlzLmlzVGFiYmFibGUoKSkge1xuXG4gICAgICAgICAgICAvLyBhbGxvdyB0aGUgdmlydHVhbCBzY3JvbGwgdG8gdXBkYXRlXG4gICAgICAgICAgICB0aGlzLl9jaGFuZ2VEZXRlY3Rvci5kZXRlY3RDaGFuZ2VzKCk7XG5cbiAgICAgICAgICAgIC8vIHRoaXMgaXRlbSBzaG91bGQgbm8gbG9uZ2VyIGJlIHRhYmJhYmxlXG4gICAgICAgICAgICB0aGlzLl90YWJiYWJsZUxpc3QuZm9jdXNLZXlNYW5hZ2VyLnVwZGF0ZUFjdGl2ZUl0ZW0oLTEpO1xuXG4gICAgICAgICAgICAvLyBzdG9yZSB0aGUgZm9jdXMgb3JpZ2luIGJlZm9yZSB3ZSBibHVyXG4gICAgICAgICAgICBjb25zdCBvcmlnaW4gPSB0aGlzLl9mb2N1c09yaWdpbjtcblxuICAgICAgICAgICAgLy8gYmx1ciB0aGlzIGl0ZW1cbiAgICAgICAgICAgIHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5ibHVyKCk7XG5cbiAgICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgcmVmZXJlbmNlXG4gICAgICAgICAgICB0aGlzLl90YWJiYWJsZUxpc3QuaXRlbVJlZmVyZW5jZUNoYW5nZShwcmV2aW91c0tleSwgb3JpZ2luKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgICBcbiAgICBnZXQga2V5KCk6IGFueSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9rZXkgfHwgdGhpcy5fZGVmYXVsdEtleTtcbiAgICB9XG5cbiAgICAvKiogRW1pdCB3aGVuIHRoZSBleHBhbmRlZCBzdGF0ZSBjaGFuZ2VzLiAqL1xuICAgIEBPdXRwdXQoKSBleHBhbmRlZENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcblxuICAgIC8qKiBFbWl0IHdoZW4gdGhlIGVsZW1lbnQgcmVjZWl2ZXMgZm9jdXMgdmlhIHRoZSB0YWJiYWJsZSBsaXN0LiAqL1xuICAgIEBPdXRwdXQoKSBhY3RpdmF0ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPEZvY3VzT3JpZ2luPigpO1xuXG4gICAgZ2V0IHRhYmluZGV4KCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLl90YWJiYWJsZUxpc3QuaXNJdGVtQWN0aXZlKHRoaXMpID8gMCA6IC0xO1xuICAgIH1cblxuICAgIC8qKiBHaXZlIGVhY2ggdGFiYmFibGUgaXRlbSBhIHVuaXF1ZSBpZCAqL1xuICAgIGlkOiBudW1iZXIgPSBuZXh0SWQrKztcblxuICAgIC8qKiBFYWNoIGl0ZW0gaW4gdGhlIGxpc3QgbmVlZHMgdG8gYmUgaW5pdGlhbGlzZWQgYnkgdGhlIHNlcnZpY2UuIFdoZW4gdGhlIGl0ZW0gUXVlcnlMaXN0IGNoYW5nZXMgdGhpcyBpcyB1c2VkIHRvIGlkZW50aWZ5IHdoaWNoIGl0ZW1zIHByZXZpb3VzbHkgZXhpc3RlZCBhbmQgd2hpY2ggYXJlIG5ldyAqL1xuICAgIGluaXRpYWxpemVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogU3RvcmUgYSBsaXN0IG9mIGFsbCBjaGlsZCB0YWJiYWJsZSBpdGVtcyAqL1xuICAgIGNoaWxkcmVuOiBUYWJiYWJsZUxpc3RJdGVtRGlyZWN0aXZlW10gPSBbXTtcblxuICAgIC8qKiBFbWl0IHdoZW5ldmVyIHRoZSBleHBhbmRlZCBzdGF0ZSBjaGFuZ2VzICovXG4gICAga2V5Ym9hcmRFeHBhbmRlZCQgPSBuZXcgU3ViamVjdDxib29sZWFuPigpO1xuXG4gICAgLyoqIEF1dG9tYXRpY2FsbHkgdW5zdWJzY3JpYmUgZnJvbSBhbGwgb2JzZXJ2YWJsZXMgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9vbkRlc3Ryb3kgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gICAgLyoqIFN0b3JlIGEgcmVmZXJlbmNlIHRvIHRoZSBmb2N1cyBpbmRpY2F0b3IgaW5zdGFuY2UgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9mb2N1c0luZGljYXRvcjogRm9jdXNJbmRpY2F0b3I7XG5cbiAgICAvKiogU3RvcmUgdGhlIGN1cnJlbnQga2V5IC0gaXQgbWF5IGNoYW5nZSBpbiBhIG5nRm9yL3V4VmlydHVhbEZvciBpZiB0aGUgY2VsbCBpcyByZXVzZWQuICovXG4gICAgIFxuICAgIHByaXZhdGUgX2tleTogYW55O1xuXG4gICAgLyoqIFN0b3JlIGEgZGVmYXVsdCBrZXkgdG8gdXNlIGlmIG9uZSBpcyBub3QgcHJvdmlkZWQgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9kZWZhdWx0S2V5OiBzdHJpbmcgPSBgdGFiYmFibGUtbGlzdC1rZXktJHt1bmlxdWVLZXkrK31gO1xuXG4gICAgLyoqIERldGVybWluZSBpZiB0aGlzIGVsZW1lbnQgaGFzIGEgZm9jdXMgaW5kaWNhdG9yIHZpc2libGUgKi9cbiAgICBwcml2YXRlIF9mb2N1c09yaWdpbjogRm9jdXNPcmlnaW4gPSBudWxsO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG5cbiAgICAgICAgLy8gY3JlYXRlIHRoZSBmb2N1cyBpbmRpY2F0b3JcbiAgICAgICAgdGhpcy5fZm9jdXNJbmRpY2F0b3IgPSB0aGlzLmZvY3VzSW5kaWNhdG9yU2VydmljZS5tb25pdG9yKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCk7XG5cbiAgICAgICAgLy8gc3RvcmUgdGhlIG1vc3QgY3VycmVudCBmb2N1cyBvcmlnaW5cbiAgICAgICAgdGhpcy5fZm9jdXNJbmRpY2F0b3Iub3JpZ2luJC5waXBlKHRha2VVbnRpbCh0aGlzLl9vbkRlc3Ryb3kpKVxuICAgICAgICAgICAgLnN1YnNjcmliZShvcmlnaW4gPT4gdGhpcy5fZm9jdXNPcmlnaW4gPSBvcmlnaW4pO1xuXG4gICAgICAgIC8vIHdhdGNoIGZvciBjaGFuZ2VzIHRvIHRhYmluZGV4ZXNcbiAgICAgICAgdGhpcy5fdGFiYmFibGVMaXN0Lm9uVGFiSW5kZXhDaGFuZ2UucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5zZXRUYWJJbmRleCgpKTtcblxuICAgICAgICB0aGlzLmtleWJvYXJkRXhwYW5kZWQkLnBpcGUodGljaygpLCB0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSkuc3Vic2NyaWJlKGV4cGFuZGVkID0+IHtcblxuICAgICAgICAgICAgLy8gRW1pdCBldmVudCB3aGljaCBtYXkgYWx0ZXIgdGhlIERPTVxuICAgICAgICAgICAgdGhpcy5leHBhbmRlZENoYW5nZS5lbWl0KGV4cGFuZGVkKTtcblxuICAgICAgICAgICAgLy8gQWN0aXZhdGUgdGhlIGFwcHJvcHJpYXRlIGl0ZW1cbiAgICAgICAgICAgIGlmIChleHBhbmRlZCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNoaWxkcmVuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdGFiYmFibGVMaXN0LmFjdGl2YXRlKHRoaXMuY2hpbGRyZW5bMF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdGFiYmFibGVMaXN0LmFjdGl2YXRlKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBvbkluaXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuXG4gICAgICAgIC8vIFdhdGNoIGZvciBmb2N1cyB3aXRoaW4gdGhlIGNvbnRhaW5lciBlbGVtZW50IGFuZCBtYW5hZ2UgdGFiaW5kZXggb2YgZGVzY2VuZGFudHNcbiAgICAgICAgdGhpcy5fbWFuYWdlZEZvY3VzQ29udGFpbmVyU2VydmljZS5yZWdpc3Rlcih0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsIHRoaXMpO1xuXG4gICAgICAgIC8vIGVuc3VyZSB0aGUgdGFiIGluZGV4IGlzIGluaXRpYWxseSBzZXRcbiAgICAgICAgdGhpcy5zZXRUYWJJbmRleCgpO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuXG4gICAgICAgIC8vIGNoZWNrIGlmIHRoaXMgaXMgdGhlIGN1cnJlbnRseSBmb2N1c2VkIGl0ZW0gLSBpZiBzbyB3ZSBuZWVkIHRvIG1ha2UgYW5vdGhlciBpdGVtIHRhYmJhYmxlXG4gICAgICAgIGlmICh0aGlzLnRhYmluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICB0aGlzLl90YWJiYWJsZUxpc3Quc2V0Rmlyc3RJdGVtVGFiYmFibGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX29uRGVzdHJveS5uZXh0KCk7XG4gICAgICAgIHRoaXMuX29uRGVzdHJveS5jb21wbGV0ZSgpO1xuXG4gICAgICAgIHRoaXMuX2ZvY3VzSW5kaWNhdG9yLmRlc3Ryb3koKTtcblxuICAgICAgICB0aGlzLl9tYW5hZ2VkRm9jdXNDb250YWluZXJTZXJ2aWNlLnVucmVnaXN0ZXIodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCB0aGlzKTtcbiAgICB9XG5cbiAgICBmb2N1cygpOiB2b2lkIHtcblxuICAgICAgICAvLyBjaGVjayBpZiB0aGVyZSBhcmUgY3VycmVudGx5IGFueSBpdGVtcyB0aGF0IGFyZSB0YWJiYWJsZVxuICAgICAgICBjb25zdCBoYXNUYWJiYWJsZUl0ZW0gPSB0aGlzLl90YWJiYWJsZUxpc3QuaGFzVGFiYmFibGVJdGVtKCk7XG5cbiAgICAgICAgLy8gZGV0ZXJtaW5lIHRoZSBmb2N1cyBvcmlnaW5cbiAgICAgICAgY29uc3Qgb3JpZ2luID0gaGFzVGFiYmFibGVJdGVtID8gdGhpcy5fZm9jdXNPcmlnaW5TZXJ2aWNlLmdldE9yaWdpbigpIHx8ICdrZXlib2FyZCcgOiAna2V5Ym9hcmQnO1xuXG4gICAgICAgIC8vIGFwcGx5IGZvY3VzIHRvIHRoZSBlbGVtZW50XG4gICAgICAgIHRoaXMuZm9jdXNXaXRoT3JpZ2luKG9yaWdpbiwgIXRoaXMuX3RhYmJhYmxlTGlzdC5zaG91bGRTY3JvbGxJblZpZXcpO1xuXG4gICAgICAgIC8vIGVuc3VyZSB0aGUgZm9jdXMga2V5IG1hbmFnZXIgdXBkYXRlcyB0aGUgYWN0aXZlIGl0ZW0gY29ycmVjdGx5XG4gICAgICAgIHRoaXMuX3RhYmJhYmxlTGlzdC5hY3RpdmF0ZSh0aGlzLCBoYXNUYWJiYWJsZUl0ZW0pO1xuXG4gICAgICAgIC8vIGVtaXQgdGhlIGZvY3VzIGV2ZW50XG4gICAgICAgIHRoaXMuYWN0aXZhdGVkLmVtaXQob3JpZ2luKTtcbiAgICB9XG5cbiAgICBASG9zdExpc3RlbmVyKCdmb2N1cycpXG4gICAgQEhvc3RMaXN0ZW5lcignY2xpY2snKVxuICAgIG9uRm9jdXMoKTogdm9pZCB7XG4gICAgICAgIC8vIGlmIHRoaXMgaXRlbSBpcyBub3QgY3VycmVudGx5IGZvY3VzZWQgaW4gdGhlIGZvY3VzS2V5TWFuYWdlciBzZXQgaXQgYXMgdGhlIGFjdGl2ZSBpdGVtXG4gICAgICAgIGlmICghdGhpcy5fdGFiYmFibGVMaXN0LmlzSXRlbUFjdGl2ZSh0aGlzKSkge1xuICAgICAgICAgICAgdGhpcy5fdGFiYmFibGVMaXN0LmFjdGl2YXRlKHRoaXMsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gYWxzbyBpbmZvcm0gdGhlIHNlcnZpY2UgdGhhdCBhbiBpdGVtIHdpdGhpbiB0aGUgbGlzdCBpcyBub3cgZm9jdXNlZFxuICAgICAgICB0aGlzLl90YWJiYWJsZUxpc3QuaXNGb2N1c2VkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBASG9zdExpc3RlbmVyKCdibHVyJylcbiAgICBvbkJsdXIoKTogdm9pZCB7XG4gICAgICAgIC8vIGlmIHRoaXMgaXMgdGhlIGN1cnJlbnQgYWN0aXZlIGl0ZW0gYW5kIGl0IGlzIGJsdXJyZWQgdGhlbiB1cGRhdGUgdGhlIGlzRm9jdXNlZCBzdGF0ZVxuICAgICAgICBpZiAodGhpcy5fdGFiYmFibGVMaXN0LmlzSXRlbUFjdGl2ZSh0aGlzKSkge1xuICAgICAgICAgICAgdGhpcy5fdGFiYmFibGVMaXN0LmlzRm9jdXNlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgQEhvc3RMaXN0ZW5lcigna2V5ZG93bicsIFsnJGV2ZW50J10pXG4gICAgb25LZXlkb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgICAgIHRoaXMuX3RhYmJhYmxlTGlzdC5vbktleWRvd24odGhpcywgZXZlbnQpO1xuICAgIH1cblxuICAgIGdldEZvY3VzZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQgPT09IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqIFdlIGNhbiBwcm9ncmFtbWF0aWNhbGx5IGZvY3VzIGFuIGVsZW1lbnQgYnV0IG1heSB3YW50IGEgZGlmZmVyZW50IG9yaWdpbiB0aGFuICdwcm9ncmFtbWF0aWMnICovXG4gICAgZm9jdXNXaXRoT3JpZ2luKG9yaWdpbjogRm9jdXNPcmlnaW4sIHByZXZlbnRTY3JvbGw6IGJvb2xlYW4gPSB0cnVlKTogdm9pZCB7XG5cbiAgICAgICAgaWYgKG9yaWdpbikge1xuXG4gICAgICAgICAgICBjb25zdCBzY3JvbGxUb3AgPSB0aGlzLl90YWJiYWJsZUxpc3QuY29udGFpbmVyUmVmLnNjcm9sbFRvcDtcblxuICAgICAgICAgICAgLy8gZm9jdXMgdGhlIGl0ZW0gd2l0aCBhIGdpdmVuIG9yaWdpblxuICAgICAgICAgICAgdGhpcy5fZm9jdXNJbmRpY2F0b3IuZm9jdXMob3JpZ2luLCB7IHByZXZlbnRTY3JvbGwgfSk7XG5cbiAgICAgICAgICAgIC8vIElFIGFuZCBGaXJlZm94IGRvbid0IHN1cHBvcnQgcHJldmVudCBzY3JvbGxcbiAgICAgICAgICAgIGlmIChwcmV2ZW50U2Nyb2xsICYmICF0aGlzLl9wbGF0Zm9ybS5XRUJLSVQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl90YWJiYWJsZUxpc3QuY29udGFpbmVyUmVmLnNjcm9sbFRvcCA9IHNjcm9sbFRvcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgaXNUYWJiYWJsZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGFiaW5kZXggPT09IDA7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZXRUYWJJbmRleCgpOiB2b2lkIHtcbiAgICAgICAgLy8gdXBkYXRlIHRoZSB0YWJpbmRleCBhdHRyaWJ1dGVcbiAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0QXR0cmlidXRlKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ3RhYmluZGV4JywgdGhpcy50YWJpbmRleC50b1N0cmluZygpKTtcbiAgICB9XG59XG4iXX0=