carbon-components-angular
Version:
Next generation components
359 lines • 30.1 kB
JavaScript
import { Component, Input, Output, EventEmitter, TemplateRef } from "@angular/core";
import * as i0 from "@angular/core";
import * as i1 from "./treeview.service";
import * as i2 from "@angular/common";
import * as i3 from "carbon-components-angular/icon";
export class TreeNodeComponent {
constructor(treeViewService) {
this.treeViewService = treeViewService;
this.id = `tree-node-${TreeNodeComponent.treeNodeCount++}`;
this.active = false;
this.disabled = false;
this.expanded = false;
this.selected = false;
this.children = [];
/**
* Determines the depth of the node
* Calculated by default when passing `Node` array to `TreeViewComponent`, manual entry required otherwise
*/
this.depth = 0;
this.nodeFocus = new EventEmitter();
this.nodeBlur = new EventEmitter();
this.nodeSelect = new EventEmitter();
this.nodetoggle = new EventEmitter();
}
/**
* Simple way to set all attributes of Node component via node object
* Would simplify setting component attributes when dynamically rendering node.
*/
set node(node) {
this._node = node;
this.id = node.id ?? this.id;
this.active = node.active ?? this.active;
this.disabled = node.disabled ?? this.disabled;
this.expanded = node.expanded ?? this.expanded;
this.label = node.label ?? this.label;
this.value = node.value ?? this.value;
this.icon = node.icon ?? this.icon;
this.selected = node.selected ?? this.selected;
this.depth = node.depth ?? this.depth;
this.children = node.children ?? this.children;
}
get node() {
return this._node;
}
/**
* Caclulate offset for margin/padding
*/
ngAfterContentChecked() {
this.offset = this.calculateOffset();
}
/**
* Highlight the node
*/
ngOnInit() {
// Highlight the node
this.subscription = this.treeViewService.selectionObservable.subscribe((value) => {
this.selected = value.has(this.id);
this.active = this.selected;
});
}
/**
* Unsubscribe from subscriptions
*/
ngOnDestroy() {
this.subscription?.unsubscribe();
}
/**
* Selects the node and emits the event from the tree view component
* @param event
*/
nodeClick(event) {
if (!this.disabled) {
this.selected = true;
this.active = true;
event.target.parentElement.focus();
// Passes event to all nodes to update highlighting & parent to emit
this.treeViewService.selectNode({ id: this.id, label: this.label, value: this.value });
}
}
/**
* Calculate the node offset
* @returns Number
*/
calculateOffset() {
// Parent node with icon
if (this.children.length && this.icon) {
return this.depth + 1 + this.depth * 0.5;
}
// parent node without icon
if (this.children.length) {
return this.depth + 1;
}
// leaf node with icon
if (this.icon) {
return this.depth + 2 + this.depth * 0.5;
}
return this.depth + 2.5;
}
emitFocusEvent(event) {
this.nodeFocus.emit({ node: { id: this.id, label: this.label, value: this.value }, event });
}
emitBlurEvent(event) {
this.nodeBlur.emit({ node: { id: this.id, label: this.label, value: this.value }, event });
}
/**
* Expand children if not disabled
* @param event: Event
*/
toggleExpanded(event) {
if (!this.disabled) {
this.nodetoggle.emit({ node: { id: this.id, label: this.label, value: this.value }, event });
this.expanded = !this.expanded;
// Prevent selection of the node
event.stopPropagation();
}
}
/**
* Manages the keyboard accessibility for children expansion & selection
*/
navigateTree(event) {
if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "Enter") {
event.stopPropagation();
}
// Unexpand
if (event.key === "ArrowLeft") {
if (this.expanded && this.children) {
this.toggleExpanded(event);
}
}
if (event.key === "ArrowRight") {
if (!this.expanded && this.children) {
this.toggleExpanded(event);
}
}
if (event.key === "Enter") {
event.preventDefault();
this.nodeClick(event);
}
}
isTemplate(value) {
return value instanceof TemplateRef;
}
isProjected() {
return this.treeViewService.contentProjected;
}
}
TreeNodeComponent.treeNodeCount = 0;
TreeNodeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TreeNodeComponent, deps: [{ token: i1.TreeViewService }], target: i0.ɵɵFactoryTarget.Component });
TreeNodeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: TreeNodeComponent, selector: "cds-tree-node", inputs: { id: "id", active: "active", disabled: "disabled", expanded: "expanded", label: "label", selected: "selected", value: "value", icon: "icon", children: "children", depth: "depth", node: "node" }, outputs: { nodeFocus: "nodeFocus", nodeBlur: "nodeBlur", nodeSelect: "nodeSelect", nodetoggle: "nodetoggle" }, ngImport: i0, template: `
<div
[id]="id"
class="cds--tree-node"
[ngClass]="{
'cds--tree-node--active': active,
'cds--tree-node--disabled': disabled,
'cds--tree-node--selected': selected,
'cds--tree-leaf-node': !children.length,
'cds--tree-parent-node': children.length,
'cds--tree-node--with-icon': icon
}"
[attr.aria-expanded]="expanded || null"
[attr.aria-current]="active || null"
[attr.aria-selected]="disabled ? null : selected"
[attr.aria-disabled]="disabled"
role="treeitem"
[attr.tabindex]="selected ? 0 : -1"
(focus)="emitFocusEvent($event)"
(blur)="emitBlurEvent($event)"
(keydown)="navigateTree($event)">
<div
*ngIf="!children.length"
class="cds--tree-node__label"
[style.padding-inline-start.rem]="offset"
[style.margin-inline-start.rem]="-offset"
(click)="nodeClick($event)">
<!-- Icon -->
<ng-container *ngIf="icon && !isTemplate(icon)">
<svg
class="cds--tree-node__icon"
[cdsIcon]="icon"
size="16">
</svg>
</ng-container>
<ng-template *ngIf="isTemplate(icon)" [ngTemplateOutlet]="icon"></ng-template>
{{label}}
</div>
<div
*ngIf="children.length"
class="cds--tree-node__label"
[style.padding-inline-start.rem]="offset"
[style.margin-inline-start.rem]="-offset"
role="group"
(click)="nodeClick($event)">
<span
class="cds--tree-parent-node__toggle"
[attr.disabled]="disabled || null"
(click)="toggleExpanded($event)">
<svg
class="cds--tree-parent-node__toggle-icon"
[ngClass]="{'cds--tree-parent-node__toggle-icon--expanded' : expanded}"
ibmIcon="caret--down"
size="16">
</svg>
</span>
<span class="cds--tree-node__label__details">
<!-- Icon -->
<ng-container *ngIf="icon && !isTemplate(icon)">
<svg
class="cds--tree-node__icon"
[cdsIcon]="icon"
size="16">
</svg>
</ng-container>
<ng-template *ngIf="isTemplate(icon)" [ngTemplateOutlet]="icon"></ng-template>
{{label}}
</span>
</div>
<div
*ngIf="expanded"
role="group"
class="cds--tree-node__children">
<ng-container *ngIf="isProjected(); else notProjected">
<ng-content></ng-content>
</ng-container>
<ng-template #notProjected>
<cds-tree-node
*ngFor="let childNode of children"
[node]="childNode"
[depth]="depth + 1"
[disabled]="disabled">
</cds-tree-node>
</ng-template>
</div>
</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: "directive", type: i3.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }, { kind: "component", type: TreeNodeComponent, selector: "cds-tree-node", inputs: ["id", "active", "disabled", "expanded", "label", "selected", "value", "icon", "children", "depth", "node"], outputs: ["nodeFocus", "nodeBlur", "nodeSelect", "nodetoggle"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TreeNodeComponent, decorators: [{
type: Component,
args: [{
selector: "cds-tree-node",
template: `
<div
[id]="id"
class="cds--tree-node"
[ngClass]="{
'cds--tree-node--active': active,
'cds--tree-node--disabled': disabled,
'cds--tree-node--selected': selected,
'cds--tree-leaf-node': !children.length,
'cds--tree-parent-node': children.length,
'cds--tree-node--with-icon': icon
}"
[attr.aria-expanded]="expanded || null"
[attr.aria-current]="active || null"
[attr.aria-selected]="disabled ? null : selected"
[attr.aria-disabled]="disabled"
role="treeitem"
[attr.tabindex]="selected ? 0 : -1"
(focus)="emitFocusEvent($event)"
(blur)="emitBlurEvent($event)"
(keydown)="navigateTree($event)">
<div
*ngIf="!children.length"
class="cds--tree-node__label"
[style.padding-inline-start.rem]="offset"
[style.margin-inline-start.rem]="-offset"
(click)="nodeClick($event)">
<!-- Icon -->
<ng-container *ngIf="icon && !isTemplate(icon)">
<svg
class="cds--tree-node__icon"
[cdsIcon]="icon"
size="16">
</svg>
</ng-container>
<ng-template *ngIf="isTemplate(icon)" [ngTemplateOutlet]="icon"></ng-template>
{{label}}
</div>
<div
*ngIf="children.length"
class="cds--tree-node__label"
[style.padding-inline-start.rem]="offset"
[style.margin-inline-start.rem]="-offset"
role="group"
(click)="nodeClick($event)">
<span
class="cds--tree-parent-node__toggle"
[attr.disabled]="disabled || null"
(click)="toggleExpanded($event)">
<svg
class="cds--tree-parent-node__toggle-icon"
[ngClass]="{'cds--tree-parent-node__toggle-icon--expanded' : expanded}"
ibmIcon="caret--down"
size="16">
</svg>
</span>
<span class="cds--tree-node__label__details">
<!-- Icon -->
<ng-container *ngIf="icon && !isTemplate(icon)">
<svg
class="cds--tree-node__icon"
[cdsIcon]="icon"
size="16">
</svg>
</ng-container>
<ng-template *ngIf="isTemplate(icon)" [ngTemplateOutlet]="icon"></ng-template>
{{label}}
</span>
</div>
<div
*ngIf="expanded"
role="group"
class="cds--tree-node__children">
<ng-container *ngIf="isProjected(); else notProjected">
<ng-content></ng-content>
</ng-container>
<ng-template #notProjected>
<cds-tree-node
*ngFor="let childNode of children"
[node]="childNode"
[depth]="depth + 1"
[disabled]="disabled">
</cds-tree-node>
</ng-template>
</div>
</div>
`
}]
}], ctorParameters: function () { return [{ type: i1.TreeViewService }]; }, propDecorators: { id: [{
type: Input
}], active: [{
type: Input
}], disabled: [{
type: Input
}], expanded: [{
type: Input
}], label: [{
type: Input
}], selected: [{
type: Input
}], value: [{
type: Input
}], icon: [{
type: Input
}], children: [{
type: Input
}], depth: [{
type: Input
}], node: [{
type: Input
}], nodeFocus: [{
type: Output
}], nodeBlur: [{
type: Output
}], nodeSelect: [{
type: Output
}], nodetoggle: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZS1ub2RlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90cmVldmlldy90cmVlLW5vZGUuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTixTQUFTLEVBQ1QsS0FBSyxFQUNMLE1BQU0sRUFDTixZQUFZLEVBSVosV0FBVyxFQUVYLE1BQU0sZUFBZSxDQUFDOzs7OztBQStGdkIsTUFBTSxPQUFPLGlCQUFpQjtJQWtEN0IsWUFBb0IsZUFBZ0M7UUFBaEMsb0JBQWUsR0FBZixlQUFlLENBQWlCO1FBaEQzQyxPQUFFLEdBQUcsYUFBYSxpQkFBaUIsQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDO1FBQ3RELFdBQU0sR0FBRyxLQUFLLENBQUM7UUFDZixhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ2pCLGFBQVEsR0FBRyxLQUFLLENBQUM7UUFFakIsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUdqQixhQUFRLEdBQVcsRUFBRSxDQUFDO1FBRS9COzs7V0FHRztRQUNNLFVBQUssR0FBRyxDQUFDLENBQUM7UUF5QlQsY0FBUyxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDL0IsYUFBUSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDOUIsZUFBVSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDaEMsZUFBVSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7SUFNYSxDQUFDO0lBaEN4RDs7O09BR0c7SUFDSCxJQUFhLElBQUksQ0FBQyxJQUFVO1FBQzNCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBRWxCLElBQUksQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUUsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQ3pDLElBQUksQ0FBQyxRQUFR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Ozs7Ozs7Ozs7RUFzRlQ7aUJBQ0Q7c0dBR1MsRUFBRTtzQkFBVixLQUFLO2dCQUNHLE1BQU07c0JBQWQsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csS0FBSztzQkFBYixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csS0FBSztzQkFBYixLQUFLO2dCQUNHLElBQUk7c0JBQVosS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQU1HLEtBQUs7c0JBQWIsS0FBSztnQkFNTyxJQUFJO3NCQUFoQixLQUFLO2dCQW1CSSxTQUFTO3NCQUFsQixNQUFNO2dCQUNHLFFBQVE7c0JBQWpCLE1BQU07Z0JBQ0csVUFBVTtzQkFBbkIsTUFBTTtnQkFDRyxVQUFVO3NCQUFuQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcblx0Q29tcG9uZW50LFxuXHRJbnB1dCxcblx0T3V0cHV0LFxuXHRFdmVudEVtaXR0ZXIsXG5cdE9uSW5pdCxcblx0T25EZXN0cm95LFxuXHRBZnRlckNvbnRlbnRJbml0LFxuXHRUZW1wbGF0ZVJlZixcblx0QWZ0ZXJDb250ZW50Q2hlY2tlZFxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IFRyZWVWaWV3U2VydmljZSB9IGZyb20gXCIuL3RyZWV2aWV3LnNlcnZpY2VcIjtcbmltcG9ydCB7IE5vZGUgfSBmcm9tIFwiLi90cmVlLW5vZGUudHlwZXNcIjtcblxuQENvbXBvbmVudCh7XG5cdHNlbGVjdG9yOiBcImNkcy10cmVlLW5vZGVcIixcblx0dGVtcGxhdGU6IGBcblx0XHQ8ZGl2XG5cdFx0XHRbaWRdPVwiaWRcIlxuXHRcdFx0Y2xhc3M9XCJjZHMtLXRyZWUtbm9kZVwiXG5cdFx0XHRbbmdDbGFzc109XCJ7XG5cdFx0XHRcdCdjZHMtLXRyZWUtbm9kZS0tYWN0aXZlJzogYWN0aXZlLFxuXHRcdFx0XHQnY2RzLS10cmVlLW5vZGUtLWRpc2FibGVkJzogZGlzYWJsZWQsXG5cdFx0XHRcdCdjZHMtLXRyZWUtbm9kZS0tc2VsZWN0ZWQnOiBzZWxlY3RlZCxcblx0XHRcdFx0J2Nkcy0tdHJlZS1sZWFmLW5vZGUnOiAhY2hpbGRyZW4ubGVuZ3RoLFxuXHRcdFx0XHQnY2RzLS10cmVlLXBhcmVudC1ub2RlJzogY2hpbGRyZW4ubGVuZ3RoLFxuXHRcdFx0XHQnY2RzLS10cmVlLW5vZGUtLXdpdGgtaWNvbic6IGljb25cblx0XHRcdH1cIlxuXHRcdFx0W2F0dHIuYXJpYS1leHBhbmRlZF09XCJleHBhbmRlZCB8fCBudWxsXCJcblx0XHRcdFthdHRyLmFyaWEtY3VycmVudF09XCJhY3RpdmUgfHwgbnVsbFwiXG5cdFx0XHRbYXR0ci5hcmlhLXNlbGVjdGVkXT1cImRpc2FibGVkID8gbnVsbCA6IHNlbGVjdGVkXCJcblx0XHRcdFthdHRyLmFyaWEtZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuXHRcdFx0cm9sZT1cInRyZWVpdGVtXCJcblx0XHRcdFthdHRyLnRhYmluZGV4XT1cInNlbGVjdGVkID8gMCA6IC0xXCJcblx0XHRcdChmb2N1cyk9XCJlbWl0Rm9jdXNFdmVudCgkZXZlbnQpXCJcblx0XHRcdChibHVyKT1cImVtaXRCbHVyRXZlbnQoJGV2ZW50KVwiXG5cdFx0XHQoa2V5ZG93bik9XCJuYXZpZ2F0ZVRyZWUoJGV2ZW50KVwiPlxuXHRcdFx0PGRpdlxuXHRcdFx0XHQqbmdJZj1cIiFjaGlsZHJlbi5sZW5ndGhcIlxuXHRcdFx0XHRjbGFzcz1cImNkcy0tdHJlZS1ub2RlX19sYWJlbFwiXG5cdFx0XHRcdFtzdHlsZS5wYWRkaW5nLWlubGluZS1zdGFydC5yZW1dPVwib2Zmc2V0XCJcblx0XHRcdFx0W3N0eWxlLm1hcmdpbi1pbmxpbmUtc3RhcnQucmVtXT1cIi1vZmZzZXRcIlxuXHRcdFx0XHQoY2xpY2spPVwibm9kZUNsaWNrKCRldmVudClcIj5cblx0XHRcdFx0PCEtLSBJY29uIC0tPlxuXHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiaWNvbiAmJiAhaXNUZW1wbGF0ZShpY29uKVwiPlxuXHRcdFx0XHRcdDxzdmdcblx0XHRcdFx0XHRcdGNsYXNzPVwiY2RzLS10cmVlLW5vZGVfX2ljb25cIlxuXHRcdFx0XHRcdFx0W2Nkc0ljb25dPVwiaWNvblwiXG5cdFx0XHRcdFx0XHRzaXplPVwiMTZcIj5cblx0XHRcdFx0XHQ8L3N2Zz5cblx0XHRcdFx0PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdDxuZy10ZW1wbGF0ZSAqbmdJZj1cImlzVGVtcGxhdGUoaWNvbilcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJpY29uXCI+PC9uZy10ZW1wbGF0ZT5cblx0XHRcdFx0e3tsYWJlbH19XG5cdFx0XHQ8L2Rpdj5cblx0XHRcdDxkaXZcblx0XHRcdFx0Km5nSWY9XCJjaGlsZHJlbi5sZW5ndGhcIlxuXHRcdFx0XHRjbGFzcz1cImNkcy0tdHJlZS1ub2RlX19sYWJlbFwiXG5cdFx0XHRcdFtzdHlsZS5wYWRkaW5nLWlubGluZS1zdGFydC5yZW1dPVwib2Zmc2V0XCJcblx0XHRcdFx0W3N0eWxlLm1hcmdpbi1pbmxpbmUtc3RhcnQucmVtXT1cIi1vZmZzZXRcIlxuXHRcdFx0XHRyb2xlPVwiZ3JvdXBcIlxuXHRcdFx0XHQoY2xpY2spPVwibm9kZUNsaWNrKCRldmVudClcIj5cblx0XHRcdFx0PHNwYW5cblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tdHJlZS1wYXJlbnQtbm9kZV9fdG9nZ2xlXCJcblx0XHRcdFx0XHRbYXR0ci5kaXNhYmxlZF09XCJkaXNhYmxlZCB8fCBudWxsXCJcblx0XHRcdFx0XHQoY2xpY2spPVwidG9nZ2xlRXhwYW5kZWQoJGV2ZW50KVwiPlxuXHRcdFx0XHRcdDxzdmdcblx0XHRcdFx0XHRcdGNsYXNzPVwiY2RzLS10cmVlLXBhcmVudC1ub2RlX190b2dnbGUtaWNvblwiXG5cdFx0XHRcdFx0XHRbbmdDbGFzc109XCJ7J2Nkcy0tdHJlZS1wYXJlbnQtbm9kZV9fdG9nZ2xlLWljb24tLWV4cGFuZGVkJyA6IGV4cGFuZGVkfVwiXG5cdFx0XHRcdFx0XHRpYm1JY29uPVwiY2FyZXQtLWRvd25cIlxuXHRcdFx0XHRcdFx0c2l6ZT1cIjE2XCI+XG5cdFx0XHRcdFx0PC9zdmc+XG5cdFx0XHRcdDwvc3Bhbj5cblx0XHRcdFx0PHNwYW4gY2xhc3M9XCJjZHMtLXRyZWUtbm9kZV9fbGFiZWxfX2RldGFpbHNcIj5cblx0XHRcdFx0XHQ8IS0tIEljb24gLS0+XG5cdFx0XHRcdFx0PG5nLWNvbnRhaW5lciAqbmdJZj1cImljb24gJiYgIWlzVGVtcGxhdGUoaWNvbilcIj5cblx0XHRcdFx0XHRcdDxzdmdcblx0XHRcdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLXRyZWUtbm9kZV9faWNvblwiXG5cdFx0XHRcdFx0XHRcdFtjZHNJY29uXT1cImljb25cIlxuXHRcdFx0XHRcdFx0XHRzaXplPVwiMTZcIj5cblx0XHRcdFx0XHRcdDwvc3ZnPlxuXHRcdFx0XHRcdDwvbmctY29udGFpbmVyPlxuXHRcdFx0XHRcdDxuZy10ZW1wbGF0ZSAqbmdJZj1cImlzVGVtcGxhdGUoaWNvbilcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJpY29uXCI+PC9uZy10ZW1wbGF0ZT5cblx0XHRcdFx0XHR7e2xhYmVsfX1cblx0XHRcdFx0PC9zcGFuPlxuXHRcdFx0PC9kaXY+XG5cdFx0XHQ8ZGl2XG5cdFx0XHRcdCpuZ0lmPVwiZXhwYW5kZWRcIlxuXHRcdFx0XHRyb2xlPVwiZ3JvdXBcIlxuXHRcdFx0XHRjbGFzcz1cImNkcy0tdHJlZS1ub2RlX19jaGlsZHJlblwiPlxuXHRcdFx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiaXNQcm9qZWN0ZWQoKTsgZWxzZSBub3RQcm9qZWN0ZWRcIj5cblx0XHRcdFx0XHQ8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG5cdFx0XHRcdDwvbmctY29udGFpbmVyPlxuXHRcdFx0XHQ8bmctdGVtcGxhdGUgI25vdFByb2plY3RlZD5cblx0XHRcdFx0XHQ8Y2RzLXRyZWUtbm9kZVxuXHRcdFx0XHRcdFx0Km5nRm9yPVwibGV0IGNoaWxkTm9kZSBvZiBjaGlsZHJlblwiXG5cdFx0XHRcdFx0XHRbbm9kZV09XCJjaGlsZE5vZGVcIlxuXHRcdFx0XHRcdFx0W2RlcHRoXT1cImRlcHRoICsgMVwiXG5cdFx0XHRcdFx0XHRbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIj5cblx0XHRcdFx0XHQ8L2Nkcy10cmVlLW5vZGU+XG5cdFx0XHRcdDwvbmctdGVtcGxhdGU+XG5cdFx0XHQ8L2Rpdj5cblx0XHQ8L2Rpdj5cblx0YFxufSlcbmV4cG9ydCBjbGFzcyBUcmVlTm9kZUNvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyQ29udGVudENoZWNrZWQsIE9uSW5pdCwgT25EZXN0cm95IHtcblx0c3RhdGljIHRyZWVOb2RlQ291bnQgPSAwO1xuXHRASW5wdXQoKSBpZCA9IGB0cmVlLW5vZGUtJHtUcmVlTm9kZUNvbXBvbmVudC50cmVlTm9kZUNvdW50Kyt9YDtcblx0QElucHV0KCkgYWN0aXZlID0gZmFsc2U7XG5cdEBJbnB1dCgpIGRpc2FibGVkID0gZmFsc2U7XG5cdEBJbnB1dCgpIGV4cGFuZGVkID0gZmFsc2U7XG5cdEBJbnB1dCgpIGxhYmVsOiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXHRASW5wdXQoKSBzZWxlY3RlZCA9IGZhbHNlO1xuXHRASW5wdXQoKSB2YWx1ZTtcblx0QElucHV0KCkgaWNvbjogc3RyaW5nIHwgVGVtcGxhdGVSZWY8YW55Pjtcblx0QElucHV0KCkgY2hpbGRyZW46IE5vZGVbXSA9IFtdO1xuXG5cdC8qKlxuXHQgKiBEZXRlcm1pbmVzIHRoZSBkZXB0aCBvZiB0aGUgbm9kZVxuXHQgKiBDYWxjdWxhdGVkIGJ5IGRlZmF1bHQgd2hlbiBwYXNzaW5nIGBOb2RlYCBhcnJheSB0byBgVHJlZVZpZXdDb21wb25lbnRgLCBtYW51YWwgZW50cnkgcmVxdWlyZWQgb3RoZXJ3aXNlXG5cdCAqL1xuXHRASW5wdXQoKSBkZXB0aCA9IDA7XG5cblx0LyoqXG5cdCAqIFNpbXBsZSB3YXkgdG8gc2V0IGFsbCBhdHRyaWJ1dGVzIG9mIE5vZGUgY29tcG9uZW50IHZpYSBub2RlIG9iamVjdFxuXHQgKiBXb3VsZCBzaW1wbGlmeSBzZXR0aW5nIGNvbXBvbmVudCBhdHRyaWJ1dGVzIHdoZW4gZHluYW1pY2FsbHkgcmVuZGVyaW5nIG5vZGUuXG5cdCAqL1xuXHRASW5wdXQoKSBzZXQgbm9kZShub2RlOiBOb2RlKSB7XG5cdFx0dGhpcy5fbm9kZSA9IG5vZGU7XG5cblx0XHR0aGlzLmlkID0gbm9kZS5pZCA/PyB0aGlzLmlkO1xuXHRcdHRoaXMuYWN0aXZlID0gbm9kZS5hY3RpdmUgPz8gdGhpcy5hY3RpdmU7XG5cdFx0dGhpcy5kaXNhYmxlZCA9IG5vZGUuZGlzYWJsZWQgPz8gdGhpcy5kaXNhYmxlZDtcblx0XHR0aGlzLmV4cGFuZGVkID0gbm9kZS5leHBhbmRlZCA/PyB0aGlzLmV4cGFuZGVkO1xuXHRcdHRoaXMubGFiZWwgPSBub2RlLmxhYmVsID8/IHRoaXMubGFiZWw7XG5cdFx0dGhpcy52YWx1ZSA9IG5vZGUudmFsdWUgPz8gdGhpcy52YWx1ZTtcblx0XHR0aGlzLmljb24gPSBub2RlLmljb24gPz8gdGhpcy5pY29uO1xuXHRcdHRoaXMuc2VsZWN0ZWQgPSBub2RlLnNlbGVjdGVkID8/IHRoaXMuc2VsZWN0ZWQ7XG5cdFx0dGhpcy5kZXB0aCA9IG5vZGUuZGVwdGggPz8gdGhpcy5kZXB0aDtcblx0XHR0aGlzLmNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbiA/PyB0aGlzLmNoaWxkcmVuO1xuXHR9XG5cblx0Z2V0IG5vZGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX25vZGU7XG5cdH1cblxuXHRAT3V0cHV0KCkgbm9kZUZvY3VzID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXHRAT3V0cHV0KCkgbm9kZUJsdXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cdEBPdXRwdXQoKSBub2RlU2VsZWN0ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXHRAT3V0cHV0KCkgbm9kZXRvZ2dsZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuXHRvZmZzZXQ7XG5cdHByaXZhdGUgX25vZGU7XG5cdHByaXZhdGUgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cblx0Y29uc3RydWN0b3IocHJpdmF0ZSB0cmVlVmlld1NlcnZpY2U6IFRyZWVWaWV3U2VydmljZSkge31cblxuXHQvKipcblx0ICogQ2FjbHVsYXRlIG9mZnNldCBmb3IgbWFyZ2luL3BhZGRpbmdcblx0ICovXG5cdG5nQWZ0ZXJDb250ZW50Q2hlY2tlZCgpOiB2b2lkIHtcblx0XHR0aGlzLm9mZnNldCA9IHRoaXMuY2FsY3VsYXRlT2Zmc2V0KCk7XG5cdH1cblxuXHQvKipcblx0ICogSGlnaGxpZ2h0IHRoZSBub2RlXG5cdCAqL1xuXHRuZ09uSW5pdCgpOiB2b2lkIHtcblx0XHQvLyBIaWdobGlnaHQgdGhlIG5vZGVcblx0XHR0aGlzLnN1YnNjcmlwdGlvbiA9IHRoaXMudHJlZVZpZXdTZXJ2aWNlLnNlbGVjdGlvbk9ic2VydmFibGUuc3Vic2NyaWJlKCh2YWx1ZTogTWFwPHN0cmluZywgTm9kZT4pID0+IHtcblx0XHRcdHRoaXMuc2VsZWN0ZWQgPSB2YWx1ZS5oYXModGhpcy5pZCk7XG5cdFx0XHR0aGlzLmFjdGl2ZSA9IHRoaXMuc2VsZWN0ZWQ7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogVW5zdWJzY3JpYmUgZnJvbSBzdWJzY3JpcHRpb25zXG5cdCAqL1xuXHRuZ09uRGVzdHJveSgpOiB2b2lkIHtcblx0XHR0aGlzLnN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTZWxlY3RzIHRoZSBub2RlIGFuZCBlbWl0cyB0aGUgZXZlbnQgZnJvbSB0aGUgdHJlZSB2aWV3IGNvbXBvbmVudFxuXHQgKiBAcGFyYW0gZXZlbnRcblx0ICovXG5cdG5vZGVDbGljayhldmVudCkge1xuXHRcdGlmICghdGhpcy5kaXNhYmxlZCkge1xuXHRcdFx0dGhpcy5zZWxlY3RlZCA9IHRydWU7XG5cdFx0XHR0aGlzLmFjdGl2ZSA9IHRydWU7XG5cdFx0XHRldmVudC50YXJnZXQucGFyZW50RWxlbWVudC5mb2N1cygpO1xuXHRcdFx0Ly8gUGFzc2VzIGV2ZW50IHRvIGFsbCBub2RlcyB0byB1cGRhdGUgaGlnaGxpZ2h0aW5nICYgcGFyZW50IHRvIGVtaXRcblx0XHRcdHRoaXMudHJlZVZpZXdTZXJ2aWNlLnNlbGVjdE5vZGUoeyBpZDogdGhpcy5pZCwgbGFiZWw6IHRoaXMubGFiZWwsIHZhbHVlOiB0aGlzLnZhbHVlIH0pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDYWxjdWxhdGUgdGhlIG5vZGUgb2Zmc2V0XG5cdCAqIEByZXR1cm5zIE51bWJlclxuXHQgKi9cblx0Y2FsY3VsYXRlT2Zmc2V0KCkge1xuXHRcdC8vIFBhcmVudCBub2RlIHdpdGggaWNvblxuXHRcdGlmICh0aGlzLmNoaWxkcmVuLmxlbmd0aCAmJiB0aGlzLmljb24pIHtcblx0XHRcdHJldHVybiB0aGlzLmRlcHRoICsgMSArIHRoaXMuZGVwdGggKiAwLjU7XG5cdFx0fVxuXG5cdFx0Ly8gcGFyZW50IG5vZGUgd2l0aG91dCBpY29uXG5cdFx0aWYgKHRoaXMuY2hpbGRyZW4ubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5kZXB0aCArIDE7XG5cdFx0fVxuXG5cdFx0Ly8gbGVhZiBub2RlIHdpdGggaWNvblxuXHRcdGlmICh0aGlzLmljb24pIHtcblx0XHRcdHJldHVybiB0aGlzLmRlcHRoICsgMiArIHRoaXMuZGVwdGggKiAwLjU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZGVwdGggKyAyLjU7XG5cdH1cblxuXHRlbWl0Rm9jdXNFdmVudChldmVudCkge1xuXHRcdHRoaXMubm9kZUZvY3VzLmVtaXQoeyBub2RlOiB7IGlkOiB0aGlzLmlkLCBsYWJlbDogdGhpcy5sYWJlbCwgdmFsdWU6IHRoaXMudmFsdWUgfSwgZXZlbnQgfSk7XG5cdH1cblxuXHRlbWl0Qmx1ckV2ZW50KGV2ZW50KSB7XG5cdFx0dGhpcy5ub2RlQmx1ci5lbWl0KHsgbm9kZTogeyBpZDogdGhpcy5pZCwgbGFiZWw6IHRoaXMubGFiZWwsIHZhbHVlOiB0aGlzLnZhbHVlIH0sIGV2ZW50IH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4cGFuZCBjaGlsZHJlbiBpZiBub3QgZGlzYWJsZWRcblx0ICogQHBhcmFtIGV2ZW50OiBFdmVudFxuXHQgKi9cblx0dG9nZ2xlRXhwYW5kZWQoZXZlbnQpIHtcblx0XHRpZiAoIXRoaXMuZGlzYWJsZWQpIHtcblx0XHRcdHRoaXMubm9kZXRvZ2dsZS5lbWl0KHsgbm9kZTogeyBpZDogdGhpcy5pZCwgbGFiZWw6IHRoaXMubGFiZWwsIHZhbHVlOiB0aGlzLnZhbHVlIH0sIGV2ZW50IH0pO1xuXHRcdFx0dGhpcy5leHBhbmRlZCA9ICF0aGlzLmV4cGFuZGVkO1xuXHRcdFx0Ly8gUHJldmVudCBzZWxlY3Rpb24gb2YgdGhlIG5vZGVcblx0XHRcdGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNYW5hZ2VzIHRoZSBrZXlib2FyZCBhY2Nlc3NpYmlsaXR5IGZvciBjaGlsZHJlbiBleHBhbnNpb24gJiBzZWxlY3Rpb25cblx0ICovXG5cdG5hdmlnYXRlVHJlZShldmVudDogS2V5Ym9hcmRFdmVudCkge1xuXHRcdGlmIChldmVudC5rZXkgPT09IFwiQXJyb3dMZWZ0XCIgfHwgZXZlbnQua2V5ID09PSBcIkFycm93UmlnaHRcIiB8fCBldmVudC5rZXkgPT09IFwiRW50ZXJcIikge1xuXHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0fVxuXHRcdC8vIFVuZXhwYW5kXG5cdFx0aWYgKGV2ZW50LmtleSA9PT0gXCJBcnJvd0xlZnRcIikge1xuXHRcdFx0aWYgKHRoaXMuZXhwYW5kZWQgJiYgdGhpcy5jaGlsZHJlbikge1xuXHRcdFx0XHR0aGlzLnRvZ2dsZUV4cGFuZGVkKGV2ZW50KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoZXZlbnQua2V5ID09PSBcIkFycm93UmlnaHRcIikge1xuXHRcdFx0aWYgKCF0aGlzLmV4cGFuZGVkICYmIHRoaXMuY2hpbGRyZW4pIHtcblx0XHRcdFx0dGhpcy50b2dnbGVFeHBhbmRlZChldmVudCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKGV2ZW50LmtleSA9PT0gXCJFbnRlclwiKSB7XG5cdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0dGhpcy5ub2RlQ2xpY2soZXZlbnQpO1xuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBpc1RlbXBsYXRlKHZhbHVlKSB7XG5cdFx0cmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVGVtcGxhdGVSZWY7XG5cdH1cblxuXHRwdWJsaWMgaXNQcm9qZWN0ZWQoKSB7XG5cdFx0cmV0dXJuIHRoaXMudHJlZVZpZXdTZXJ2aWNlLmNvbnRlbnRQcm9qZWN0ZWQ7XG5cdH1cbn1cbiJdfQ==