UNPKG

carbon-components-angular

Version:
231 lines 21.9 kB
import { DOCUMENT } from "@angular/common"; import { Component, Input, Output, TemplateRef, EventEmitter, Inject, ViewChild } from "@angular/core"; import { TreeViewService } from "./treeview.service"; import * as i0 from "@angular/core"; import * as i1 from "./treeview.service"; import * as i2 from "@angular/common"; import * as i3 from "./tree-node.component"; /** * Get started with importing the module: * * ```typescript * import { TreeviewModule } from 'carbon-components-angular'; * ``` * * [See demo](../../?path=/story/components-tree-view--basic) */ export class TreeViewComponent { constructor(document, treeViewService, elementRef) { this.document = document; this.treeViewService = treeViewService; this.elementRef = elementRef; this.id = `tree-view-${TreeViewComponent.treeViewCount++}`; /** * Specify the size of the list items in the tree */ this.size = "sm"; this.select = new EventEmitter(); this.toggle = new EventEmitter(); this._tree = []; } /** * Pass `Node[]` array to have tree view render the nodes * Passing value will disregard projected content */ set tree(treeNodes) { this._tree = treeNodes.map((node) => this.copyNode(node)); this.treeViewService.contentProjected = false; } get tree() { return this._tree; } /** * **Experimental** - Enable to select multiple nodes */ set isMultiSelect(isMulti) { this.treeViewService.isMultiSelect = isMulti; } /** * Subscribe for node selection */ ngOnInit() { this.subscription = this.treeViewService.selectionObservable.subscribe((nodesMap) => { // Get all values from the map to emit const nodes = [...nodesMap.values()]; this.select.emit(this.treeViewService.isMultiSelect ? nodes : nodes[0]); }); this.subscription.add(this.treeViewService.focusNodeObservable.subscribe(node => this.onNodeFocusChange(node))); } ngOnDestroy() { this.subscription.unsubscribe(); } /** * Initialize tree walker to support keyboard navigation */ ngAfterViewInit() { this.treeWalker = this.document.createTreeWalker(this.root.nativeElement, NodeFilter.SHOW_ELEMENT, { acceptNode: function (node) { if (node.classList.contains(`cds--tree-node--disabled`)) { return NodeFilter.FILTER_REJECT; } if (node.matches(`div.cds--tree-node`)) { return NodeFilter.FILTER_ACCEPT; } return NodeFilter.FILTER_SKIP; } }); } /** * Navigate tree using tree walker * @param event - KeyboardEvent */ navigateTree(event) { if (event.key === "ArrowUp") { this.treeWalker.previousNode()?.focus(); } if (event.key === "ArrowDown") { this.treeWalker.nextNode()?.focus(); } } /** * Propagate node toggle event * @param eventOnNode - EventOnNode */ onNodeToggle(eventOnNode) { if (!eventOnNode) { return; } this.toggle.emit(eventOnNode.node); } /** * Node focus change * @param node - Node */ onNodeFocusChange(node) { if (!node) { // if for some reason the focused node is not defined we fallback on the root element of the treeview this.treeWalker.currentNode = this.treeWalker.root; return; } // Update current node based on focus change to have a better keyboard navigation experience this.treeWalker.currentNode = this.elementRef.nativeElement.querySelector(`#${CSS.escape(node.id)}`); } isTemplate(value) { return value instanceof TemplateRef; } isProjected() { return this.treeViewService.contentProjected; } copyNode(node) { // making a recursive shallow copy to avoid performance issues when deeply cloning templateRefs if defined in the node const copiedNode = Object.assign({}, node); if (node.children) { copiedNode.children = node.children.map(child => this.copyNode(child)); } return copiedNode; } } TreeViewComponent.treeViewCount = 0; TreeViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TreeViewComponent, deps: [{ token: DOCUMENT }, { token: i1.TreeViewService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); TreeViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: TreeViewComponent, selector: "cds-tree-view", inputs: { tree: "tree", id: "id", label: "label", labelContext: "labelContext", size: "size", isMultiSelect: "isMultiSelect" }, outputs: { select: "select", toggle: "toggle" }, providers: [TreeViewService], viewQueries: [{ propertyName: "root", first: true, predicate: ["treeWrapper"], descendants: true }], ngImport: i0, template: ` <label *ngIf="label" [id]="id" class="cds--label"> <ng-container *ngIf="!isTemplate(label)">{{label}}</ng-container> <ng-template *ngIf="isTemplate(label)" [ngTemplateOutlet]="label" [ngTemplateOutletContext]="{ $implicit: labelContext }"> </ng-template> </label> <div class="cds--tree" [ngClass]="{ 'cds--tree--sm': size === 'sm', 'cds--tree--xs': size === 'xs' }" [attr.aria-label]="label ? label : null" [attr.aria-labelledby]="!label ? id : null" [attr.aria-multiselectable]="isMultiSelect || null" role="tree" (keydown)="navigateTree($event)" #treeWrapper> <ng-container *ngIf="isProjected(); else notProjected"> <ng-content></ng-content> </ng-container> <ng-template #notProjected> <cds-tree-node *ngFor="let node of tree" [node]="node" (nodetoggle)="onNodeToggle($event)"> </cds-tree-node> </ng-template> </div> `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.TreeNodeComponent, selector: "cds-tree-node", inputs: ["id", "active", "disabled", "selectable", "expanded", "label", "labelContext", "selected", "value", "icon", "iconContext", "gap", "children", "depth", "node"], outputs: ["nodeFocus", "nodeBlur", "nodeSelect", "nodetoggle"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TreeViewComponent, decorators: [{ type: Component, args: [{ selector: "cds-tree-view", template: ` <label *ngIf="label" [id]="id" class="cds--label"> <ng-container *ngIf="!isTemplate(label)">{{label}}</ng-container> <ng-template *ngIf="isTemplate(label)" [ngTemplateOutlet]="label" [ngTemplateOutletContext]="{ $implicit: labelContext }"> </ng-template> </label> <div class="cds--tree" [ngClass]="{ 'cds--tree--sm': size === 'sm', 'cds--tree--xs': size === 'xs' }" [attr.aria-label]="label ? label : null" [attr.aria-labelledby]="!label ? id : null" [attr.aria-multiselectable]="isMultiSelect || null" role="tree" (keydown)="navigateTree($event)" #treeWrapper> <ng-container *ngIf="isProjected(); else notProjected"> <ng-content></ng-content> </ng-container> <ng-template #notProjected> <cds-tree-node *ngFor="let node of tree" [node]="node" (nodetoggle)="onNodeToggle($event)"> </cds-tree-node> </ng-template> </div> `, providers: [TreeViewService] }] }], ctorParameters: function () { return [{ type: Document, decorators: [{ type: Inject, args: [DOCUMENT] }] }, { type: i1.TreeViewService }, { type: i0.ElementRef }]; }, propDecorators: { tree: [{ type: Input }], id: [{ type: Input }], label: [{ type: Input }], labelContext: [{ type: Input }], size: [{ type: Input }], isMultiSelect: [{ type: Input }], select: [{ type: Output }], toggle: [{ type: Output }], root: [{ type: ViewChild, args: ["treeWrapper"] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZXZpZXcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyZWV2aWV3L3RyZWV2aWV3LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUNOLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFdBQVcsRUFDWCxZQUFZLEVBRVosTUFBTSxFQUNOLFNBQVMsRUFJVCxNQUFNLGVBQWUsQ0FBQztBQUd2QixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7Ozs7O0FBRXJEOzs7Ozs7OztHQVFHO0FBeUNILE1BQU0sT0FBTyxpQkFBaUI7SUE0QzdCLFlBQzJCLFFBQWtCLEVBQ3JDLGVBQWdDLEVBQy9CLFVBQXNCO1FBRkosYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUNyQyxvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7UUFDL0IsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQS9CdEIsT0FBRSxHQUFHLGFBQWEsaUJBQWlCLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQztRQVMvRDs7V0FFRztRQUNNLFNBQUksR0FBZ0IsSUFBSSxDQUFDO1FBUXhCLFdBQU0sR0FBRyxJQUFJLFlBQVksRUFBaUIsQ0FBQztRQUMzQyxXQUFNLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztRQUlwQyxVQUFLLEdBQVcsRUFBRSxDQUFDO0lBT3hCLENBQUM7SUEvQ0o7OztPQUdHO0lBQ0gsSUFBYSxJQUFJLENBQUMsU0FBaUI7UUFDbEMsSUFBSSxDQUFDLEtBQUssR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDMUQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7SUFDL0Ms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RyxNQUFNO3NCQUFmLE1BQU07Z0JBQ21CLElBQUk7c0JBQTdCLFNBQVM7dUJBQUMsYUFBYSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERPQ1VNRU5UIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuaW1wb3J0IHtcblx0Q29tcG9uZW50LFxuXHRJbnB1dCxcblx0T3V0cHV0LFxuXHRUZW1wbGF0ZVJlZixcblx0RXZlbnRFbWl0dGVyLFxuXHRBZnRlclZpZXdJbml0LFxuXHRJbmplY3QsXG5cdFZpZXdDaGlsZCxcblx0RWxlbWVudFJlZixcblx0T25Jbml0LFxuXHRPbkRlc3Ryb3lcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyBFdmVudE9uTm9kZSwgTm9kZSB9IGZyb20gXCIuL3RyZWUtbm9kZS50eXBlc1wiO1xuaW1wb3J0IHsgVHJlZVZpZXdTZXJ2aWNlIH0gZnJvbSBcIi4vdHJlZXZpZXcuc2VydmljZVwiO1xuXG4vKipcbiAqIEdldCBzdGFydGVkIHdpdGggaW1wb3J0aW5nIHRoZSBtb2R1bGU6XG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgVHJlZXZpZXdNb2R1bGUgfSBmcm9tICdjYXJib24tY29tcG9uZW50cy1hbmd1bGFyJztcbiAqIGBgYFxuICpcbiAqIFtTZWUgZGVtb10oLi4vLi4vP3BhdGg9L3N0b3J5L2NvbXBvbmVudHMtdHJlZS12aWV3LS1iYXNpYylcbiAqL1xuQENvbXBvbmVudCh7XG5cdHNlbGVjdG9yOiBcImNkcy10cmVlLXZpZXdcIixcblx0dGVtcGxhdGU6IGBcblx0XHQ8bGFiZWxcblx0XHRcdCpuZ0lmPVwibGFiZWxcIlxuXHRcdFx0W2lkXT1cImlkXCJcblx0XHRcdGNsYXNzPVwiY2RzLS1sYWJlbFwiPlxuXHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpc1RlbXBsYXRlKGxhYmVsKVwiPnt7bGFiZWx9fTwvbmctY29udGFpbmVyPlxuXHRcdFx0PG5nLXRlbXBsYXRlXG5cdFx0XHRcdCpuZ0lmPVwiaXNUZW1wbGF0ZShsYWJlbClcIlxuXHRcdFx0XHRbbmdUZW1wbGF0ZU91dGxldF09XCJsYWJlbFwiXG5cdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ICRpbXBsaWNpdDogbGFiZWxDb250ZXh0IH1cIj5cblx0XHRcdDwvbmctdGVtcGxhdGU+XG5cdFx0PC9sYWJlbD5cblx0XHQ8ZGl2XG5cdFx0XHRjbGFzcz1cImNkcy0tdHJlZVwiXG5cdFx0XHRbbmdDbGFzc109XCJ7XG5cdFx0XHRcdCdjZHMtLXRyZWUtLXNtJzogc2l6ZSA9PT0gJ3NtJyxcblx0XHRcdFx0J2Nkcy0tdHJlZS0teHMnOiBzaXplID09PSAneHMnXG5cdFx0XHR9XCJcblx0XHRcdFthdHRyLmFyaWEtbGFiZWxdPVwibGFiZWwgPyBsYWJlbCA6IG51bGxcIlxuXHRcdFx0W2F0dHIuYXJpYS1sYWJlbGxlZGJ5XT1cIiFsYWJlbCA/IGlkIDogbnVsbFwiXG5cdFx0XHRbYXR0ci5hcmlhLW11bHRpc2VsZWN0YWJsZV09XCJpc011bHRpU2VsZWN0IHx8IG51bGxcIlxuXHRcdFx0cm9sZT1cInRyZWVcIlxuXHRcdFx0KGtleWRvd24pPVwibmF2aWdhdGVUcmVlKCRldmVudClcIlxuXHRcdFx0I3RyZWVXcmFwcGVyPlxuXHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cImlzUHJvamVjdGVkKCk7IGVsc2Ugbm90UHJvamVjdGVkXCI+XG5cdFx0XHRcdDxuZy1jb250ZW50PjwvbmctY29udGVudD5cblx0XHRcdDwvbmctY29udGFpbmVyPlxuXHRcdFx0PG5nLXRlbXBsYXRlICNub3RQcm9qZWN0ZWQ+XG5cdFx0XHRcdDxjZHMtdHJlZS1ub2RlXG5cdFx0XHRcdFx0Km5nRm9yPVwibGV0IG5vZGUgb2YgdHJlZVwiXG5cdFx0XHRcdFx0W25vZGVdPVwibm9kZVwiXG5cdFx0XHRcdFx0KG5vZGV0b2dnbGUpPVwib25Ob2RlVG9nZ2xlKCRldmVudClcIj5cblx0XHRcdFx0PC9jZHMtdHJlZS1ub2RlPlxuXHRcdFx0PC9uZy10ZW1wbGF0ZT5cblx0XHQ8L2Rpdj5cblx0YCxcblx0cHJvdmlkZXJzOiBbVHJlZVZpZXdTZXJ2aWNlXVxufSlcbmV4cG9ydCBjbGFzcyBUcmVlVmlld0NvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uSW5pdCwgT25EZXN0cm95IHtcblx0LyoqXG5cdCAqIFBhc3MgYE5vZGVbXWAgYXJyYXkgdG8gaGF2ZSB0cmVlIHZpZXcgcmVuZGVyIHRoZSBub2Rlc1xuXHQgKiBQYXNzaW5nIHZhbHVlIHdpbGwgZGlzcmVnYXJkIHByb2plY3RlZCBjb250ZW50XG5cdCAqL1xuXHRASW5wdXQoKSBzZXQgdHJlZSh0cmVlTm9kZXM6IE5vZGVbXSkge1xuXHRcdHRoaXMuX3RyZWUgPSB0cmVlTm9kZXMubWFwKChub2RlKSA9PiB0aGlzLmNvcHlOb2RlKG5vZGUpKTtcblx0XHR0aGlzLnRyZWVWaWV3U2VydmljZS5jb250ZW50UHJvamVjdGVkID0gZmFsc2U7XG5cdH1cblxuXHRnZXQgdHJlZSgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdHJlZTtcblx0fVxuXG5cdHN0YXRpYyB0cmVlVmlld0NvdW50ID0gMDtcblxuXHRASW5wdXQoKSBpZCA9IGB0cmVlLXZpZXctJHtUcmVlVmlld0NvbXBvbmVudC50cmVlVmlld0NvdW50Kyt9YDtcblx0LyoqXG5cdCAqIFRyZWUgdmlldyBsYWJlbFxuXHQgKi9cblx0QElucHV0KCkgbGFiZWw6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT47XG5cdC8qKlxuXHQgKiBPcHRpb25hbCBjb250ZXh0IGZvciBsYWJlbCBpZiBpdCdzIGEgdGVtcGxhdGVcblx0ICovXG5cdEBJbnB1dCgpIGxhYmVsQ29udGV4dDogYW55O1xuXHQvKipcblx0ICogU3BlY2lmeSB0aGUgc2l6ZSBvZiB0aGUgbGlzdCBpdGVtcyBpbiB0aGUgdHJlZVxuXHQgKi9cblx0QElucHV0KCkgc2l6ZTogXCJ4c1wiIHwgXCJzbVwiID0gXCJzbVwiO1xuXHQvKipcblx0ICogKipFeHBlcmltZW50YWwqKiAtIEVuYWJsZSB0byBzZWxlY3QgbXVsdGlwbGUgbm9kZXNcblx0ICovXG5cdEBJbnB1dCgpIHNldCBpc011bHRpU2VsZWN0KGlzTXVsdGk6IGJvb2xlYW4pIHtcblx0XHR0aGlzLnRyZWVWaWV3U2VydmljZS5pc011bHRpU2VsZWN0ID0gaXNNdWx0aTtcblx0fVxuXG5cdEBPdXRwdXQoKSBzZWxlY3QgPSBuZXcgRXZlbnRFbWl0dGVyPE5vZGUgfCBOb2RlW10+KCk7XG5cdEBPdXRwdXQoKSB0b2dnbGUgPSBuZXcgRXZlbnRFbWl0dGVyPE5vZGU+KCk7XG5cdEBWaWV3Q2hpbGQoXCJ0cmVlV3JhcHBlclwiKSByb290OiBFbGVtZW50UmVmO1xuXG5cdHByaXZhdGUgdHJlZVdhbGtlcjogVHJlZVdhbGtlcjtcblx0cHJpdmF0ZSBfdHJlZTogTm9kZVtdID0gW107XG5cdHByaXZhdGUgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cblx0Y29uc3RydWN0b3IoXG5cdFx0QEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQsXG5cdFx0cHVibGljIHRyZWVWaWV3U2VydmljZTogVHJlZVZpZXdTZXJ2aWNlLFxuXHRcdHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZlxuXHQpIHt9XG5cblx0LyoqXG5cdCAqIFN1YnNjcmliZSBmb3Igbm9kZSBzZWxlY3Rpb25cblx0ICovXG5cdG5nT25Jbml0KCk6IHZvaWQge1xuXHRcdHRoaXMuc3Vic2NyaXB0aW9uID0gdGhpcy50cmVlVmlld1NlcnZpY2Uuc2VsZWN0aW9uT2JzZXJ2YWJsZS5zdWJzY3JpYmUoKG5vZGVzTWFwOiBNYXA8c3RyaW5nLCBOb2RlPikgPT4ge1xuXHRcdFx0Ly8gR2V0IGFsbCB2YWx1ZXMgZnJvbSB0aGUgbWFwIHRvIGVtaXRcblx0XHRcdGNvbnN0IG5vZGVzID0gWy4uLm5vZGVzTWFwLnZhbHVlcygpXTtcblxuXHRcdFx0dGhpcy5zZWxlY3QuZW1pdCh0aGlzLnRyZWVWaWV3U2VydmljZS5pc011bHRpU2VsZWN0ID8gbm9kZXMgOiBub2Rlc1swXSk7XG5cdFx0fSk7XG5cdFx0dGhpcy5zdWJzY3JpcHRpb24uYWRkKHRoaXMudHJlZVZpZXdTZXJ2aWNlLmZvY3VzTm9kZU9ic2VydmFibGUuc3Vic2NyaWJlKG5vZGUgPT4gdGhpcy5vbk5vZGVGb2N1c0NoYW5nZShub2RlKSkpO1xuXHR9XG5cblx0bmdPbkRlc3Ryb3koKTogdm9pZCB7XG5cdFx0dGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbml0aWFsaXplIHRyZWUgd2Fsa2VyIHRvIHN1cHBvcnQga2V5Ym9hcmQgbmF2aWdhdGlvblxuXHQgKi9cblx0bmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuXHRcdHRoaXMudHJlZVdhbGtlciA9IHRoaXMuZG9jdW1lbnQuY3JlYXRlVHJlZVdhbGtlcih0aGlzLnJvb3QubmF0aXZlRWxlbWVudCwgTm9kZUZpbHRlci5TSE9XX0VMRU1FTlQsIHtcblx0XHRcdGFjY2VwdE5vZGU6IGZ1bmN0aW9uIChub2RlOiBIVE1MRWxlbWVudCkge1xuXHRcdFx0XHRpZiAobm9kZS5jbGFzc0xpc3QuY29udGFpbnMoYGNkcy0tdHJlZS1ub2RlLS1kaXNhYmxlZGApKSB7XG5cdFx0XHRcdFx0cmV0dXJuIE5vZGVGaWx0ZXIuRklMVEVSX1JFSkVDVDtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAobm9kZS5tYXRjaGVzKGBkaXYuY2RzLS10cmVlLW5vZGVgKSkge1xuXHRcdFx0XHRcdHJldHVybiBOb2RlRmlsdGVyLkZJTFRFUl9BQ0NFUFQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIE5vZGVGaWx0ZXIuRklMVEVSX1NLSVA7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogTmF2aWdhdGUgdHJlZSB1c2luZyB0cmVlIHdhbGtlclxuXHQgKiBAcGFyYW0gZXZlbnQgLSBLZXlib2FyZEV2ZW50XG5cdCAqL1xuXHRuYXZpZ2F0ZVRyZWUoZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcblx0XHRpZiAoZXZlbnQua2V5ID09PSBcIkFycm93VXBcIikge1xuXHRcdFx0KHRoaXMudHJlZVdhbGtlci5wcmV2aW91c05vZGUoKSBhcyBIVE1MRWxlbWVudCk/LmZvY3VzKCk7XG5cdFx0fVxuXG5cdFx0aWYgKGV2ZW50LmtleSA9PT0gXCJBcnJvd0Rvd25cIikge1xuXHRcdFx0KHRoaXMudHJlZVdhbGtlci5uZXh0Tm9kZSgpIGFzIEhUTUxFbGVtZW50KT8uZm9jdXMoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUHJvcGFnYXRlIG5vZGUgdG9nZ2xlIGV2ZW50XG5cdCAqIEBwYXJhbSBldmVudE9uTm9kZSAtIEV2ZW50T25Ob2RlXG5cdCAqL1xuXHRvbk5vZGVUb2dnbGUoZXZlbnRPbk5vZGU6IEV2ZW50T25Ob2RlKSB7XG5cdFx0aWYgKCFldmVudE9uTm9kZSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLnRvZ2dsZS5lbWl0KGV2ZW50T25Ob2RlLm5vZGUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE5vZGUgZm9jdXMgY2hhbmdlXG5cdCAqIEBwYXJhbSBub2RlIC0gTm9kZVxuXHQgKi9cblx0b25Ob2RlRm9jdXNDaGFuZ2Uobm9kZTogTm9kZSkge1xuXHRcdGlmICghbm9kZSkge1xuXHRcdFx0Ly8gaWYgZm9yIHNvbWUgcmVhc29uIHRoZSBmb2N1c2VkIG5vZGUgaXMgbm90IGRlZmluZWQgd2UgZmFsbGJhY2sgb24gdGhlIHJvb3QgZWxlbWVudCBvZiB0aGUgdHJlZXZpZXdcblx0XHRcdHRoaXMudHJlZVdhbGtlci5jdXJyZW50Tm9kZSA9IHRoaXMudHJlZVdhbGtlci5yb290O1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHQvLyBVcGRhdGUgY3VycmVudCBub2RlIGJhc2VkIG9uIGZvY3VzIGNoYW5nZSB0byBoYXZlIGEgYmV0dGVyIGtleWJvYXJkIG5hdmlnYXRpb24gZXhwZXJpZW5jZVxuXHRcdHRoaXMudHJlZVdhbGtlci5jdXJyZW50Tm9kZSA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoYCMke0NTUy5lc2NhcGUobm9kZS5pZCl9YCk7XG5cdH1cblxuXHRwdWJsaWMgaXNUZW1wbGF0ZSh2YWx1ZSkge1xuXHRcdHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFRlbXBsYXRlUmVmO1xuXHR9XG5cblx0cHVibGljIGlzUHJvamVjdGVkKCkge1xuXHRcdHJldHVybiB0aGlzLnRyZWVWaWV3U2VydmljZS5jb250ZW50UHJvamVjdGVkO1xuXHR9XG5cblx0cHJpdmF0ZSBjb3B5Tm9kZShub2RlOiBOb2RlKTogTm9kZSB7XG5cdFx0Ly8gbWFraW5nIGEgcmVjdXJzaXZlIHNoYWxsb3cgY29weSB0byBhdm9pZCBwZXJmb3JtYW5jZSBpc3N1ZXMgd2hlbiBkZWVwbHkgY2xvbmluZyB0ZW1wbGF0ZVJlZnMgaWYgZGVmaW5lZCBpbiB0aGUgbm9kZVxuXHRcdGNvbnN0IGNvcGllZE5vZGUgPSBPYmplY3QuYXNzaWduKHt9LCBub2RlKTtcblx0XHRpZiAobm9kZS5jaGlsZHJlbikge1xuXHRcdFx0Y29waWVkTm9kZS5jaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW4ubWFwKGNoaWxkID0+IHRoaXMuY29weU5vZGUoY2hpbGQpKTtcblx0XHR9XG5cdFx0cmV0dXJuIGNvcGllZE5vZGU7XG5cdH1cbn1cbiJdfQ==