ngx-bootstrap-treeview
Version:
Ngx Bootstrap Treeview - Simple library to visualize, search and interact with tree data
1,229 lines (1,214 loc) • 119 kB
JavaScript
import { __extends, __assign, __spread } from 'tslib';
import { Injectable, NgModule, defineInjectable, Inject, NgZone, inject, EventEmitter, Component, Renderer2, Input, Output, ViewChild, ElementRef, ChangeDetectorRef, ViewChildren } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { faSquare, faCheckSquare, faFolder, faFolderOpen, faMinus, faCheck } from '@fortawesome/free-solid-svg-icons';
import { trigger, style, transition, animate, keyframes } from '@angular/animations';
import { EVENT_MANAGER_PLUGINS, EventManager } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var Tree = /** @class */ (function () {
function Tree() {
}
return Tree;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var Leaf = /** @class */ (function () {
function Leaf(tree) {
this.value = tree.value;
this.label = tree.label;
this.data = tree.data;
}
return Leaf;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var LeafClickedEvent = /** @class */ (function () {
function LeafClickedEvent(leaf, selectedLeaves) {
this.leaf = leaf;
this.selectedLeaves = selectedLeaves;
}
return LeafClickedEvent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @template TreeSourceType, LeafSourceType
*/
var /**
* @template TreeSourceType, LeafSourceType
*/
NgxBootstrapTreeviewMapper = /** @class */ (function () {
function NgxBootstrapTreeviewMapper(treeMap, leafMap) {
this.treeMap = treeMap;
this.leafMap = leafMap;
}
/**
* @param {?} item
* @return {?}
*/
NgxBootstrapTreeviewMapper.prototype.mapTree = /**
* @param {?} item
* @return {?}
*/
function (item) {
var _this = this;
var _a = {
value: item[this.treeMap.value],
label: item[this.treeMap.label],
children: item[this.treeMap.children],
leaves: item[this.treeMap.leavesKey],
data: item
}, value = _a.value, label = _a.label, children = _a.children, leaves = _a.leaves, data = _a.data;
/** @type {?} */
var result = {
value: value,
label: label,
data: data,
children: __spread(children.map(function (child) { return _this.mapTree(child); }), leaves.map(function (leaf) { return _this.mapLeaf(leaf); }))
};
return result;
};
/**
* @param {?} item
* @return {?}
*/
NgxBootstrapTreeviewMapper.prototype.mapLeaf = /**
* @param {?} item
* @return {?}
*/
function (item) {
return {
value: item[this.leafMap.value],
label: item[this.leafMap.label],
data: item
};
};
return NgxBootstrapTreeviewMapper;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var ContextMenuService = /** @class */ (function () {
function ContextMenuService() {
this.lastContextMenuEvent = new BehaviorSubject(null);
}
/**
* @param {?} event
* @return {?}
*/
ContextMenuService.prototype.fire = /**
* @param {?} event
* @return {?}
*/
function (event) {
this.lastContextMenuEvent.next(event);
};
ContextMenuService.decorators = [
{ type: Injectable, args: [{
providedIn: 'root'
},] }
];
/** @nocollapse */
ContextMenuService.ctorParameters = function () { return []; };
/** @nocollapse */ ContextMenuService.ngInjectableDef = defineInjectable({ factory: function ContextMenuService_Factory() { return new ContextMenuService(); }, token: ContextMenuService, providedIn: "root" });
return ContextMenuService;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var NgxBootstrapTreeviewComponent = /** @class */ (function () {
function NgxBootstrapTreeviewComponent(_host, _renderer, _zone, _changeDetector, _contextMenuService) {
this._host = _host;
this._renderer = _renderer;
this._zone = _zone;
this._changeDetector = _changeDetector;
this._contextMenuService = _contextMenuService;
this.contextMenus = {
leafMenu: {},
branchMenu: {},
rootMenu: {}
};
this.disableSelectedElements = false;
this.emptyFolderLabel = 'This folder is empty';
this.isAnimationDisabled = false;
this.isFirstLevel = true;
// This one is true IF AND ONLY IF we're at the top level, be it a root or a branch.
// This is because a branch where isFirstLevel = true is not always our first treeview instance
this.isFirstInstance = true;
this.preselectedItems = [];
// Icons inputs
this.openedFolderIcon = faFolderOpen;
this.closedFolderIcon = faFolder;
this.unselectedLeafIcon = faSquare;
this.selectedLeafIcon = faCheckSquare;
this.anyChildrenSelectedIcon = faMinus;
this.allChildrenSelectedIcon = faCheck;
this.filterString = '';
this.matchBranches = true;
this.branchClicked = new EventEmitter();
this.leafClicked = new EventEmitter();
this.selectedLeaves = [];
}
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
// We throw an exception if we have item or items but no mapper indicating how to handle them
if (!this.mapper && (this.item || this.items)) {
throw new Error('"item" or "items" are invalid parameters if you don\'t provide a mapper');
}
// If we have a mapper, it will handle "item" and "items"
if (this.mapper) {
if (this.items) {
this.trees = this.items.map(function (item) { return _this.mapper.mapTree(item); });
}
if (this.item) {
this.tree = this.mapper.mapTree(this.item);
}
}
// If we want to display one or more trees
if (this.trees && this.trees.length > 1) {
this.isRoot = true;
this.isBranch = this.isLeaf = false;
// return;
}
else if (this.trees) {
// Otherwise, we have trees but with less than 2 elements, we assign it to tree
// So ngOnInit() can keep going normaly
this.tree = this.trees[0];
}
if (this.tree && (this.tree.children || this.tree.loadChildren)) {
this.isBranch = true;
}
else {
this.isBranch = false;
}
this._resetDisplayedData();
if (!this.isRoot) {
this.isLeaf = !this.isBranch;
}
this.leavesCount = this.countLeaves(this.tree);
if (this.preselectedItems) {
this.preselectedItems.forEach(function (value) {
_this.select(value);
});
}
};
/**
* @param {?} changes
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
var _this = this;
// The this.tree || this.trees is used to avoid anerror since ngOnChanges is called before ngOnInit()
if ('filterString' in changes && (this.displayedTree || this.displayedTrees)) {
this._zone.runOutsideAngular(function () {
if (_this._filterTrigger) {
clearTimeout(_this._filterTrigger);
_this._filterTrigger = null;
}
_this._filterTrigger = setTimeout(function () {
_this._zone.run(function () {
if (_this.displayedTrees) {
_this.displayedTrees = _this._filterTrees();
}
else if (_this.displayedTree) {
_this.displayedTree = _this._filterTree(_this.displayedTree);
}
_this._changeDetector.detectChanges();
if (_this.filterString) {
_this.unfoldAll();
}
else {
_this._resetDisplayedData();
_this.foldAll();
}
});
}, 250);
});
}
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.onClick = /**
* @return {?}
*/
function () {
if (this.isLeaf) {
this.onLeafClicked();
}
if (this.isBranch) {
if (this.loggingService) {
this.loggingService.log("\uD83C\uDF34 Branche cliqu\u00E9e: " + this.tree.label);
}
this.onBranchClicked();
}
};
/**
* @param {?} leafClickedEvent
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.onChildLeafClicked = /**
* @param {?} leafClickedEvent
* @return {?}
*/
function (leafClickedEvent) {
if (this.loggingService && this.isBranch) {
this.loggingService.log("\u27A1 Event entrant dans le parent " + this.tree.label + ":", leafClickedEvent);
}
else if (this.loggingService && this.isRoot) {
this.loggingService.log("\u27A1 Event entrant dans la racine:", leafClickedEvent);
}
// When a child leaf is clicked, we check our selectedLeaves to select or unselect the clicked one
if (!this._leafExistsIn(this.selectedLeaves, leafClickedEvent.leaf)) {
this._selectLeaf(leafClickedEvent.leaf);
}
else {
this._unselectLeaf(leafClickedEvent.leaf);
}
// Now that the leaf is selected/unselected, we merge our selectedLeaves with the ones of the event
leafClickedEvent.selectedLeaves = this.selectedLeaves;
if (this.isBranch && this.loggingService) {
this.loggingService.log("\u2B05 Event sortant de " + this.tree.label + " vers un parent:", leafClickedEvent);
}
else if (this.loggingService && this.isRoot) {
this.loggingService.log("\u2B05 Event sortant de la racine:", leafClickedEvent);
}
this.leafClicked.emit(leafClickedEvent);
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.onLeafClicked = /**
* @return {?}
*/
function () {
if (this.loggingService) {
this.loggingService.log('🍂 Feuille cliqué:', this.tree.label);
}
if (!this.disableSelectedElements || !this.isOpened) {
this._leafToggle();
}
};
/**
* @param {?} tree
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.countLeaves = /**
* @param {?} tree
* @return {?}
*/
function (tree) {
var _this = this;
/** @type {?} */
var leavesCount = 0;
if (tree && (!tree.children || tree.loadChildren)) {
leavesCount = 1;
}
else if (tree) {
tree.children.forEach(function (child) {
leavesCount += _this.countLeaves(child);
});
}
return leavesCount;
};
/**
* @param {?} value
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.select = /**
* @param {?} value
* @return {?}
*/
function (value) {
if (this.isLeaf && this.tree.value === value && !this.isOpened) {
this._leafToggle();
}
else if (this.isRoot || this.isBranch) {
this.children.forEach(function (child) {
child.select(value);
});
}
};
/**
* @param {?} value
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.unselect = /**
* @param {?} value
* @return {?}
*/
function (value) {
if (this.isLeaf && this.tree.value === value && this.isOpened) {
this._leafToggle();
}
else if (this.isRoot || this.isBranch) {
this.children.forEach(function (child) {
child.unselect(value);
});
}
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.onBranchClicked = /**
* @return {?}
*/
function () {
this._branchToggle();
this.branchClicked.emit(this.tree);
};
/**
* @param {?} branch
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.onChildBranchClicked = /**
* @param {?} branch
* @return {?}
*/
function (branch) {
var _this = this;
this.branchClicked.emit(branch);
if (this.rootsContainer) {
requestAnimationFrame(function () {
// We use requestAnimationFrame because we want this to be processed once rerendering is complete
_this.rootsContainer.nativeElement.style.height = _this.computeHeight() + 'px';
});
}
};
/**
* @param {?} event
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.onContextMenu = /**
* @param {?} event
* @return {?}
*/
function (event) {
event.stopPropagation();
event.preventDefault();
this._contextMenuService.fire({
target: this.tree,
event: event
});
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.onElementAdded = /**
* @return {?}
*/
function () {
this.leavesCount = this.countLeaves(this.tree);
return true;
};
/**
* @param {?} event
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.onRootContextMenu = /**
* @param {?} event
* @return {?}
*/
function (event) {
event.stopPropagation();
event.preventDefault();
this._contextMenuService.fire({
event: event,
target: null
});
};
/**
* @param {?=} id
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.fold = /**
* @param {?=} id
* @return {?}
*/
function (id) {
if (!id) {
this._fold();
}
else {
this._foldId(id);
}
};
/**
* @param {?=} id
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.unfold = /**
* @param {?=} id
* @return {?}
*/
function (id) {
if (!id) {
this._unfold();
}
else {
this._unfoldId(id);
}
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.show = /**
* @return {?}
*/
function () {
/** @type {?} */
var domElement = this._host.nativeElement;
this._renderer.removeClass(domElement, 'd-none');
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.hide = /**
* @return {?}
*/
function () {
/** @type {?} */
var domElement = this._host.nativeElement;
this._renderer.addClass(domElement, 'd-none');
};
/**
* @param {?} filterString
* @param {?=} item
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.filter = /**
* @param {?} filterString
* @param {?=} item
* @return {?}
*/
function (filterString, item) {
var _this = this;
if (this.isRoot) {
this.children.forEach(function (child) {
child.filter(_this.filterString);
});
}
else {
if (!item) {
item = this.tree;
}
/** @type {?} */
var matchingElementsCount = this.countFilteredItems(filterString, item);
if (matchingElementsCount === 0) {
this.hide();
}
else {
this.show();
if (filterString !== '') {
this._unfold();
}
else {
this._fold();
}
}
}
};
/**
* @param {?} filterString
* @param {?} item
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.countFilteredItems = /**
* @param {?} filterString
* @param {?} item
* @return {?}
*/
function (filterString, item) {
var _this = this;
/** @type {?} */
var matchingElementsCount = 0;
if (item.children) {
if (!filterString.length) {
return 1;
}
matchingElementsCount = item.children.reduce(function (acc, child) { return acc + _this.countFilteredItems(filterString, child); }, 0);
}
else {
/** @type {?} */
var regex = new RegExp(filterString, 'i');
if (regex.test(item.label)) {
matchingElementsCount++;
}
}
return matchingElementsCount;
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.unfoldAll = /**
* @return {?}
*/
function () {
// A branch will unfold itself
if (this.isBranch && !this.isOpened) {
this._branchToggle();
this._changeDetector.detectChanges();
}
// If we're not a leaf, we unfold all of our children
if (!this.isLeaf) {
this.children.forEach(function (child) {
child.unfoldAll();
});
}
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.foldAll = /**
* @return {?}
*/
function () {
// A branch will fold itself
if (this.isBranch && this.isOpened) {
this._branchToggle();
}
// If we're not a leaf, we unfold all of our children
if (!this.isLeaf) {
this.children.forEach(function (child) {
child.foldAll();
});
}
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype.computeHeight = /**
* @return {?}
*/
function () {
if (!this.isRoot) {
return this.treeview.nativeElement.scrollHeight;
}
return this.children.reduce(function (prevValue, currentValue) {
return prevValue + currentValue.computeHeight();
}, 0);
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._unfold = /**
* @return {?}
*/
function () {
if (this.isBranch && !this.isOpened) {
this._branchToggle();
}
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._fold = /**
* @return {?}
*/
function () {
if (this.isBranch && this.isOpened) {
this._branchToggle();
}
};
/**
* @param {?} id
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._unfoldId = /**
* @param {?} id
* @return {?}
*/
function (id) {
if (this.isBranch && this.tree.value === id && !this.isOpened) {
this._branchToggle();
}
else if (this.isBranch && this.children.length) {
this.children.forEach(function (child) {
child.unfold(id);
});
}
};
/**
* @param {?} id
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._foldId = /**
* @param {?} id
* @return {?}
*/
function (id) {
if (this.isBranch && this.tree.value === id && this.isOpened) {
this._branchToggle();
}
else if (this.isBranch && this.children.length) {
this.children.forEach(function (child) {
child.fold(id);
});
}
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._leafToggle = /**
* @return {?}
*/
function () {
this.isOpened = !this.isOpened;
/** @type {?} */
var leaf = new Leaf(this.tree);
if (this.isOpened) {
this._selectLeaf(leaf);
}
else {
this._unselectLeaf(leaf);
}
/** @type {?} */
var event = new LeafClickedEvent(leaf, this.selectedLeaves);
this.leafClicked.emit(event);
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._branchToggle = /**
* @return {?}
*/
function () {
this.isOpened = !this.isOpened;
};
/**
* @param {?} leaf
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._selectLeaf = /**
* @param {?} leaf
* @return {?}
*/
function (leaf) {
if (!this.isRoot && this.loggingService) {
this.loggingService.log("\u2714\uFE0F Feuille s\u00E9lectionn\u00E9e dans " + this.tree.label + ":", leaf);
}
else if (this.loggingService) {
this.loggingService.log("\u2714\uFE0F Feuille s\u00E9lectionn\u00E9e dans la racine:", leaf);
}
if (!this._leafExistsIn(this.selectedLeaves, leaf)) {
this.selectedLeaves = __spread(this.selectedLeaves, [leaf]);
}
};
/**
* @param {?} leaf
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._unselectLeaf = /**
* @param {?} leaf
* @return {?}
*/
function (leaf) {
if (!this.isRoot && this.loggingService) {
this.loggingService.log("\u274C Feuille d\u00E9s\u00E9lectionn\u00E9e dans " + this.tree.label + ":", leaf);
}
else if (this.loggingService) {
this.loggingService.log("\u274C Feuille d\u00E9s\u00E9lectionn\u00E9e dans la racine:", leaf);
}
/** @type {?} */
var index = this._leafIndex(this.selectedLeaves, leaf);
if (index !== -1) {
this.selectedLeaves.splice(index, 1);
}
};
// Function used to check if a given leaf does exist in sleectedLeaves array
// We use this because of the new Leaf(), which causes reference comparison of Array.indexOf() not to work
// Function used to check if a given leaf does exist in sleectedLeaves array
// We use this because of the new Leaf(), which causes reference comparison of Array.indexOf() not to work
/**
* @param {?} leaves
* @param {?} leaf
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._leafIndex =
// Function used to check if a given leaf does exist in sleectedLeaves array
// We use this because of the new Leaf(), which causes reference comparison of Array.indexOf() not to work
/**
* @param {?} leaves
* @param {?} leaf
* @return {?}
*/
function (leaves, leaf) {
/** @type {?} */
var result = -1;
leaves.forEach(function (selectedLeaf, index) {
if (selectedLeaf.value === leaf.value && selectedLeaf.label === leaf.label) {
result = index;
}
});
return result;
};
/**
* @param {?} leaves
* @param {?} leaf
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._leafExistsIn = /**
* @param {?} leaves
* @param {?} leaf
* @return {?}
*/
function (leaves, leaf) {
return this._leafIndex(leaves, leaf) !== -1;
};
/**
* @param {?} tree
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._copyTree = /**
* @param {?} tree
* @return {?}
*/
function (tree) {
var _this = this;
/** @type {?} */
var isTree = !!tree.children;
/** @type {?} */
var result = {
value: tree.value,
label: tree.label,
data: tree.data
};
if (isTree) {
/** @type {?} */
var children = tree.children.map(function (child) { return _this._copyTree(child); });
return __assign({}, result, { children: children });
}
else {
return result;
}
};
/**
* @param {?} trees
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._copyTrees = /**
* @param {?} trees
* @return {?}
*/
function (trees) {
var _this = this;
return trees.map(function (tree) { return _this._copyTree(tree); });
};
/**
* @param {?=} trees
* @param {?=} filterString
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._filterTrees = /**
* @param {?=} trees
* @param {?=} filterString
* @return {?}
*/
function (trees, filterString) {
var _this = this;
if (trees === void 0) { trees = this.trees; }
if (filterString === void 0) { filterString = this.filterString; }
/** @type {?} */
var copies = this._copyTrees(trees);
if (filterString !== '') {
/** @type {?} */
var displayedTrees = copies
.map(function (copy) {
return _this._filterTree(copy, filterString);
})
.filter(function (filteredCopy) { return !!filteredCopy; });
return displayedTrees;
}
else {
return copies;
}
};
// This method alters tree.children and returns true if any elements matched the filter string
// This method alters tree.children and returns true if any elements matched the filter string
/**
* @param {?} tree
* @param {?=} filterString
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._filterTree =
// This method alters tree.children and returns true if any elements matched the filter string
/**
* @param {?} tree
* @param {?=} filterString
* @return {?}
*/
function (tree, filterString) {
var _this = this;
if (filterString === void 0) { filterString = this.filterString; }
/** @type {?} */
var regex = new RegExp(filterString, 'i');
if (!tree.children) {
// Leaf handling
return regex.test(tree.label) ? tree : null;
}
else if (tree.children && tree.children.length) {
if (this.matchBranches && regex.test(tree.label)) {
return tree;
}
// Non empty branches handling
tree.children = tree.children.map(function (child) { return _this._filterTree(child); }).filter(function (child) { return !!child; });
return tree.children.length ? tree : null;
}
return null;
};
/**
* @return {?}
*/
NgxBootstrapTreeviewComponent.prototype._resetDisplayedData = /**
* @return {?}
*/
function () {
if (this.tree) {
this.displayedTree = this._copyTree(this.tree);
}
else if (this.trees) {
this.displayedTrees = this._copyTrees(this.trees);
}
};
NgxBootstrapTreeviewComponent.decorators = [
{ type: Component, args: [{
// tslint:disable-next-line:component-selector
selector: 'ngx-bootstrap-treeview',
template: "<!-- This part is used if we have a single tree inputed to our component -->\r\n<ul\r\n [ngClass]=\"{\r\n branch: displayedTree.children,\r\n leaf: !displayedTree.children,\r\n opened: isOpened,\r\n 'pl-0': isFirstLevel,\r\n disabled: isLeaf && isOpened && disableSelectedElements\r\n }\"\r\n *ngIf=\"displayedTree\"\r\n class=\"mb-0\"\r\n #treeview\r\n>\r\n <li>\r\n <a [routerLink]=\"[]\" (click)=\"onClick()\" (contextmenu)=\"onContextMenu($event)\">\r\n <!-- Icons if we're reprensenting a branch -->\r\n <span class=\"icon\">\r\n <!-- Folder closed, no children selected -->\r\n <fa-icon\r\n [fixedWidth]=\"true\"\r\n [icon]=\"closedFolderIcon\"\r\n *ngIf=\"displayedTree.children && !isOpened && !selectedLeaves.length\"\r\n ></fa-icon>\r\n\r\n <!-- Folder closed, children selected but not all -->\r\n <fa-layers\r\n [fixedWidth]=\"true\"\r\n *ngIf=\"\r\n displayedTree.children &&\r\n !isOpened &&\r\n selectedLeaves.length > 0 &&\r\n selectedLeaves.length < this.leavesCount\r\n \"\r\n >\r\n <fa-icon [fixedWidth]=\"true\" [icon]=\"closedFolderIcon\"></fa-icon>\r\n <fa-icon [fixedWidth]=\"true\" [icon]=\"anyChildrenSelectedIcon\" transform=\"shrink-6 down-1\"></fa-icon>\r\n </fa-layers>\r\n\r\n <!-- Folder closed, all children selected -->\r\n <fa-layers\r\n [fixedWidth]=\"true\"\r\n *ngIf=\"\r\n displayedTree.children && !isOpened && selectedLeaves.length === leavesCount && leavesCount > 0\r\n \"\r\n >\r\n <fa-icon [fixedWidth]=\"true\" [icon]=\"closedFolderIcon\"></fa-icon>\r\n <fa-icon [fixedWidth]=\"true\" [icon]=\"allChildrenSelectedIcon\" transform=\"shrink-8 down-1\"></fa-icon>\r\n </fa-layers>\r\n\r\n <!-- Folder opened, no children selected -->\r\n <fa-icon\r\n [fixedWidth]=\"true\"\r\n [icon]=\"openedFolderIcon\"\r\n *ngIf=\"displayedTree.children && isOpened && !selectedLeaves.length\"\r\n ></fa-icon>\r\n\r\n <!-- Folder opened, children selected but not all -->\r\n <fa-layers\r\n [fixedWidth]=\"true\"\r\n *ngIf=\"\r\n displayedTree.children &&\r\n isOpened &&\r\n selectedLeaves.length > 0 &&\r\n selectedLeaves.length < this.leavesCount\r\n \"\r\n >\r\n <fa-icon [fixedWidth]=\"true\" [icon]=\"openedFolderIcon\"></fa-icon>\r\n <fa-icon\r\n [fixedWidth]=\"true\"\r\n [icon]=\"anyChildrenSelectedIcon\"\r\n transform=\"shrink-8 down-3 right-2\"\r\n class=\"opened-folder-mask\"\r\n ></fa-icon>\r\n </fa-layers>\r\n <!-- Folder opened, all children selected -->\r\n <fa-layers\r\n [fixedWidth]=\"true\"\r\n *ngIf=\"\r\n displayedTree.children && isOpened && selectedLeaves.length === leavesCount && leavesCount > 0\r\n \"\r\n >\r\n <fa-icon [fixedWidth]=\"true\" [icon]=\"openedFolderIcon\"></fa-icon>\r\n <fa-icon\r\n [fixedWidth]=\"true\"\r\n [icon]=\"allChildrenSelectedIcon\"\r\n transform=\"shrink-12 down-3 right-1\"\r\n class=\"opened-folder-mask\"\r\n ></fa-icon>\r\n </fa-layers>\r\n <!-- /branch icons -->\r\n\r\n <!-- Icons if we're reprensenting a leaf -->\r\n <fa-icon\r\n [fixedWidth]=\"true\"\r\n [icon]=\"unselectedLeafIcon\"\r\n *ngIf=\"!displayedTree.children && !isOpened\"\r\n ></fa-icon>\r\n <fa-icon\r\n [fixedWidth]=\"true\"\r\n [icon]=\"selectedLeafIcon\"\r\n *ngIf=\"!displayedTree.children && isOpened\"\r\n ></fa-icon>\r\n </span>\r\n <span class=\"label\">\r\n {{ displayedTree.label }}\r\n </span>\r\n </a>\r\n\r\n <div\r\n *ngIf=\"displayedTree.children && isOpened\"\r\n class=\"children\"\r\n [@.disabled]=\"isAnimationDisabled\"\r\n [@childrenAnimationTrigger]\r\n >\r\n <ul *ngIf=\"displayedTree.children.length === 0\">\r\n <li>\r\n <i>{{ emptyFolderLabel }}</i>\r\n </li>\r\n </ul>\r\n <ng-container *ngFor=\"let branch of displayedTree.children\">\r\n <ngx-bootstrap-treeview\r\n *ngIf=\"onElementAdded()\"\r\n [tree]=\"branch\"\r\n (branchClicked)=\"onChildBranchClicked($event)\"\r\n (leafClicked)=\"onChildLeafClicked($event)\"\r\n [selectedLeafIcon]=\"selectedLeafIcon\"\r\n [unselectedLeafIcon]=\"unselectedLeafIcon\"\r\n [openedFolderIcon]=\"openedFolderIcon\"\r\n [closedFolderIcon]=\"closedFolderIcon\"\r\n [canSelectBranch]=\"canSelectBranch\"\r\n [anyChildrenSelectedIcon]=\"anyChildrenSelectedIcon\"\r\n [allChildrenSelectedIcon]=\"allChildrenSelectedIcon\"\r\n [loggingService]=\"loggingService\"\r\n [isFirstInstance]=\"false\"\r\n [isFirstLevel]=\"false\"\r\n [disableSelectedElements]=\"disableSelectedElements\"\r\n [emptyFolderLabel]=\"emptyFolderLabel\"\r\n >\r\n </ngx-bootstrap-treeview>\r\n </ng-container>\r\n </div>\r\n </li>\r\n</ul>\r\n<!-- END Single tree provided -->\r\n\r\n<!-- Context menu, only shown once, so either on root or on branch if first level -->\r\n<ngx-bootstrap-treeview-context-menu\r\n *ngIf=\"contextMenus && isFirstInstance\"\r\n [config]=\"contextMenus\"\r\n [rootContextMenu]=\"contextMenus.rootMenu\"\r\n [branchContextMenu]=\"contextMenus.branchMenu\"\r\n [leafContextMenu]=\"contextMenus.leafMenu\"\r\n>\r\n</ngx-bootstrap-treeview-context-menu>\r\n\r\n<!-- If we provided an array of trees as an input, this part will be called -->\r\n<div *ngIf=\"displayedTrees\" (contextmenu)=\"onRootContextMenu($event)\" #rootsContainer>\r\n <ngx-bootstrap-treeview\r\n *ngFor=\"let displayedTree of displayedTrees\"\r\n [tree]=\"displayedTree\"\r\n (branchClicked)=\"onChildBranchClicked($event)\"\r\n (leafClicked)=\"onChildLeafClicked($event)\"\r\n [selectedLeafIcon]=\"selectedLeafIcon\"\r\n [unselectedLeafIcon]=\"unselectedLeafIcon\"\r\n [openedFolderIcon]=\"openedFolderIcon\"\r\n [closedFolderIcon]=\"closedFolderIcon\"\r\n [canSelectBranch]=\"canSelectBranch\"\r\n [anyChildrenSelectedIcon]=\"anyChildrenSelectedIcon\"\r\n [allChildrenSelectedIcon]=\"allChildrenSelectedIcon\"\r\n [loggingService]=\"loggingService\"\r\n [disableSelectedElements]=\"disableSelectedElements\"\r\n [isAnimationDisabled]=\"isAnimationDisabled\"\r\n [isFirstInstance]=\"false\"\r\n [emptyFolderLabel]=\"emptyFolderLabel\"\r\n ></ngx-bootstrap-treeview>\r\n</div>\r\n<!-- End multiple trees provided -->\r\n",
animations: [
trigger('childrenAnimationTrigger', [
transition(':leave', [animate('0.25s', style({ transform: 'translateX(-100%)', display: 'none' }))]),
transition(':enter', [
animate('0.25s', keyframes([
style({ transform: 'translateX(-100%)', display: 'block', offset: 0 }),
style({ transform: 'translateX(0%)', offset: 1 })
]))
])
])
],
styles: ["ul{list-style-type:none;overflow:visible;float:left;clear:left}ul li{position:relative;display:inline-block}ul fa-icon,ul fa-layers fa-icon{color:#000}ul fa-layers fa-icon:not(:first-child) ::ng-deep svg[data-prefix=fas]{color:#fff}ul fa-layers fa-icon.opened-folder-mask ::ng-deep svg{-webkit-transform:skew(-45deg,0);transform:skew(-45deg,0)}:host{display:block}:host>div{position:relative}"]
}] }
];
/** @nocollapse */
NgxBootstrapTreeviewComponent.ctorParameters = function () { return [
{ type: ElementRef },
{ type: Renderer2 },
{ type: NgZone },
{ type: ChangeDetectorRef },
{ type: ContextMenuService }
]; };
NgxBootstrapTreeviewComponent.propDecorators = {
canSelectBranch: [{ type: Input }],
contextMenus: [{ type: Input }],
disableSelectedElements: [{ type: Input }],
emptyFolderLabel: [{ type: Input }],
isAnimationDisabled: [{ type: Input }],
isFirstLevel: [{ type: Input }],
isFirstInstance: [{ type: Input }],
isOpened: [{ type: Input }],
item: [{ type: Input }],
items: [{ type: Input }],
loggingService: [{ type: Input }],
mapper: [{ type: Input }],
preselectedItems: [{ type: Input }],
tree: [{ type: Input }],
trees: [{ type: Input }],
openedFolderIcon: [{ type: Input }],
closedFolderIcon: [{ type: Input }],
unselectedLeafIcon: [{ type: Input }],
selectedLeafIcon: [{ type: Input }],
anyChildrenSelectedIcon: [{ type: Input }],
allChildrenSelectedIcon: [{ type: Input }],
filterString: [{ type: Input }],
matchBranches: [{ type: Input }],
branchClicked: [{ type: Output }],
leafClicked: [{ type: Output }],
children: [{ type: ViewChildren, args: [NgxBootstrapTreeviewComponent,] }],
treeview: [{ type: ViewChild, args: ['treeview',] }],
rootsContainer: [{ type: ViewChild, args: ['rootsContainer',] }]
};
return NgxBootstrapTreeviewComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var NgxBootstrapTreeviewContextMenuComponent = /** @class */ (function () {
function NgxBootstrapTreeviewContextMenuComponent(_renderer, _zone, _contextMenuService) {
this._renderer = _renderer;
this._zone = _zone;
this._contextMenuService = _contextMenuService;
this._defaultConfig = {
containerClass: '',
hoveredItemClass: '',
itemsClass: ''
};
this.config = {};
this.rootContextMenu = null;
this.branchContextMenu = null;
this.leafContextMenu = null;
this.hidden = new EventEmitter();
this.shown = new EventEmitter();
this._activeMenu = null;
}
/**
* @return {?}
*/
NgxBootstrapTreeviewContextMenuComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
this.config = __assign({}, this._defaultConfig, this.config);
this._contextMenuService.lastContextMenuEvent.subscribe(function (lastContextMenuEvent) {
if (lastContextMenuEvent) {
_this.show(lastContextMenuEvent);
}
else {
_this.hide();
}
});
this._renderer.listen(document, 'click.out-zone', this.onDocumentClicked.bind(this));
this._renderer.listen(document, 'keyup.out-zone', this.onKeyPressed.bind(this));
};
/**
* @param {?} changes
* @return {?}
*/
NgxBootstrapTreeviewContextMenuComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
if ('config' in changes) {
this.config = __assign({}, this._defaultConfig, changes.config.currentValue);
}
};
/**
* @param {?} event
* @return {?}
*/
NgxBootstrapTreeviewContextMenuComponent.prototype.onDocumentClicked = /**
* @param {?} event
* @return {?}
*/
function (event) {
if (this.lastContextMenuEvent) {
event.preventDefault();
event.stopPropagation();
this.hide();
}
};
/**
* @param {?} event
* @return {?}
*/
NgxBootstrapTreeviewContextMenuComponent.prototype.onKeyPressed = /**
* @param {?} event
* @return {?}
*/
function (event) {
if (this.lastContextMenuEvent && event.key.toLowerCase() === 'escape') {
this.hide();
}
};
/**
* @return {?}
*/
NgxBootstrapTreeviewContextMenuComponent.prototype.getLabels = /**
* @return {?}
*/
function () {
return this._activeMenu ? Object.keys(this._activeMenu) : [];
};
/**
* @param {?} label
* @return {?}
*/
NgxBootstrapTreeviewContextMenuComponent.prototype.onItemClicked = /**
* @param {?} label
* @return {?}
*/
function (label) {
this._activeMenu[label](this.lastContextMenuEvent.target);
};
/**
* @return {?}
*/
NgxBootstrapTreeviewContextMenuComponent.prototype.hide = /**
* @return {?}
*/
function () {
var _this = this;
this._zone.run(function () {
_this._activeMenu = null;
_this.lastContextMenuEvent = null;
_this.hidden.emit();
});
};
/**
* @param {?} contextMenuEvent
* @return {?}
*/
NgxBootstrapTreeviewContextMenuComponent.prototype.show = /**
* @param {?} contextMenuEvent
* @return {?}
*/
function (contextMenuEvent) {
this.lastContextMenuEvent = contextMenuEvent;
if (!contextMenuEvent.target) {
this._activeMenu = this.rootContextMenu;
}
else if (contextMenuEvent.target.children) {
this._activeMenu = this.branchContextMenu;
}
else {
this._activeMenu = this.leafContextMenu;
}
/** @type {?} */
var nativeElement = this.container.nativeElement;
/** @type {?} */
var x = this.lastContextMenuEvent.event.pageX.toString();
/** @type {?} */
var y = this.lastContextMenuEvent.event.pageY.toString();
this._renderer.setStyle(nativeElement, 'top', y + 'px');
this._renderer.setStyle(nativeElement, 'left', x + 'px');
this.shown.emit();
};
NgxBootstrapTreeviewContextMenuComponent.decorators = [
{ type: Component, args: [{
// tslint:disable-next-line: component-selector
selector: 'ngx-bootstrap-treeview-context-menu',
template: "<div\r\n class=\"context-menu list-group\"\r\n [ngClass]=\"{ 'd-none': !lastContextMenuEvent, 'd-block': lastContextMenuEvent }\"\r\n #container\r\n>\r\n <button\r\n class=\"context-menu-item {{ config.itemsClass }}\"\r\n *ngFor=\"let label of getLabels()\"\r\n (click)=\"onItemClicked(label)\"\r\n [ngClass]=\"{ 'list-group-item list-group-item-action px-3': !config.itemsClass }\"\r\n >\r\n {{ label }}\r\n </button>\r\n</div>\r\n",
styles: [".context-menu{background-color:#fff;border-radius:.25rem;left:0;position:fixed;top:0;z-index:100}.context-menu .context-menu-item{border-top-width:0;border-bottom-width:0;padding-top:.0625rem;padding-bottom:.0625rem;transition:background-color .3s}.context-menu .context-menu-item:first-of-type{padding-top:.125rem;border-top-width:1px}.context-menu .context-menu-item:last-of-type{padding-bottom:.125rem;border-bottom-width:1px}.context-menu .context-menu-item:hover{background:rgba(0,0,0,.8);color:#fff}"]
}] }
];
/** @nocollapse */
NgxBootstrapTreeviewContextMenuComponent.ctorParameters = function () { return [
{ type: Renderer2 },
{ type: NgZone },
{ type: ContextMenuService }
]; };
NgxBootstrapTreeviewContextMenuComponent.propDecorators = {
config: [{ type: Input }],
rootContextMenu: [{ type: Input }],
branchContextMenu: [{ type: Input }],
leafContextMenu: [{ type: Input }],
hidden: [{ type: Output }],
shown: [{ type: Output }],
container: [{ type: ViewChild, args: ['container',] }]
};
return NgxBootstrapTreeviewContextMenuComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var NgxBootstrapTreeviewEventManagerService = /** @class */ (function (_super) {
__extends(NgxBootstrapTreeviewEventManagerService, _super);
function NgxBootstrapTreeviewEventManagerService(plugins, zone) {
var _this = _super.call(this, plugins, zone) || this;
_this.zone = zone;
return _this;
}
/**
* @param {?} element
* @param {?} eventName
* @param {?} handler
* @return {?}
*/
NgxBootstrapTreeviewEventManagerService.prototype.addEventListener = /**
* @param {?} element
* @param {?} eventName
* @param {?} handler
* @return {?}
*/
function (element, eventName, handler) {
var _this = this;
if (eventName.endsWith('out-zone')) {
eventName = eventName.split('.')[0];
return this.zone.runOutsideAngular(function () { return _super.prototype.addEventListener.call(_this, element, eventName, handler); });
}
return _super.prototype.addEventListener.call(this, element, eventName, handler);
};
NgxBootstrapTreeviewEventManagerService.decorators = [
{ type: Injectable, args: [{
providedIn: 'root'
},] }
];
/** @nocollapse */
NgxBootstrapTreeviewEventManagerService.ctorParameters = function () { return [
{ type: Array, decorators: [{ type: Inject, args: [EVENT_MANAGER_PLUGINS,] }] },
{ type: NgZone }
]; };
/** @nocollapse */ NgxBootstrapTreeviewEventManagerService.ngInjectableDef = defineInjectable({ factory: function NgxBootstrapTreeviewEventManagerService_Factory() { return new NgxBootstrapTreeviewEventManagerService(inject(EVENT_MANAGER_PLUGINS), inject(NgZone)); }, token: NgxBootstrapTreeviewEventManagerService, providedIn: "root" });
return NgxBootstrapTreeviewEventManagerService;
}(EventManager));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var NgxBootstrapTreeviewModule = /** @class */ (function () {
function NgxBootstrapTreeviewModule() {
}
NgxBootstrapTreeviewModule.decorators = [
{ type: NgModule, args: [{
imports: [CommonModule, FontAwesomeModule, RouterModule.forChild([])],
declarations: [NgxBootstrapTreeviewComponent, NgxBootstrapTreeviewContextMenuComponent],
exports: [NgxBootstrapTreeviewComponent],
providers: [ContextMenuService, { provide: EventManager, useClass: NgxBootstrapTreeviewEventManagerService }]
},] }
];
return NgxBootstrapTreeviewModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var TreeMap = /** @class */ (function () {
function TreeMap() {
}
return TreeMap;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview adde