carbon-components-angular
Version:
Next generation components
231 lines • 21.9 kB
JavaScript
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==