@odymaui/angular-tree-component
Version:
A simple yet powerful tree component for Angular16. WARNING: This is an unsupported fork for use in a dependent project to upgrade it to Angular 16. Unit tests pass and the example-app works as expected.
602 lines (596 loc) • 58.6 kB
JavaScript
import { Component, ContentChild, EventEmitter, HostListener, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { TreeModel } from '../models/tree.model';
import { makeObservable, reaction } from 'mobx';
import { observable, computed, action } from '../mobx-angular/mobx-proxy';
import * as i0 from "@angular/core";
import * as i1 from "../models/tree.model";
import * as i2 from "../models/tree-dragged-element.model";
import * as i3 from "@angular/common";
import * as i4 from "./tree-node-drop-slot.component";
import * as i5 from "./tree-viewport.component";
import * as i6 from "./loading.component";
import * as i7 from "../directives/tree-animate-open.directive";
import * as i8 from "../mobx-angular/tree-mobx-autorun.directive";
import * as i9 from "../directives/tree-drop.directive";
import * as i10 from "../directives/tree-drag.directive";
import * as i11 from "./tree-node-expander.component";
import * as i12 from "./tree-node-checkbox.component";
export class TreeComponent {
treeModel;
treeDraggedElement;
_nodes;
_options;
loadingTemplate;
treeNodeTemplate;
treeNodeWrapperTemplate;
treeNodeFullTemplate;
viewportComponent;
// Will be handled in ngOnChanges
set nodes(nodes) {
}
;
set options(options) {
}
;
set focused(value) {
this.treeModel.setFocus(value);
}
set state(state) {
this.treeModel.setState(state);
}
toggleExpanded;
activate;
deactivate;
nodeActivate;
nodeDeactivate;
select;
deselect;
focus;
blur;
updateData;
initialized;
moveNode;
copyNode;
loadNodeChildren;
changeFilter;
event;
stateChange;
constructor(treeModel, treeDraggedElement) {
this.treeModel = treeModel;
this.treeDraggedElement = treeDraggedElement;
treeModel.eventNames.forEach((name) => this[name] = new EventEmitter());
treeModel.subscribeToState((state) => this.stateChange.emit(state));
}
onKeydown($event) {
if (!this.treeModel.isFocused)
return;
if (['input', 'textarea'].includes(document.activeElement.tagName.toLowerCase()))
return;
const focusedNode = this.treeModel.getFocusedNode();
this.treeModel.performKeyAction(focusedNode, $event);
}
onMousedown($event) {
function isOutsideClick(startElement, nodeName) {
return !startElement ? true : startElement.localName === nodeName ? false : isOutsideClick(startElement.parentElement, nodeName);
}
if (isOutsideClick($event.target, 'tree-root')) {
this.treeModel.setFocus(false);
}
}
ngOnChanges(changes) {
if (changes.options || changes.nodes) {
this.treeModel.setData({
options: changes.options && changes.options.currentValue,
nodes: changes.nodes && changes.nodes.currentValue,
events: this.pick(this, this.treeModel.eventNames)
});
}
}
sizeChanged() {
this.viewportComponent.setViewport();
}
pick(object, keys) {
return keys.reduce((obj, key) => {
if (object && object.hasOwnProperty(key)) {
obj[key] = object[key];
}
return obj;
}, {});
}
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeComponent, deps: [{ token: i1.TreeModel }, { token: i2.TreeDraggedElement }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: TreeComponent, selector: "Tree, tree-root", inputs: { nodes: "nodes", options: "options", focused: "focused", state: "state" }, outputs: { toggleExpanded: "toggleExpanded", activate: "activate", deactivate: "deactivate", nodeActivate: "nodeActivate", nodeDeactivate: "nodeDeactivate", select: "select", deselect: "deselect", focus: "focus", blur: "blur", updateData: "updateData", initialized: "initialized", moveNode: "moveNode", copyNode: "copyNode", loadNodeChildren: "loadNodeChildren", changeFilter: "changeFilter", event: "event", stateChange: "stateChange" }, host: { listeners: { "body: keydown": "onKeydown($event)", "body: mousedown": "onMousedown($event)" } }, providers: [TreeModel], queries: [{ propertyName: "loadingTemplate", first: true, predicate: ["loadingTemplate"], descendants: true }, { propertyName: "treeNodeTemplate", first: true, predicate: ["treeNodeTemplate"], descendants: true }, { propertyName: "treeNodeWrapperTemplate", first: true, predicate: ["treeNodeWrapperTemplate"], descendants: true }, { propertyName: "treeNodeFullTemplate", first: true, predicate: ["treeNodeFullTemplate"], descendants: true }], viewQueries: [{ propertyName: "viewportComponent", first: true, predicate: ["viewport"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
<tree-viewport #viewport>
<div
class="angular-tree-component"
[class.node-dragging]="treeDraggedElement.isDragging()"
[class.angular-tree-component-rtl]="treeModel.options.rtl">
<tree-node-collection
*ngIf="treeModel.roots"
[nodes]="treeModel.roots"
[treeModel]="treeModel"
[templates]="{
loadingTemplate: loadingTemplate,
treeNodeTemplate: treeNodeTemplate,
treeNodeWrapperTemplate: treeNodeWrapperTemplate,
treeNodeFullTemplate: treeNodeFullTemplate
}">
</tree-node-collection>
<tree-node-drop-slot
class="empty-tree-drop-slot"
*ngIf="treeModel.isEmptyTree()"
[dropIndex]="0"
[node]="treeModel.virtualRoot">
</tree-node-drop-slot>
</div>
</tree-viewport>
`, isInline: true, dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return i3.NgIf; }), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i0.forwardRef(function () { return i4.TreeNodeDropSlot; }), selector: "TreeNodeDropSlot, tree-node-drop-slot", inputs: ["node", "dropIndex"] }, { kind: "component", type: i0.forwardRef(function () { return TreeNodeCollectionComponent; }), selector: "tree-node-collection", inputs: ["nodes", "treeModel", "templates"] }, { kind: "component", type: i0.forwardRef(function () { return i5.TreeViewportComponent; }), selector: "tree-viewport" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeComponent, decorators: [{
type: Component,
args: [{ selector: 'Tree, tree-root', providers: [TreeModel], template: `
<tree-viewport #viewport>
<div
class="angular-tree-component"
[class.node-dragging]="treeDraggedElement.isDragging()"
[class.angular-tree-component-rtl]="treeModel.options.rtl">
<tree-node-collection
*ngIf="treeModel.roots"
[nodes]="treeModel.roots"
[treeModel]="treeModel"
[templates]="{
loadingTemplate: loadingTemplate,
treeNodeTemplate: treeNodeTemplate,
treeNodeWrapperTemplate: treeNodeWrapperTemplate,
treeNodeFullTemplate: treeNodeFullTemplate
}">
</tree-node-collection>
<tree-node-drop-slot
class="empty-tree-drop-slot"
*ngIf="treeModel.isEmptyTree()"
[dropIndex]="0"
[node]="treeModel.virtualRoot">
</tree-node-drop-slot>
</div>
</tree-viewport>
` }]
}], ctorParameters: function () { return [{ type: i1.TreeModel }, { type: i2.TreeDraggedElement }]; }, propDecorators: { loadingTemplate: [{
type: ContentChild,
args: ['loadingTemplate', { static: false }]
}], treeNodeTemplate: [{
type: ContentChild,
args: ['treeNodeTemplate', { static: false }]
}], treeNodeWrapperTemplate: [{
type: ContentChild,
args: ['treeNodeWrapperTemplate', { static: false }]
}], treeNodeFullTemplate: [{
type: ContentChild,
args: ['treeNodeFullTemplate', { static: false }]
}], viewportComponent: [{
type: ViewChild,
args: ['viewport', { static: false }]
}], nodes: [{
type: Input
}], options: [{
type: Input
}], focused: [{
type: Input
}], state: [{
type: Input
}], toggleExpanded: [{
type: Output
}], activate: [{
type: Output
}], deactivate: [{
type: Output
}], nodeActivate: [{
type: Output
}], nodeDeactivate: [{
type: Output
}], select: [{
type: Output
}], deselect: [{
type: Output
}], focus: [{
type: Output
}], blur: [{
type: Output
}], updateData: [{
type: Output
}], initialized: [{
type: Output
}], moveNode: [{
type: Output
}], copyNode: [{
type: Output
}], loadNodeChildren: [{
type: Output
}], changeFilter: [{
type: Output
}], event: [{
type: Output
}], stateChange: [{
type: Output
}], onKeydown: [{
type: HostListener,
args: ['body: keydown', ['$event']]
}], onMousedown: [{
type: HostListener,
args: ['body: mousedown', ['$event']]
}] } });
//imported from tree-node.children to avoid NG3003 cycle error
export class TreeNodeChildrenComponent {
node;
templates;
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeNodeChildrenComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: TreeNodeChildrenComponent, selector: "tree-node-children", inputs: { node: "node", templates: "templates" }, ngImport: i0, template: `
<ng-container *treeMobxAutorun="{ dontDetach: true }">
<div
[class.tree-children]="true"
[class.tree-children-no-padding]="node.options.levelPadding"
*treeAnimateOpen="
node.isExpanded;
speed: node.options.animateSpeed;
acceleration: node.options.animateAcceleration;
enabled: node.options.animateExpand
"
>
<tree-node-collection
*ngIf="node.children"
[nodes]="node.children"
[templates]="templates"
[treeModel]="node.treeModel"
>
</tree-node-collection>
<tree-loading-component
[style.padding-left]="node.getNodePadding()"
class="tree-node-loading"
*ngIf="!node.children"
[template]="templates.loadingTemplate"
[node]="node"
></tree-loading-component>
</div>
</ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return i3.NgIf; }), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i0.forwardRef(function () { return i6.LoadingComponent; }), selector: "tree-loading-component", inputs: ["template", "node"] }, { kind: "component", type: i0.forwardRef(function () { return TreeNodeCollectionComponent; }), selector: "tree-node-collection", inputs: ["nodes", "treeModel", "templates"] }, { kind: "directive", type: i0.forwardRef(function () { return i7.TreeAnimateOpenDirective; }), selector: "[treeAnimateOpen]", inputs: ["treeAnimateOpenSpeed", "treeAnimateOpenAcceleration", "treeAnimateOpenEnabled", "treeAnimateOpen"] }, { kind: "directive", type: i0.forwardRef(function () { return i8.TreeMobxAutorunDirective; }), selector: "[treeMobxAutorun]", inputs: ["treeMobxAutorun"] }], encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeNodeChildrenComponent, decorators: [{
type: Component,
args: [{ selector: 'tree-node-children', encapsulation: ViewEncapsulation.None, template: `
<ng-container *treeMobxAutorun="{ dontDetach: true }">
<div
[class.tree-children]="true"
[class.tree-children-no-padding]="node.options.levelPadding"
*treeAnimateOpen="
node.isExpanded;
speed: node.options.animateSpeed;
acceleration: node.options.animateAcceleration;
enabled: node.options.animateExpand
"
>
<tree-node-collection
*ngIf="node.children"
[nodes]="node.children"
[templates]="templates"
[treeModel]="node.treeModel"
>
</tree-node-collection>
<tree-loading-component
[style.padding-left]="node.getNodePadding()"
class="tree-node-loading"
*ngIf="!node.children"
[template]="templates.loadingTemplate"
[node]="node"
></tree-loading-component>
</div>
</ng-container>
` }]
}], propDecorators: { node: [{
type: Input
}], templates: [{
type: Input
}] } });
//imported from tree-node-collection.component.ts to avoid NG3003 cycle error
export class TreeNodeCollectionComponent {
get nodes() {
return this._nodes;
}
set nodes(nodes) {
this.setNodes(nodes);
}
treeModel;
constructor() {
makeObservable(this, {
_nodes: observable,
viewportNodes: observable,
marginTop: computed,
setNodes: action
});
}
_nodes;
virtualScroll; // Cannot inject this, because we might be inside treeNodeTemplateFull
templates;
viewportNodes;
get marginTop() {
const firstNode = this.viewportNodes && this.viewportNodes.length && this.viewportNodes[0];
const relativePosition = firstNode && firstNode.parent
? firstNode.position -
firstNode.parent.position -
firstNode.parent.getSelfHeight()
: 0;
return `${relativePosition}px`;
}
_dispose = [];
setNodes(nodes) {
this._nodes = nodes;
}
ngOnInit() {
this.virtualScroll = this.treeModel.virtualScroll;
this._dispose = [
// return node indexes so we can compare structurally,
reaction(() => {
return this.virtualScroll
.getViewportNodes(this.nodes)
.map(n => n.index);
}, nodeIndexes => {
this.viewportNodes = nodeIndexes.map(i => this.nodes[i]);
}, { compareStructural: true, fireImmediately: true }),
reaction(() => this.nodes, nodes => {
this.viewportNodes = this.virtualScroll.getViewportNodes(nodes);
})
];
}
ngOnDestroy() {
this._dispose.forEach(d => d());
}
trackNode(index, node) {
return node.id;
}
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeNodeCollectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: TreeNodeCollectionComponent, selector: "tree-node-collection", inputs: { nodes: "nodes", treeModel: "treeModel", templates: "templates" }, ngImport: i0, template: `
<ng-container *treeMobxAutorun="{ dontDetach: true }">
<div [style.margin-top]="marginTop">
<tree-node
*ngFor="let node of viewportNodes; let i = index; trackBy: trackNode"
[node]="node"
[index]="i"
[templates]="templates"
>
</tree-node>
</div>
</ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return i3.NgForOf; }), selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i0.forwardRef(function () { return TreeNodeComponent; }), selector: "TreeNode, tree-node", inputs: ["node", "index", "templates"] }, { kind: "directive", type: i0.forwardRef(function () { return i8.TreeMobxAutorunDirective; }), selector: "[treeMobxAutorun]", inputs: ["treeMobxAutorun"] }], encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeNodeCollectionComponent, decorators: [{
type: Component,
args: [{
selector: 'tree-node-collection',
encapsulation: ViewEncapsulation.None,
template: `
<ng-container *treeMobxAutorun="{ dontDetach: true }">
<div [style.margin-top]="marginTop">
<tree-node
*ngFor="let node of viewportNodes; let i = index; trackBy: trackNode"
[node]="node"
[index]="i"
[templates]="templates"
>
</tree-node>
</div>
</ng-container>
`
}]
}], ctorParameters: function () { return []; }, propDecorators: { nodes: [{
type: Input
}], treeModel: [{
type: Input
}], templates: [{
type: Input
}] } });
//from tree.node.component.ts to avoid NG3003 cycle error
export class TreeNodeComponent {
node;
index;
templates;
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: TreeNodeComponent, selector: "TreeNode, tree-node", inputs: { node: "node", index: "index", templates: "templates" }, ngImport: i0, template: `
<ng-container *treeMobxAutorun="{ dontDetach: true }">
<div
*ngIf="!templates.treeNodeFullTemplate"
[class]="node.getClass()"
[class.tree-node]="true"
[class.tree-node-expanded]="node.isExpanded && node.hasChildren"
[class.tree-node-collapsed]="node.isCollapsed && node.hasChildren"
[class.tree-node-leaf]="node.isLeaf"
[class.tree-node-active]="node.isActive"
[class.tree-node-focused]="node.isFocused"
>
<tree-node-drop-slot
*ngIf="index === 0"
[dropIndex]="node.index"
[node]="node.parent"
></tree-node-drop-slot>
<tree-node-wrapper
[node]="node"
[index]="index"
[templates]="templates"
></tree-node-wrapper>
<tree-node-children
[node]="node"
[templates]="templates"
></tree-node-children>
<tree-node-drop-slot
[dropIndex]="node.index + 1"
[node]="node.parent"
></tree-node-drop-slot>
</div>
<ng-container
[ngTemplateOutlet]="templates.treeNodeFullTemplate"
[ngTemplateOutletContext]="{
$implicit: node,
node: node,
index: index,
templates: templates
}"
>
</ng-container>
</ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return i3.NgIf; }), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i0.forwardRef(function () { return i3.NgTemplateOutlet; }), selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i0.forwardRef(function () { return TreeNodeChildrenComponent; }), selector: "tree-node-children", inputs: ["node", "templates"] }, { kind: "component", type: i0.forwardRef(function () { return i4.TreeNodeDropSlot; }), selector: "TreeNodeDropSlot, tree-node-drop-slot", inputs: ["node", "dropIndex"] }, { kind: "component", type: i0.forwardRef(function () { return TreeNodeWrapperComponent; }), selector: "tree-node-wrapper", inputs: ["node", "index", "templates"] }, { kind: "directive", type: i0.forwardRef(function () { return i8.TreeMobxAutorunDirective; }), selector: "[treeMobxAutorun]", inputs: ["treeMobxAutorun"] }], encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeNodeComponent, decorators: [{
type: Component,
args: [{ selector: 'TreeNode, tree-node', encapsulation: ViewEncapsulation.None, template: `
<ng-container *treeMobxAutorun="{ dontDetach: true }">
<div
*ngIf="!templates.treeNodeFullTemplate"
[class]="node.getClass()"
[class.tree-node]="true"
[class.tree-node-expanded]="node.isExpanded && node.hasChildren"
[class.tree-node-collapsed]="node.isCollapsed && node.hasChildren"
[class.tree-node-leaf]="node.isLeaf"
[class.tree-node-active]="node.isActive"
[class.tree-node-focused]="node.isFocused"
>
<tree-node-drop-slot
*ngIf="index === 0"
[dropIndex]="node.index"
[node]="node.parent"
></tree-node-drop-slot>
<tree-node-wrapper
[node]="node"
[index]="index"
[templates]="templates"
></tree-node-wrapper>
<tree-node-children
[node]="node"
[templates]="templates"
></tree-node-children>
<tree-node-drop-slot
[dropIndex]="node.index + 1"
[node]="node.parent"
></tree-node-drop-slot>
</div>
<ng-container
[ngTemplateOutlet]="templates.treeNodeFullTemplate"
[ngTemplateOutletContext]="{
$implicit: node,
node: node,
index: index,
templates: templates
}"
>
</ng-container>
</ng-container>
` }]
}], propDecorators: { node: [{
type: Input
}], index: [{
type: Input
}], templates: [{
type: Input
}] } });
//from tree-node-content.component.ts to avoid NG3003 cycle error.
export class TreeNodeContent {
node;
index;
template;
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeNodeContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: TreeNodeContent, selector: "tree-node-content", inputs: { node: "node", index: "index", template: "template" }, ngImport: i0, template: `
<span *ngIf="!template">{{ node.displayField }}</span>
<ng-container
[ngTemplateOutlet]="template"
[ngTemplateOutletContext]="{ $implicit: node, node: node, index: index }">
</ng-container>`, isInline: true, dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeNodeContent, decorators: [{
type: Component,
args: [{
selector: 'tree-node-content',
encapsulation: ViewEncapsulation.None,
template: `
<span *ngIf="!template">{{ node.displayField }}</span>
<ng-container
[ngTemplateOutlet]="template"
[ngTemplateOutletContext]="{ $implicit: node, node: node, index: index }">
</ng-container>`,
}]
}], propDecorators: { node: [{
type: Input
}], index: [{
type: Input
}], template: [{
type: Input
}] } });
//from tree-node-wrapper.component.ts file to avoid NG3003 cycle error.
export class TreeNodeWrapperComponent {
node;
index;
templates;
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeNodeWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: TreeNodeWrapperComponent, selector: "tree-node-wrapper", inputs: { node: "node", index: "index", templates: "templates" }, ngImport: i0, template: `
<div *ngIf="!templates.treeNodeWrapperTemplate" class="node-wrapper" [style.padding-left]="node.getNodePadding()">
<tree-node-checkbox *ngIf="node.options.useCheckbox" [node]="node"></tree-node-checkbox>
<tree-node-expander [node]="node"></tree-node-expander>
<div class="node-content-wrapper"
[class.node-content-wrapper-active]="node.isActive"
[class.node-content-wrapper-focused]="node.isFocused"
(click)="node.mouseAction('click', $event)"
(dblclick)="node.mouseAction('dblClick', $event)"
(mouseover)="node.mouseAction('mouseOver', $event)"
(mouseout)="node.mouseAction('mouseOut', $event)"
(contextmenu)="node.mouseAction('contextMenu', $event)"
(treeDrop)="node.onDrop($event)"
(treeDropDragOver)="node.mouseAction('dragOver', $event)"
(treeDropDragLeave)="node.mouseAction('dragLeave', $event)"
(treeDropDragEnter)="node.mouseAction('dragEnter', $event)"
[treeAllowDrop]="node.allowDrop"
[allowDragoverStyling]="node.allowDragoverStyling()"
[treeDrag]="node"
[treeDragEnabled]="node.allowDrag()">
<tree-node-content [node]="node" [index]="index" [template]="templates.treeNodeTemplate">
</tree-node-content>
</div>
</div>
<ng-container
[ngTemplateOutlet]="templates.treeNodeWrapperTemplate"
[ngTemplateOutletContext]="{ $implicit: node, node: node, index: index, templates: templates }">
</ng-container>
`, isInline: true, dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: TreeNodeContent, selector: "tree-node-content", inputs: ["node", "index", "template"] }, { kind: "directive", type: i9.TreeDropDirective, selector: "[treeDrop]", inputs: ["allowDragoverStyling", "treeAllowDrop"], outputs: ["treeDrop", "treeDropDragOver", "treeDropDragLeave", "treeDropDragEnter"] }, { kind: "directive", type: i10.TreeDragDirective, selector: "[treeDrag]", inputs: ["treeDrag", "treeDragEnabled"] }, { kind: "component", type: i11.TreeNodeExpanderComponent, selector: "tree-node-expander", inputs: ["node"] }, { kind: "component", type: i12.TreeNodeCheckboxComponent, selector: "tree-node-checkbox", inputs: ["node"] }], encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TreeNodeWrapperComponent, decorators: [{
type: Component,
args: [{ selector: 'tree-node-wrapper', encapsulation: ViewEncapsulation.None, template: `
<div *ngIf="!templates.treeNodeWrapperTemplate" class="node-wrapper" [style.padding-left]="node.getNodePadding()">
<tree-node-checkbox *ngIf="node.options.useCheckbox" [node]="node"></tree-node-checkbox>
<tree-node-expander [node]="node"></tree-node-expander>
<div class="node-content-wrapper"
[class.node-content-wrapper-active]="node.isActive"
[class.node-content-wrapper-focused]="node.isFocused"
(click)="node.mouseAction('click', $event)"
(dblclick)="node.mouseAction('dblClick', $event)"
(mouseover)="node.mouseAction('mouseOver', $event)"
(mouseout)="node.mouseAction('mouseOut', $event)"
(contextmenu)="node.mouseAction('contextMenu', $event)"
(treeDrop)="node.onDrop($event)"
(treeDropDragOver)="node.mouseAction('dragOver', $event)"
(treeDropDragLeave)="node.mouseAction('dragLeave', $event)"
(treeDropDragEnter)="node.mouseAction('dragEnter', $event)"
[treeAllowDrop]="node.allowDrop"
[allowDragoverStyling]="node.allowDragoverStyling()"
[treeDrag]="node"
[treeDragEnabled]="node.allowDrag()">
<tree-node-content [node]="node" [index]="index" [template]="templates.treeNodeTemplate">
</tree-node-content>
</div>
</div>
<ng-container
[ngTemplateOutlet]="templates.treeNodeWrapperTemplate"
[ngTemplateOutletContext]="{ $implicit: node, node: node, index: index, templates: templates }">
</ng-container>
` }]
}], propDecorators: { node: [{
type: Input
}], index: [{
type: Input
}], templates: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLXRyZWUtY29tcG9uZW50L3NyYy9saWIvY29tcG9uZW50cy90cmVlLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBYSxNQUFNLEVBQWUsU0FBUyxFQUFFLGlCQUFpQixFQUFxQixNQUFNLGVBQWUsQ0FBQztBQUM1SyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFRakQsT0FBTyxFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDaEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7Ozs7Ozs7Ozs7Ozs7O0FBa0MxRSxNQUFNLE9BQU8sYUFBYTtJQTRDZjtJQUNBO0lBNUNULE1BQU0sQ0FBUTtJQUNkLFFBQVEsQ0FBYztJQUU4QixlQUFlLENBQW1CO0lBQ2pDLGdCQUFnQixDQUFtQjtJQUM1Qix1QkFBdUIsQ0FBbUI7SUFDN0Msb0JBQW9CLENBQW1CO0lBQ3RELGlCQUFpQixDQUF3QjtJQUVuRixpQ0FBaUM7SUFDakMsSUFBYSxLQUFLLENBQUMsS0FBWTtJQUMvQixDQUFDO0lBQUEsQ0FBQztJQUVGLElBQWEsT0FBTyxDQUFDLE9BQXFCO0lBQzFDLENBQUM7SUFBQSxDQUFDO0lBRUYsSUFBYSxPQUFPLENBQUMsS0FBYztRQUNqQyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQsSUFBYSxLQUFLLENBQUMsS0FBSztRQUN0QixJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lB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bGQsIEV2ZW50RW1pdHRlciwgSG9zdExpc3RlbmVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPdXRwdXQsIFRlbXBsYXRlUmVmLCBWaWV3Q2hpbGQsIFZpZXdFbmNhcHN1bGF0aW9uLCBPbkluaXQsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBUcmVlTW9kZWwgfSBmcm9tICcuLi9tb2RlbHMvdHJlZS5tb2RlbCc7XHJcbmltcG9ydCB7IFRyZWVEcmFnZ2VkRWxlbWVudCB9IGZyb20gJy4uL21vZGVscy90cmVlLWRyYWdnZWQtZWxlbWVudC5tb2RlbCc7XHJcbmltcG9ydCB7IFRyZWVPcHRpb25zIH0gZnJvbSAnLi4vbW9kZWxzL3RyZWUtb3B0aW9ucy5tb2RlbCc7XHJcbmltcG9ydCB7IElUcmVlT3B0aW9ucyB9IGZyb20gJy4uL2RlZnMvYXBpJztcclxuaW1wb3J0IHsgVHJlZVZpZXdwb3J0Q29tcG9uZW50IH0gZnJvbSAnLi90cmVlLXZpZXdwb3J0LmNvbXBvbmVudCc7XHJcblxyXG5pbXBvcnQgeyBUcmVlTm9kZSB9IGZyb20gJy4uL21vZGVscy90cmVlLW5vZGUubW9kZWwnO1xyXG5cclxuaW1wb3J0IHsgbWFrZU9ic2VydmFibGUsIHJlYWN0aW9uIH0gZnJvbSAnbW9ieCc7XHJcbmltcG9ydCB7IG9ic2VydmFibGUsIGNvbXB1dGVkLCBhY3Rpb24gfSBmcm9tICcuLi9tb2J4LWFuZ3VsYXIvbW9ieC1wcm94eSc7XHJcbmltcG9ydCB7IFRyZWVWaXJ0dWFsU2Nyb2xsIH0gZnJvbSAnLi4vbW9kZWxzL3RyZWUtdmlydHVhbC1zY3JvbGwubW9kZWwnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdUcmVlLCB0cmVlLXJvb3QnLFxyXG4gIHByb3ZpZGVyczogW1RyZWVNb2RlbF0sXHJcbiAgc3R5bGVzOiBbXSxcclxuICB0ZW1wbGF0ZTogYFxyXG4gICAgICA8dHJlZS12aWV3cG9ydCAjdmlld3BvcnQ+XHJcbiAgICAgICAgICA8ZGl2XHJcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYW5ndWxhci10cmVlLWNvbXBvbmVudFwiXHJcbiAgICAgICAgICAgICAgICAgIFtjbGFzcy5ub2RlLWRyYWdnaW5nXT1cInRyZWVEcmFnZ2VkRWxlbWVudC5pc0RyYWdnaW5nKClcIlxyXG4gICAgICAgICAgICAgICAgICBbY2xhc3MuYW5ndWxhci10cmVlLWNvbXBvbmVudC1ydGxdPVwidHJlZU1vZGVsLm9wdGlvbnMucnRsXCI+XHJcbiAgICAgICAgICAgICAgPHRyZWUtbm9kZS1jb2xsZWN0aW9uXHJcbiAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cInRyZWVNb2RlbC5yb290c1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICBbbm9kZXNdPVwidHJlZU1vZGVsLnJvb3RzXCJcclxuICAgICAgICAgICAgICAgICAgICAgIFt0cmVlTW9kZWxdPVwidHJlZU1vZGVsXCJcclxuICAgICAgICAgICAgICAgICAgICAgIFt0ZW1wbGF0ZXNdPVwie1xyXG4gICAgICAgICAgICBsb2FkaW5nVGVtcGxhdGU6IGxvYWRpbmdUZW1wbGF0ZSxcclxuICAgICAgICAgICAgdHJlZU5vZGVUZW1wbGF0ZTogdHJlZU5vZGVUZW1wbGF0ZSxcclxuICAgICAgICAgICAgdHJlZU5vZGVXcmFwcGVyVGVtcGxhdGU6IHRyZWVOb2RlV3JhcHBlclRlbXBsYXRlLFxyXG4gICAgICAgICAgICB0cmVlTm9kZUZ1bGxUZW1wbGF0ZTogdHJlZU5vZGVGdWxsVGVtcGxhdGVcclxuICAgICAgICAgIH1cIj5cclxuICAgICAgICAgICAgICA8L3RyZWUtbm9kZS1jb2xsZWN0aW9uPlxyXG4gICAgICAgICAgICAgIDx0cmVlLW5vZGUtZHJvcC1zbG90XHJcbiAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImVtcHR5LXRyZWUtZHJvcC1zbG90XCJcclxuICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwidHJlZU1vZGVsLmlzRW1wdHlUcmVlKClcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgW2Ryb3BJbmRleF09XCIwXCJcclxuICAgICAgICAgICAgICAgICAgICAgIFtub2RlXT1cInRyZWVNb2RlbC52aXJ0dWFsUm9vdFwiPlxyXG4gICAgICAgICAgICAgIDwvdHJlZS1ub2RlLWRyb3Atc2xvdD5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICA8L3RyZWUtdmlld3BvcnQ+XHJcbiAgYFxyXG59KVxyXG5leHBvcnQgY2xhc3MgVHJlZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XHJcbiAgX25vZGVzOiBhbnlbXTtcclxuICBfb3B0aW9uczogVHJlZU9wdGlvbnM7XHJcblxyXG4gIEBDb250ZW50Q2hpbGQoJ2xvYWRpbmdUZW1wbGF0ZScsIHsgc3RhdGljOiBmYWxzZSB9KSBsb2FkaW5nVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgQENvbnRlbnRDaGlsZCgndHJlZU5vZGVUZW1wbGF0ZScsIHsgc3RhdGljOiBmYWxzZSB9KSB0cmVlTm9kZVRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIEBDb250ZW50Q2hpbGQoJ3RyZWVOb2RlV3JhcHBlclRlbXBsYXRlJywgeyBzdGF0aWM6IGZhbHNlIH0pIHRyZWVOb2RlV3JhcHBlclRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIEBDb250ZW50Q2hpbGQoJ3RyZWVOb2RlRnVsbFRlbXBsYXRlJywgeyBzdGF0aWM6IGZhbHNlIH0pIHRyZWVOb2RlRnVsbFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIEBWaWV3Q2hpbGQoJ3ZpZXdwb3J0JywgeyBzdGF0aWM6IGZhbHNlIH0pIHZpZXdwb3J0Q29tcG9uZW50OiBUcmVlVmlld3BvcnRDb21wb25lbnQ7XHJcblxyXG4gIC8vIFdpbGwgYmUgaGFuZGxlZCBpbiBuZ09uQ2hhbmdlc1xyXG4gIEBJbnB1dCgpIHNldCBub2Rlcyhub2RlczogYW55W10pIHtcclxuICB9O1xyXG5cclxuICBASW5wdXQoKSBzZXQgb3B0aW9ucyhvcHRpb25zOiBJVHJlZU9wdGlvbnMpIHtcclxuICB9O1xyXG5cclxuICBASW5wdXQoKSBzZXQgZm9jdXNlZCh2YWx1ZTogYm9vbGVhbikge1xyXG4gICAgdGhpcy50cmVlTW9kZWwuc2V0Rm9jdXModmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgQElucHV0KCkgc2V0IHN0YXRlKHN0YXRlKSB7XHJcbiAgICB0aGlzLnRyZWVNb2RlbC5zZXRTdGF0ZShzdGF0ZSk7XHJcbiAgfVxyXG5cclxuICBAT3V0cHV0KCkgdG9nZ2xlRXhwYW5kZWQ7XHJcbiAgQE91dHB1dCgpIGFjdGl2YXRlO1xyXG4gIEBPdXRwdXQoKSBkZWFjdGl2YXRlO1xyXG4gIEBPdXRwdXQoKSBub2RlQWN0aXZhdGU7XHJcbiAgQE91dHB1dCgpIG5vZGVEZWFjdGl2YXRlO1xyXG4gIEBPdXRwdXQoKSBzZWxlY3Q7XHJcbiAgQE91dHB1dCgpIGRlc2VsZWN0O1xyXG4gIEBPdXRwdXQoKSBmb2N1cztcclxuICBAT3V0cHV0KCkgYmx1cjtcclxuICBAT3V0cHV0KCkgdXBkYXRlRGF0YTtcclxuICBAT3V0cHV0KCkgaW5pdGlhbGl6ZWQ7XHJcbiAgQE91dHB1dCgpIG1vdmVOb2RlO1xyXG4gIEBPdXRwdXQoKSBjb3B5Tm9kZTtcclxuICBAT3V0cHV0KCkgbG9hZE5vZGVDaGlsZHJlbjtcclxuICBAT3V0cHV0KCkgY2hhbmdlRmlsdGVyO1xyXG4gIEBPdXRwdXQoKSBldmVudDtcclxuICBAT3V0cHV0KCkgc3RhdGVDaGFuZ2U7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHVibGljIHRyZWVNb2RlbDogVHJlZU1vZGVsLFxyXG4gICAgcHVibGljIHRyZWVEcmFnZ2VkRWxlbWVudDogVHJlZURyYWdnZWRFbGVtZW50KSB7XHJcblxyXG4gICAgdHJlZU1vZGVsLmV2ZW50TmFtZXMuZm9yRWFjaCgobmFtZSkgPT4gdGhpc1tuYW1lXSA9IG5ldyBFdmVudEVtaXR0ZXIoKSk7XHJcbiAgICB0cmVlTW9kZWwuc3Vic2NyaWJlVG9TdGF0ZSgoc3RhdGUpID0+IHRoaXMuc3RhdGVDaGFuZ2UuZW1pdChzdGF0ZSkpO1xyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignYm9keToga2V5ZG93bicsIFsnJGV2ZW50J10pXHJcbiAgb25LZXlkb3duKCRldmVudCkge1xyXG4gICAgaWYgKCF0aGlzLnRyZWVNb2RlbC5pc0ZvY3VzZWQpIHJldHVybjtcclxuICAgIGlmIChbJ2lucHV0JywgJ3RleHRhcmVhJ10uaW5jbHVkZXMoZG9jdW1lbnQuYWN0aXZlRWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkpKSByZXR1cm47XHJcblxyXG4gICAgY29uc3QgZm9jdXNlZE5vZGUgPSB0aGlzLnRyZWVNb2RlbC5nZXRGb2N1c2VkTm9kZSgpO1xyXG5cclxuICAgIHRoaXMudHJlZU1vZGVsLnBlcmZvcm1LZXlBY3Rpb24oZm9jdXNlZE5vZGUsICRldmVudCk7XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCdib2R5OiBtb3VzZWRvd24nLCBbJyRldmVudCddKVxyXG4gIG9uTW91c2Vkb3duKCRldmVudCkge1xyXG4gICAgZnVuY3Rpb24gaXNPdXRzaWRlQ2xpY2soc3RhcnRFbGVtZW50OiBFbGVtZW50LCBub2RlTmFtZTogc3RyaW5nKSB7XHJcbiAgICAgIHJldHVybiAhc3RhcnRFbGVtZW50ID8gdHJ1ZSA6IHN0YXJ0RWxlbWVudC5sb2NhbE5hbWUgPT09IG5vZGVOYW1lID8gZmFsc2UgOiBpc091dHNpZGVDbGljayhzdGFydEVsZW1lbnQucGFyZW50RWxlbWVudCwgbm9kZU5hbWUpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChpc091dHNpZGVDbGljaygkZXZlbnQudGFyZ2V0LCAndHJlZS1yb290JykpIHtcclxuICAgICAgdGhpcy50cmVlTW9kZWwuc2V0Rm9jdXMoZmFsc2UpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlcykge1xyXG4gICAgaWYgKGNoYW5nZXMub3B0aW9ucyB8fCBjaGFuZ2VzLm5vZGVzKSB7XHJcbiAgICAgIHRoaXMudHJlZU1vZGVsLnNldERhdGEoe1xyXG4gICAgICAgIG9wdGlvbnM6IGNoYW5nZXMub3B0aW9ucyAmJiBjaGFuZ2VzLm9wdGlvbnMuY3VycmVudFZhbHVlLFxyXG4gICAgICAgIG5vZGVzOiBjaGFuZ2VzLm5vZGVzICYmIGNoYW5nZXMubm9kZXMuY3VycmVudFZhbHVlLFxyXG4gICAgICAgIGV2ZW50czogdGhpcy5waWNrKHRoaXMsIHRoaXMudHJlZU1vZGVsLmV2ZW50TmFtZXMpXHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc2l6ZUNoYW5nZWQoKSB7XHJcbiAgICB0aGlzLnZpZXdwb3J0Q29tcG9uZW50LnNldFZpZXdwb3J0KCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHBpY2sob2JqZWN0LCBrZXlzKSB7XHJcbiAgICByZXR1cm4ga2V5cy5yZWR1Y2UoKG9iaiwga2V5KSA9PiB7XHJcbiAgICAgIGlmIChvYmplY3QgJiYgb2JqZWN0Lmhhc093blByb3BlcnR5KGtleSkpIHtcclxuICAgICAgICBvYmpba2V5XSA9IG9iamVjdFtrZXldO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBvYmo7XHJcbiAgICB9LCB7fSk7XHJcbiAgfVxyXG59XHJcblxyXG4vL2ltcG9ydGVkIGZyb20gdHJlZS1ub2RlLmNoaWxkcmVuIHRvIGF2b2lkIE5HMzAwMyBjeWNsZSBlcnJvclxyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICd0cmVlLW5vZGUtY2hpbGRyZW4nLFxyXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXHJcbiAgc3R5bGVzOiBbXSxcclxuICB0ZW1wbGF0ZTogYFxyXG4gICAgPG5nLWNvbnRhaW5lciAqdHJlZU1vYnhBdXRvcnVuPVwieyBkb250RGV0YWNoOiB0cnVlIH1cIj5cclxuICAgICAgPGRpdlxyXG4gICAgICAgIFtjbGFzcy50cmVlLWNoaWxkcmVuXT1cInRydWVcIlxyXG4gICAgICAgIFtjbGFzcy50cmVlLWNoaWxkcmVuLW5vLXBhZGRpbmddPVwibm9kZS5vcHRpb25zLmxldmVsUGFkZGluZ1wiXHJcbiAgICAgICAgKnRyZWVBbmltYXRlT3Blbj1cIlxyXG4gICAgICAgICAgbm9kZS5pc0V4cGFuZGVkO1xyXG4gICAgICAgICAgc3BlZWQ6IG5vZGUub3B0aW9ucy5hbmltYXRlU3BlZWQ7XHJcbiAgICAgICAgICBhY2NlbGVyYXRpb246IG5vZGUub3B0aW9ucy5hbmltYXRlQWNjZWxlcmF0aW9uO1xyXG4gICAgICAgICAgZW5hYmxlZDogbm9kZS5vcHRpb25zLmFuaW1hdGVFeHBhbmRcclxuICAgICAgICBcIlxyXG4gICAgICA+XHJcbiAgICAgICAgPHRyZWUtbm9kZS1jb2xsZWN0aW9uXHJcbiAgICAgICAgICAqbmdJZj1cIm5vZGUuY2hpbGRyZW5cIlxyXG4gICAgICAgICAgW25vZGVzXT1cIm5vZGUuY2hpbGRyZW5cIlxyXG4gICAgICAgICAgW3RlbXBsYXRlc109XCJ0ZW1wbGF0ZXNcIlxyXG4gICAgICAgICAgW3RyZWVNb2RlbF09XCJub2RlLnRyZWVNb2RlbFwiXHJcbiAgICAgICAgPlxyXG4gICAgICAgIDwvdHJlZS1ub2RlLWNvbGxlY3Rpb24+XHJcbiAgICAgICAgPHRyZWUtbG9hZGluZy1jb21wb25lbnRcclxuICAgICAgICAgIFtzdHlsZS5wYWRkaW5nLWxlZnRdPVwibm9kZS5nZXROb2RlUGFkZGluZygpXCJcclxuICAgICAgICAgIGNsYXNzPVwidHJlZS1ub2RlLWxvYWRpbmdcIlxyXG4gICAgICAgICAgKm5nSWY9XCIhbm9kZS5jaGlsZHJlblwiXHJcbiAgICAgICAgICBbdGVtcGxhdGVdPVwidGVtcGxhdGVzLmxvYWRpbmdUZW1wbGF0ZVwiXHJcbiAgICAgICAgICBbbm9kZV09XCJub2RlXCJcclxuICAgICAgICA+PC90cmVlLWxvYWRpbmctY29tcG9uZW50PlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvbmctY29udGFpbmVyPlxyXG4gIGBcclxufSlcclxuZXhwb3J0IGNsYXNzIFRyZWVOb2RlQ2hpbGRyZW5Db21wb25lbnQge1xyXG4gIEBJbnB1dCgpIG5vZGU6IFRyZWVOb2RlO1xyXG4gIEBJbnB1dCgpIHRlbXBsYXRlczogYW55O1xyXG59XHJcblxyXG5cclxuLy9pbXBvcnRlZCBmcm9tIHRyZWUtbm9kZS1jb2xsZWN0aW9uLmNvbXBvbmVudC50cyB0byBhdm9pZCBORzMwMDMgY3ljbGUgZXJyb3JcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAndHJlZS1ub2RlLWNvbGxlY3Rpb24nLFxyXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXHJcbiAgdGVtcGxhdGU6IGBcclxuICAgIDxuZy1jb250YWluZXIgKnRyZWVNb2J4QXV0b3J1bj1cInsgZG9udERldGFjaDogdHJ1ZSB9XCI+XHJcbiAgICAgIDxkaXYgW3N0eWxlLm1hcmdpbi10b3BdPVwibWFyZ2luVG9wXCI+XHJcbiAgICAgICAgPHRyZWUtbm9kZVxyXG4gICAgICAgICAgKm5nRm9yPVwibGV0IG5vZGUgb2Ygdmlld3BvcnROb2RlczsgbGV0IGkgPSBpbmRleDsgdHJhY2tCeTogdHJhY2tOb2RlXCJcclxuICAgICAgICAgIFtub2RlXT1cIm5vZGVcIlxyXG4gICAgICAgICAgW2luZGV4XT1cImlcIlxyXG4gICAgICAgICAgW3RlbXBsYXRlc109XCJ0ZW1wbGF0ZXNcIlxyXG4gICAgICAgID5cclxuICAgICAgICA8L3RyZWUtbm9kZT5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L25nLWNvbnRhaW5lcj5cclxuICBgXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBUcmVlTm9kZUNvbGxlY3Rpb25Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XHJcbiAgQElucHV0KClcclxuICBnZXQgbm9kZXMoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5fbm9kZXM7XHJcbiAgfVxyXG4gIHNl