UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

281 lines (280 loc) • 9 kB
import { Component, Element, Prop, Host, Event, Listen, h } from "@stencil/core"; import { nodeListToArray } from "../../utils/dom"; import { TreeSelectionMode } from "./interfaces"; export class CalciteTree { constructor() { //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- /** Display indentation guide lines */ this.lines = false; /** Specify the scale of the tree, defaults to m */ this.scale = "m"; /** Customize how tree selection works (single, multi, children, multi-children) */ this.selectionMode = TreeSelectionMode.Single; //-------------------------------------------------------------------------- // // Public Methods // //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // // Private State/Props // //-------------------------------------------------------------------------- /** @internal If this tree is nested within another tree, set to false */ this.root = true; } //-------------------------------------------------------------------------- // // Lifecycle // //-------------------------------------------------------------------------- componentWillRender() { const parent = this.el.parentElement.closest("calcite-tree"); // this.theme = getElementTheme(this.el); this.lines = parent ? parent.lines : this.lines; this.scale = parent ? parent.scale : this.scale; this.selectionMode = parent ? parent.selectionMode : this.selectionMode; this.root = parent ? false : true; } render() { return (h(Host, { "aria-multiselectable": this.selectionMode === TreeSelectionMode.Multi || this.selectionMode === TreeSelectionMode.MultiChildren, role: this.root ? "tree" : undefined, tabindex: this.root ? "0" : undefined }, h("slot", null))); } //-------------------------------------------------------------------------- // // Event Listeners // //-------------------------------------------------------------------------- onFocus() { if (this.root) { const selectedNode = this.el.querySelector("calcite-tree-item[selected]"); const firstNode = this.el.querySelector("calcite-tree-item"); (selectedNode || firstNode).focus(); } } onClick(e) { const target = e.target; const childItems = nodeListToArray(target.querySelectorAll("calcite-tree-item")); const shouldSelect = this.selectionMode !== null && (!target.hasChildren || (target.hasChildren && (this.selectionMode === TreeSelectionMode.Children || this.selectionMode === TreeSelectionMode.MultiChildren))); const shouldModifyToCurrentSelection = e.detail.modifyCurrentSelection && (this.selectionMode === TreeSelectionMode.Multi || this.selectionMode === TreeSelectionMode.MultiChildren); const shouldSelectChildren = this.selectionMode === TreeSelectionMode.MultiChildren || this.selectionMode === TreeSelectionMode.Children; const shouldClearCurrentSelection = !shouldModifyToCurrentSelection && (((this.selectionMode === TreeSelectionMode.Single || this.selectionMode === TreeSelectionMode.Multi) && childItems.length <= 0) || this.selectionMode === TreeSelectionMode.Children || this.selectionMode === TreeSelectionMode.MultiChildren); const shouldExpandTarget = this.selectionMode === TreeSelectionMode.Children || this.selectionMode === TreeSelectionMode.MultiChildren; if (this.root) { const targetItems = []; if (shouldSelect) { targetItems.push(target); } if (shouldSelectChildren) { childItems.forEach((treeItem) => { targetItems.push(treeItem); }); } if (shouldClearCurrentSelection) { const selectedItems = nodeListToArray(this.el.querySelectorAll("calcite-tree-item[selected]")); selectedItems.forEach((treeItem) => { if (!targetItems.includes(treeItem)) { treeItem.selected = false; } }); } if (shouldExpandTarget && !e.detail.forceToggle) { target.expanded = true; } if (shouldModifyToCurrentSelection) { window.getSelection().removeAllRanges(); } if ((shouldModifyToCurrentSelection && target.selected) || (shouldSelectChildren && e.detail.forceToggle)) { targetItems.forEach((treeItem) => { treeItem.selected = false; }); } else { targetItems.forEach((treeItem) => { treeItem.selected = true; }); } } if (this.root) { e.preventDefault(); e.stopPropagation(); } this.calciteTreeSelect.emit({ selected: nodeListToArray(this.el.querySelectorAll("calcite-tree-item")).filter((i) => i.selected) }); } static get is() { return "calcite-tree"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["calcite-tree.scss"] }; } static get styleUrls() { return { "$": ["calcite-tree.css"] }; } static get properties() { return { "lines": { "type": "boolean", "mutable": true, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Display indentation guide lines" }, "attribute": "lines", "reflect": true, "defaultValue": "false" }, "theme": { "type": "string", "mutable": false, "complexType": { "original": "Theme", "resolved": "\"dark\" | \"light\"", "references": { "Theme": { "location": "import", "path": "../interfaces" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "Select theme (light or dark)" }, "attribute": "theme", "reflect": true }, "scale": { "type": "string", "mutable": true, "complexType": { "original": "Extract<\"s\" | \"m\", Scale>", "resolved": "\"m\" | \"s\"", "references": { "Extract": { "location": "global" }, "Scale": { "location": "import", "path": "../interfaces" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specify the scale of the tree, defaults to m" }, "attribute": "scale", "reflect": true, "defaultValue": "\"m\"" }, "selectionMode": { "type": "string", "mutable": true, "complexType": { "original": "TreeSelectionMode", "resolved": "TreeSelectionMode.Children | TreeSelectionMode.Multi | TreeSelectionMode.MultiChildren | TreeSelectionMode.Single", "references": { "TreeSelectionMode": { "location": "import", "path": "./interfaces" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "Customize how tree selection works (single, multi, children, multi-children)" }, "attribute": "selection-mode", "reflect": true, "defaultValue": "TreeSelectionMode.Single" }, "root": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [{ "text": "If this tree is nested within another tree, set to false", "name": "internal" }], "text": "" }, "attribute": "root", "reflect": true, "defaultValue": "true" } }; } static get events() { return [{ "method": "calciteTreeSelect", "name": "calciteTreeSelect", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "" }, "complexType": { "original": "TreeSelectDetail", "resolved": "TreeSelectDetail", "references": { "TreeSelectDetail": { "location": "import", "path": "./interfaces" } } } }]; } static get elementRef() { return "el"; } static get listeners() { return [{ "name": "focus", "method": "onFocus", "target": undefined, "capture": false, "passive": false }, { "name": "calciteTreeItemSelect", "method": "onClick", "target": undefined, "capture": false, "passive": false }]; } }