carbon-components-angular
Version:
Next generation components
239 lines • 22.6 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++}`;
/**
* Set to `true` to visually hide the label while keeping it available to assistive technologies.
*/
this.hideLabel = false;
/**
* 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", hideLabel: "hideLabel", 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"
[ngClass]="{'cds--visually-hidden': hideLabel}">
<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"
[ngClass]="{'cds--visually-hidden': hideLabel}">
<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
}], hideLabel: [{
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZXZpZXcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyZWV2aWV3L3RyZWV2aWV3LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUNOLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFdBQVcsRUFDWCxZQUFZLEVBRVosTUFBTSxFQUNOLFNBQVMsRUFJVCxNQUFNLGVBQWUsQ0FBQztBQUd2QixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7Ozs7O0FBRXJEOzs7Ozs7OztHQVFHO0FBMENILE1BQU0sT0FBTyxpQkFBaUI7SUFpRDdCLFlBQzJCLFFBQWtCLEVBQ3JDLGVBQWdDLEVBQy9CLFVBQXNCO1FBRkosYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUNyQyxvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7UUFDL0IsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQXBDdEIsT0FBRSxHQUFHLGFBQWEsaUJBQWlCLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQztRQU0vRDs7V0FFRztRQUNNLGNBQVMsR0FBRyxLQUFLLENBQUM7UUFLM0I7O1dBRUc7UUFDTSxTQUFJLEdBQWdCLElBQUksQ0FBQztRQVF4QixXQUFNLEdBQUcsSUFBSSxZQUFZLEVBQWlCLENBQUM7UUFDM0MsV0FBTSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFJcEMsVUFBSyxHQUFXLEVBQUUsQ0FBQztJQU94QixDQUFDO0lBcERKOzs7T0FHRztJQUNILElBQWEsSUFBSSxDQUFDLFNBQWlCO1FBQ2xDLElBQUksQ0FBQyxLQUFLLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxl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STtzQkFBWixLQUFLO2dCQUlPLGFBQWE7c0JBQXpCLEtBQUs7Z0JBSUksTUFBTTtzQkFBZixNQUFNO2dCQUNHLE1BQU07c0JBQWYsTUFBTTtnQkFDbUIsSUFBSTtzQkFBN0IsU0FBUzt1QkFBQyxhQUFhIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uXCI7XG5pbXBvcnQge1xuXHRDb21wb25lbnQsXG5cdElucHV0LFxuXHRPdXRwdXQsXG5cdFRlbXBsYXRlUmVmLFxuXHRFdmVudEVtaXR0ZXIsXG5cdEFmdGVyVmlld0luaXQsXG5cdEluamVjdCxcblx0Vmlld0NoaWxkLFxuXHRFbGVtZW50UmVmLFxuXHRPbkluaXQsXG5cdE9uRGVzdHJveVxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IEV2ZW50T25Ob2RlLCBOb2RlIH0gZnJvbSBcIi4vdHJlZS1ub2RlLnR5cGVzXCI7XG5pbXBvcnQgeyBUcmVlVmlld1NlcnZpY2UgfSBmcm9tIFwiLi90cmVldmlldy5zZXJ2aWNlXCI7XG5cbi8qKlxuICogR2V0IHN0YXJ0ZWQgd2l0aCBpbXBvcnRpbmcgdGhlIG1vZHVsZTpcbiAqXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBUcmVldmlld01vZHVsZSB9IGZyb20gJ2NhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXInO1xuICogYGBgXG4gKlxuICogW1NlZSBkZW1vXSguLi8uLi8/cGF0aD0vc3RvcnkvY29tcG9uZW50cy10cmVlLXZpZXctLWJhc2ljKVxuICovXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6IFwiY2RzLXRyZWUtdmlld1wiLFxuXHR0ZW1wbGF0ZTogYFxuXHRcdDxsYWJlbFxuXHRcdFx0Km5nSWY9XCJsYWJlbFwiXG5cdFx0XHRbaWRdPVwiaWRcIlxuXHRcdFx0Y2xhc3M9XCJjZHMtLWxhYmVsXCJcblx0XHRcdFtuZ0NsYXNzXT1cInsnY2RzLS12aXN1YWxseS1oaWRkZW4nOiBoaWRlTGFiZWx9XCI+XG5cdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIWlzVGVtcGxhdGUobGFiZWwpXCI+e3tsYWJlbH19PC9uZy1jb250YWluZXI+XG5cdFx0XHQ8bmctdGVtcGxhdGVcblx0XHRcdFx0Km5nSWY9XCJpc1RlbXBsYXRlKGxhYmVsKVwiXG5cdFx0XHRcdFtuZ1RlbXBsYXRlT3V0bGV0XT1cImxhYmVsXCJcblx0XHRcdFx0W25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiBsYWJlbENvbnRleHQgfVwiPlxuXHRcdFx0PC9uZy10ZW1wbGF0ZT5cblx0XHQ8L2xhYmVsPlxuXHRcdDxkaXZcblx0XHRcdGNsYXNzPVwiY2RzLS10cmVlXCJcblx0XHRcdFtuZ0NsYXNzXT1cIntcblx0XHRcdFx0J2Nkcy0tdHJlZS0tc20nOiBzaXplID09PSAnc20nLFxuXHRcdFx0XHQnY2RzLS10cmVlLS14cyc6IHNpemUgPT09ICd4cydcblx0XHRcdH1cIlxuXHRcdFx0W2F0dHIuYXJpYS1sYWJlbF09XCJsYWJlbCA/IGxhYmVsIDogbnVsbFwiXG5cdFx0XHRbYXR0ci5hcmlhLWxhYmVsbGVkYnldPVwiIWxhYmVsID8gaWQgOiBudWxsXCJcblx0XHRcdFthdHRyLmFyaWEtbXVsdGlzZWxlY3RhYmxlXT1cImlzTXVsdGlTZWxlY3QgfHwgbnVsbFwiXG5cdFx0XHRyb2xlPVwidHJlZVwiXG5cdFx0XHQoa2V5ZG93bik9XCJuYXZpZ2F0ZVRyZWUoJGV2ZW50KVwiXG5cdFx0XHQjdHJlZVdyYXBwZXI+XG5cdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiaXNQcm9qZWN0ZWQoKTsgZWxzZSBub3RQcm9qZWN0ZWRcIj5cblx0XHRcdFx0PG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuXHRcdFx0PC9uZy1jb250YWluZXI+XG5cdFx0XHQ8bmctdGVtcGxhdGUgI25vdFByb2plY3RlZD5cblx0XHRcdFx0PGNkcy10cmVlLW5vZGVcblx0XHRcdFx0XHQqbmdGb3I9XCJsZXQgbm9kZSBvZiB0cmVlXCJcblx0XHRcdFx0XHRbbm9kZV09XCJub2RlXCJcblx0XHRcdFx0XHQobm9kZXRvZ2dsZSk9XCJvbk5vZGVUb2dnbGUoJGV2ZW50KVwiPlxuXHRcdFx0XHQ8L2Nkcy10cmVlLW5vZGU+XG5cdFx0XHQ8L25nLXRlbXBsYXRlPlxuXHRcdDwvZGl2PlxuXHRgLFxuXHRwcm92aWRlcnM6IFtUcmVlVmlld1NlcnZpY2VdXG59KVxuZXhwb3J0IGNsYXNzIFRyZWVWaWV3Q29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25Jbml0LCBPbkRlc3Ryb3kge1xuXHQvKipcblx0ICogUGFzcyBgTm9kZVtdYCBhcnJheSB0byBoYXZlIHRyZWUgdmlldyByZW5kZXIgdGhlIG5vZGVzXG5cdCAqIFBhc3NpbmcgdmFsdWUgd2lsbCBkaXNyZWdhcmQgcHJvamVjdGVkIGNvbnRlbnRcblx0ICovXG5cdEBJbnB1dCgpIHNldCB0cmVlKHRyZWVOb2RlczogTm9kZVtdKSB7XG5cdFx0dGhpcy5fdHJlZSA9IHRyZWVOb2Rlcy5tYXAoKG5vZGUpID0+IHRoaXMuY29weU5vZGUobm9kZSkpO1xuXHRcdHRoaXMudHJlZVZpZXdTZXJ2aWNlLmNvbnRlbnRQcm9qZWN0ZWQgPSBmYWxzZTtcblx0fVxuXG5cdGdldCB0cmVlKCkge1xuXHRcdHJldHVybiB0aGlzLl90cmVlO1xuXHR9XG5cblx0c3RhdGljIHRyZWVWaWV3Q291bnQgPSAwO1xuXG5cdEBJbnB1dCgpIGlkID0gYHRyZWUtdmlldy0ke1RyZWVWaWV3Q29tcG9uZW50LnRyZWVWaWV3Q291bnQrK31gO1xuXHQvKipcblx0ICogVHJlZSB2aWV3IGxhYmVsXG5cdCAqL1xuXHRASW5wdXQoKSBsYWJlbDogc3RyaW5nIHwgVGVtcGxhdGVSZWY8YW55PjtcblxuXHQvKipcblx0ICogU2V0IHRvIGB0cnVlYCB0byB2aXN1YWxseSBoaWRlIHRoZSBsYWJlbCB3aGlsZSBrZWVwaW5nIGl0IGF2YWlsYWJsZSB0byBhc3Npc3RpdmUgdGVjaG5vbG9naWVzLlxuXHQgKi9cblx0QElucHV0KCkgaGlkZUxhYmVsID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBPcHRpb25hbCBjb250ZXh0IGZvciBsYWJlbCBpZiBpdCdzIGEgdGVtcGxhdGVcblx0ICovXG5cdEBJbnB1dCgpIGxhYmVsQ29udGV4dDogYW55O1xuXHQvKipcblx0ICogU3BlY2lmeSB0aGUgc2l6ZSBvZiB0aGUgbGlzdCBpdGVtcyBpbiB0aGUgdHJlZVxuXHQgKi9cblx0QElucHV0KCkgc2l6ZTogXCJ4c1wiIHwgXCJzbVwiID0gXCJzbVwiO1xuXHQvKipcblx0ICogKipFeHBlcmltZW50YWwqKiAtIEVuYWJsZSB0byBzZWxlY3QgbXVsdGlwbGUgbm9kZXNcblx0ICovXG5cdEBJbnB1dCgpIHNldCBpc011bHRpU2VsZWN0KGlzTXVsdGk6IGJvb2xlYW4pIHtcblx0XHR0aGlzLnRyZWVWaWV3U2VydmljZS5pc011bHRpU2VsZWN0ID0gaXNNdWx0aTtcblx0fVxuXG5cdEBPdXRwdXQoKSBzZWxlY3QgPSBuZXcgRXZlbnRFbWl0dGVyPE5vZGUgfCBOb2RlW10+KCk7XG5cdEBPdXRwdXQoKSB0b2dnbGUgPSBuZXcgRXZlbnRFbWl0dGVyPE5vZGU+KCk7XG5cdEBWaWV3Q2hpbGQoXCJ0cmVlV3JhcHBlclwiKSByb290OiBFbGVtZW50UmVmO1xuXG5cdHByaXZhdGUgdHJlZVdhbGtlcjogVHJlZVdhbGtlcjtcblx0cHJpdmF0ZSBfdHJlZTogTm9kZVtdID0gW107XG5cdHByaXZhdGUgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cblx0Y29uc3RydWN0b3IoXG5cdFx0QEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQsXG5cdFx0cHVibGljIHRyZWVWaWV3U2VydmljZTogVHJlZVZpZXdTZXJ2aWNlLFxuXHRcdHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZlxuXHQpIHt9XG5cblx0LyoqXG5cdCAqIFN1YnNjcmliZSBmb3Igbm9kZSBzZWxlY3Rpb25cblx0ICovXG5cdG5nT25Jbml0KCk6IHZvaWQge1xuXHRcdHRoaXMuc3Vic2NyaXB0aW9uID0gdGhpcy50cmVlVmlld1NlcnZpY2Uuc2VsZWN0aW9uT2JzZXJ2YWJsZS5zdWJzY3JpYmUoKG5vZGVzTWFwOiBNYXA8c3RyaW5nLCBOb2RlPikgPT4ge1xuXHRcdFx0Ly8gR2V0IGFsbCB2YWx1ZXMgZnJvbSB0aGUgbWFwIHRvIGVtaXRcblx0XHRcdGNvbnN0IG5vZGVzID0gWy4uLm5vZGVzTWFwLnZhbHVlcygpXTtcblxuXHRcdFx0dGhpcy5zZWxlY3QuZW1pdCh0aGlzLnRyZWVWaWV3U2VydmljZS5pc011bHRpU2VsZWN0ID8gbm9kZXMgOiBub2Rlc1swXSk7XG5cdFx0fSk7XG5cdFx0dGhpcy5zdWJzY3JpcHRpb24uYWRkKHRoaXMudHJlZVZpZXdTZXJ2aWNlLmZvY3VzTm9kZU9ic2VydmFibGUuc3Vic2NyaWJlKG5vZGUgPT4gdGhpcy5vbk5vZGVGb2N1c0NoYW5nZShub2RlKSkpO1xuXHR9XG5cblx0bmdPbkRlc3Ryb3koKTogdm9pZCB7XG5cdFx0dGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBJbml0aWFsaXplIHRyZWUgd2Fsa2VyIHRvIHN1cHBvcnQga2V5Ym9hcmQgbmF2aWdhdGlvblxuXHQgKi9cblx0bmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuXHRcdHRoaXMudHJlZVdhbGtlciA9IHRoaXMuZG9jdW1lbnQuY3JlYXRlVHJlZVdhbGtlcih0aGlzLnJvb3QubmF0aXZlRWxlbWVudCwgTm9kZUZpbHRlci5TSE9XX0VMRU1FTlQsIHtcblx0XHRcdGFjY2VwdE5vZGU6IGZ1bmN0aW9uIChub2RlOiBIVE1MRWxlbWVudCkge1xuXHRcdFx0XHRpZiAobm9kZS5jbGFzc0xpc3QuY29udGFpbnMoYGNkcy0tdHJlZS1ub2RlLS1kaXNhYmxlZGApKSB7XG5cdFx0XHRcdFx0cmV0dXJuIE5vZGVGaWx0ZXIuRklMVEVSX1JFSkVDVDtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAobm9kZS5tYXRjaGVzKGBkaXYuY2RzLS10cmVlLW5vZGVgKSkge1xuXHRcdFx0XHRcdHJldHVybiBOb2RlRmlsdGVyLkZJTFRFUl9BQ0NFUFQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIE5vZGVGaWx0ZXIuRklMVEVSX1NLSVA7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogTmF2aWdhdGUgdHJlZSB1c2luZyB0cmVlIHdhbGtlclxuXHQgKiBAcGFyYW0gZXZlbnQgLSBLZXlib2FyZEV2ZW50XG5cdCAqL1xuXHRuYXZpZ2F0ZVRyZWUoZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcblx0XHRpZiAoZXZlbnQua2V5ID09PSBcIkFycm93VXBcIikge1xuXHRcdFx0KHRoaXMudHJlZVdhbGtlci5wcmV2aW91c05vZGUoKSBhcyBIVE1MRWxlbWVudCk/LmZvY3VzKCk7XG5cdFx0fVxuXG5cdFx0aWYgKGV2ZW50LmtleSA9PT0gXCJBcnJvd0Rvd25cIikge1xuXHRcdFx0KHRoaXMudHJlZVdhbGtlci5uZXh0Tm9kZSgpIGFzIEhUTUxFbGVtZW50KT8uZm9jdXMoKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogUHJvcGFnYXRlIG5vZGUgdG9nZ2xlIGV2ZW50XG5cdCAqIEBwYXJhbSBldmVudE9uTm9kZSAtIEV2ZW50T25Ob2RlXG5cdCAqL1xuXHRvbk5vZGVUb2dnbGUoZXZlbnRPbk5vZGU6IEV2ZW50T25Ob2RlKSB7XG5cdFx0aWYgKCFldmVudE9uTm9kZSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLnRvZ2dsZS5lbWl0KGV2ZW50T25Ob2RlLm5vZGUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIE5vZGUgZm9jdXMgY2hhbmdlXG5cdCAqIEBwYXJhbSBub2RlIC0gTm9kZVxuXHQgKi9cblx0b25Ob2RlRm9jdXNDaGFuZ2Uobm9kZTogTm9kZSkge1xuXHRcdGlmICghbm9kZSkge1xuXHRcdFx0Ly8gaWYgZm9yIHNvbWUgcmVhc29uIHRoZSBmb2N1c2VkIG5vZGUgaXMgbm90IGRlZmluZWQgd2UgZmFsbGJhY2sgb24gdGhlIHJvb3QgZWxlbWVudCBvZiB0aGUgdHJlZXZpZXdcblx0XHRcdHRoaXMudHJlZVdhbGtlci5jdXJyZW50Tm9kZSA9IHRoaXMudHJlZVdhbGtlci5yb290O1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHQvLyBVcGRhdGUgY3VycmVudCBub2RlIGJhc2VkIG9uIGZvY3VzIGNoYW5nZSB0byBoYXZlIGEgYmV0dGVyIGtleWJvYXJkIG5hdmlnYXRpb24gZXhwZXJpZW5jZVxuXHRcdHRoaXMudHJlZVdhbGtlci5jdXJyZW50Tm9kZSA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoYCMke0NTUy5lc2NhcGUobm9kZS5pZCl9YCk7XG5cdH1cblxuXHRwdWJsaWMgaXNUZW1wbGF0ZSh2YWx1ZSkge1xuXHRcdHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFRlbXBsYXRlUmVmO1xuXHR9XG5cblx0cHVibGljIGlzUHJvamVjdGVkKCkge1xuXHRcdHJldHVybiB0aGlzLnRyZWVWaWV3U2VydmljZS5jb250ZW50UHJvamVjdGVkO1xuXHR9XG5cblx0cHJpdmF0ZSBjb3B5Tm9kZShub2RlOiBOb2RlKTogTm9kZSB7XG5cdFx0Ly8gbWFraW5nIGEgcmVjdXJzaXZlIHNoYWxsb3cgY29weSB0byBhdm9pZCBwZXJmb3JtYW5jZSBpc3N1ZXMgd2hlbiBkZWVwbHkgY2xvbmluZyB0ZW1wbGF0ZVJlZnMgaWYgZGVmaW5lZCBpbiB0aGUgbm9kZVxuXHRcdGNvbnN0IGNvcGllZE5vZGUgPSBPYmplY3QuYXNzaWduKHt9LCBub2RlKTtcblx0XHRpZiAobm9kZS5jaGlsZHJlbikge1xuXHRcdFx0Y29waWVkTm9kZS5jaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW4ubWFwKGNoaWxkID0+IHRoaXMuY29weU5vZGUoY2hpbGQpKTtcblx0XHR9XG5cdFx0cmV0dXJuIGNvcGllZE5vZGU7XG5cdH1cbn1cbiJdfQ==