@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
208 lines • 30.9 kB
JavaScript
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=