tree-element 0.3.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +23 -20
  2. package/lib/classNames.js +4 -4
  3. package/lib/classNames.js.map +1 -1
  4. package/lib/dataLoader.d.ts +0 -1
  5. package/lib/dataLoader.d.ts.map +1 -1
  6. package/lib/dataLoader.js +10 -7
  7. package/lib/dataLoader.js.map +1 -1
  8. package/lib/dragAndDropHandler/generateHitAreas.d.ts.map +1 -1
  9. package/lib/dragAndDropHandler/generateHitAreas.js +3 -2
  10. package/lib/dragAndDropHandler/generateHitAreas.js.map +1 -1
  11. package/lib/dragAndDropHandler/index.d.ts +2 -4
  12. package/lib/dragAndDropHandler/index.d.ts.map +1 -1
  13. package/lib/dragAndDropHandler/index.js +2 -9
  14. package/lib/dragAndDropHandler/index.js.map +1 -1
  15. package/lib/elementsRenderer.d.ts +11 -4
  16. package/lib/elementsRenderer.d.ts.map +1 -1
  17. package/lib/elementsRenderer.js +104 -43
  18. package/lib/elementsRenderer.js.map +1 -1
  19. package/lib/events.d.ts +13 -7
  20. package/lib/events.d.ts.map +1 -1
  21. package/lib/folderOpenState.d.ts +8 -0
  22. package/lib/folderOpenState.d.ts.map +1 -0
  23. package/lib/folderOpenState.js +22 -0
  24. package/lib/folderOpenState.js.map +1 -0
  25. package/lib/index.d.ts +27 -20
  26. package/lib/index.d.ts.map +1 -1
  27. package/lib/index.js +166 -65
  28. package/lib/index.js.map +1 -1
  29. package/lib/keyHandler.d.ts +16 -3
  30. package/lib/keyHandler.d.ts.map +1 -1
  31. package/lib/keyHandler.js +79 -32
  32. package/lib/keyHandler.js.map +1 -1
  33. package/lib/methodTypes.d.ts +3 -0
  34. package/lib/methodTypes.d.ts.map +1 -1
  35. package/lib/mouseHandler.d.ts.map +1 -1
  36. package/lib/mouseHandler.js +12 -12
  37. package/lib/mouseHandler.js.map +1 -1
  38. package/lib/node.d.ts +12 -10
  39. package/lib/node.d.ts.map +1 -1
  40. package/lib/node.js +12 -10
  41. package/lib/node.js.map +1 -1
  42. package/lib/nodeElement/folderElement.d.ts +7 -5
  43. package/lib/nodeElement/folderElement.d.ts.map +1 -1
  44. package/lib/nodeElement/folderElement.js +35 -55
  45. package/lib/nodeElement/folderElement.js.map +1 -1
  46. package/lib/nodeElement/index.d.ts +3 -2
  47. package/lib/nodeElement/index.d.ts.map +1 -1
  48. package/lib/nodeElement/index.js +15 -12
  49. package/lib/nodeElement/index.js.map +1 -1
  50. package/lib/options.d.ts +29 -14
  51. package/lib/options.d.ts.map +1 -1
  52. package/lib/options.js +12 -0
  53. package/lib/options.js.map +1 -0
  54. package/lib/saveStateHandler.d.ts.map +1 -1
  55. package/lib/saveStateHandler.js +6 -6
  56. package/lib/saveStateHandler.js.map +1 -1
  57. package/lib/selectNodeHandler.d.ts +3 -0
  58. package/lib/selectNodeHandler.d.ts.map +1 -1
  59. package/lib/selectNodeHandler.js +66 -22
  60. package/lib/selectNodeHandler.js.map +1 -1
  61. package/lib/setDefaultOptions.d.ts.map +1 -1
  62. package/lib/setDefaultOptions.js +1 -0
  63. package/lib/setDefaultOptions.js.map +1 -1
  64. package/lib/version.d.ts +1 -1
  65. package/lib/version.js +1 -1
  66. package/lib/version.js.map +1 -1
  67. package/package.json +38 -32
  68. package/src/classNames.ts +4 -4
  69. package/src/dataLoader.ts +9 -10
  70. package/src/dragAndDropHandler/generateHitAreas.ts +3 -2
  71. package/src/dragAndDropHandler/index.ts +3 -17
  72. package/src/elementsRenderer.ts +124 -55
  73. package/src/events.ts +13 -7
  74. package/src/folderOpenState.ts +38 -0
  75. package/src/index.ts +191 -82
  76. package/src/keyHandler.ts +104 -34
  77. package/src/methodTypes.ts +6 -0
  78. package/src/mouseHandler.ts +15 -13
  79. package/src/node.ts +12 -10
  80. package/src/nodeElement/folderElement.ts +47 -72
  81. package/src/nodeElement/index.ts +20 -17
  82. package/src/options.ts +46 -14
  83. package/src/saveStateHandler.ts +5 -8
  84. package/src/selectNodeHandler.ts +69 -25
  85. package/src/setDefaultOptions.ts +1 -0
  86. package/src/version.ts +1 -1
  87. package/tree_element.css +48 -5
  88. package/tree_element.debug.js +540 -278
  89. package/tree_element.debug.js.map +1 -1
  90. package/tree_element.js +2 -2
  91. package/tree_element.js.map +1 -1
