@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
211 lines • 32.1 kB
JavaScript
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { SPACE } from '@angular/cdk/keycodes';
import { ChangeDetectorRef, Directive, ElementRef, EventEmitter, HostBinding, HostListener, inject, Input, Output } from '@angular/core';
import { Subject } from 'rxjs';
import { debounceTime, map, skip, takeUntil, tap } from 'rxjs/operators';
import { FocusIndicatorService, ManagedFocusContainerService } from '../accessibility/index';
import { SelectionService } from './selection.service';
import * as i0 from "@angular/core";
export class SelectionItemDirective {
/** Defines whether or not this item is currently selected. */
set selected(selected) {
selected ? this.select() : this.deselect();
}
get selected() {
return this._selected;
}
/** Determine whether or not this item can be selected */
set uxSelectionDisabled(isDisabled) {
// if this item was selected then deselect it
if (this._selected && isDisabled) {
this.deselect();
}
// inform the selection service of the disabled state
this._selectionService.setItemDisabled(this.uxSelectionItem, isDisabled);
// store the current disabled state
this._isDisabled = isDisabled;
}
/** Whether aria-selected is added to the host element */
set addAriaAttributes(value) {
this._addAriaAttributes = coerceBooleanProperty(value);
}
get addAriaAttributes() {
return this._addAriaAttributes;
}
get attrTabIndex() {
return (this.tabindex !== null) ? this.tabindex : this._managedTabIndex;
}
constructor() {
this.focusIndicatorService = inject(FocusIndicatorService);
this._selectionService = inject(SelectionService);
this._elementRef = inject(ElementRef);
this._managedFocusContainerService = inject(ManagedFocusContainerService);
this._changeDetector = inject(ChangeDetectorRef);
/** Defines the tab index of the row */
this.tabindex = null;
/** Defines whether or not this item is currently selected. */
this.selectedChange = new EventEmitter();
/** Store whether this item is the focusable item */
this.active = false;
/** Store the focused state of the element */
this.isFocused = false;
/** Store the current selected state */
this._selected = false;
/** Store the disabled state */
this._isDisabled = false;
/** Store the tab indexed if using the managed focus container */
this._managedTabIndex = -1;
/** Determine if there is a pending state change as we debounce before emitting */
this._hasPendingStateChange = false;
/** Store value for _addAriaAttributes */
this._addAriaAttributes = true;
/** Automatically unsubscribe when the component is destroyed */
this._onDestroy = new Subject();
this._focusIndicator = this.focusIndicatorService.monitor(this._elementRef.nativeElement);
}
ngOnInit() {
// if there is no associated data then throw an error
if (!this.uxSelectionItem) {
throw new Error('The uxSelectionItem directive must have data associated with it.');
}
// subscribe to changes to the active state
this._selectionService.active$.pipe(takeUntil(this._onDestroy), map(active => active === this.uxSelectionItem)).subscribe(active => {
// store the focus state
this.active = active;
// if it is active then focus the element
if (active === true) {
this._selectionService.focus$.next(this.uxSelectionItem);
this._elementRef.nativeElement.focus();
}
});
// Subscribe to changes to the focus target
// This is mostly the same as active$, except that it has an initial value of the first item in the collection.
this._selectionService.focus$.pipe(takeUntil(this._onDestroy)).subscribe(focusTarget => {
this._managedTabIndex = (focusTarget === this.uxSelectionItem) ? 0 : -1;
});
// Watch for focus within the container element and manage tabindex of descendants
this._managedFocusContainerService.register(this._elementRef.nativeElement, this);
// Listen for changes to the focus state and apply the appropriate class
this._focusIndicator.origin$.pipe(map(origin => origin === 'keyboard'), takeUntil(this._onDestroy))
.subscribe(isFocused => {
this.isFocused = isFocused;
this._changeDetector.markForCheck();
});
}
ngOnChanges(changes) {
if (changes.uxSelectionItem) {
this.updateSelectionItem();
}
}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
this._focusIndicator.destroy();
this._managedFocusContainerService.unregister(this._elementRef.nativeElement, this);
}
click(event) {
if (!this._isDisabled && !this._hasPendingStateChange && this._selectionService.isEnabled && this._selectionService.isClickEnabled) {
this._selectionService.strategy.click(event, this.uxSelectionItem);
}
}
mousedown(event) {
if (!this._isDisabled && this._selectionService.isEnabled && this._selectionService.isClickEnabled) {
this._selectionService.strategy.mousedown(event, this.uxSelectionItem);
}
}
keydown(event) {
// if the space key (selection key) is pressed and we are disabled then we should block
// the event from propagating. However if this is a key such as arrow presses then we do
// still want this to propagate to allow keyboard navigation for accessibility purposes.
const isDisabled = this._isDisabled && event.keyCode === SPACE;
if (!isDisabled && this._selectionService.isEnabled && this._selectionService.isKeyboardEnabled) {
this._selectionService.strategy.keydown(event, this.uxSelectionItem);
}
}
focus() {
// If tabbed to from outside the component, activate.
if (this._selectionService.active$.getValue() !== this.uxSelectionItem) {
this._selectionService.activate(this.uxSelectionItem);
}
}
/**
* Select this item using the current strategy
*/
select() {
if (!this._isDisabled && this._selectionService.isEnabled) {
this._selectionService.strategy.select(this.uxSelectionItem);
}
}
/**
* Deselect this item using the current strategy
*/
deselect() {
if (!this._isDisabled && this._selectionService.isEnabled) {
this._selectionService.strategy.deselect(this.uxSelectionItem);
}
}
updateSelectionItem() {
if (this._selectionStateSubscription) {
this._selectionStateSubscription.unsubscribe();
}
// subscribe to selection changes on this item (don't emit the initial value)
this._selectionStateSubscription = this._selectionService.getSelectionState(this.uxSelectionItem).pipe(skip(1), tap(() => this._hasPendingStateChange = true), debounceTime(0), takeUntil(this._onDestroy)).subscribe(selected => {
this._hasPendingStateChange = false;
if (this._selected === selected) {
return;
}
// store the selected state
this._selected = selected;
// emit the selected state
this.selectedChange.emit(selected);
this._changeDetector.markForCheck();
});
this._selected = this._selectionService.isSelected(this.uxSelectionItem);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: SelectionItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.12", type: SelectionItemDirective, selector: "[uxSelectionItem]", inputs: { uxSelectionItem: "uxSelectionItem", selected: "selected", tabindex: "tabindex", uxSelectionDisabled: "uxSelectionDisabled", addAriaAttributes: "addAriaAttributes" }, outputs: { selectedChange: "selectedChange" }, host: { listeners: { "click": "click($event)", "mousedown": "mousedown($event)", "keydown": "keydown($event)", "focus": "focus()" }, properties: { "attr.aria-selected": "addAriaAttributes ? selected : null", "class.ux-selection-selected": "this.selected", "class.ux-selection-focused": "this.isFocused", "attr.tabindex": "this.attrTabIndex" } }, exportAs: ["ux-selection-item"], usesOnChanges: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: SelectionItemDirective, decorators: [{
type: Directive,
args: [{
selector: '[uxSelectionItem]',
exportAs: 'ux-selection-item',
host: {
'[attr.aria-selected]': 'addAriaAttributes ? selected : null',
}
}]
}], ctorParameters: () => [], propDecorators: { uxSelectionItem: [{
type: Input
}], selected: [{
type: Input
}, {
type: HostBinding,
args: ['class.ux-selection-selected']
}], tabindex: [{
type: Input
}], uxSelectionDisabled: [{
type: Input
}], addAriaAttributes: [{
type: Input
}], selectedChange: [{
type: Output
}], isFocused: [{
type: HostBinding,
args: ['class.ux-selection-focused']
}], attrTabIndex: [{
type: HostBinding,
args: ['attr.tabindex']
}], click: [{
type: HostListener,
args: ['click', ['$event']]
}], mousedown: [{
type: HostListener,
args: ['mousedown', ['$event']]
}], keydown: [{
type: HostListener,
args: ['keydown', ['$event']]
}], focus: [{
type: HostListener,
args: ['focus']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0aW9uLWl0ZW0uZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2RpcmVjdGl2ZXMvc2VsZWN0aW9uL3NlbGVjdGlvbi1pdGVtLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWdCLHFCQUFxQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDNUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzlDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQWdDLE1BQU0sRUFBaUIsTUFBTSxlQUFlLENBQUM7QUFDdEwsT0FBTyxFQUFFLE9BQU8sRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RSxPQUFPLEVBQWtCLHFCQUFxQixFQUFFLDRCQUE0QixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDN0csT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7O0FBU3ZELE1BQU0sT0FBTyxzQkFBc0I7SUFjL0IsOERBQThEO0lBQzlELElBRUksUUFBUSxDQUFDLFFBQWlCO1FBQzFCLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDL0MsQ0FBQztJQUVELElBQUksUUFBUTtRQUNSLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUMxQixDQUFDO0lBS0QseURBQXlEO0lBQ3pELElBQWEsbUJBQW1CLENBQUMsVUFBbUI7UUFDaEQsNkNBQTZDO1FBQzdDLElBQUksSUFBSSxD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QUFZO3VCQUFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFRakMsU0FBUztzQkFEUixZQUFZO3VCQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFRckMsT0FBTztzQkFETixZQUFZO3VCQUFDLFNBQVMsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFjbkMsS0FBSztzQkFESixZQUFZO3VCQUFDLE9BQU8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCb29sZWFuSW5wdXQsIGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XHJcbmltcG9ydCB7IFNQQUNFIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2tleWNvZGVzJztcclxuaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0b3JSZWYsIERpcmVjdGl2ZSwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBIb3N0QmluZGluZywgSG9zdExpc3RlbmVyLCBpbmplY3QsIElucHV0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgT25Jbml0LCBPdXRwdXQsIFNpbXBsZUNoYW5nZXMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IGRlYm91bmNlVGltZSwgbWFwLCBza2lwLCB0YWtlVW50aWwsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgRm9jdXNJbmRpY2F0b3IsIEZvY3VzSW5kaWNhdG9yU2VydmljZSwgTWFuYWdlZEZvY3VzQ29udGFpbmVyU2VydmljZSB9IGZyb20gJy4uL2FjY2Vzc2liaWxpdHkvaW5kZXgnO1xyXG5pbXBvcnQgeyBTZWxlY3Rpb25TZXJ2aWNlIH0gZnJvbSAnLi9zZWxlY3Rpb24uc2VydmljZSc7XHJcblxyXG5ARGlyZWN0aXZlKHtcclxuICAgIHNlbGVjdG9yOiAnW3V4U2VsZWN0aW9uSXRlbV0nLFxyXG4gICAgZXhwb3J0QXM6ICd1eC1zZWxlY3Rpb24taXRlbScsXHJcbiAgICBob3N0OiB7XHJcbiAgICAgICAgJ1thdHRyLmFyaWEtc2VsZWN0ZWRdJzogJ2FkZEFyaWFBdHRyaWJ1dGVzID8gc2VsZWN0ZWQgOiBudWxsJyxcclxuICAgIH1cclxufSlcclxuZXhwb3J0IGNsYXNzIFNlbGVjdGlvbkl0ZW1EaXJlY3RpdmU8VD4gaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcclxuICAgIHJlYWRvbmx5IGZvY3VzSW5kaWNhdG9yU2VydmljZSA9IGluamVjdChGb2N1c0luZGljYXRvclNlcnZpY2UpO1xyXG5cclxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3NlbGVjdGlvblNlcnZpY2UgPSBpbmplY3Q8U2VsZWN0aW9uU2VydmljZTxUPj4oU2VsZWN0aW9uU2VydmljZSk7XHJcblxyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfZWxlbWVudFJlZiA9IGluamVjdChFbGVtZW50UmVmKTtcclxuXHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9tYW5hZ2VkRm9jdXNDb250YWluZXJTZXJ2aWNlID0gaW5qZWN0KE1hbmFnZWRGb2N1c0NvbnRhaW5lclNlcnZpY2UpO1xyXG5cclxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NoYW5nZURldGVjdG9yID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcclxuXHJcbiAgICAvKiogRGVmaW5lcyB0aGUgZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhpcyBpdGVtLiAqL1xyXG4gICAgQElucHV0KCkgdXhTZWxlY3Rpb25JdGVtOiBUO1xyXG5cclxuICAgIC8qKiBEZWZpbmVzIHdoZXRoZXIgb3Igbm90IHRoaXMgaXRlbSBpcyBjdXJyZW50bHkgc2VsZWN0ZWQuICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy51eC1zZWxlY3Rpb24tc2VsZWN0ZWQnKVxyXG4gICAgc2V0IHNlbGVjdGVkKHNlbGVjdGVkOiBib29sZWFuKSB7XHJcbiAgICAgICAgc2VsZWN0ZWQgPyB0aGlzLnNlbGVjdCgpIDogdGhpcy5kZXNlbGVjdCgpO1xyXG4gICAgfVxyXG5cclxuICAgIGdldCBzZWxlY3RlZCgpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fc2VsZWN0ZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIERlZmluZXMgdGhlIHRhYiBpbmRleCBvZiB0aGUgcm93ICovXHJcbiAgICBASW5wdXQoKSB0YWJpbmRleDogbnVtYmVyID0gbnVsbDtcclxuXHJcbiAgICAvKiogRGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IHRoaXMgaXRlbSBjYW4gYmUgc2VsZWN0ZWQgKi9cclxuICAgIEBJbnB1dCgpIHNldCB1eFNlbGVjdGlvbkRpc2FibGVkKGlzRGlzYWJsZWQ6IGJvb2xlYW4pIHtcclxuICAgICAgICAvLyBpZiB0aGlzIGl0ZW0gd2FzIHNlbGVjdGVkIHRoZW4gZGVzZWxlY3QgaXRcclxuICAgICAgICBpZiAodGhpcy5fc2VsZWN0ZWQgJiYgaXNEaXNhYmxlZCkge1xyXG4gICAgICAgICAgICB0aGlzLmRlc2VsZWN0KCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBpbmZvcm0gdGhlIHNlbGVjdGlvbiBzZXJ2aWNlIG9mIHRoZSBkaXNhYmxlZCBzdGF0ZVxyXG4gICAgICAgIHRoaXMuX3NlbGVjdGlvblNlcnZpY2Uuc2V0SXRlbURpc2FibGVkKHRoaXMudXhTZWxlY3Rpb25JdGVtLCBpc0Rpc2FibGVkKTtcclxuXHJcbiAgICAgICAgLy8gc3RvcmUgdGhlIGN1cnJlbnQgZGlzYWJsZWQgc3RhdGVcclxuICAgICAgICB0aGlzLl9pc0Rpc2FibGVkID0gaXNEaXNhYmxlZDtcclxuICAgIH1cclxuXHJcbiAgICAvKiogV2hldGhlciBhcmlhLXNlbGVjdGVkIGlzIGFkZGVkIHRvIHRoZSBob3N0IGVsZW1lbnQgKi9cclxuICAgIEBJbnB1dCgpIHNldCBhZGRBcmlhQXR0cmlidXRlcyh2YWx1ZTogYm9vbGVhbikge1xyXG4gICAgICAgIHRoaXMuX2FkZEFyaWFBdHRyaWJ1dGVzID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbHVlKTtcclxuICAgIH1cclxuXHJcbiAgICBnZXQgYWRkQXJpYUF0dHJpYnV0ZXMoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FkZEFyaWFBdHRyaWJ1dGVzO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBEZWZpbmVzIHdoZXRoZXIgb3Igbm90IHRoaXMgaXRlbSBpcyBjdXJyZW50bHkgc2VsZWN0ZWQuICovXHJcbiAgICBAT3V0cHV0KCkgc2VsZWN0ZWRDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XHJcblxyXG4gICAgLyoqIFN0b3JlIHdoZXRoZXIgdGhpcyBpdGVtIGlzIHRoZSBmb2N1c2FibGUgaXRlbSAqL1xyXG4gICAgYWN0aXZlOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgLyoqIFN0b3JlIHRoZSBmb2N1c2VkIHN0YXRlIG9mIHRoZSBlbGVtZW50ICovXHJcbiAgICBASG9zdEJpbmRpbmcoJ2NsYXNzLnV4LXNlbGVjdGlvbi1mb2N1c2VkJykgaXNGb2N1c2VkOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgQEhvc3RCaW5kaW5nKCdhdHRyLnRhYmluZGV4JylcclxuICAgIGdldCBhdHRyVGFiSW5kZXgoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gKHRoaXMudGFiaW5kZXggIT09IG51bGwpID8gdGhpcy50YWJpbmRleCA6IHRoaXMuX21hbmFnZWRUYWJJbmRleDtcclxuICAgIH1cclxuXHJcbiAgICAvKiogU3RvcmUgdGhlIGN1cnJlbnQgc2VsZWN0ZWQgc3RhdGUgKi9cclxuICAgIHByaXZhdGUgX3NlbGVjdGVkOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgLyoqIFN0b3JlIHRoZSBkaXNhYmxlZCBzdGF0ZSAqL1xyXG4gICAgcHJpdmF0ZSBfaXNEaXNhYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAgIC8qKiBTdG9yZSB0aGUgdGFiIGluZGV4ZWQgaWYgdXNpbmcgdGhlIG1hbmFnZWQgZm9jdXMgY29udGFpbmVyICovXHJcbiAgICBwcml2YXRlIF9tYW5hZ2VkVGFiSW5kZXg6IG51bWJlciA9IC0xO1xyXG5cclxuICAgIC8qKiBEZXRlcm1pbmUgaWYgdGhlcmUgaXMgYSBwZW5kaW5nIHN0YXRlIGNoYW5nZSBhcyB3ZSBkZWJvdW5jZSBiZWZvcmUgZW1pdHRpbmcgKi9cclxuICAgIHByaXZhdGUgX2hhc1BlbmRpbmdTdGF0ZUNoYW5nZTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAgIC8qKiBTdWJzY3JpcHRpb24gdG8gdGhlIHNlbGVjdGlvbiBzdGF0ZSBvYnNlcnZhYmxlLiAqL1xyXG4gICAgcHJpdmF0ZSBfc2VsZWN0aW9uU3RhdGVTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcclxuXHJcbiAgICAvKiogU3RvcmUgdmFsdWUgZm9yIF9hZGRBcmlhQXR0cmlidXRlcyAqL1xyXG4gICAgcHJpdmF0ZSBfYWRkQXJpYUF0dHJpYnV0ZXM6IGJvb2xlYW4gPSB0cnVlO1xyXG5cclxuICAgIC8qKiBBdXRvbWF0aWNhbGx5IHVuc3Vic2NyaWJlIHdoZW4gdGhlIGNvbXBvbmVudCBpcyBkZXN0cm95ZWQgKi9cclxuICAgIHByaXZhdGUgcmVhZG9ubHkgX29uRGVzdHJveSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XHJcblxyXG4gICAgLyoqIFRoZSB0aGUgaW5zdGFuY2Ugb2YgdGhlIGZvY3VzIGluZGljYXRvciAqL1xyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfZm9jdXNJbmRpY2F0b3I6IEZvY3VzSW5kaWNhdG9yO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKCkge1xyXG4gICAgICAgIHRoaXMuX2ZvY3VzSW5kaWNhdG9yID0gdGhpcy5mb2N1c0luZGljYXRvclNlcnZpY2UubW9uaXRvcih0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpO1xyXG4gICAgfVxyXG5cclxuICAgIG5nT25Jbml0KCk6IHZvaWQge1xyXG5cclxuICAgICAgICAvLyBpZiB0aGVyZSBpcyBubyBhc3NvY2lhdGVkIGRhdGEgdGhlbiB0aHJvdyBhbiBlcnJvclxyXG4gICAgICAgIGlmICghdGhpcy51eFNlbGVjdGlvbkl0ZW0pIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgdXhTZWxlY3Rpb25JdGVtIGRpcmVjdGl2ZSBtdXN0IGhhdmUgZGF0YSBhc3NvY2lhdGVkIHdpdGggaXQuJyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBzdWJzY3JpYmUgdG8gY2hhbmdlcyB0byB0aGUgYWN0aXZlIHN0YXRlXHJcbiAgICAgICAgdGhpcy5fc2VsZWN0aW9uU2VydmljZS5hY3RpdmUkLnBpcGUodGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSksIG1hcChhY3RpdmUgPT4gYWN0aXZlID09PSB0aGlzLnV4U2VsZWN0aW9uSXRlbSkpLnN1YnNjcmliZShhY3RpdmUgPT4ge1xyXG5cclxuICAgICAgICAgICAgLy8gc3RvcmUgdGhlIGZvY3VzIHN0YXRlXHJcbiAgICAgICAgICAgIHRoaXMuYWN0aXZlID0gYWN0aXZlO1xyXG5cclxuICAgICAgICAgICAgLy8gaWYgaXQgaXMgYWN0aXZlIHRoZW4gZm9jdXMgdGhlIGVsZW1lbnRcclxuICAgICAgICAgICAgaWYgKGFjdGl2ZSA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fc2VsZWN0aW9uU2VydmljZS5mb2N1cyQubmV4dCh0aGlzLnV4U2VsZWN0aW9uSXRlbSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICAvLyBTdWJzY3JpYmUgdG8gY2hhbmdlcyB0byB0aGUgZm9jdXMgdGFyZ2V0XHJcbiAgICAgICAgLy8gVGhpcyBpcyBtb3N0bHkgdGhlIHNhbWUgYXMgYWN0aXZlJCwgZXhjZXB0IHRoYXQgaXQgaGFzIGFuIGluaXRpYWwgdmFsdWUgb2YgdGhlIGZpcnN0IGl0ZW0gaW4gdGhlIGNvbGxlY3Rpb24uXHJcbiAgICAgICAgdGhpcy5fc2VsZWN0aW9uU2VydmljZS5mb2N1cyQucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSkuc3Vic2NyaWJlKGZvY3VzVGFyZ2V0ID0+IHtcclxuICAgICAgICAgICAgdGhpcy5fbWFuYWdlZFRhYkluZGV4ID0gKGZvY3VzVGFyZ2V0ID09PSB0aGlzLnV4U2VsZWN0aW9uSXRlbSkgPyAwIDogLTE7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIC8vIFdhdGNoIGZvciBmb2N1cyB3aXRoaW4gdGhlIGNvbnRhaW5lciBlbGVtZW50IGFuZCBtYW5hZ2UgdGFiaW5kZXggb2YgZGVzY2VuZGFudHNcclxuICAgICAgICB0aGlzLl9tYW5hZ2VkRm9jdXNDb250YWluZXJTZXJ2aWNlLnJlZ2lzdGVyKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgdGhpcyk7XHJcblxyXG4gICAgICAgIC8vIExpc3RlbiBmb3IgY2hhbmdlcyB0byB0aGUgZm9jdXMgc3RhdGUgYW5kIGFwcGx5IHRoZSBhcHByb3ByaWF0ZSBjbGFzc1xyXG4gICAgICAgdGhpcy5fZm9jdXNJbmRpY2F0b3Iub3JpZ2luJC5waXBlKG1hcChvcmlnaW4gPT4gb3JpZ2luID09PSAna2V5Ym9hcmQnKSwgdGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSkpXHJcbiAgICAgICAgICAgLnN1YnNjcmliZShpc0ZvY3VzZWQgPT4ge1xyXG4gICAgICAgICAgICAgICB0aGlzLmlzRm9jdXNlZCA9IGlzRm9jdXNlZDtcclxuICAgICAgICAgICAgICAgdGhpcy5fY2hhbmdlRGV0ZWN0b3IubWFya0ZvckNoZWNrKCk7XHJcbiAgICAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xyXG4gICAgICAgIGlmIChjaGFuZ2VzLnV4U2VsZWN0aW9uSXRlbSkge1xyXG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVNlbGVjdGlvbkl0ZW0oKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5fb25EZXN0cm95Lm5leHQoKTtcclxuICAgICAgICB0aGlzLl9vbkRlc3Ryb3kuY29tcGxldGUoKTtcclxuICAgICAgICB0aGlzLl9mb2N1c0luZGljYXRvci5kZXN0cm95KCk7XHJcbiAgICAgICAgdGhpcy5fbWFuYWdlZEZvY3VzQ29udGFpbmVyU2VydmljZS51bnJlZ2lzdGVyKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgdGhpcyk7XHJcbiAgICB9XHJcblxyXG4gICAgQEhvc3RMaXN0ZW5lcignY2xpY2snLCBbJyRldmVudCddKVxyXG4gICAgY2xpY2soZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcclxuICAgICAgICBpZiAoIXRoaXMuX2lzRGlzYWJsZWQgJiYgIXRoaXMuX2hhc1BlbmRpbmdTdGF0ZUNoYW5nZSAmJiB0aGlzLl9zZWxlY3Rpb25TZXJ2aWNlLmlzRW5hYmxlZCAmJiB0aGlzLl9zZWxlY3Rpb25TZXJ2aWNlLmlzQ2xpY2tFbmFibGVkKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX3NlbGVjdGlvblNlcnZpY2Uuc3RyYXRlZ3kuY2xpY2soZXZlbnQsIHRoaXMudXhTZWxlY3Rpb25JdGVtKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgQEhvc3RMaXN0ZW5lcignbW91c2Vkb3duJywgWyckZXZlbnQnXSlcclxuICAgIG1vdXNlZG93bihldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xyXG4gICAgICAgIGlmICghdGhpcy5faXNEaXNhYmxlZCAmJiB0aGlzLl9zZWxlY3Rpb25TZXJ2aWNlLmlzRW5hYmxlZCAmJiB0aGlzLl9zZWxlY3Rpb25TZXJ2aWNlLmlzQ2xpY2tFbmFibGVkKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX3NlbGVjdGlvblNlcnZpY2Uuc3RyYXRlZ3kubW91c2Vkb3duKGV2ZW50LCB0aGlzLnV4U2VsZWN0aW9uSXRlbSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIEBIb3N0TGlzdGVuZXIoJ2tleWRvd24nLCBbJyRldmVudCddKVxyXG4gICAga2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xyXG5cclxuICAgICAgICAvLyBpZiB0aGUgc3BhY2Uga2V5IChzZWxlY3Rpb24ga2V5KSBpcyBwcmVzc2VkIGFuZCB3ZSBhcmUgZGlzYWJsZWQgdGhlbiB3ZSBzaG91bGQgYmxvY2tcclxuICAgICAgICAvLyB0aGUgZXZlbnQgZnJvbSBwcm9wYWdhdGluZy4gSG93ZXZlciBpZiB0aGlzIGlzIGEga2V5IHN1Y2ggYXMgYXJyb3cgcHJlc3NlcyB0aGVuIHdlIGRvXHJcbiAgICAgICAgLy8gc3RpbGwgd2FudCB0aGlzIHRvIHByb3BhZ2F0ZSB0byBhbGxvdyBrZXlib2FyZCBuYXZpZ2F0aW9uIGZvciBhY2Nlc3NpYmlsaXR5IHB1cnBvc2VzLlxyXG4gICAgICAgIGNvbnN0IGlzRGlzYWJsZWQgPSB0aGlzLl9pc0Rpc2FibGVkICYmIGV2ZW50LmtleUNvZGUgPT09IFNQQUNFO1xyXG5cclxuICAgICAgICBpZiAoIWlzRGlzYWJsZWQgJiYgdGhpcy5fc2VsZWN0aW9uU2VydmljZS5pc0VuYWJsZWQgJiYgdGhpcy5fc2VsZWN0aW9uU2VydmljZS5pc0tleWJvYXJkRW5hYmxlZCkge1xyXG4gICAgICAgICAgICB0aGlzLl9zZWxlY3Rpb25TZXJ2aWNlLnN0cmF0ZWd5LmtleWRvd24oZXZlbnQsIHRoaXMudXhTZWxlY3Rpb25JdGVtKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgQEhvc3RMaXN0ZW5lcignZm9jdXMnKVxyXG4gICAgZm9jdXMoKTogdm9pZCB7XHJcbiAgICAgICAgLy8gSWYgdGFiYmVkIHRvIGZyb20gb3V0c2lkZSB0aGUgY29tcG9uZW50LCBhY3RpdmF0ZS5cclxuICAgICAgICBpZiAodGhpcy5fc2VsZWN0aW9uU2VydmljZS5hY3RpdmUkLmdldFZhbHVlKCkgIT09IHRoaXMudXhTZWxlY3Rpb25JdGVtKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX3NlbGVjdGlvblNlcnZpY2UuYWN0aXZhdGUodGhpcy51eFNlbGVjdGlvbkl0ZW0pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFNlbGVjdCB0aGlzIGl0ZW0gdXNpbmcgdGhlIGN1cnJlbnQgc3RyYXRlZ3lcclxuICAgICAqL1xyXG4gICAgc2VsZWN0KCk6IHZvaWQge1xyXG4gICAgICAgIGlmICghdGhpcy5faXNEaXNhYmxlZCAmJiB0aGlzLl9zZWxlY3Rpb25TZXJ2aWNlLmlzRW5hYmxlZCkge1xyXG4gICAgICAgICAgICB0aGlzLl9zZWxlY3Rpb25TZXJ2aWNlLnN0cmF0ZWd5LnNlbGVjdCh0aGlzLnV4U2VsZWN0aW9uSXRlbSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVzZWxlY3QgdGhpcyBpdGVtIHVzaW5nIHRoZSBjdXJyZW50IHN0cmF0ZWd5XHJcbiAgICAgKi9cclxuICAgIGRlc2VsZWN0KCk6IHZvaWQge1xyXG4gICAgICAgIGlmICghdGhpcy5faXNEaXNhYmxlZCAmJiB0aGlzLl9zZWxlY3Rpb25TZXJ2aWNlLmlzRW5hYmxlZCkge1xyXG4gICAgICAgICAgICB0aGlzLl9zZWxlY3Rpb25TZXJ2aWNlLnN0cmF0ZWd5LmRlc2VsZWN0KHRoaXMudXhTZWxlY3Rpb25JdGVtKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSB1cGRhdGVTZWxlY3Rpb25JdGVtKCk6IHZvaWQge1xyXG5cclxuICAgICAgICBpZiAodGhpcy5fc2VsZWN0aW9uU3RhdGVTdWJzY3JpcHRpb24pIHtcclxuICAgICAgICAgICAgdGhpcy5fc2VsZWN0aW9uU3RhdGVTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHN1YnNjcmliZSB0byBzZWxlY3Rpb24gY2hhbmdlcyBvbiB0aGlzIGl0ZW0gKGRvbid0IGVtaXQgdGhlIGluaXRpYWwgdmFsdWUpXHJcbiAgICAgICAgdGhpcy5fc2VsZWN0aW9uU3RhdGVTdWJzY3JpcHRpb24gPSB0aGlzLl9zZWxlY3Rpb25TZXJ2aWNlLmdldFNlbGVjdGlvblN0YXRlKHRoaXMudXhTZWxlY3Rpb25JdGVtKS5waXBlKFxyXG4gICAgICAgICAgICBza2lwKDEpLFxyXG4gICAgICAgICAgICB0YXAoKCkgPT4gdGhpcy5faGFzUGVuZGluZ1N0YXRlQ2hhbmdlID0gdHJ1ZSksXHJcbiAgICAgICAgICAgIGRlYm91bmNlVGltZSgwKSxcclxuICAgICAgICAgICAgdGFrZVVudGlsKHRoaXMuX29uRGVzdHJveSlcclxuICAgICAgICApLnN1YnNjcmliZShzZWxlY3RlZCA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuX2hhc1BlbmRpbmdTdGF0ZUNoYW5nZSA9IGZhbHNlO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuX3NlbGVjdGVkID09PSBzZWxlY3RlZCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBzdG9yZSB0aGUgc2VsZWN0ZWQgc3RhdGVcclxuICAgICAgICAgICAgdGhpcy5fc2VsZWN0ZWQgPSBzZWxlY3RlZDtcclxuXHJcbiAgICAgICAgICAgIC8vIGVtaXQgdGhlIHNlbGVjdGVkIHN0YXRlXHJcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRDaGFuZ2UuZW1pdChzZWxlY3RlZCk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLl9jaGFuZ2VEZXRlY3Rvci5tYXJrRm9yQ2hlY2soKTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5fc2VsZWN0ZWQgPSB0aGlzLl9zZWxlY3Rpb25TZXJ2aWNlLmlzU2VsZWN0ZWQodGhpcy51eFNlbGVjdGlvbkl0ZW0pO1xyXG4gICAgfVxyXG5cclxuICAgIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9hZGRBcmlhQXR0cmlidXRlczogQm9vbGVhbklucHV0O1xyXG59XHJcbiJdfQ==