carbon-components-angular
Version:
Next generation components
182 lines • 16.8 kB
JavaScript
import { DOCUMENT } from "@angular/common";
import { Component, Input, Output, EventEmitter, Inject, ViewChild } from "@angular/core";
import { TreeViewService } from "./treeview.service";
import * as i0 from "@angular/core";
import * as i1 from "./treeview.service";
import * as i2 from "@angular/common";
import * as i3 from "./tree-node.component";
/**
* Get started with importing the module:
*
* ```typescript
* import { TreeviewModule } from 'carbon-components-angular';
* ```
*
* [See demo](../../?path=/story/components-tree-view--basic)
*/
export class TreeViewComponent {
constructor(document, treeViewService, elementRef) {
this.document = document;
this.treeViewService = treeViewService;
this.elementRef = elementRef;
this.id = `tree-view-${TreeViewComponent.treeViewCount++}`;
/**
* Specify the size of the list items in the tree
*/
this.size = "sm";
this.select = new EventEmitter();
this._tree = [];
}
/**
* Pass `Node[]` array to have tree view render the nodes
* Passing value will disregard projected content
*/
set tree(treeNodes) {
this._tree = treeNodes.map((node) => Object.assign({}, node));
this.treeViewService.contentProjected = false;
}
get tree() {
return this._tree;
}
/**
* **Experimental** - Enable to select multiple nodes
*/
set isMultiSelect(isMulti) {
this.treeViewService.isMultiSelect = isMulti;
}
/**
* Subscribe for node selection
*/
ngOnInit() {
this.subscription = this.treeViewService.selectionObservable.subscribe((nodesMap) => {
// Get all values from the map to emit
const nodes = [...nodesMap.values()];
// Update focus to reset arrow key traversal
// Select the current highlight node as the last node, since we preserve order in map
this.treeWalker.currentNode = this.elementRef.nativeElement.querySelector(`#${CSS.escape(nodes[nodes.length - 1].id)}`);
this.select.emit(this.treeViewService.isMultiSelect ? nodes : nodes[0]);
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
/**
* Initialize tree walker to support keyboard navigation
*/
ngAfterViewInit() {
this.treeWalker = this.document.createTreeWalker(this.root.nativeElement, NodeFilter.SHOW_ELEMENT, {
acceptNode: function (node) {
if (node.classList.contains(`cds--tree-node--disabled`)) {
return NodeFilter.FILTER_REJECT;
}
if (node.matches(`div.cds--tree-node`)) {
return NodeFilter.FILTER_ACCEPT;
}
return NodeFilter.FILTER_SKIP;
}
});
}
/**
* Navigate tree using tree walker
* @param event - KeyboardEvent
*/
navigateTree(event) {
if (event.key === "ArrowUp") {
this.treeWalker.previousNode()?.focus();
}
if (event.key === "ArrowDown") {
this.treeWalker.nextNode()?.focus();
}
}
isProjected() {
return this.treeViewService.contentProjected;
}
}
TreeViewComponent.treeViewCount = 0;
TreeViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TreeViewComponent, deps: [{ token: DOCUMENT }, { token: i1.TreeViewService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
TreeViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: TreeViewComponent, selector: "cds-tree-view", inputs: { tree: "tree", id: "id", label: "label", size: "size", isMultiSelect: "isMultiSelect" }, outputs: { select: "select" }, providers: [TreeViewService], viewQueries: [{ propertyName: "root", first: true, predicate: ["treeWrapper"], descendants: true }], ngImport: i0, template: `
<label
*ngIf="label"
[id]="id"
class="cds--label">
{{label}}
</label>
<div
class="cds--tree"
[ngClass]="{
'cds--tree--sm': size === 'sm',
'cds--tree--xs': size === 'xs'
}"
[attr.aria-label]="label ? label : null"
[attr.aria-labelledby]="!label ? id : null"
[attr.aria-multiselectable]="isMultiSelect || null"
role="tree"
(keydown)="navigateTree($event)"
#treeWrapper>
<ng-container *ngIf="isProjected(); else notProjected">
<ng-content></ng-content>
</ng-container>
<ng-template #notProjected>
<cds-tree-node
*ngFor="let node of tree"
[node]="node">
</cds-tree-node>
</ng-template>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.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: TreeViewComponent, decorators: [{
type: Component,
args: [{
selector: "cds-tree-view",
template: `
<label
*ngIf="label"
[id]="id"
class="cds--label">
{{label}}
</label>
<div
class="cds--tree"
[ngClass]="{
'cds--tree--sm': size === 'sm',
'cds--tree--xs': size === 'xs'
}"
[attr.aria-label]="label ? label : null"
[attr.aria-labelledby]="!label ? id : null"
[attr.aria-multiselectable]="isMultiSelect || null"
role="tree"
(keydown)="navigateTree($event)"
#treeWrapper>
<ng-container *ngIf="isProjected(); else notProjected">
<ng-content></ng-content>
</ng-container>
<ng-template #notProjected>
<cds-tree-node
*ngFor="let node of tree"
[node]="node">
</cds-tree-node>
</ng-template>
</div>
`,
providers: [TreeViewService]
}]
}], ctorParameters: function () { return [{ type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: i1.TreeViewService }, { type: i0.ElementRef }]; }, propDecorators: { tree: [{
type: Input
}], id: [{
type: Input
}], label: [{
type: Input
}], size: [{
type: Input
}], isMultiSelect: [{
type: Input
}], select: [{
type: Output
}], root: [{
type: ViewChild,
args: ["treeWrapper"]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZXZpZXcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RyZWV2aWV3L3RyZWV2aWV3LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUNOLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUVOLFlBQVksRUFFWixNQUFNLEVBQ04sU0FBUyxFQUlULE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7Ozs7QUFFckQ7Ozs7Ozs7O0dBUUc7QUFtQ0gsTUFBTSxPQUFPLGlCQUFpQjtJQXVDN0IsWUFDMkIsUUFBa0IsRUFDbEMsZUFBZ0MsRUFDbEMsVUFBc0I7UUFGSixhQUFRLEdBQVIsUUFBUSxDQUFVO1FBQ2xDLG9CQUFlLEdBQWYsZUFBZSxDQUFpQjtRQUNsQyxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBMUJ0QixPQUFFLEdBQUcsYUFBYSxpQkFBaUIsQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDO1FBSy9EOztXQUVHO1FBQ00sU0FBSSxHQUFnQixJQUFJLENBQUM7UUFReEIsV0FBTSxHQUFHLElBQUksWUFBWSxFQUFpQixDQUFDO1FBSTdDLFVBQUssR0FBVyxFQUFFLENBQUM7SUFPeEIsQ0FBQztJQTFDSjs7O09BR0c7SUFDSCxJQUFhLElBQUksQ0FBQyxTQUFpQjtRQUNsQyxJQUFJLENBQUMsS0FBSyxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7SUFDL0MsQ0FBQztJQUVELElBQUksSUFBSTtRQUNQLE9BQU8sSUFBSSxD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QUFLO2dCQUlHLElBQUk7c0JBQVosS0FBSztnQkFJTyxhQUFhO3NCQUF6QixLQUFLO2dCQUlJLE1BQU07c0JBQWYsTUFBTTtnQkFDbUIsSUFBSTtzQkFBN0IsU0FBUzt1QkFBQyxhQUFhIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uXCI7XG5pbXBvcnQge1xuXHRDb21wb25lbnQsXG5cdElucHV0LFxuXHRPdXRwdXQsXG5cdFRlbXBsYXRlUmVmLFxuXHRFdmVudEVtaXR0ZXIsXG5cdEFmdGVyVmlld0luaXQsXG5cdEluamVjdCxcblx0Vmlld0NoaWxkLFxuXHRFbGVtZW50UmVmLFxuXHRPbkluaXQsXG5cdE9uRGVzdHJveVxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IE5vZGUgfSBmcm9tIFwiLi90cmVlLW5vZGUudHlwZXNcIjtcbmltcG9ydCB7IFRyZWVWaWV3U2VydmljZSB9IGZyb20gXCIuL3RyZWV2aWV3LnNlcnZpY2VcIjtcblxuLyoqXG4gKiBHZXQgc3RhcnRlZCB3aXRoIGltcG9ydGluZyB0aGUgbW9kdWxlOlxuICpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IFRyZWV2aWV3TW9kdWxlIH0gZnJvbSAnY2FyYm9uLWNvbXBvbmVudHMtYW5ndWxhcic7XG4gKiBgYGBcbiAqXG4gKiBbU2VlIGRlbW9dKC4uLy4uLz9wYXRoPS9zdG9yeS9jb21wb25lbnRzLXRyZWUtdmlldy0tYmFzaWMpXG4gKi9cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogXCJjZHMtdHJlZS12aWV3XCIsXG5cdHRlbXBsYXRlOiBgXG5cdFx0PGxhYmVsXG5cdFx0XHQqbmdJZj1cImxhYmVsXCJcblx0XHRcdFtpZF09XCJpZFwiXG5cdFx0XHRjbGFzcz1cImNkcy0tbGFiZWxcIj5cblx0XHRcdHt7bGFiZWx9fVxuXHRcdDwvbGFiZWw+XG5cdFx0PGRpdlxuXHRcdFx0Y2xhc3M9XCJjZHMtLXRyZWVcIlxuXHRcdFx0W25nQ2xhc3NdPVwie1xuXHRcdFx0XHQnY2RzLS10cmVlLS1zbSc6IHNpemUgPT09ICdzbScsXG5cdFx0XHRcdCdjZHMtLXRyZWUtLXhzJzogc2l6ZSA9PT0gJ3hzJ1xuXHRcdFx0fVwiXG5cdFx0XHRbYXR0ci5hcmlhLWxhYmVsXT1cImxhYmVsID8gbGFiZWwgOiBudWxsXCJcblx0XHRcdFthdHRyLmFyaWEtbGFiZWxsZWRieV09XCIhbGFiZWwgPyBpZCA6IG51bGxcIlxuXHRcdFx0W2F0dHIuYXJpYS1tdWx0aXNlbGVjdGFibGVdPVwiaXNNdWx0aVNlbGVjdCB8fCBudWxsXCJcblx0XHRcdHJvbGU9XCJ0cmVlXCJcblx0XHRcdChrZXlkb3duKT1cIm5hdmlnYXRlVHJlZSgkZXZlbnQpXCJcblx0XHRcdCN0cmVlV3JhcHBlcj5cblx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCJpc1Byb2plY3RlZCgpOyBlbHNlIG5vdFByb2plY3RlZFwiPlxuXHRcdFx0XHQ8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG5cdFx0XHQ8L25nLWNvbnRhaW5lcj5cblx0XHRcdDxuZy10ZW1wbGF0ZSAjbm90UHJvamVjdGVkPlxuXHRcdFx0XHQ8Y2RzLXRyZWUtbm9kZVxuXHRcdFx0XHRcdCpuZ0Zvcj1cImxldCBub2RlIG9mIHRyZWVcIlxuXHRcdFx0XHRcdFtub2RlXT1cIm5vZGVcIj5cblx0XHRcdFx0PC9jZHMtdHJlZS1ub2RlPlxuXHRcdFx0PC9uZy10ZW1wbGF0ZT5cblx0XHQ8L2Rpdj5cblx0YCxcblx0cHJvdmlkZXJzOiBbVHJlZVZpZXdTZXJ2aWNlXVxufSlcbmV4cG9ydCBjbGFzcyBUcmVlVmlld0NvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uSW5pdCwgT25EZXN0cm95IHtcblx0LyoqXG5cdCAqIFBhc3MgYE5vZGVbXWAgYXJyYXkgdG8gaGF2ZSB0cmVlIHZpZXcgcmVuZGVyIHRoZSBub2Rlc1xuXHQgKiBQYXNzaW5nIHZhbHVlIHdpbGwgZGlzcmVnYXJkIHByb2plY3RlZCBjb250ZW50XG5cdCAqL1xuXHRASW5wdXQoKSBzZXQgdHJlZSh0cmVlTm9kZXM6IE5vZGVbXSkge1xuXHRcdHRoaXMuX3RyZWUgPSB0cmVlTm9kZXMubWFwKChub2RlKSA9PiBPYmplY3QuYXNzaWduKHt9LCBub2RlKSk7XG5cdFx0dGhpcy50cmVlVmlld1NlcnZpY2UuY29udGVudFByb2plY3RlZCA9IGZhbHNlO1xuXHR9XG5cblx0Z2V0IHRyZWUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3RyZWU7XG5cdH1cblxuXHRzdGF0aWMgdHJlZVZpZXdDb3VudCA9IDA7XG5cblx0QElucHV0KCkgaWQgPSBgdHJlZS12aWV3LSR7VHJlZVZpZXdDb21wb25lbnQudHJlZVZpZXdDb3VudCsrfWA7XG5cdC8qKlxuXHQgKiBUcmVlIHZpZXcgbGFiZWxcblx0ICovXG5cdEBJbnB1dCgpIGxhYmVsOiBzdHJpbmcgfCBUZW1wbGF0ZVJlZjxhbnk+O1xuXHQvKipcblx0ICogU3BlY2lmeSB0aGUgc2l6ZSBvZiB0aGUgbGlzdCBpdGVtcyBpbiB0aGUgdHJlZVxuXHQgKi9cblx0QElucHV0KCkgc2l6ZTogXCJ4c1wiIHwgXCJzbVwiID0gXCJzbVwiO1xuXHQvKipcblx0ICogKipFeHBlcmltZW50YWwqKiAtIEVuYWJsZSB0byBzZWxlY3QgbXVsdGlwbGUgbm9kZXNcblx0ICovXG5cdEBJbnB1dCgpIHNldCBpc011bHRpU2VsZWN0KGlzTXVsdGk6IGJvb2xlYW4pIHtcblx0XHR0aGlzLnRyZWVWaWV3U2VydmljZS5pc011bHRpU2VsZWN0ID0gaXNNdWx0aTtcblx0fVxuXG5cdEBPdXRwdXQoKSBzZWxlY3QgPSBuZXcgRXZlbnRFbWl0dGVyPE5vZGUgfCBOb2RlW10+KCk7XG5cdEBWaWV3Q2hpbGQoXCJ0cmVlV3JhcHBlclwiKSByb290OiBFbGVtZW50UmVmO1xuXG5cdHByaXZhdGUgdHJlZVdhbGtlcjogVHJlZVdhbGtlcjtcblx0cHJpdmF0ZSBfdHJlZTogTm9kZVtdID0gW107XG5cdHByaXZhdGUgc3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb247XG5cblx0Y29uc3RydWN0b3IoXG5cdFx0QEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQsXG5cdFx0cHJvdGVjdGVkIHRyZWVWaWV3U2VydmljZTogVHJlZVZpZXdTZXJ2aWNlLFxuXHRcdHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZlxuXHQpIHt9XG5cblx0LyoqXG5cdCAqIFN1YnNjcmliZSBmb3Igbm9kZSBzZWxlY3Rpb25cblx0ICovXG5cdG5nT25Jbml0KCk6IHZvaWQge1xuXHRcdHRoaXMuc3Vic2NyaXB0aW9uID0gdGhpcy50cmVlVmlld1NlcnZpY2Uuc2VsZWN0aW9uT2JzZXJ2YWJsZS5zdWJzY3JpYmUoKG5vZGVzTWFwOiBNYXA8c3RyaW5nLCBOb2RlPikgPT4ge1xuXHRcdFx0Ly8gR2V0IGFsbCB2YWx1ZXMgZnJvbSB0aGUgbWFwIHRvIGVtaXRcblx0XHRcdGNvbnN0IG5vZGVzID0gWy4uLm5vZGVzTWFwLnZhbHVlcygpXTtcblxuXHRcdFx0Ly8gVXBkYXRlIGZvY3VzIHRvIHJlc2V0IGFycm93IGtleSB0cmF2ZXJzYWxcblx0XHRcdC8vIFNlbGVjdCB0aGUgY3VycmVudCBoaWdobGlnaHQgbm9kZSBhcyB0aGUgbGFzdCBub2RlLCBzaW5jZSB3ZSBwcmVzZXJ2ZSBvcmRlciBpbiBtYXBcblx0XHRcdHRoaXMudHJlZVdhbGtlci5jdXJyZW50Tm9kZSA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoYCMke0NTUy5lc2NhcGUobm9kZXNbbm9kZXMubGVuZ3RoIC0gMV0uaWQpfWApO1xuXHRcdFx0dGhpcy5zZWxlY3QuZW1pdCh0aGlzLnRyZWVWaWV3U2VydmljZS5pc011bHRpU2VsZWN0ID8gbm9kZXMgOiBub2Rlc1swXSk7XG5cdFx0fSk7XG5cdH1cblxuXHRuZ09uRGVzdHJveSgpOiB2b2lkIHtcblx0XHR0aGlzLnN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEluaXRpYWxpemUgdHJlZSB3YWxrZXIgdG8gc3VwcG9ydCBrZXlib2FyZCBuYXZpZ2F0aW9uXG5cdCAqL1xuXHRuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG5cdFx0dGhpcy50cmVlV2Fsa2VyID0gdGhpcy5kb2N1bWVudC5jcmVhdGVUcmVlV2Fsa2VyKHRoaXMucm9vdC5uYXRpdmVFbGVtZW50LCBOb2RlRmlsdGVyLlNIT1dfRUxFTUVOVCwge1xuXHRcdFx0YWNjZXB0Tm9kZTogZnVuY3Rpb24gKG5vZGU6IEhUTUxFbGVtZW50KSB7XG5cdFx0XHRcdGlmIChub2RlLmNsYXNzTGlzdC5jb250YWlucyhgY2RzLS10cmVlLW5vZGUtLWRpc2FibGVkYCkpIHtcblx0XHRcdFx0XHRyZXR1cm4gTm9kZUZpbHRlci5GSUxURVJfUkVKRUNUO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChub2RlLm1hdGNoZXMoYGRpdi5jZHMtLXRyZWUtbm9kZWApKSB7XG5cdFx0XHRcdFx0cmV0dXJuIE5vZGVGaWx0ZXIuRklMVEVSX0FDQ0VQVDtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gTm9kZUZpbHRlci5GSUxURVJfU0tJUDtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBOYXZpZ2F0ZSB0cmVlIHVzaW5nIHRyZWUgd2Fsa2VyXG5cdCAqIEBwYXJhbSBldmVudCAtIEtleWJvYXJkRXZlbnRcblx0ICovXG5cdG5hdmlnYXRlVHJlZShldmVudDogS2V5Ym9hcmRFdmVudCkge1xuXHRcdGlmIChldmVudC5rZXkgPT09IFwiQXJyb3dVcFwiKSB7XG5cdFx0XHQodGhpcy50cmVlV2Fsa2VyLnByZXZpb3VzTm9kZSgpIGFzIEhUTUxFbGVtZW50KT8uZm9jdXMoKTtcblx0XHR9XG5cblx0XHRpZiAoZXZlbnQua2V5ID09PSBcIkFycm93RG93blwiKSB7XG5cdFx0XHQodGhpcy50cmVlV2Fsa2VyLm5leHROb2RlKCkgYXMgSFRNTEVsZW1lbnQpPy5mb2N1cygpO1xuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBpc1Byb2plY3RlZCgpIHtcblx0XHRyZXR1cm4gdGhpcy50cmVlVmlld1NlcnZpY2UuY29udGVudFByb2plY3RlZDtcblx0fVxufVxuIl19