@@ -75,9 +75,9 @@ class SelectNodeHandler {
75
75
  } else {
76
76
  this._selectedNodes.delete(node.id);
77
77
  if (includeChildren) {
78
- node.iterate(() => {
79
- if (node.id != null) {
80
- this._selectedNodes.delete(node.id);
78
+ node.iterate(child => {
79
+ if (child.id != null) {
80
+ this._selectedNodes.delete(child.id);
81
81
  }
82
82
  return true;
83
83
  });
@@ -96,6 +96,9 @@ class SelectNodeHandler {
96
96
  * mustToggle: support deselecting the selected node
97
97
  */
98
98
  _selectSingleNode(node, optionsParam) {
99
+ if (!this._canSelect(node)) {
100
+ return;
101
+ }
99
102
  let defaultOptions = {
100
103
  mustSetFocus: true,
101
104
  mustToggle: true
@@ -104,35 +107,39 @@ class SelectNodeHandler {
104
107
  ...defaultOptions,
105
108
  ...optionsParam
106
109
  };
107
- let canSelect = () => {
108
- if (!this._getSelectable()) {
109
- return false;
110
- }
111
- let onCanSelectNode = this._getOnCanSelectNode();
112
- return onCanSelectNode ? onCanSelectNode(node) : true;
113
- };
114
- if (!canSelect()) {
115
- return;
116
- }
117
- let deselectCurrentNode = deselectedNode => {
118
- this._removeFromSelection(deselectedNode);
119
- this._getNodeElementForNode(deselectedNode)._deselect();
120
- };
110
+ let otherSelectedNodes = this._getSelectedNodes().filter(selectedNode => selectedNode !== node);
121
111
  if (this._isNodeSelected(node)) {
122
- if (selectOptions.mustToggle) {
123
- deselectCurrentNode(node);
112
+ if (otherSelectedNodes.length) {
113
+ // Part of a multiple selection: keep only this node selected
114
+ for (let otherNode of otherSelectedNodes) {
115
+ this._deselectNode(otherNode);
116
+ }
117
+ for (let otherNode of otherSelectedNodes) {
118
+ this._triggerEvent("tree.deselect", {
119
+ node: otherNode
120
+ });
121
+ }
122
+ } else if (selectOptions.mustToggle) {
123
+ this._deselectNode(node);
124
124
  this._triggerEvent("tree.deselect", {
125
125
  node
126
126
  });
127
127
  }
128
128
  } else {
129
- let deselectedNode = this._getSelectedNode();
130
- if (deselectedNode) {
131
- deselectCurrentNode(deselectedNode);
129
+ // tree.select reports the first deselected node; the others, from a
130
+ // multiple selection, get a tree.deselect.
131
+ let [deselectedNode = null, ...alsoDeselectedNodes] = otherSelectedNodes;
132
+ for (let otherNode of otherSelectedNodes) {
133
+ this._deselectNode(otherNode);
132
134
  }
133
135
  this._addToSelection(node);
134
136
  this._openParents(node);
135
137
  this._getNodeElementForNode(node)._select(selectOptions.mustSetFocus);
138
+ for (let otherNode of alsoDeselectedNodes) {
139
+ this._triggerEvent("tree.deselect", {
140
+ node: otherNode
141
+ });
142
+ }
136
143
  this._triggerEvent("tree.select", {
137
144
  deselectedNode,
138
145
  node
@@ -141,6 +148,43 @@ class SelectNodeHandler {
141
148
  this._updateTabStop();
142
149
  this._saveState();
143
150
  }
151
+
152
+ /* Add a node to the selection, or remove it when it is selected, without
153
+ * changing the other selected nodes.
154
+ * Checks if the node is selectable and saves the state.
155
+ */
156
+ _toggleNodeInSelection(node, mustSetFocus = true) {
157
+ if (!this._canSelect(node)) {
158
+ return;
159
+ }
160
+ if (this._isNodeSelected(node)) {
161
+ this._deselectNode(node);
162
+ this._triggerEvent("tree.deselect", {
163
+ node
164
+ });
165
+ } else {
166
+ this._addToSelection(node);
167
+ this._openParents(node);
168
+ this._getNodeElementForNode(node)._select(mustSetFocus);
169
+ this._triggerEvent("tree.select", {
170
+ deselectedNode: null,
171
+ node
172
+ });
173
+ }
174
+ this._updateTabStop();
175
+ this._saveState();
176
+ }
177
+ _canSelect(node) {
178
+ if (!this._getSelectable()) {
179
+ return false;
180
+ }
181
+ let onCanSelectNode = this._getOnCanSelectNode();
182
+ return onCanSelectNode ? onCanSelectNode(node) : true;
183
+ }
184
+ _deselectNode(node) {
185
+ this._removeFromSelection(node);
186
+ this._getNodeElementForNode(node)._deselect();
187
+ }
144
188
  }
145
189
 
146
190
  export { SelectNodeHandler as default };
@@ -1 +1 @@
1
- {"version":3,"file":"selectNodeHandler.js","sources":["../src/selectNodeHandler.ts"],"sourcesContent":["import type {\n GetNodeById,\n GetNodeElementForNode,\n OpenParents,\n TriggerEvent,\n} from \"./methodTypes\";\nimport type { Node, NodeId } from \"./node\";\nimport type { OnCanSelectNode } from \"./options\";\n\nexport interface SelectNodeOptions {\n mustSetFocus?: boolean;\n mustToggle?: boolean;\n}\n\ninterface SelectNodeHandlerParameters {\n getNodeById: GetNodeById;\n getNodeElementForNode: GetNodeElementForNode;\n getOnCanSelectNode: () => OnCanSelectNode | undefined;\n getSelectable: () => boolean;\n openParents: OpenParents;\n saveState: () => void;\n triggerEvent: TriggerEvent;\n updateTabStop: () => void;\n}\n\nexport default class SelectNodeHandler {\n private getNodeById: GetNodeById;\n private getNodeElementForNode: GetNodeElementForNode;\n private getOnCanSelectNode: () => OnCanSelectNode | undefined;\n private getSelectable: () => boolean;\n private openParents: OpenParents;\n private saveState: () => void;\n private selectedNodes: Set<NodeId>;\n private selectedSingleNode: Node | null;\n private triggerEvent: TriggerEvent;\n private updateTabStop: () => void;\n\n constructor({\n getNodeById,\n getNodeElementForNode,\n getOnCanSelectNode,\n getSelectable,\n openParents,\n saveState,\n triggerEvent,\n updateTabStop,\n }: SelectNodeHandlerParameters) {\n this.getNodeById = getNodeById;\n this.getNodeElementForNode = getNodeElementForNode;\n this.getOnCanSelectNode = getOnCanSelectNode;\n this.getSelectable = getSelectable;\n this.openParents = openParents;\n this.saveState = saveState;\n this.selectedNodes = new Set<NodeId>();\n this.selectedSingleNode = null;\n this.triggerEvent = triggerEvent;\n this.updateTabStop = updateTabStop;\n }\n\n public addToSelection(node: Node): void {\n if (node.id == null) {\n this.selectedSingleNode = node;\n } else {\n this.selectedNodes.add(node.id);\n }\n }\n\n public clear(): void {\n this.selectedNodes.clear();\n this.selectedSingleNode = null;\n }\n\n public getSelectedNode(): Node | null {\n const selectedNodes = this.getSelectedNodes();\n\n return selectedNodes.length ? (selectedNodes[0] ?? null) : null;\n }\n\n public getSelectedNodes(): Node[] {\n if (this.selectedSingleNode) {\n return [this.selectedSingleNode];\n }\n\n const selectedNodes: Node[] = [];\n\n this.selectedNodes.forEach((id) => {\n const node = this.getNodeById(id);\n if (node) {\n selectedNodes.push(node);\n }\n });\n\n return selectedNodes;\n }\n\n public getSelectedNodesUnder(parent: Node): Node[] {\n if (this.selectedSingleNode) {\n return parent.isParentOf(this.selectedSingleNode)\n ? [this.selectedSingleNode]\n : [];\n }\n\n const selectedNodes: Node[] = [];\n\n this.selectedNodes.forEach((id) => {\n const node = this.getNodeById(id);\n if (node && parent.isParentOf(node)) {\n selectedNodes.push(node);\n }\n });\n\n return selectedNodes;\n }\n\n public isNodeSelected(node: Node): boolean {\n if (node.id != null) {\n return this.selectedNodes.has(node.id);\n }\n return this.selectedSingleNode ? this.selectedSingleNode === node : false;\n }\n\n public removeFromSelection(node: Node, includeChildren = false): void {\n if (node.id == null) {\n if (this.selectedSingleNode === node) {\n this.selectedSingleNode = null;\n }\n } else {\n this.selectedNodes.delete(node.id);\n\n if (includeChildren) {\n node.iterate(() => {\n if (node.id != null) {\n this.selectedNodes.delete(node.id);\n }\n return true;\n });\n }\n }\n }\n\n /* Select a single node.\n * Renders the changed elements.\n * Deselects if the node is currently selected (if the mustToggle is on).\n * Deselects the previously selected node.\n * Check if the node is selectable.\n * Saves the state.\n * Options:\n * mustSetFocus: set the focus to the selected node\n * mustToggle: support deselecting the selected node\n */\n public selectSingleNode(node: Node, optionsParam?: SelectNodeOptions) {\n const defaultOptions = { mustSetFocus: true, mustToggle: true };\n const selectOptions = { ...defaultOptions, ...optionsParam };\n\n const canSelect = (): boolean => {\n if (!this.getSelectable()) {\n return false;\n }\n\n const onCanSelectNode = this.getOnCanSelectNode();\n return onCanSelectNode ? onCanSelectNode(node) : true;\n };\n\n if (!canSelect()) {\n return;\n }\n\n const deselectCurrentNode = (deselectedNode: Node) => {\n this.removeFromSelection(deselectedNode);\n this.getNodeElementForNode(deselectedNode).deselect();\n };\n\n if (this.isNodeSelected(node)) {\n if (selectOptions.mustToggle) {\n deselectCurrentNode(node);\n this.triggerEvent(\"tree.deselect\", { node });\n }\n } else {\n const deselectedNode = this.getSelectedNode();\n\n if (deselectedNode) {\n deselectCurrentNode(deselectedNode);\n }\n\n this.addToSelection(node);\n this.openParents(node);\n this.getNodeElementForNode(node).select(selectOptions.mustSetFocus);\n\n this.triggerEvent(\"tree.select\", {\n deselectedNode,\n node,\n });\n }\n\n this.updateTabStop();\n this.saveState();\n }\n}\n"],"names":["getNodeById","getNodeElementForNode","getOnCanSelectNode","getSelectable","openParents","saveState","selectedNodes","selectedSingleNode","triggerEvent","updateTabStop","addToSelection","clear","getSelectedNode","getSelectedNodes","getSelectedNodesUnder","isNodeSelected","removeFromSelection","selectSingleNode","deselect","select"],"mappings":"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"}
1
+ {"version":3,"file":"selectNodeHandler.js","sources":["../src/selectNodeHandler.ts"],"sourcesContent":["import type {\n GetNodeById,\n GetNodeElementForNode,\n OpenParents,\n TriggerEvent,\n} from \"./methodTypes\";\nimport type { Node, NodeId } from \"./node\";\nimport type { OnCanSelectNode } from \"./options\";\n\nexport interface SelectNodeOptions {\n mustSetFocus?: boolean;\n mustToggle?: boolean;\n}\n\ninterface SelectNodeHandlerParameters {\n getNodeById: GetNodeById;\n getNodeElementForNode: GetNodeElementForNode;\n getOnCanSelectNode: () => OnCanSelectNode | undefined;\n getSelectable: () => boolean;\n openParents: OpenParents;\n saveState: () => void;\n triggerEvent: TriggerEvent;\n updateTabStop: () => void;\n}\n\nexport default class SelectNodeHandler {\n private getNodeById: GetNodeById;\n private getNodeElementForNode: GetNodeElementForNode;\n private getOnCanSelectNode: () => OnCanSelectNode | undefined;\n private getSelectable: () => boolean;\n private openParents: OpenParents;\n private saveState: () => void;\n private selectedNodes: Set<NodeId>;\n private selectedSingleNode: Node | null;\n private triggerEvent: TriggerEvent;\n private updateTabStop: () => void;\n\n constructor({\n getNodeById,\n getNodeElementForNode,\n getOnCanSelectNode,\n getSelectable,\n openParents,\n saveState,\n triggerEvent,\n updateTabStop,\n }: SelectNodeHandlerParameters) {\n this.getNodeById = getNodeById;\n this.getNodeElementForNode = getNodeElementForNode;\n this.getOnCanSelectNode = getOnCanSelectNode;\n this.getSelectable = getSelectable;\n this.openParents = openParents;\n this.saveState = saveState;\n this.selectedNodes = new Set<NodeId>();\n this.selectedSingleNode = null;\n this.triggerEvent = triggerEvent;\n this.updateTabStop = updateTabStop;\n }\n\n public addToSelection(node: Node): void {\n if (node.id == null) {\n this.selectedSingleNode = node;\n } else {\n this.selectedNodes.add(node.id);\n }\n }\n\n public clear(): void {\n this.selectedNodes.clear();\n this.selectedSingleNode = null;\n }\n\n public getSelectedNode(): Node | null {\n const selectedNodes = this.getSelectedNodes();\n\n return selectedNodes.length ? (selectedNodes[0] ?? null) : null;\n }\n\n public getSelectedNodes(): Node[] {\n if (this.selectedSingleNode) {\n return [this.selectedSingleNode];\n }\n\n const selectedNodes: Node[] = [];\n\n this.selectedNodes.forEach((id) => {\n const node = this.getNodeById(id);\n if (node) {\n selectedNodes.push(node);\n }\n });\n\n return selectedNodes;\n }\n\n public getSelectedNodesUnder(parent: Node): Node[] {\n if (this.selectedSingleNode) {\n return parent.isParentOf(this.selectedSingleNode)\n ? [this.selectedSingleNode]\n : [];\n }\n\n const selectedNodes: Node[] = [];\n\n this.selectedNodes.forEach((id) => {\n const node = this.getNodeById(id);\n if (node && parent.isParentOf(node)) {\n selectedNodes.push(node);\n }\n });\n\n return selectedNodes;\n }\n\n public isNodeSelected(node: Node): boolean {\n if (node.id != null) {\n return this.selectedNodes.has(node.id);\n }\n return this.selectedSingleNode ? this.selectedSingleNode === node : false;\n }\n\n public removeFromSelection(node: Node, includeChildren = false): void {\n if (node.id == null) {\n if (this.selectedSingleNode === node) {\n this.selectedSingleNode = null;\n }\n } else {\n this.selectedNodes.delete(node.id);\n\n if (includeChildren) {\n node.iterate((child: Node) => {\n if (child.id != null) {\n this.selectedNodes.delete(child.id);\n }\n return true;\n });\n }\n }\n }\n\n /* Select a single node.\n * Renders the changed elements.\n * Deselects if the node is currently selected (if the mustToggle is on).\n * Deselects the previously selected node.\n * Check if the node is selectable.\n * Saves the state.\n * Options:\n * mustSetFocus: set the focus to the selected node\n * mustToggle: support deselecting the selected node\n */\n public selectSingleNode(node: Node, optionsParam?: SelectNodeOptions) {\n if (!this.canSelect(node)) {\n return;\n }\n\n const defaultOptions = { mustSetFocus: true, mustToggle: true };\n const selectOptions = { ...defaultOptions, ...optionsParam };\n\n const otherSelectedNodes = this.getSelectedNodes().filter(\n (selectedNode) => selectedNode !== node,\n );\n\n if (this.isNodeSelected(node)) {\n if (otherSelectedNodes.length) {\n // Part of a multiple selection: keep only this node selected\n for (const otherNode of otherSelectedNodes) {\n this.deselectNode(otherNode);\n }\n\n for (const otherNode of otherSelectedNodes) {\n this.triggerEvent(\"tree.deselect\", { node: otherNode });\n }\n } else if (selectOptions.mustToggle) {\n this.deselectNode(node);\n this.triggerEvent(\"tree.deselect\", { node });\n }\n } else {\n // tree.select reports the first deselected node; the others, from a\n // multiple selection, get a tree.deselect.\n const [deselectedNode = null, ...alsoDeselectedNodes] =\n otherSelectedNodes;\n\n for (const otherNode of otherSelectedNodes) {\n this.deselectNode(otherNode);\n }\n\n this.addToSelection(node);\n this.openParents(node);\n this.getNodeElementForNode(node).select(selectOptions.mustSetFocus);\n\n for (const otherNode of alsoDeselectedNodes) {\n this.triggerEvent(\"tree.deselect\", { node: otherNode });\n }\n\n this.triggerEvent(\"tree.select\", {\n deselectedNode,\n node,\n });\n }\n\n this.updateTabStop();\n this.saveState();\n }\n\n /* Add a node to the selection, or remove it when it is selected, without\n * changing the other selected nodes.\n * Checks if the node is selectable and saves the state.\n */\n public toggleNodeInSelection(node: Node, mustSetFocus = true): void {\n if (!this.canSelect(node)) {\n return;\n }\n\n if (this.isNodeSelected(node)) {\n this.deselectNode(node);\n this.triggerEvent(\"tree.deselect\", { node });\n } else {\n this.addToSelection(node);\n this.openParents(node);\n this.getNodeElementForNode(node).select(mustSetFocus);\n\n this.triggerEvent(\"tree.select\", { deselectedNode: null, node });\n }\n\n this.updateTabStop();\n this.saveState();\n }\n\n private canSelect(node: Node): boolean {\n if (!this.getSelectable()) {\n return false;\n }\n\n const onCanSelectNode = this.getOnCanSelectNode();\n return onCanSelectNode ? onCanSelectNode(node) : true;\n }\n\n private deselectNode(node: Node): void {\n this.removeFromSelection(node);\n this.getNodeElementForNode(node).deselect();\n }\n}\n"],"names":["getNodeById","getNodeElementForNode","getOnCanSelectNode","getSelectable","openParents","saveState","selectedNodes","selectedSingleNode","triggerEvent","updateTabStop","addToSelection","clear","getSelectedNode","getSelectedNodes","getSelectedNodesUnder","isNodeSelected","removeFromSelection","selectSingleNode","canSelect","deselectNode","select","toggleNodeInSelection","deselect"],"mappings":"AAyBe,MAAM,iBAAiB,CAAC;AAYrC,EAAA,WAAW,CAAC;IACV,YAAA,EAAA,WAAW;IACX,sBAAA,EAAA,qBAAqB;IACrB,mBAAA,EAAA,kBAAkB;IAClB,cAAA,EAAA,aAAa;IACb,YAAA,EAAA,WAAW;IACX,UAAA,EAAA,SAAS;IACT,aAAA,EAAA,YAAY;AACZ,IAAA,cAAA,EAAA;AAC2B,GAAC,EAAE;IAC9B,IAAI,CAACA,YAAW,GAAG,WAAW;IAC9B,IAAI,CAACC,sBAAqB,GAAG,qBAAqB;IAClD,IAAI,CAACC,mBAAkB,GAAG,kBAAkB;IAC5C,IAAI,CAACC,cAAa,GAAG,aAAa;IAClC,IAAI,CAACC,YAAW,GAAG,WAAW;IAC9B,IAAI,CAACC,UAAS,GAAG,SAAS;AAC1B,IAAA,IAAI,CAACC,cAAa,GAAG,IAAI,GAAG,EAAU;IACtC,IAAI,CAACC,mBAAkB,GAAG,IAAI;IAC9B,IAAI,CAACC,aAAY,GAAG,YAAY;IAChC,IAAI,CAACC,cAAa,GAAG,aAAa;AACpC,EAAA;EAEOC,eAAcA,CAAC,IAAU,EAAQ;AACtC,IAAA,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,EAAE;MACnB,IAAI,CAACH,mBAAkB,GAAG,IAAI;AAChC,IAAA,CAAC,MAAM;MACL,IAAI,CAACD,cAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AACjC,IAAA;AACF,EAAA;AAEOK,EAAAA,MAAKA,GAAS;AACnB,IAAA,IAAI,CAACL,cAAa,CAAC,KAAK,EAAE;IAC1B,IAAI,CAACC,mBAAkB,GAAG,IAAI;AAChC,EAAA;AAEOK,EAAAA,gBAAeA,GAAgB;AACpC,IAAA,IAAM,aAAa,GAAG,IAAI,CAACC,iBAAgB,EAAE;IAE7C,OAAO,aAAa,CAAC,MAAM,GAAI,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,GAAI,IAAI;AACjE,EAAA;AAEOA,EAAAA,iBAAgBA,GAAW;IAChC,IAAI,IAAI,CAACN,mBAAkB,EAAE;AAC3B,MAAA,OAAO,CAAC,IAAI,CAACA,mBAAkB,CAAC;AAClC,IAAA;IAEA,IAAM,aAAqB,GAAG,EAAE;AAEhC,IAAA,IAAI,CAACD,cAAa,CAAC,OAAO,CAAE,EAAE,IAAK;AACjC,MAAA,IAAM,IAAI,GAAG,IAAI,CAACN,YAAW,CAAC,EAAE,CAAC;AACjC,MAAA,IAAI,IAAI,EAAE;AACR,QAAA,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;AAC1B,MAAA;AACF,IAAA,CAAC,CAAC;AAEF,IAAA,OAAO,aAAa;AACtB,EAAA;EAEOc,sBAAqBA,CAAC,MAAY,EAAU;IACjD,IAAI,IAAI,CAACP,mBAAkB,EAAE;AAC3B,MAAA,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAACA,mBAAkB,CAAC,GAC7C,CAAC,IAAI,CAACA,mBAAkB,CAAC,GACzB,EAAE;AACR,IAAA;IAEA,IAAM,aAAqB,GAAG,EAAE;AAEhC,IAAA,IAAI,CAACD,cAAa,CAAC,OAAO,CAAE,EAAE,IAAK;AACjC,MAAA,IAAM,IAAI,GAAG,IAAI,CAACN,YAAW,CAAC,EAAE,CAAC;MACjC,IAAI,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;AACnC,QAAA,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;AAC1B,MAAA;AACF,IAAA,CAAC,CAAC;AAEF,IAAA,OAAO,aAAa;AACtB,EAAA;EAEOe,eAAcA,CAAC,IAAU,EAAW;AACzC,IAAA,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,EAAE;MACnB,OAAO,IAAI,CAACT,cAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AACxC,IAAA;IACA,OAAO,IAAI,CAACC,mBAAkB,GAAG,IAAI,CAACA,mBAAkB,KAAK,IAAI,GAAG,KAAK;AAC3E,EAAA;AAEOS,EAAAA,oBAAmBA,CAAC,IAAU,EAAE,eAAe,GAAG,KAAK,EAAQ;AACpE,IAAA,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,EAAE;AACnB,MAAA,IAAI,IAAI,CAACT,mBAAkB,KAAK,IAAI,EAAE;QACpC,IAAI,CAACA,mBAAkB,GAAG,IAAI;AAChC,MAAA;AACF,IAAA,CAAC,MAAM;MACL,IAAI,CAACD,cAAa,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;AAElC,MAAA,IAAI,eAAe,EAAE;AACnB,QAAA,IAAI,CAAC,OAAO,CAAE,KAAW,IAAK;AAC5B,UAAA,IAAI,KAAK,CAAC,EAAE,IAAI,IAAI,EAAE;YACpB,IAAI,CAACA,cAAa,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACrC,UAAA;AACA,UAAA,OAAO,IAAI;AACb,QAAA,CAAC,CAAC;AACJ,MAAA;AACF,IAAA;AACF,EAAA;;AAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACSW,EAAAA,iBAAgBA,CAAC,IAAU,EAAE,YAAgC,EAAE;AACpE,IAAA,IAAI,CAAC,IAAI,CAACC,UAAS,CAAC,IAAI,CAAC,EAAE;AACzB,MAAA;AACF,IAAA;AAEA,IAAA,IAAM,cAAc,GAAG;AAAE,MAAA,YAAY,EAAE,IAAI;AAAE,MAAA,UAAU,EAAE;KAAM;AAC/D,IAAA,IAAM,aAAa,GAAG;AAAE,MAAA,GAAG,cAAc;MAAE,GAAG;KAAc;AAE5D,IAAA,IAAM,kBAAkB,GAAG,IAAI,CAACL,iBAAgB,EAAE,CAAC,MAAM,CACtD,YAAY,IAAK,YAAY,KAAK,IACrC,CAAC;AAED,IAAA,IAAI,IAAI,CAACE,eAAc,CAAC,IAAI,CAAC,EAAE;MAC7B,IAAI,kBAAkB,CAAC,MAAM,EAAE;AAC7B;AACA,QAAA,KAAK,IAAM,SAAS,IAAI,kBAAkB,EAAE;AAC1C,UAAA,IAAI,CAACI,aAAY,CAAC,SAAS,CAAC;AAC9B,QAAA;AAEA,QAAA,KAAK,IAAM,SAAS,IAAI,kBAAkB,EAAE;AAC1C,UAAA,IAAI,CAACX,aAAY,CAAC,eAAe,EAAE;AAAE,YAAA,IAAI,EAAE;AAAU,WAAC,CAAC;AACzD,QAAA;AACF,MAAA,CAAC,MAAM,IAAI,aAAa,CAAC,UAAU,EAAE;AACnC,QAAA,IAAI,CAACW,aAAY,CAAC,IAAI,CAAC;AACvB,QAAA,IAAI,CAACX,aAAY,CAAC,eAAe,EAAE;AAAE,UAAA;AAAK,SAAC,CAAC;AAC9C,MAAA;AACF,IAAA,CAAC,MAAM;AACL;AACA;MACA,IAAM,CAAC,cAAc,GAAG,IAAI,EAAE,GAAG,mBAAmB,CAAC,GACnD,kBAAkB;AAEpB,MAAA,KAAK,IAAM,SAAS,IAAI,kBAAkB,EAAE;AAC1C,QAAA,IAAI,CAACW,aAAY,CAAC,SAAS,CAAC;AAC9B,MAAA;AAEA,MAAA,IAAI,CAACT,eAAc,CAAC,IAAI,CAAC;AACzB,MAAA,IAAI,CAACN,YAAW,CAAC,IAAI,CAAC;MACtB,IAAI,CAACH,sBAAqB,CAAC,IAAI,CAAC,CAACmB,OAAM,CAAC,aAAa,CAAC,YAAY,CAAC;AAEnE,MAAA,KAAK,IAAM,SAAS,IAAI,mBAAmB,EAAE;AAC3C,QAAA,IAAI,CAACZ,aAAY,CAAC,eAAe,EAAE;AAAE,UAAA,IAAI,EAAE;AAAU,SAAC,CAAC;AACzD,MAAA;AAEA,MAAA,IAAI,CAACA,aAAY,CAAC,aAAa,EAAE;QAC/B,cAAc;AACd,QAAA;AACF,OAAC,CAAC;AACJ,IAAA;IAEA,IAAI,CAACC,cAAa,EAAE;IACpB,IAAI,CAACJ,UAAS,EAAE;AAClB,EAAA;;AAEA;AACF;AACA;AACA;AACSgB,EAAAA,sBAAqBA,CAAC,IAAU,EAAE,YAAY,GAAG,IAAI,EAAQ;AAClE,IAAA,IAAI,CAAC,IAAI,CAACH,UAAS,CAAC,IAAI,CAAC,EAAE;AACzB,MAAA;AACF,IAAA;AAEA,IAAA,IAAI,IAAI,CAACH,eAAc,CAAC,IAAI,CAAC,EAAE;AAC7B,MAAA,IAAI,CAACI,aAAY,CAAC,IAAI,CAAC;AACvB,MAAA,IAAI,CAACX,aAAY,CAAC,eAAe,EAAE;AAAE,QAAA;AAAK,OAAC,CAAC;AAC9C,IAAA,CAAC,MAAM;AACL,MAAA,IAAI,CAACE,eAAc,CAAC,IAAI,CAAC;AACzB,MAAA,IAAI,CAACN,YAAW,CAAC,IAAI,CAAC;MACtB,IAAI,CAACH,sBAAqB,CAAC,IAAI,CAAC,CAACmB,OAAM,CAAC,YAAY,CAAC;AAErD,MAAA,IAAI,CAACZ,aAAY,CAAC,aAAa,EAAE;AAAE,QAAA,cAAc,EAAE,IAAI;AAAE,QAAA;AAAK,OAAC,CAAC;AAClE,IAAA;IAEA,IAAI,CAACC,cAAa,EAAE;IACpB,IAAI,CAACJ,UAAS,EAAE;AAClB,EAAA;EAEQa,UAASA,CAAC,IAAU,EAAW;AACrC,IAAA,IAAI,CAAC,IAAI,CAACf,cAAa,EAAE,EAAE;AACzB,MAAA,OAAO,KAAK;AACd,IAAA;AAEA,IAAA,IAAM,eAAe,GAAG,IAAI,CAACD,mBAAkB,EAAE;AACjD,IAAA,OAAO,eAAe,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,IAAI;AACvD,EAAA;EAEQiB,aAAYA,CAAC,IAAU,EAAQ;AACrC,IAAA,IAAI,CAACH,oBAAmB,CAAC,IAAI,CAAC;IAC9B,IAAI,CAACf,sBAAqB,CAAC,IAAI,CAAC,CAACqB,SAAQ,EAAE;AAC7C,EAAA;AACF;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"setDefaultOptions.d.ts","sourceRoot":"","sources":["../src/setDefaultOptions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAapD,eAAO,MAAM,YAAY,QAAoC,CAAC;AAC9D,eAAO,MAAM,YAAY,QAAoC,CAAC;AAC9D,eAAO,MAAM,aAAa,QAAoC,CAAC;AAsC/D,QAAA,MAAM,iBAAiB,GACrB,aAAa,WAAW,EACxB,cAAc,OAAO,CAAC,kBAAkB,CAAC,KACxC,kBAaF,CAAC;AAuBF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"setDefaultOptions.d.ts","sourceRoot":"","sources":["../src/setDefaultOptions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAapD,eAAO,MAAM,YAAY,QAAoC,CAAC;AAC9D,eAAO,MAAM,YAAY,QAAoC,CAAC;AAC9D,eAAO,MAAM,aAAa,QAAoC,CAAC;AAuC/D,QAAA,MAAM,iBAAiB,GACrB,aAAa,WAAW,EACxB,cAAc,OAAO,CAAC,kBAAkB,CAAC,KACxC,kBAaF,CAAC;AAuBF,eAAe,iBAAiB,CAAC"}
@@ -25,6 +25,7 @@ let defaults = {
25
25
  // dataUrl: undefined,
26
26
  dragAndDrop: false,
27
27
  keyboardSupport: true,
28
+ multiSelect: false,
28
29
  nodeClass: Node,
29
30
  // onCanMove: undefined, // Can this node be moved?
30
31
  // onCanMoveTo: undefined, // Can this node be moved to this position? function(moved_node, target_node, position)
@@ -1 +1 @@
1
- {"version":3,"file":"setDefaultOptions.js","sources":["../src/setDefaultOptions.ts"],"sourcesContent":["import type { AnimationSpeed } from \"./animation\";\nimport type { TreeElementOptions } from \"./options\";\n\nimport { DEFAULT_CLASS_PREFIX } from \"./classNames\";\nimport { Node } from \"./node\";\n\n/* The default icons are svg instead of text: the triangle characters come\n * from different fonts on each platform, so they differ in shape and size.\n * They are sized in em to follow the font size, and use currentColor to follow\n * --tree-element-toggler-color.\n */\nconst triangle = (points: string): string =>\n `<svg width=\"0.8em\" height=\"0.8em\" viewBox=\"0 0 10 10\" focusable=\"false\"><polygon points=\"${points}\" fill=\"currentColor\"/></svg>`;\n\nexport const triangleDown = triangle(\"0.5,0.5 9.5,0.5 5,9.5\");\nexport const triangleLeft = triangle(\"9.5,0.5 9.5,9.5 0.5,5\");\nexport const triangleRight = triangle(\"0.5,0.5 0.5,9.5 9.5,5\");\n\nconst defaults: TreeElementOptions = {\n animationSpeed: \"fast\",\n autoEscape: true,\n autoOpen: false, // true / false / int (open n levels starting at 0)\n buttonLeft: true,\n classPrefix: DEFAULT_CLASS_PREFIX, // the prefix of all css classes\n // closedIcon: undefined, // the default is a triangle; see getDefaultClosedIcon\n // commonClassName: undefined, // the class of every element; the default is \"<classPrefix>-common\"\n // data: undefined,\n // dataFilter: undefined,\n // dataUrl: undefined,\n dragAndDrop: false,\n keyboardSupport: true,\n nodeClass: Node,\n // onCanMove: undefined, // Can this node be moved?\n // onCanMoveTo: undefined, // Can this node be moved to this position? function(moved_node, target_node, position)\n // onCanSelectNode: undefined,\n // onCreateLi: undefined,\n // onDragMove: undefined,\n // onDragStop: undefined,\n // onGetStateFromStorage: undefined,\n // onIsMoveHandle: undefined,\n // onSetStateFromStorage: undefined,\n // openedIcon: undefined, // the default is a triangle pointing down\n openFolderDelay: 500, // The delay for opening a folder during drag and drop; the value is in milliseconds\n // rtl: undefined, // right-to-left support; true / false (default)\n saveState: false, // true / false / string (local storage key; the default key is \"tree\")\n selectable: true,\n showEmptyFolder: false,\n slide: true, // must display slide animation?\n startDndDelay: 300, // The delay for starting dnd (in milliseconds)\n tabIndex: 0,\n // treeClassName: undefined, // the class of the root element; the default is classPrefix\n useContextMenu: true,\n};\n\nconst setDefaultOptions = (\n htmlElement: HTMLElement,\n inputOptions: Partial<TreeElementOptions>,\n): TreeElementOptions => {\n const options = {\n ...defaults,\n ...inputOptions,\n animationSpeed: inputOptions.animationSpeed ?? getDefaultAnimationSpeed(),\n };\n\n options.dataUrl ??= htmlElement.dataset.url;\n options.rtl ??= getRtlOptionFromHTMLElement(htmlElement);\n options.closedIcon ??= getDefaultClosedIcon(options);\n options.openedIcon ??= triangleDown;\n\n return options;\n};\n\n// No animation when the user asked the system for reduced motion\nconst getDefaultAnimationSpeed = (): AnimationSpeed =>\n prefersReducedMotion() ? 0 : defaults.animationSpeed;\n\nconst prefersReducedMotion = (): boolean =>\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\nconst getDefaultClosedIcon = (options: TreeElementOptions): string => {\n return options.rtl ? triangleLeft : triangleRight;\n};\n\nconst getRtlOptionFromHTMLElement = (htmlElement: HTMLElement): boolean => {\n const dataRtl = htmlElement.dataset.rtl;\n\n if (dataRtl == \"\") {\n return true;\n }\n return dataRtl === \"false\" ? false : Boolean(dataRtl);\n};\n\nexport default setDefaultOptions;\n"],"names":[],"mappings":";;;AAMA;AACA;AACA;AACA;AACA;AACA,IAAM,QAAQ,GAAI,MAAc,IAC9B,CAAA,yFAAA,EAA4F,MAAM,CAAA,6BAAA,CAA+B;IAEtH,YAAY,GAAG,QAAQ,CAAC,uBAAuB;IAC/C,YAAY,GAAG,QAAQ,CAAC,uBAAuB;IAC/C,aAAa,GAAG,QAAQ,CAAC,uBAAuB;AAE7D,IAAM,QAA4B,GAAG;AACnC,EAAA,cAAc,EAAE,MAAM;AACtB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,QAAQ,EAAE,KAAK;AAAE;AACjB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,WAAW,EAAE,oBAAoB;AAAE;AACnC;AACA;AACA;AACA;AACA;AACA,EAAA,WAAW,EAAE,KAAK;AAClB,EAAA,eAAe,EAAE,IAAI;AACrB,EAAA,SAAS,EAAE,IAAI;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA,eAAe,EAAE,GAAG;AAAE;AACtB;AACA,EAAA,SAAS,EAAE,KAAK;AAAE;AAClB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,eAAe,EAAE,KAAK;AACtB,EAAA,KAAK,EAAE,IAAI;AAAE;AACb,EAAA,aAAa,EAAE,GAAG;AAAE;AACpB,EAAA,QAAQ,EAAE,CAAC;AACX;AACA,EAAA,cAAc,EAAE;AAClB,CAAC;AAED,IAAM,iBAAiB,GAAG,CACxB,WAAwB,EACxB,YAAyC,KAClB;AACvB,EAAA,IAAM,OAAO,GAAG;AACd,IAAA,GAAG,QAAQ;AACX,IAAA,GAAG,YAAY;AACf,IAAA,cAAc,EAAE,YAAY,CAAC,cAAc,IAAI,wBAAwB;GACxE;AAED,EAAA,OAAO,CAAC,OAAO,KAAK,WAAW,CAAC,OAAO,CAAC,GAAG;AAC3C,EAAA,OAAO,CAAC,GAAG,KAAK,2BAA2B,CAAC,WAAW,CAAC;AACxD,EAAA,OAAO,CAAC,UAAU,KAAK,oBAAoB,CAAC,OAAO,CAAC;EACpD,OAAO,CAAC,UAAU,KAAK,YAAY;AAEnC,EAAA,OAAO,OAAO;AAChB;;AAEA;AACA,IAAM,wBAAwB,GAAG,MAC/B,oBAAoB,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,cAAc;AAEtD,IAAM,oBAAoB,GAAG,MAC3B,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU,IACvC,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC,OAAO;AAE/D,IAAM,oBAAoB,GAAI,OAA2B,IAAa;AACpE,EAAA,OAAO,OAAO,CAAC,GAAG,GAAG,YAAY,GAAG,aAAa;AACnD,CAAC;AAED,IAAM,2BAA2B,GAAI,WAAwB,IAAc;AACzE,EAAA,IAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG;EAEvC,IAAI,OAAO,IAAI,EAAE,EAAE;AACjB,IAAA,OAAO,IAAI;AACb,EAAA;EACA,OAAO,OAAO,KAAK,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;AACvD,CAAC;;"}
1
+ {"version":3,"file":"setDefaultOptions.js","sources":["../src/setDefaultOptions.ts"],"sourcesContent":["import type { AnimationSpeed } from \"./animation\";\nimport type { TreeElementOptions } from \"./options\";\n\nimport { DEFAULT_CLASS_PREFIX } from \"./classNames\";\nimport { Node } from \"./node\";\n\n/* The default icons are svg instead of text: the triangle characters come\n * from different fonts on each platform, so they differ in shape and size.\n * They are sized in em to follow the font size, and use currentColor to follow\n * --tree-element-toggler-color.\n */\nconst triangle = (points: string): string =>\n `<svg width=\"0.8em\" height=\"0.8em\" viewBox=\"0 0 10 10\" focusable=\"false\"><polygon points=\"${points}\" fill=\"currentColor\"/></svg>`;\n\nexport const triangleDown = triangle(\"0.5,0.5 9.5,0.5 5,9.5\");\nexport const triangleLeft = triangle(\"9.5,0.5 9.5,9.5 0.5,5\");\nexport const triangleRight = triangle(\"0.5,0.5 0.5,9.5 9.5,5\");\n\nconst defaults: TreeElementOptions = {\n animationSpeed: \"fast\",\n autoEscape: true,\n autoOpen: false, // true / false / int (open n levels starting at 0)\n buttonLeft: true,\n classPrefix: DEFAULT_CLASS_PREFIX, // the prefix of all css classes\n // closedIcon: undefined, // the default is a triangle; see getDefaultClosedIcon\n // commonClassName: undefined, // the class of every element; the default is \"<classPrefix>-common\"\n // data: undefined,\n // dataFilter: undefined,\n // dataUrl: undefined,\n dragAndDrop: false,\n keyboardSupport: true,\n multiSelect: false,\n nodeClass: Node,\n // onCanMove: undefined, // Can this node be moved?\n // onCanMoveTo: undefined, // Can this node be moved to this position? function(moved_node, target_node, position)\n // onCanSelectNode: undefined,\n // onCreateLi: undefined,\n // onDragMove: undefined,\n // onDragStop: undefined,\n // onGetStateFromStorage: undefined,\n // onIsMoveHandle: undefined,\n // onSetStateFromStorage: undefined,\n // openedIcon: undefined, // the default is a triangle pointing down\n openFolderDelay: 500, // The delay for opening a folder during drag and drop; the value is in milliseconds\n // rtl: undefined, // right-to-left support; true / false (default)\n saveState: false, // true / false / string (local storage key; the default key is \"tree\")\n selectable: true,\n showEmptyFolder: false,\n slide: true, // must display slide animation?\n startDndDelay: 300, // The delay for starting dnd (in milliseconds)\n tabIndex: 0,\n // treeClassName: undefined, // the class of the root element; the default is classPrefix\n useContextMenu: true,\n};\n\nconst setDefaultOptions = (\n htmlElement: HTMLElement,\n inputOptions: Partial<TreeElementOptions>,\n): TreeElementOptions => {\n const options = {\n ...defaults,\n ...inputOptions,\n animationSpeed: inputOptions.animationSpeed ?? getDefaultAnimationSpeed(),\n };\n\n options.dataUrl ??= htmlElement.dataset.url;\n options.rtl ??= getRtlOptionFromHTMLElement(htmlElement);\n options.closedIcon ??= getDefaultClosedIcon(options);\n options.openedIcon ??= triangleDown;\n\n return options;\n};\n\n// No animation when the user asked the system for reduced motion\nconst getDefaultAnimationSpeed = (): AnimationSpeed =>\n prefersReducedMotion() ? 0 : defaults.animationSpeed;\n\nconst prefersReducedMotion = (): boolean =>\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\nconst getDefaultClosedIcon = (options: TreeElementOptions): string => {\n return options.rtl ? triangleLeft : triangleRight;\n};\n\nconst getRtlOptionFromHTMLElement = (htmlElement: HTMLElement): boolean => {\n const dataRtl = htmlElement.dataset.rtl;\n\n if (dataRtl == \"\") {\n return true;\n }\n return dataRtl === \"false\" ? false : Boolean(dataRtl);\n};\n\nexport default setDefaultOptions;\n"],"names":[],"mappings":";;;AAMA;AACA;AACA;AACA;AACA;AACA,IAAM,QAAQ,GAAI,MAAc,IAC9B,CAAA,yFAAA,EAA4F,MAAM,CAAA,6BAAA,CAA+B;IAEtH,YAAY,GAAG,QAAQ,CAAC,uBAAuB;IAC/C,YAAY,GAAG,QAAQ,CAAC,uBAAuB;IAC/C,aAAa,GAAG,QAAQ,CAAC,uBAAuB;AAE7D,IAAM,QAA4B,GAAG;AACnC,EAAA,cAAc,EAAE,MAAM;AACtB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,QAAQ,EAAE,KAAK;AAAE;AACjB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,WAAW,EAAE,oBAAoB;AAAE;AACnC;AACA;AACA;AACA;AACA;AACA,EAAA,WAAW,EAAE,KAAK;AAClB,EAAA,eAAe,EAAE,IAAI;AACrB,EAAA,WAAW,EAAE,KAAK;AAClB,EAAA,SAAS,EAAE,IAAI;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA,eAAe,EAAE,GAAG;AAAE;AACtB;AACA,EAAA,SAAS,EAAE,KAAK;AAAE;AAClB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,eAAe,EAAE,KAAK;AACtB,EAAA,KAAK,EAAE,IAAI;AAAE;AACb,EAAA,aAAa,EAAE,GAAG;AAAE;AACpB,EAAA,QAAQ,EAAE,CAAC;AACX;AACA,EAAA,cAAc,EAAE;AAClB,CAAC;AAED,IAAM,iBAAiB,GAAG,CACxB,WAAwB,EACxB,YAAyC,KAClB;AACvB,EAAA,IAAM,OAAO,GAAG;AACd,IAAA,GAAG,QAAQ;AACX,IAAA,GAAG,YAAY;AACf,IAAA,cAAc,EAAE,YAAY,CAAC,cAAc,IAAI,wBAAwB;GACxE;AAED,EAAA,OAAO,CAAC,OAAO,KAAK,WAAW,CAAC,OAAO,CAAC,GAAG;AAC3C,EAAA,OAAO,CAAC,GAAG,KAAK,2BAA2B,CAAC,WAAW,CAAC;AACxD,EAAA,OAAO,CAAC,UAAU,KAAK,oBAAoB,CAAC,OAAO,CAAC;EACpD,OAAO,CAAC,UAAU,KAAK,YAAY;AAEnC,EAAA,OAAO,OAAO;AAChB;;AAEA;AACA,IAAM,wBAAwB,GAAG,MAC/B,oBAAoB,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,cAAc;AAEtD,IAAM,oBAAoB,GAAG,MAC3B,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU,IACvC,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC,OAAO;AAE/D,IAAM,oBAAoB,GAAI,OAA2B,IAAa;AACpE,EAAA,OAAO,OAAO,CAAC,GAAG,GAAG,YAAY,GAAG,aAAa;AACnD,CAAC;AAED,IAAM,2BAA2B,GAAI,WAAwB,IAAc;AACzE,EAAA,IAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG;EAEvC,IAAI,OAAO,IAAI,EAAE,EAAE;AACjB,IAAA,OAAO,IAAI;AACb,EAAA;EACA,OAAO,OAAO,KAAK,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;AACvD,CAAC;;"}
package/lib/version.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- declare const version = "0.3.2";
1
+ declare const version = "0.4.1";
2
2
  export default version;
3
3
  //# sourceMappingURL=version.d.ts.map
package/lib/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Generated by config/generateVersion.mjs. Do not edit.
2
- let version = "0.3.2";
2
+ let version = "0.4.1";
3
3
 
4
4
  export { version as default };
5
5
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["// Generated by config/generateVersion.mjs. Do not edit.\nconst version = \"0.3.2\";\n\nexport default version;\n"],"names":[],"mappings":"AAAA;AACA,IAAM,OAAO,GAAG;;"}
1
+ {"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["// Generated by config/generateVersion.mjs. Do not edit.\nconst version = \"0.4.1\";\n\nexport default version;\n"],"names":[],"mappings":"AAAA;AACA,IAAM,OAAO,GAAG;;"}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "tree-element",
3
- "version": "0.3.2",
3
+ "version": "0.4.1",
4
+ "packageManager": "pnpm@12.16.1",
4
5
  "description": "Tree widget in plain javascript",
5
6
  "keywords": [
6
7
  "tree"
@@ -43,6 +44,7 @@
43
44
  "vitest": "pnpm build-debug && vitest run --coverage --config config/vitest.config.mjs",
44
45
  "vitest-watch": "vitest --config config/vitest.config.mjs",
45
46
  "lint": "eslint css src playwright test",
47
+ "lint-docs": "pnpm docs-api && vale --glob='!docs/.vitepress/**' README.md CHANGELOG.md docs",
46
48
  "production": "./config/production",
47
49
  "devserver": "SERVE=true rollup --config config/rollup.config.mjs --watch",
48
50
  "docs-api": "typedoc && node docs/scripts/fixApiLinks.mjs",
@@ -58,66 +60,70 @@
58
60
  "release": "node config/release.mjs",
59
61
  "playwright": "pnpm build-with-coverage && playwright test --config config/playwright.config.js",
60
62
  "test": "pnpm vitest && pnpm playwright",
61
- "docs-check": "kiira check"
63
+ "docs-check": "kiira check",
64
+ "mutation": "stryker run config/stryker.config.mjs"
62
65
  },
63
66
  "devDependencies": {
64
- "@axe-core/playwright": "^4.13.0",
65
- "@babel/cli": "^8.0.6",
66
- "@babel/core": "^8.0.7",
67
+ "@axe-core/playwright": "^4.14.0",
68
+ "@babel/cli": "^8.1.0",
69
+ "@babel/core": "^8.1.2",
67
70
  "@babel/preset-env": "^8.0.7",
68
71
  "@babel/preset-typescript": "^8.0.7",
69
- "@cspell/eslint-plugin": "^10.3.6",
70
- "@eslint/css": "^2.0.0",
72
+ "@cspell/eslint-plugin": "^10.4.1",
73
+ "@eslint/css": "^2.0.1",
71
74
  "@eslint/js": "^10.0.1",
72
- "@playwright/test": "^1.64.0",
75
+ "@playwright/test": "^1.65.0",
73
76
  "@rollup/plugin-babel": "^7.1.0",
74
77
  "@rollup/plugin-node-resolve": "^16.0.3",
75
- "@rollup/plugin-terser": "^1.0.0",
78
+ "@rollup/plugin-terser": "^1.0.2",
79
+ "@stryker-mutator/core": "^10.1.1",
80
+ "@stryker-mutator/typescript-checker": "^10.1.1",
81
+ "@stryker-mutator/vitest-runner": "^10.1.1",
76
82
  "@testing-library/dom": "^10.4.2",
77
83
  "@testing-library/jest-dom": "^7.0.1",
78
- "@testing-library/user-event": "^14.6.7",
84
+ "@testing-library/user-event": "^14.6.10",
79
85
  "@types/debug": "^4.1.13",
80
- "@types/node": "^26.6.5",
81
- "@vitest/coverage-istanbul": "^5.0.3",
82
- "@vitest/eslint-plugin": "^1.6.27",
86
+ "@types/node": "^26.6.6",
87
+ "@vitest/coverage-istanbul": "^5.1.0",
88
+ "@vitest/eslint-plugin": "^1.6.28",
83
89
  "axe-core": "^4.14.0",
84
90
  "babel-plugin-istanbul": "^8.0.0",
85
91
  "babel-plugin-prefix-private-members": "^0.3.1",
86
- "eslint": "^10.12.0",
92
+ "eslint": "^10.14.0",
87
93
  "eslint-import-resolver-typescript": "^4.4.5",
88
94
  "eslint-plugin-compat": "^7.0.2",
89
- "eslint-plugin-import-x": "^4.17.1",
90
- "eslint-plugin-jest-dom": "^5.10.1",
95
+ "eslint-plugin-import-x": "^4.18.1",
96
+ "eslint-plugin-jest-dom": "^5.10.2",
91
97
  "eslint-plugin-jest-extended": "github:mbraak/eslint-plugin-jest-extended#modernize",
92
98
  "eslint-plugin-no-unsanitized": "^4.1.5",
93
- "eslint-plugin-perfectionist": "^5.12.1",
94
- "eslint-plugin-playwright": "^2.12.1",
99
+ "eslint-plugin-perfectionist": "^5.13.0",
100
+ "eslint-plugin-playwright": "^2.12.2",
95
101
  "eslint-plugin-testing-library": "^7.16.2",
96
102
  "eslint-plugin-tsdoc": "^0.5.4",
97
- "eslint-plugin-unicorn": "^77.0.0",
103
+ "eslint-plugin-unicorn": "^79.0.0",
98
104
  "jest-extended": "^7.0.0",
99
- "jsdom": "^30.1.2",
105
+ "jsdom": "^31.0.1",
100
106
  "jsdom-testing-mocks": "^1.16.0",
101
107
  "jsonfile": "^6.2.1",
102
- "kiira": "^0.6.0",
103
- "kiira-core": "^0.6.0",
108
+ "kiira": "^0.7.1",
109
+ "kiira-core": "^0.7.1",
104
110
  "lodash": "^4.18.1",
105
- "msw": "^3.0.3",
106
- "postcss": "^8.5.29",
111
+ "msw": "^3.0.5",
112
+ "postcss": "^8.5.32",
107
113
  "postcss-cli": "^12.0.0",
108
- "postcss-import": "^17.0.0",
114
+ "postcss-import": "^17.0.1",
109
115
  "postcss-load-config": "^6.0.1",
110
- "postcss-nested": "^8.0.1",
111
- "prettier": "^3.9.10",
112
- "rollup": "^4.64.5",
116
+ "postcss-nested": "^9.0.1",
117
+ "prettier": "^3.10.1",
118
+ "rollup": "^4.68.2",
113
119
  "rollup-plugin-serve": "^3.0.0",
114
120
  "rollup-plugin-tsconfig-paths": "^1.5.2",
115
- "tslib": "^2.8.1",
121
+ "tslib": "^2.9.1",
116
122
  "typedoc": "^0.28.20",
117
- "typedoc-plugin-markdown": "^4.13.1",
123
+ "typedoc-plugin-markdown": "^4.14.1",
118
124
  "typescript": "^6.0.3",
119
- "typescript-eslint": "^8.71.1",
125
+ "typescript-eslint": "^8.72.2",
120
126
  "vitepress": "^1.6.4",
121
- "vitest": "^5.0.3"
127
+ "vitest": "^5.1.0"
122
128
  }
123
129
  }
package/src/classNames.ts CHANGED
@@ -39,13 +39,13 @@ export const DEFAULT_CLASS_PREFIX = "tree-element";
39
39
  */
40
40
  const createClassNames = ({
41
41
  classPrefix,
42
- commonClassName,
43
- treeClassName,
42
+ commonClassName = `${classPrefix}-common`,
43
+ treeClassName = classPrefix,
44
44
  }: ClassNamesOptions): ClassNames => ({
45
45
  border: `${classPrefix}-border`,
46
46
  circle: `${classPrefix}-circle`,
47
47
  closed: `${classPrefix}-closed`,
48
- common: commonClassName ?? `${classPrefix}-common`,
48
+ common: commonClassName,
49
49
  dnd: `${classPrefix}-dnd`,
50
50
  dragging: `${classPrefix}-dragging`,
51
51
  element: `${classPrefix}-element`,
@@ -64,7 +64,7 @@ const createClassNames = ({
64
64
  toggler: `${classPrefix}-toggler`,
65
65
  togglerLeft: `${classPrefix}-toggler-left`,
66
66
  togglerRight: `${classPrefix}-toggler-right`,
67
- tree: treeClassName ?? classPrefix,
67
+ tree: treeClassName,
68
68
  });
69
69
 
70
70
  export default createClassNames;
package/src/dataLoader.ts CHANGED
@@ -44,8 +44,9 @@ export default class DataLoader {
44
44
  element.classList.add(this.classNames.loading);
45
45
 
46
46
  // Tell screen readers that the children of the folder are loading
47
- const titleSpan = node ? this.getTitleSpan(element) : null;
48
- titleSpan?.setAttribute("aria-busy", "true");
47
+ if (node) {
48
+ element.setAttribute("aria-busy", "true");
49
+ }
49
50
 
50
51
  this.triggerEvent("tree.loading_data", {
51
52
  element,
@@ -54,7 +55,9 @@ export default class DataLoader {
54
55
 
55
56
  const stopLoading = (): void => {
56
57
  element.classList.remove(this.classNames.loading);
57
- titleSpan?.removeAttribute("aria-busy");
58
+ if (node) {
59
+ element.removeAttribute("aria-busy");
60
+ }
58
61
  this.triggerEvent("tree.loaded_data", {
59
62
  element,
60
63
  node,
@@ -77,8 +80,10 @@ export default class DataLoader {
77
80
  const signal = this.abortController.signal;
78
81
  url.setSearchParam("_", Date.now().toString());
79
82
 
83
+ // Accept, not Content-Type: the request has no body. A cross-origin request
84
+ // with only an Accept header also needs no CORS preflight.
80
85
  return fetch(url.value(), {
81
- headers: { "Content-Type": "application/json" },
86
+ headers: { Accept: "application/json" },
82
87
  signal,
83
88
  })
84
89
  .then(handleResponse)
@@ -92,10 +97,4 @@ export default class DataLoader {
92
97
  this.triggerEvent("tree.load_failed", { error });
93
98
  });
94
99
  }
95
-
96
- private getTitleSpan(element: HTMLElement): HTMLElement | null {
97
- return element.querySelector<HTMLElement>(
98
- `:scope > .${this.classNames.element} > .${this.classNames.title}`,
99
- );
100
- }
101
100
  }
@@ -31,8 +31,9 @@ export const generateHitPositions = (
31
31
  };
32
32
 
33
33
  const handleAfterOpenFolder = (node: Node, nextNode: Node | null) => {
34
- if (node === currentNode || nextNode === currentNode) {
35
- // Cannot move before or after current item
34
+ // Not called for the current node: handleOpenFolder stops iterating there
35
+ if (nextNode === currentNode) {
36
+ // Dropping the current node after this folder would leave it where it is
36
37
  addHitPosition(node, null, lastTop);
37
38
  } else {
38
39
  addHitPosition(node, "after", lastTop);
@@ -44,7 +44,6 @@ interface DragAndDropHandlerParams {
44
44
  openFolderDelay: false | number;
45
45
  openNode: OpenNode;
46
46
  refreshElements: RefreshElements;
47
- slide: boolean;
48
47
  treeElement: HTMLElement;
49
48
  triggerEvent: TriggerEvent;
50
49
  }
@@ -75,7 +74,6 @@ export class DragAndDropHandler {
75
74
  private openNode: OpenNode;
76
75
  private previousGhost: DropHint | null;
77
76
  private refreshElements: RefreshElements;
78
- private slide: boolean;
79
77
  private treeElement: HTMLElement;
80
78
  private triggerEvent: TriggerEvent;
81
79
 
@@ -94,7 +92,6 @@ export class DragAndDropHandler {
94
92
  openFolderDelay,
95
93
  openNode,
96
94
  refreshElements,
97
- slide,
98
95
  treeElement,
99
96
  triggerEvent,
100
97
  }: DragAndDropHandlerParams) {
@@ -112,7 +109,6 @@ export class DragAndDropHandler {
112
109
  this.openFolderDelay = openFolderDelay;
113
110
  this.openNode = openNode;
114
111
  this.refreshElements = refreshElements;
115
- this.slide = slide;
116
112
  this.treeElement = treeElement;
117
113
  this.triggerEvent = triggerEvent;
118
114
 
@@ -157,10 +153,6 @@ export class DragAndDropHandler {
157
153
  const area = this.findHoveredArea(positionInfo.pageX, positionInfo.pageY);
158
154
 
159
155
  if (area && this.canMoveToArea(area, this.currentItem)) {
160
- if (!area.node.isFolder()) {
161
- this.stopOpenFolderTimer();
162
- }
163
-
164
156
  if (this.hoveredArea !== area) {
165
157
  this.hoveredArea = area;
166
158
 
@@ -212,7 +204,7 @@ export class DragAndDropHandler {
212
204
  return true;
213
205
  }
214
206
 
215
- public mouseStop(positionInfo: PositionInfo): boolean {
207
+ public mouseStop(positionInfo: PositionInfo): void {
216
208
  this.moveItem(positionInfo);
217
209
  this.clear();
218
210
  this.removeHover();
@@ -231,8 +223,6 @@ export class DragAndDropHandler {
231
223
  if (!this.hoveredArea && currentItem && this.onDragStop) {
232
224
  this.onDragStop(currentItem.node, positionInfo.originalEvent);
233
225
  }
234
-
235
- return false;
236
226
  }
237
227
 
238
228
  public refresh(): void {
@@ -360,11 +350,7 @@ export class DragAndDropHandler {
360
350
  }
361
351
 
362
352
  private mustCaptureElement(element: HTMLElement): boolean {
363
- const nodeName = element.nodeName;
364
-
365
- return (
366
- nodeName !== "INPUT" && nodeName !== "SELECT" && nodeName !== "TEXTAREA"
367
- );
353
+ return !["INPUT", "SELECT", "TEXTAREA"].includes(element.nodeName);
368
354
  }
369
355
 
370
356
  private mustOpenFolderTimer(area: HitArea): boolean {
@@ -389,7 +375,7 @@ export class DragAndDropHandler {
389
375
 
390
376
  private startOpenFolderTimer(folder: Node): void {
391
377
  const openFolder = (): void => {
392
- void this.openNode(folder, this.slide).then(() => {
378
+ void this.openNode(folder).then(() => {
393
379
  this.refresh();
394
380
  this.updateDropHint();
395
381
  });