tree-element 0.2.0 → 0.3.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 (123) hide show
  1. package/README.md +14 -6
  2. package/lib/animation.d.ts +2 -2
  3. package/lib/animation.d.ts.map +1 -1
  4. package/lib/animation.js +13 -9
  5. package/lib/animation.js.map +1 -1
  6. package/lib/dataLoader.d.ts +1 -0
  7. package/lib/dataLoader.d.ts.map +1 -1
  8. package/lib/dataLoader.js +8 -0
  9. package/lib/dataLoader.js.map +1 -1
  10. package/lib/dragAndDropHandler/dragElement.d.ts.map +1 -1
  11. package/lib/dragAndDropHandler/dragElement.js +2 -1
  12. package/lib/dragAndDropHandler/dragElement.js.map +1 -1
  13. package/lib/dragAndDropHandler/index.d.ts.map +1 -1
  14. package/lib/dragAndDropHandler/index.js +56 -65
  15. package/lib/dragAndDropHandler/index.js.map +1 -1
  16. package/lib/dragAndDropHandler/iterateVisibleNodes.d.ts.map +1 -1
  17. package/lib/dragAndDropHandler/iterateVisibleNodes.js +16 -15
  18. package/lib/dragAndDropHandler/iterateVisibleNodes.js.map +1 -1
  19. package/lib/elementsRenderer.d.ts +5 -1
  20. package/lib/elementsRenderer.d.ts.map +1 -1
  21. package/lib/elementsRenderer.js +62 -39
  22. package/lib/elementsRenderer.js.map +1 -1
  23. package/lib/events.d.ts +44 -11
  24. package/lib/events.d.ts.map +1 -1
  25. package/lib/index.d.ts +31 -8
  26. package/lib/index.d.ts.map +1 -1
  27. package/lib/index.js +162 -122
  28. package/lib/index.js.map +1 -1
  29. package/lib/keyHandler.d.ts +11 -5
  30. package/lib/keyHandler.d.ts.map +1 -1
  31. package/lib/keyHandler.js +87 -33
  32. package/lib/keyHandler.js.map +1 -1
  33. package/lib/methodTypes.d.ts +2 -2
  34. package/lib/methodTypes.d.ts.map +1 -1
  35. package/lib/mouseHandler.d.ts +1 -1
  36. package/lib/mouseHandler.d.ts.map +1 -1
  37. package/lib/mouseHandler.js +10 -7
  38. package/lib/mouseHandler.js.map +1 -1
  39. package/lib/node.d.ts +45 -15
  40. package/lib/node.d.ts.map +1 -1
  41. package/lib/node.js +136 -139
  42. package/lib/node.js.map +1 -1
  43. package/lib/nodeElement/folderElement.d.ts +1 -1
  44. package/lib/nodeElement/folderElement.d.ts.map +1 -1
  45. package/lib/nodeElement/folderElement.js +46 -57
  46. package/lib/nodeElement/folderElement.js.map +1 -1
  47. package/lib/nodeElement/ghostDropHint.d.ts.map +1 -1
  48. package/lib/nodeElement/ghostDropHint.js +8 -4
  49. package/lib/nodeElement/ghostDropHint.js.map +1 -1
  50. package/lib/nodeElement/index.d.ts.map +1 -1
  51. package/lib/nodeElement/index.js +6 -6
  52. package/lib/nodeElement/index.js.map +1 -1
  53. package/lib/nodeUtils.d.ts.map +1 -1
  54. package/lib/nodeUtils.js +1 -1
  55. package/lib/nodeUtils.js.map +1 -1
  56. package/lib/options.d.ts +23 -6
  57. package/lib/options.d.ts.map +1 -1
  58. package/lib/requestUrl.d.ts +0 -1
  59. package/lib/requestUrl.d.ts.map +1 -1
  60. package/lib/requestUrl.js +4 -22
  61. package/lib/requestUrl.js.map +1 -1
  62. package/lib/saveStateHandler.d.ts.map +1 -1
  63. package/lib/saveStateHandler.js +21 -41
  64. package/lib/saveStateHandler.js.map +1 -1
  65. package/lib/scrollHandler/containerScrollParent.d.ts.map +1 -1
  66. package/lib/scrollHandler/containerScrollParent.js +3 -8
  67. package/lib/scrollHandler/containerScrollParent.js.map +1 -1
  68. package/lib/scrollHandler/createScrollParent.d.ts.map +1 -1
  69. package/lib/scrollHandler/createScrollParent.js +4 -5
  70. package/lib/scrollHandler/createScrollParent.js.map +1 -1
  71. package/lib/scrollHandler/documentScrollParent.d.ts.map +1 -1
  72. package/lib/scrollHandler/documentScrollParent.js +3 -9
  73. package/lib/scrollHandler/documentScrollParent.js.map +1 -1
  74. package/lib/scrollHandler/scrollParent.d.ts.map +1 -1
  75. package/lib/scrollHandler/scrollParent.js +19 -17
  76. package/lib/scrollHandler/scrollParent.js.map +1 -1
  77. package/lib/selectNodeHandler.d.ts +3 -1
  78. package/lib/selectNodeHandler.d.ts.map +1 -1
  79. package/lib/selectNodeHandler.js +27 -37
  80. package/lib/selectNodeHandler.js.map +1 -1
  81. package/lib/setDefaultOptions.d.ts +3 -0
  82. package/lib/setDefaultOptions.d.ts.map +1 -1
  83. package/lib/setDefaultOptions.js +21 -20
  84. package/lib/setDefaultOptions.js.map +1 -1
  85. package/lib/util.d.ts.map +1 -1
  86. package/lib/util.js +1 -1
  87. package/lib/util.js.map +1 -1
  88. package/lib/version.d.ts +1 -1
  89. package/lib/version.js +1 -1
  90. package/lib/version.js.map +1 -1
  91. package/package.json +44 -35
  92. package/src/animation.ts +13 -11
  93. package/src/dataLoader.ts +11 -0
  94. package/src/dragAndDropHandler/dragElement.ts +2 -1
  95. package/src/dragAndDropHandler/index.ts +70 -75
  96. package/src/dragAndDropHandler/iterateVisibleNodes.ts +18 -16
  97. package/src/elementsRenderer.ts +76 -46
  98. package/src/events.ts +44 -11
  99. package/src/index.ts +210 -150
  100. package/src/keyHandler.ts +95 -41
  101. package/src/methodTypes.ts +3 -3
  102. package/src/mouseHandler.ts +10 -7
  103. package/src/node.ts +155 -148
  104. package/src/nodeElement/folderElement.ts +54 -63
  105. package/src/nodeElement/ghostDropHint.ts +4 -2
  106. package/src/nodeElement/index.ts +9 -15
  107. package/src/nodeUtils.ts +1 -1
  108. package/src/options.ts +23 -6
  109. package/src/requestUrl.ts +4 -25
  110. package/src/saveStateHandler.ts +29 -43
  111. package/src/scrollHandler/containerScrollParent.ts +3 -9
  112. package/src/scrollHandler/createScrollParent.ts +1 -2
  113. package/src/scrollHandler/documentScrollParent.ts +5 -11
  114. package/src/scrollHandler/scrollParent.ts +29 -25
  115. package/src/selectNodeHandler.ts +34 -38
  116. package/src/setDefaultOptions.ts +31 -19
  117. package/src/util.ts +1 -2
  118. package/src/version.ts +1 -1
  119. package/tree_element.css +87 -69
  120. package/tree_element.debug.js +717 -659
  121. package/tree_element.debug.js.map +1 -1
  122. package/tree_element.js +2 -2
  123. package/tree_element.js.map +1 -1
@@ -3,6 +3,8 @@ import type { GetTree, IsNodeSelected } from "./methodTypes.js";
3
3
  import type { Node } from "./node.js";
4
4
  import type { IconElement, OnCreateLi } from "./options.js";
5
5
  interface ElementsRendererParams {
6
+ ariaLabel?: string;
7
+ ariaLabelledBy?: string;
6
8
  autoEscape: boolean;
7
9
  buttonLeft: boolean;
8
10
  classNames: ClassNames;
@@ -21,6 +23,8 @@ interface ElementsRendererParams {
21
23
  export default class ElementsRenderer {
22
24
  closedIconElement?: globalThis.Node;
23
25
  openedIconElement?: globalThis.Node;
26
+ private ariaLabel?;
27
+ private ariaLabelledBy?;
24
28
  private autoEscape;
25
29
  private buttonLeft;
26
30
  private classNames;
@@ -38,7 +42,7 @@ export default class ElementsRenderer {
38
42
  private setNodeElement;
39
43
  private showEmptyFolder;
40
44
  private tabIndex?;
41
- constructor({ autoEscape, buttonLeft, classNames, closedIcon, dragAndDrop, getTree, htmlElement, isNodeSelected, onCreateLi, openedIcon, rtl, setNodeElement, showEmptyFolder, tabIndex, }: ElementsRendererParams);
45
+ constructor({ ariaLabel, ariaLabelledBy, autoEscape, buttonLeft, classNames, closedIcon, dragAndDrop, getTree, htmlElement, isNodeSelected, onCreateLi, openedIcon, rtl, setNodeElement, showEmptyFolder, tabIndex, }: ElementsRendererParams);
42
46
  render(fromNode: Node | null): void;
43
47
  renderChildren(node: Node): HTMLUListElement | null;
44
48
  renderFromNode(node: Node): void;
@@ -1 +1 @@
1
- {"version":3,"file":"elementsRenderer.d.ts","sourceRoot":"","sources":["../src/elementsRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAIzD,UAAU,sBAAsB;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,WAAW,CAAC;IACzB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,cAAc,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC3D,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAaD,MAAM,CAAC,OAAO,OAAO,gBAAgB;IAC5B,iBAAiB,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC;IACpC,iBAAiB,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC;IAC3C,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,oBAAoB,CAAgB;IAC5C,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,eAAe,CAAmB;IAC1C,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,UAAU,CAAC,CAAa;IAChC,OAAO,CAAC,oBAAoB,CAAgB;IAC5C,OAAO,CAAC,cAAc,CAAmB;IACzC,OAAO,CAAC,GAAG,CAAC,CAAU;IACtB,OAAO,CAAC,cAAc,CAA6C;IACnE,OAAO,CAAC,eAAe,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,CAAS;gBAEd,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,WAAW,EACX,OAAO,EACP,WAAW,EACX,cAAc,EACd,UAAU,EACV,UAAU,EACV,GAAG,EACH,cAAc,EACd,eAAe,EACf,QAAQ,GACT,EAAE,sBAAsB;IAuBlB,MAAM,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IAWnC,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,gBAAgB,GAAG,IAAI;IAanD,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAchC,cAAc,IAAI,IAAI;IAU7B,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,cAAc;IAkCtB,OAAO,CAAC,oBAAoB;IA0C5B,OAAO,CAAC,QAAQ;IAoBhB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,uBAAuB;IAkB/B,OAAO,CAAC,gBAAgB;IA6BxB,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,kBAAkB;CAG3B"}
1
+ {"version":3,"file":"elementsRenderer.d.ts","sourceRoot":"","sources":["../src/elementsRenderer.ts"],"names":[],"mappings":"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"}
@@ -13,21 +13,25 @@ import { getBoolString } from './util.js';
13
13
  */
14
14
  class ElementsRenderer {
15
15
  constructor({
16
+ _ariaLabel: ariaLabel,
17
+ _ariaLabelledBy: ariaLabelledBy,
16
18
  _autoEscape: autoEscape,
17
19
  _buttonLeft: buttonLeft,
18
20
  _classNames: classNames,
19
- _closedIcon: closedIcon,
21
+ _closedIcon: closedIcon = "-",
20
22
  _dragAndDrop: dragAndDrop,
21
23
  _getTree: getTree,
22
24
  _htmlElement: htmlElement,
23
25
  _isNodeSelected: isNodeSelected,
24
26
  _onCreateLi: onCreateLi,
25
- _openedIcon: openedIcon,
27
+ _openedIcon: openedIcon = "+",
26
28
  _rtl: rtl,
27
29
  _setNodeElement: setNodeElement,
28
30
  _showEmptyFolder: showEmptyFolder,
29
31
  _tabIndex: tabIndex
30
32
  }) {
33
+ this._ariaLabel = ariaLabel;
34
+ this._ariaLabelledBy = ariaLabelledBy;
31
35
  this._autoEscape = autoEscape;
32
36
  this._buttonLeft = buttonLeft;
33
37
  this._classNames = classNames;
@@ -40,8 +44,8 @@ class ElementsRenderer {
40
44
  this._setNodeElement = setNodeElement;
41
45
  this._showEmptyFolder = showEmptyFolder;
42
46
  this._tabIndex = tabIndex;
43
- this._openedIconElement = this._createButtonElement(openedIcon ?? "+");
44
- this._closedIconElement = this._createButtonElement(closedIcon ?? "-");
47
+ this._openedIconElement = this._createButtonElement(openedIcon);
48
+ this._closedIconElement = this._createButtonElement(closedIcon);
45
49
  this._rootUlTemplate = this._createUlTemplate(true);
46
50
  this._groupUlTemplate = this._createUlTemplate(false);
47
51
  this._nodeTemplate = this._createNodeTemplate();
@@ -60,10 +64,7 @@ class ElementsRenderer {
60
64
  * null when the folder is not rendered or has no children.
61
65
  */
62
66
  _renderChildren(node) {
63
- if (!node.element || !node.hasChildren()) {
64
- return null;
65
- }
66
- return this._createDomElements(node.element, node.children, false, node.getLevel() + 1);
67
+ return !node.element || !node.hasChildren() ? null : this._createDomElements(node.element, node.children, false, node.getLevel() + 1);
67
68
  }
68
69
  _renderFromNode(node) {
69
70
  if (!node.element) {
@@ -95,21 +96,19 @@ class ElementsRenderer {
95
96
  _createButtonElement(value) {
96
97
  if (typeof value === "string") {
97
98
  let template = document.createElement("template");
99
+ // eslint-disable-next-line no-unsanitized/property -- icon options are documented to accept html
98
100
  template.innerHTML = value;
99
101
  return template.content;
100
- } else if (value.nodeType) {
101
- return value;
102
- } else {
103
- return undefined;
104
102
  }
103
+ return value.nodeType ? value : undefined;
105
104
  }
106
105
  _createDomElements(element, children, isRootNode, level) {
107
106
  let template = isRootNode ? this._rootUlTemplate : this._groupUlTemplate;
108
107
  let ul = template.cloneNode();
109
- element.appendChild(ul);
108
+ element.append(ul);
110
109
  for (let child of children) {
111
110
  let li = this._createLi(child, level);
112
- ul.appendChild(li);
111
+ ul.append(li);
113
112
  if (this._mustRenderChildren(child)) {
114
113
  this._createDomElements(li, child.children, false, level + 1);
115
114
  }
@@ -122,19 +121,20 @@ class ElementsRenderer {
122
121
  if (isSelected) {
123
122
  li.classList.add(this._classNames.selected);
124
123
  }
125
- if (node.is_loading) {
126
- li.classList.add(this._classNames.loading);
127
- }
128
124
 
129
- // li > div > [button link], title span, [button link]
125
+ // li > div > [toggler], title span, [toggler]
130
126
  let div = li.firstChild;
131
127
  let titleSpan = div.childNodes[this._buttonLeft ? 1 : 0];
132
128
  this._fillTitleSpan(titleSpan, node.name, isSelected, level);
129
+ if (node.is_loading) {
130
+ li.classList.add(this._classNames.loading);
131
+ titleSpan.setAttribute("aria-busy", "true");
132
+ }
133
133
  return li;
134
134
  }
135
135
 
136
136
  /* Template for a folder <li>:
137
- * li > div > [button link], title span, [button link]
137
+ * li > div > [toggler], title span, [toggler]
138
138
  * The toggler icon and the aria-expanded attribute depend on the open
139
139
  * state, so there is a template for each.
140
140
  */
@@ -146,23 +146,25 @@ class ElementsRenderer {
146
146
  let li = this._createLiTemplate(liClasses.join(" "));
147
147
  let div = li.firstChild;
148
148
 
149
- // button link
150
- let buttonLink = document.createElement("a");
151
- buttonLink.className = this._getButtonClasses(isOpen);
149
+ // The toggler is hidden from screen readers: the icon is decoration, and
150
+ // aria-expanded on the treeitem has the open state.
151
+ let toggler = document.createElement("span");
152
+ toggler.className = this._getButtonClasses(isOpen);
153
+ toggler.setAttribute("aria-hidden", "true");
152
154
  let iconElement = isOpen ? this._openedIconElement : this._closedIconElement;
153
155
  if (iconElement) {
154
- buttonLink.appendChild(iconElement.cloneNode(true));
156
+ toggler.append(iconElement.cloneNode(true));
155
157
  }
156
158
  if (this._buttonLeft) {
157
- div.appendChild(buttonLink);
159
+ div.append(toggler);
158
160
  }
159
161
 
160
162
  // title span
161
163
  let titleSpan = this._createTitleSpanTemplate(true);
162
164
  titleSpan.setAttribute("aria-expanded", getBoolString(isOpen));
163
- div.appendChild(titleSpan);
165
+ div.append(titleSpan);
164
166
  if (!this._buttonLeft) {
165
- div.appendChild(buttonLink);
167
+ div.append(toggler);
166
168
  }
167
169
  return li;
168
170
  }
@@ -182,7 +184,9 @@ class ElementsRenderer {
182
184
  return li;
183
185
  }
184
186
 
185
- /* Create the outer part of a <li> template: li > div */
187
+ /*
188
+ Create the outer part of a <li> template: li > div
189
+ */
186
190
  _createLiTemplate(liClasses) {
187
191
  let li = document.createElement("li");
188
192
  li.className = liClasses;
@@ -190,7 +194,7 @@ class ElementsRenderer {
190
194
  let div = document.createElement("div");
191
195
  div.className = `${this._classNames.element} ${this._classNames.common}`;
192
196
  div.setAttribute("role", "none");
193
- li.appendChild(div);
197
+ li.append(div);
194
198
  return li;
195
199
  }
196
200
  _createNodeLi(node, level, isSelected) {
@@ -206,11 +210,13 @@ class ElementsRenderer {
206
210
  return li;
207
211
  }
208
212
 
209
- /* Template for a <li> without children: li > div > title span */
213
+ /*
214
+ Template for a <li> without children: li > div > title span
215
+ */
210
216
  _createNodeTemplate() {
211
217
  let li = this._createLiTemplate(this._classNames.common);
212
218
  let div = li.firstChild;
213
- div.appendChild(this._createTitleSpanTemplate(false));
219
+ div.append(this._createTitleSpanTemplate(false));
214
220
  return li;
215
221
  }
216
222
  _createTitleSpanTemplate(isFolder) {
@@ -223,20 +229,25 @@ class ElementsRenderer {
223
229
  titleSpan.className = classes;
224
230
  titleSpan.setAttribute("role", "treeitem");
225
231
  titleSpan.setAttribute("aria-selected", "false");
232
+
233
+ // Every node is focusable, but only the tab stop is in the tab order
234
+ if (this._tabIndex !== undefined) {
235
+ titleSpan.setAttribute("tabindex", "-1");
236
+ }
226
237
  return titleSpan;
227
238
  }
228
239
  _createUlTemplate(isRootNode) {
229
240
  let classString;
230
241
  let role;
231
- if (!isRootNode) {
232
- classString = "";
233
- role = "group";
234
- } else {
242
+ if (isRootNode) {
235
243
  classString = this._classNames.tree;
236
244
  role = "tree";
237
245
  if (this._rtl) {
238
246
  classString += ` ${this._classNames.rtl}`;
239
247
  }
248
+ } else {
249
+ classString = "";
250
+ role = "group";
240
251
  }
241
252
  if (this._dragAndDrop) {
242
253
  classString += ` ${this._classNames.dnd}`;
@@ -244,23 +255,33 @@ class ElementsRenderer {
244
255
  let ul = document.createElement("ul");
245
256
  ul.className = `${this._classNames.common} ${classString}`;
246
257
  ul.setAttribute("role", role);
258
+ if (isRootNode) {
259
+ if (this._ariaLabel !== undefined) {
260
+ ul.setAttribute("aria-label", this._ariaLabel);
261
+ }
262
+ if (this._ariaLabelledBy !== undefined) {
263
+ ul.setAttribute("aria-labelledby", this._ariaLabelledBy);
264
+ }
265
+ }
247
266
  return ul;
248
267
  }
249
268
 
250
- /* Set the parts of a cloned title span that differ per node */
269
+ /*
270
+ Set the parts of a cloned title span that differ per node
271
+ */
251
272
  _fillTitleSpan(titleSpan, nodeName, isSelected, level) {
252
- titleSpan.setAttribute("aria-label", nodeName);
253
- titleSpan.setAttribute("aria-level", `${level}`);
273
+ titleSpan.setAttribute("aria-level", String(level));
254
274
  if (isSelected) {
255
275
  titleSpan.setAttribute("aria-selected", "true");
256
276
  let tabIndex = this._tabIndex;
257
277
  if (tabIndex !== undefined) {
258
- titleSpan.setAttribute("tabindex", `${tabIndex}`);
278
+ titleSpan.setAttribute("tabindex", String(tabIndex));
259
279
  }
260
280
  }
261
281
  if (this._autoEscape) {
262
282
  titleSpan.textContent = nodeName;
263
283
  } else {
284
+ // eslint-disable-next-line no-unsanitized/property -- the user opted out of escaping with autoEscape: false
264
285
  titleSpan.innerHTML = nodeName;
265
286
  }
266
287
  }
@@ -277,7 +298,9 @@ class ElementsRenderer {
277
298
  return classes.join(" ");
278
299
  }
279
300
 
280
- /* The children of a closed folder are rendered when it is opened */
301
+ /*
302
+ The children of a closed folder are rendered when it is opened
303
+ */
281
304
  _mustRenderChildren(node) {
282
305
  return node.hasChildren() && node.is_open === true;
283
306
  }
@@ -1 +1 @@
1
- {"version":3,"file":"elementsRenderer.js","sources":["../src/elementsRenderer.ts"],"sourcesContent":["import type { ClassNames } from \"./classNames\";\nimport type { GetTree, IsNodeSelected } from \"./methodTypes\";\nimport type { Node } from \"./node\";\nimport type { IconElement, OnCreateLi } from \"./options\";\n\nimport { getBoolString } from \"./util\";\n\ninterface ElementsRendererParams {\n autoEscape: boolean;\n buttonLeft: boolean;\n classNames: ClassNames;\n closedIcon?: IconElement;\n dragAndDrop: boolean;\n getTree: GetTree;\n htmlElement: HTMLElement;\n isNodeSelected: IsNodeSelected;\n onCreateLi?: OnCreateLi;\n openedIcon?: IconElement;\n rtl?: boolean;\n setNodeElement: (element: HTMLElement, node: Node) => void;\n showEmptyFolder: boolean;\n tabIndex?: number;\n}\n\n/* Renders the tree to html.\n *\n * The children of a closed folder are not rendered. They are rendered when\n * the folder is opened, see renderChildren.\n *\n * The elements are created by cloning templates. A template is a fully\n * built <li> or <ul> with everything that is the same for every node\n * (structure, roles, static classes, the toggler icon). Per node only the\n * parts that differ are set: the title, the aria attributes and the\n * selected and loading classes.\n */\nexport default class ElementsRenderer {\n public closedIconElement?: globalThis.Node;\n public openedIconElement?: globalThis.Node;\n private autoEscape: boolean;\n private buttonLeft: boolean;\n private classNames: ClassNames;\n private closedFolderTemplate: HTMLLIElement;\n private dragAndDrop: boolean;\n private getTree: GetTree;\n private groupUlTemplate: HTMLUListElement;\n private htmlElement: HTMLElement;\n private isNodeSelected: IsNodeSelected;\n private nodeTemplate: HTMLLIElement;\n private onCreateLi?: OnCreateLi;\n private openedFolderTemplate: HTMLLIElement;\n private rootUlTemplate: HTMLUListElement;\n private rtl?: boolean;\n private setNodeElement: (element: HTMLElement, node: Node) => void;\n private showEmptyFolder: boolean;\n private tabIndex?: number;\n\n constructor({\n autoEscape,\n buttonLeft,\n classNames,\n closedIcon,\n dragAndDrop,\n getTree,\n htmlElement,\n isNodeSelected,\n onCreateLi,\n openedIcon,\n rtl,\n setNodeElement,\n showEmptyFolder,\n tabIndex,\n }: ElementsRendererParams) {\n this.autoEscape = autoEscape;\n this.buttonLeft = buttonLeft;\n this.classNames = classNames;\n this.dragAndDrop = dragAndDrop;\n this.getTree = getTree;\n this.htmlElement = htmlElement;\n this.isNodeSelected = isNodeSelected;\n this.onCreateLi = onCreateLi;\n this.rtl = rtl;\n this.setNodeElement = setNodeElement;\n this.showEmptyFolder = showEmptyFolder;\n this.tabIndex = tabIndex;\n this.openedIconElement = this.createButtonElement(openedIcon ?? \"+\");\n this.closedIconElement = this.createButtonElement(closedIcon ?? \"-\");\n\n this.rootUlTemplate = this.createUlTemplate(true);\n this.groupUlTemplate = this.createUlTemplate(false);\n this.nodeTemplate = this.createNodeTemplate();\n this.openedFolderTemplate = this.createFolderTemplate(true);\n this.closedFolderTemplate = this.createFolderTemplate(false);\n }\n\n public render(fromNode: Node | null): void {\n if (fromNode?.parent) {\n this.renderFromNode(fromNode);\n } else {\n this.renderFromRoot();\n }\n }\n\n /* Render the children of a rendered folder. Returns the new <ul>, or\n * null when the folder is not rendered or has no children.\n */\n public renderChildren(node: Node): HTMLUListElement | null {\n if (!node.element || !node.hasChildren()) {\n return null;\n }\n\n return this.createDomElements(\n node.element,\n node.children,\n false,\n node.getLevel() + 1,\n );\n }\n\n public renderFromNode(node: Node): void {\n if (!node.element) {\n return;\n }\n\n const currentLi = node.element;\n const newLi = this.createLi(node, node.getLevel());\n currentLi.replaceWith(newLi);\n\n if (this.mustRenderChildren(node)) {\n this.createDomElements(newLi, node.children, false, node.getLevel() + 1);\n }\n }\n\n public renderFromRoot(): void {\n this.htmlElement.textContent = \"\";\n\n const tree = this.getTree();\n\n if (tree) {\n this.createDomElements(this.htmlElement, tree.children, true, 1);\n }\n }\n\n private attachNodeData(node: Node, li: HTMLElement): void {\n node.element = li;\n this.setNodeElement(li, node);\n }\n\n /* Returns the template of a toggler icon; it is cloned for every folder.\n * A string is parsed as html and becomes a fragment, so it can hold\n * entities, text and elements.\n */\n private createButtonElement(value: IconElement): globalThis.Node | undefined {\n if (typeof value === \"string\") {\n const template = document.createElement(\"template\");\n template.innerHTML = value;\n\n return template.content;\n } else if (value.nodeType) {\n return value;\n } else {\n return undefined;\n }\n }\n\n private createDomElements(\n element: Element,\n children: Node[],\n isRootNode: boolean,\n level: number,\n ): HTMLUListElement {\n const template = isRootNode ? this.rootUlTemplate : this.groupUlTemplate;\n const ul = template.cloneNode() as HTMLUListElement;\n element.appendChild(ul);\n\n for (const child of children) {\n const li = this.createLi(child, level);\n ul.appendChild(li);\n\n if (this.mustRenderChildren(child)) {\n this.createDomElements(li, child.children, false, level + 1);\n }\n }\n\n return ul;\n }\n\n private createFolderLi(\n node: Node,\n level: number,\n isSelected: boolean,\n ): HTMLLIElement {\n const template = node.is_open\n ? this.openedFolderTemplate\n : this.closedFolderTemplate;\n const li = template.cloneNode(true) as HTMLLIElement;\n\n if (isSelected) {\n li.classList.add(this.classNames.selected);\n }\n\n if (node.is_loading) {\n li.classList.add(this.classNames.loading);\n }\n\n // li > div > [button link], title span, [button link]\n const div = li.firstChild as HTMLDivElement;\n const titleSpan = div.childNodes[\n this.buttonLeft ? 1 : 0\n ] as HTMLSpanElement;\n\n this.fillTitleSpan(titleSpan, node.name, isSelected, level);\n\n return li;\n }\n\n /* Template for a folder <li>:\n * li > div > [button link], title span, [button link]\n * The toggler icon and the aria-expanded attribute depend on the open\n * state, so there is a template for each.\n */\n private createFolderTemplate(isOpen: boolean): HTMLLIElement {\n const liClasses = [this.classNames.common, this.classNames.folder];\n\n if (!isOpen) {\n liClasses.push(this.classNames.closed);\n }\n\n const li = this.createLiTemplate(liClasses.join(\" \"));\n const div = li.firstChild as HTMLDivElement;\n\n // button link\n const buttonLink = document.createElement(\"a\");\n buttonLink.className = this.getButtonClasses(isOpen);\n\n const iconElement = isOpen\n ? this.openedIconElement\n : this.closedIconElement;\n\n if (iconElement) {\n buttonLink.appendChild(iconElement.cloneNode(true));\n }\n\n if (this.buttonLeft) {\n div.appendChild(buttonLink);\n }\n\n // title span\n const titleSpan = this.createTitleSpanTemplate(true);\n titleSpan.setAttribute(\"aria-expanded\", getBoolString(isOpen));\n div.appendChild(titleSpan);\n\n if (!this.buttonLeft) {\n div.appendChild(buttonLink);\n }\n\n return li;\n }\n\n /* Create the <li> element\n * Attach it to node.element.\n * Call onCreateLi\n */\n private createLi(node: Node, level: number): HTMLLIElement {\n const isSelected = this.isNodeSelected(node);\n\n const mustShowFolder =\n node.isFolder() || (node.isEmptyFolder && this.showEmptyFolder);\n\n const li = mustShowFolder\n ? this.createFolderLi(node, level, isSelected)\n : this.createNodeLi(node, level, isSelected);\n\n this.attachNodeData(node, li);\n\n if (this.onCreateLi) {\n this.onCreateLi(node, li, isSelected);\n }\n\n return li;\n }\n\n /* Create the outer part of a <li> template: li > div */\n private createLiTemplate(liClasses: string): HTMLLIElement {\n const li = document.createElement(\"li\");\n li.className = liClasses;\n li.setAttribute(\"role\", \"none\");\n\n const div = document.createElement(\"div\");\n div.className = `${this.classNames.element} ${this.classNames.common}`;\n div.setAttribute(\"role\", \"none\");\n\n li.appendChild(div);\n\n return li;\n }\n\n private createNodeLi(\n node: Node,\n level: number,\n isSelected: boolean,\n ): HTMLLIElement {\n const li = this.nodeTemplate.cloneNode(true) as HTMLLIElement;\n\n if (isSelected) {\n li.classList.add(this.classNames.selected);\n }\n\n // li > div > title span\n const div = li.firstChild as HTMLDivElement;\n const titleSpan = div.firstChild as HTMLSpanElement;\n\n this.fillTitleSpan(titleSpan, node.name, isSelected, level);\n\n return li;\n }\n\n /* Template for a <li> without children: li > div > title span */\n private createNodeTemplate(): HTMLLIElement {\n const li = this.createLiTemplate(this.classNames.common);\n const div = li.firstChild as HTMLDivElement;\n\n div.appendChild(this.createTitleSpanTemplate(false));\n\n return li;\n }\n\n private createTitleSpanTemplate(isFolder: boolean): HTMLSpanElement {\n const titleSpan = document.createElement(\"span\");\n\n let classes = `${this.classNames.title} ${this.classNames.common}`;\n\n if (isFolder) {\n classes += ` ${this.classNames.titleFolder}`;\n }\n\n classes += ` ${this.buttonLeft ? this.classNames.titleButtonLeft : this.classNames.titleButtonRight}`;\n\n titleSpan.className = classes;\n titleSpan.setAttribute(\"role\", \"treeitem\");\n titleSpan.setAttribute(\"aria-selected\", \"false\");\n\n return titleSpan;\n }\n\n private createUlTemplate(isRootNode: boolean): HTMLUListElement {\n let classString;\n let role;\n\n if (!isRootNode) {\n classString = \"\";\n role = \"group\";\n } else {\n classString = this.classNames.tree;\n role = \"tree\";\n\n if (this.rtl) {\n classString += ` ${this.classNames.rtl}`;\n }\n }\n\n if (this.dragAndDrop) {\n classString += ` ${this.classNames.dnd}`;\n }\n\n const ul = document.createElement(\"ul\");\n ul.className = `${this.classNames.common} ${classString}`;\n\n ul.setAttribute(\"role\", role);\n\n return ul;\n }\n\n /* Set the parts of a cloned title span that differ per node */\n private fillTitleSpan(\n titleSpan: HTMLSpanElement,\n nodeName: string,\n isSelected: boolean,\n level: number,\n ): void {\n titleSpan.setAttribute(\"aria-label\", nodeName);\n titleSpan.setAttribute(\"aria-level\", `${level}`);\n\n if (isSelected) {\n titleSpan.setAttribute(\"aria-selected\", \"true\");\n\n const tabIndex = this.tabIndex;\n\n if (tabIndex !== undefined) {\n titleSpan.setAttribute(\"tabindex\", `${tabIndex}`);\n }\n }\n\n if (this.autoEscape) {\n titleSpan.textContent = nodeName;\n } else {\n titleSpan.innerHTML = nodeName;\n }\n }\n\n private getButtonClasses(isOpen: boolean): string {\n const classes = [this.classNames.toggler, this.classNames.common];\n\n if (!isOpen) {\n classes.push(this.classNames.closed);\n }\n\n if (this.buttonLeft) {\n classes.push(this.classNames.togglerLeft);\n } else {\n classes.push(this.classNames.togglerRight);\n }\n\n return classes.join(\" \");\n }\n\n /* The children of a closed folder are rendered when it is opened */\n private mustRenderChildren(node: Node): boolean {\n return node.hasChildren() && node.is_open === true;\n }\n}\n"],"names":["autoEscape","buttonLeft","classNames","dragAndDrop","getTree","htmlElement","isNodeSelected","onCreateLi","rtl","setNodeElement","showEmptyFolder","tabIndex","openedIconElement","createButtonElement","closedIconElement","rootUlTemplate","createUlTemplate","groupUlTemplate","nodeTemplate","createNodeTemplate","openedFolderTemplate","createFolderTemplate","closedFolderTemplate","render","renderFromNode","renderFromRoot","renderChildren","createDomElements","createLi","mustRenderChildren","attachNodeData","createFolderLi","fillTitleSpan","createLiTemplate","getButtonClasses","createTitleSpanTemplate","createNodeLi"],"mappings":"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"}
1
+ {"version":3,"file":"elementsRenderer.js","sources":["../src/elementsRenderer.ts"],"sourcesContent":["import type { ClassNames } from \"./classNames\";\nimport type { GetTree, IsNodeSelected } from \"./methodTypes\";\nimport type { Node } from \"./node\";\nimport type { IconElement, OnCreateLi } from \"./options\";\n\nimport { getBoolString } from \"./util\";\n\ninterface ElementsRendererParams {\n ariaLabel?: string;\n ariaLabelledBy?: string;\n autoEscape: boolean;\n buttonLeft: boolean;\n classNames: ClassNames;\n closedIcon?: IconElement;\n dragAndDrop: boolean;\n getTree: GetTree;\n htmlElement: HTMLElement;\n isNodeSelected: IsNodeSelected;\n onCreateLi?: OnCreateLi;\n openedIcon?: IconElement;\n rtl?: boolean;\n setNodeElement: (element: HTMLElement, node: Node) => void;\n showEmptyFolder: boolean;\n tabIndex?: number;\n}\n\n/* Renders the tree to html.\n *\n * The children of a closed folder are not rendered. They are rendered when\n * the folder is opened, see renderChildren.\n *\n * The elements are created by cloning templates. A template is a fully\n * built <li> or <ul> with everything that is the same for every node\n * (structure, roles, static classes, the toggler icon). Per node only the\n * parts that differ are set: the title, the aria attributes and the\n * selected and loading classes.\n */\nexport default class ElementsRenderer {\n public closedIconElement?: globalThis.Node;\n public openedIconElement?: globalThis.Node;\n private ariaLabel?: string;\n private ariaLabelledBy?: string;\n private autoEscape: boolean;\n private buttonLeft: boolean;\n private classNames: ClassNames;\n private closedFolderTemplate: HTMLLIElement;\n private dragAndDrop: boolean;\n private getTree: GetTree;\n private groupUlTemplate: HTMLUListElement;\n private htmlElement: HTMLElement;\n private isNodeSelected: IsNodeSelected;\n private nodeTemplate: HTMLLIElement;\n private onCreateLi?: OnCreateLi;\n private openedFolderTemplate: HTMLLIElement;\n private rootUlTemplate: HTMLUListElement;\n private rtl?: boolean;\n private setNodeElement: (element: HTMLElement, node: Node) => void;\n private showEmptyFolder: boolean;\n private tabIndex?: number;\n\n constructor({\n ariaLabel,\n ariaLabelledBy,\n autoEscape,\n buttonLeft,\n classNames,\n closedIcon = \"-\",\n dragAndDrop,\n getTree,\n htmlElement,\n isNodeSelected,\n onCreateLi,\n openedIcon = \"+\",\n rtl,\n setNodeElement,\n showEmptyFolder,\n tabIndex,\n }: ElementsRendererParams) {\n this.ariaLabel = ariaLabel;\n this.ariaLabelledBy = ariaLabelledBy;\n this.autoEscape = autoEscape;\n this.buttonLeft = buttonLeft;\n this.classNames = classNames;\n this.dragAndDrop = dragAndDrop;\n this.getTree = getTree;\n this.htmlElement = htmlElement;\n this.isNodeSelected = isNodeSelected;\n this.onCreateLi = onCreateLi;\n this.rtl = rtl;\n this.setNodeElement = setNodeElement;\n this.showEmptyFolder = showEmptyFolder;\n this.tabIndex = tabIndex;\n this.openedIconElement = this.createButtonElement(openedIcon);\n this.closedIconElement = this.createButtonElement(closedIcon);\n\n this.rootUlTemplate = this.createUlTemplate(true);\n this.groupUlTemplate = this.createUlTemplate(false);\n this.nodeTemplate = this.createNodeTemplate();\n this.openedFolderTemplate = this.createFolderTemplate(true);\n this.closedFolderTemplate = this.createFolderTemplate(false);\n }\n\n public render(fromNode: Node | null): void {\n if (fromNode?.parent) {\n this.renderFromNode(fromNode);\n } else {\n this.renderFromRoot();\n }\n }\n\n /* Render the children of a rendered folder. Returns the new <ul>, or\n * null when the folder is not rendered or has no children.\n */\n public renderChildren(node: Node): HTMLUListElement | null {\n return !node.element || !node.hasChildren()\n ? null\n : this.createDomElements(\n node.element,\n node.children,\n false,\n node.getLevel() + 1,\n );\n }\n\n public renderFromNode(node: Node): void {\n if (!node.element) {\n return;\n }\n\n const currentLi = node.element;\n const newLi = this.createLi(node, node.getLevel());\n currentLi.replaceWith(newLi);\n\n if (this.mustRenderChildren(node)) {\n this.createDomElements(newLi, node.children, false, node.getLevel() + 1);\n }\n }\n\n public renderFromRoot(): void {\n this.htmlElement.textContent = \"\";\n\n const tree = this.getTree();\n\n if (tree) {\n this.createDomElements(this.htmlElement, tree.children, true, 1);\n }\n }\n\n private attachNodeData(node: Node, li: HTMLElement): void {\n node.element = li;\n this.setNodeElement(li, node);\n }\n\n /* Returns the template of a toggler icon; it is cloned for every folder.\n * A string is parsed as html and becomes a fragment, so it can hold\n * entities, text and elements.\n */\n private createButtonElement(value: IconElement): globalThis.Node | undefined {\n if (typeof value === \"string\") {\n const template = document.createElement(\"template\");\n // eslint-disable-next-line no-unsanitized/property -- icon options are documented to accept html\n template.innerHTML = value;\n\n return template.content;\n }\n return value.nodeType ? value : undefined;\n }\n\n private createDomElements(\n element: Element,\n children: Node[],\n isRootNode: boolean,\n level: number,\n ): HTMLUListElement {\n const template = isRootNode ? this.rootUlTemplate : this.groupUlTemplate;\n const ul = template.cloneNode() as HTMLUListElement;\n element.append(ul);\n\n for (const child of children) {\n const li = this.createLi(child, level);\n ul.append(li);\n\n if (this.mustRenderChildren(child)) {\n this.createDomElements(li, child.children, false, level + 1);\n }\n }\n\n return ul;\n }\n\n private createFolderLi(\n node: Node,\n level: number,\n isSelected: boolean,\n ): HTMLLIElement {\n const template = node.is_open\n ? this.openedFolderTemplate\n : this.closedFolderTemplate;\n const li = template.cloneNode(true) as HTMLLIElement;\n\n if (isSelected) {\n li.classList.add(this.classNames.selected);\n }\n\n // li > div > [toggler], title span, [toggler]\n const div = li.firstChild as HTMLDivElement;\n const titleSpan = div.childNodes[\n this.buttonLeft ? 1 : 0\n ] as HTMLSpanElement;\n\n this.fillTitleSpan(titleSpan, node.name, isSelected, level);\n\n if (node.is_loading) {\n li.classList.add(this.classNames.loading);\n titleSpan.setAttribute(\"aria-busy\", \"true\");\n }\n\n return li;\n }\n\n /* Template for a folder <li>:\n * li > div > [toggler], title span, [toggler]\n * The toggler icon and the aria-expanded attribute depend on the open\n * state, so there is a template for each.\n */\n private createFolderTemplate(isOpen: boolean): HTMLLIElement {\n const liClasses = [this.classNames.common, this.classNames.folder];\n\n if (!isOpen) {\n liClasses.push(this.classNames.closed);\n }\n\n const li = this.createLiTemplate(liClasses.join(\" \"));\n const div = li.firstChild as HTMLDivElement;\n\n // The toggler is hidden from screen readers: the icon is decoration, and\n // aria-expanded on the treeitem has the open state.\n const toggler = document.createElement(\"span\");\n toggler.className = this.getButtonClasses(isOpen);\n toggler.setAttribute(\"aria-hidden\", \"true\");\n\n const iconElement = isOpen\n ? this.openedIconElement\n : this.closedIconElement;\n\n if (iconElement) {\n toggler.append(iconElement.cloneNode(true));\n }\n\n if (this.buttonLeft) {\n div.append(toggler);\n }\n\n // title span\n const titleSpan = this.createTitleSpanTemplate(true);\n titleSpan.setAttribute(\"aria-expanded\", getBoolString(isOpen));\n div.append(titleSpan);\n\n if (!this.buttonLeft) {\n div.append(toggler);\n }\n\n return li;\n }\n\n /* Create the <li> element\n * Attach it to node.element.\n * Call onCreateLi\n */\n private createLi(node: Node, level: number): HTMLLIElement {\n const isSelected = this.isNodeSelected(node);\n\n const mustShowFolder =\n node.isFolder() || (node.isEmptyFolder && this.showEmptyFolder);\n\n const li = mustShowFolder\n ? this.createFolderLi(node, level, isSelected)\n : this.createNodeLi(node, level, isSelected);\n\n this.attachNodeData(node, li);\n\n if (this.onCreateLi) {\n this.onCreateLi(node, li, isSelected);\n }\n\n return li;\n }\n\n /*\n Create the outer part of a <li> template: li > div\n */\n private createLiTemplate(liClasses: string): HTMLLIElement {\n const li = document.createElement(\"li\");\n li.className = liClasses;\n li.setAttribute(\"role\", \"none\");\n\n const div = document.createElement(\"div\");\n div.className = `${this.classNames.element} ${this.classNames.common}`;\n div.setAttribute(\"role\", \"none\");\n\n li.append(div);\n\n return li;\n }\n\n private createNodeLi(\n node: Node,\n level: number,\n isSelected: boolean,\n ): HTMLLIElement {\n const li = this.nodeTemplate.cloneNode(true) as HTMLLIElement;\n\n if (isSelected) {\n li.classList.add(this.classNames.selected);\n }\n\n // li > div > title span\n const div = li.firstChild as HTMLDivElement;\n const titleSpan = div.firstChild as HTMLSpanElement;\n\n this.fillTitleSpan(titleSpan, node.name, isSelected, level);\n\n return li;\n }\n\n /*\n Template for a <li> without children: li > div > title span\n */\n private createNodeTemplate(): HTMLLIElement {\n const li = this.createLiTemplate(this.classNames.common);\n const div = li.firstChild as HTMLDivElement;\n\n div.append(this.createTitleSpanTemplate(false));\n\n return li;\n }\n\n private createTitleSpanTemplate(isFolder: boolean): HTMLSpanElement {\n const titleSpan = document.createElement(\"span\");\n\n let classes = `${this.classNames.title} ${this.classNames.common}`;\n\n if (isFolder) {\n classes += ` ${this.classNames.titleFolder}`;\n }\n\n classes += ` ${this.buttonLeft ? this.classNames.titleButtonLeft : this.classNames.titleButtonRight}`;\n\n titleSpan.className = classes;\n titleSpan.setAttribute(\"role\", \"treeitem\");\n titleSpan.setAttribute(\"aria-selected\", \"false\");\n\n // Every node is focusable, but only the tab stop is in the tab order\n if (this.tabIndex !== undefined) {\n titleSpan.setAttribute(\"tabindex\", \"-1\");\n }\n\n return titleSpan;\n }\n\n private createUlTemplate(isRootNode: boolean): HTMLUListElement {\n let classString;\n let role;\n\n if (isRootNode) {\n classString = this.classNames.tree;\n role = \"tree\";\n\n if (this.rtl) {\n classString += ` ${this.classNames.rtl}`;\n }\n } else {\n classString = \"\";\n role = \"group\";\n }\n\n if (this.dragAndDrop) {\n classString += ` ${this.classNames.dnd}`;\n }\n\n const ul = document.createElement(\"ul\");\n ul.className = `${this.classNames.common} ${classString}`;\n\n ul.setAttribute(\"role\", role);\n\n if (isRootNode) {\n if (this.ariaLabel !== undefined) {\n ul.setAttribute(\"aria-label\", this.ariaLabel);\n }\n\n if (this.ariaLabelledBy !== undefined) {\n ul.setAttribute(\"aria-labelledby\", this.ariaLabelledBy);\n }\n }\n\n return ul;\n }\n\n /*\n Set the parts of a cloned title span that differ per node\n */\n private fillTitleSpan(\n titleSpan: HTMLSpanElement,\n nodeName: string,\n isSelected: boolean,\n level: number,\n ): void {\n titleSpan.setAttribute(\"aria-level\", String(level));\n\n if (isSelected) {\n titleSpan.setAttribute(\"aria-selected\", \"true\");\n\n const tabIndex = this.tabIndex;\n\n if (tabIndex !== undefined) {\n titleSpan.setAttribute(\"tabindex\", String(tabIndex));\n }\n }\n\n if (this.autoEscape) {\n titleSpan.textContent = nodeName;\n } else {\n // eslint-disable-next-line no-unsanitized/property -- the user opted out of escaping with autoEscape: false\n titleSpan.innerHTML = nodeName;\n }\n }\n\n private getButtonClasses(isOpen: boolean): string {\n const classes = [this.classNames.toggler, this.classNames.common];\n\n if (!isOpen) {\n classes.push(this.classNames.closed);\n }\n\n if (this.buttonLeft) {\n classes.push(this.classNames.togglerLeft);\n } else {\n classes.push(this.classNames.togglerRight);\n }\n\n return classes.join(\" \");\n }\n\n /*\n The children of a closed folder are rendered when it is opened\n */\n private mustRenderChildren(node: Node): boolean {\n return node.hasChildren() && node.is_open === true;\n }\n}\n"],"names":["ariaLabel","ariaLabelledBy","autoEscape","buttonLeft","classNames","dragAndDrop","getTree","htmlElement","isNodeSelected","onCreateLi","rtl","setNodeElement","showEmptyFolder","tabIndex","openedIconElement","createButtonElement","closedIconElement","rootUlTemplate","createUlTemplate","groupUlTemplate","nodeTemplate","createNodeTemplate","openedFolderTemplate","createFolderTemplate","closedFolderTemplate","render","renderFromNode","renderFromRoot","renderChildren","createDomElements","createLi","mustRenderChildren","attachNodeData","createFolderLi","fillTitleSpan","createLiTemplate","getButtonClasses","createTitleSpanTemplate","createNodeLi"],"mappings":";;AA0BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,MAAM,gBAAgB,CAAC;AAuBpC,EAAA,WAAW,CAAC;IACV,UAAA,EAAA,SAAS;IACT,eAAA,EAAA,cAAc;IACd,WAAA,EAAA,UAAU;IACV,WAAA,EAAA,UAAU;IACV,WAAA,EAAA,UAAU;AACV,IAAA,WAAA,EAAA,UAAU,GAAG,GAAG;IAChB,YAAA,EAAA,WAAW;IACX,QAAA,EAAA,OAAO;IACP,YAAA,EAAA,WAAW;IACX,eAAA,EAAA,cAAc;IACd,WAAA,EAAA,UAAU;AACV,IAAA,WAAA,EAAA,UAAU,GAAG,GAAG;IAChB,IAAA,EAAA,GAAG;IACH,eAAA,EAAA,cAAc;IACd,gBAAA,EAAA,eAAe;AACf,IAAA,SAAA,EAAA;AACsB,GAAC,EAAE;IACzB,IAAI,CAACA,UAAS,GAAG,SAAS;IAC1B,IAAI,CAACC,eAAc,GAAG,cAAc;IACpC,IAAI,CAACC,WAAU,GAAG,UAAU;IAC5B,IAAI,CAACC,WAAU,GAAG,UAAU;IAC5B,IAAI,CAACC,WAAU,GAAG,UAAU;IAC5B,IAAI,CAACC,YAAW,GAAG,WAAW;IAC9B,IAAI,CAACC,QAAO,GAAG,OAAO;IACtB,IAAI,CAACC,YAAW,GAAG,WAAW;IAC9B,IAAI,CAACC,eAAc,GAAG,cAAc;IACpC,IAAI,CAACC,WAAU,GAAG,UAAU;IAC5B,IAAI,CAACC,IAAG,GAAG,GAAG;IACd,IAAI,CAACC,eAAc,GAAG,cAAc;IACpC,IAAI,CAACC,gBAAe,GAAG,eAAe;IACtC,IAAI,CAACC,SAAQ,GAAG,QAAQ;IACxB,IAAI,CAACC,kBAAiB,GAAG,IAAI,CAACC,oBAAmB,CAAC,UAAU,CAAC;IAC7D,IAAI,CAACC,kBAAiB,GAAG,IAAI,CAACD,oBAAmB,CAAC,UAAU,CAAC;IAE7D,IAAI,CAACE,eAAc,GAAG,IAAI,CAACC,iBAAgB,CAAC,IAAI,CAAC;IACjD,IAAI,CAACC,gBAAe,GAAG,IAAI,CAACD,iBAAgB,CAAC,KAAK,CAAC;AACnD,IAAA,IAAI,CAACE,aAAY,GAAG,IAAI,CAACC,mBAAkB,EAAE;IAC7C,IAAI,CAACC,qBAAoB,GAAG,IAAI,CAACC,qBAAoB,CAAC,IAAI,CAAC;IAC3D,IAAI,CAACC,qBAAoB,GAAG,IAAI,CAACD,qBAAoB,CAAC,KAAK,CAAC;AAC9D,EAAA;EAEOE,OAAMA,CAAC,QAAqB,EAAQ;IACzC,IAAI,QAAQ,EAAE,MAAM,EAAE;AACpB,MAAA,IAAI,CAACC,eAAc,CAAC,QAAQ,CAAC;AAC/B,IAAA,CAAC,MAAM;MACL,IAAI,CAACC,eAAc,EAAE;AACvB,IAAA;AACF,EAAA;;AAEA;AACF;AACA;EACSC,eAAcA,CAAC,IAAU,EAA2B;AACzD,IAAA,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GACvC,IAAI,GACJ,IAAI,CAACC,kBAAiB,CACpB,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,QAAQ,EACb,KAAK,EACL,IAAI,CAAC,QAAQ,EAAE,GAAG,CACpB,CAAC;AACP,EAAA;EAEOH,eAAcA,CAAC,IAAU,EAAQ;AACtC,IAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;AACjB,MAAA;AACF,IAAA;AAEA,IAAA,IAAM,SAAS,GAAG,IAAI,CAAC,OAAO;AAC9B,IAAA,IAAM,KAAK,GAAG,IAAI,CAACI,SAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;AAClD,IAAA,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC;AAE5B,IAAA,IAAI,IAAI,CAACC,mBAAkB,CAAC,IAAI,CAAC,EAAE;AACjC,MAAA,IAAI,CAACF,kBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAC1E,IAAA;AACF,EAAA;AAEOF,EAAAA,eAAcA,GAAS;AAC5B,IAAA,IAAI,CAACpB,YAAW,CAAC,WAAW,GAAG,EAAE;AAEjC,IAAA,IAAM,IAAI,GAAG,IAAI,CAACD,QAAO,EAAE;AAE3B,IAAA,IAAI,IAAI,EAAE;AACR,MAAA,IAAI,CAACuB,kBAAiB,CAAC,IAAI,CAACtB,YAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAClE,IAAA;AACF,EAAA;AAEQyB,EAAAA,eAAcA,CAAC,IAAU,EAAE,EAAe,EAAQ;IACxD,IAAI,CAAC,OAAO,GAAG,EAAE;AACjB,IAAA,IAAI,CAACrB,eAAc,CAAC,EAAE,EAAE,IAAI,CAAC;AAC/B,EAAA;;AAEA;AACF;AACA;AACA;EACUI,oBAAmBA,CAAC,KAAkB,EAA+B;AAC3E,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7B,MAAA,IAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC;AACnD;MACA,QAAQ,CAAC,SAAS,GAAG,KAAK;MAE1B,OAAO,QAAQ,CAAC,OAAO;AACzB,IAAA;AACA,IAAA,OAAO,KAAK,CAAC,QAAQ,GAAG,KAAK,GAAG,SAAS;AAC3C,EAAA;EAEQc,kBAAiBA,CACvB,OAAgB,EAChB,QAAgB,EAChB,UAAmB,EACnB,KAAa,EACK;IAClB,IAAM,QAAQ,GAAG,UAAU,GAAG,IAAI,CAACZ,eAAc,GAAG,IAAI,CAACE,gBAAe;AACxE,IAAA,IAAM,EAAE,GAAG,QAAQ,CAAC,SAAS,EAAsB;AACnD,IAAA,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;AAElB,IAAA,KAAK,IAAM,KAAK,IAAI,QAAQ,EAAE;MAC5B,IAAM,EAAE,GAAG,IAAI,CAACW,SAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;AACtC,MAAA,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;AAEb,MAAA,IAAI,IAAI,CAACC,mBAAkB,CAAC,KAAK,CAAC,EAAE;AAClC,QAAA,IAAI,CAACF,kBAAiB,CAAC,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC;AAC9D,MAAA;AACF,IAAA;AAEA,IAAA,OAAO,EAAE;AACX,EAAA;AAEQI,EAAAA,eAAcA,CACpB,IAAU,EACV,KAAa,EACb,UAAmB,EACJ;AACf,IAAA,IAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,GACzB,IAAI,CAACX,qBAAoB,GACzB,IAAI,CAACE,qBAAoB;AAC7B,IAAA,IAAM,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAkB;AAEpD,IAAA,IAAI,UAAU,EAAE;MACd,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAACpB,WAAU,CAAC,QAAQ,CAAC;AAC5C,IAAA;;AAEA;AACA,IAAA,IAAM,GAAG,GAAG,EAAE,CAAC,UAA4B;AAC3C,IAAA,IAAM,SAAS,GAAG,GAAG,CAAC,UAAU,CAC9B,IAAI,CAACD,WAAU,GAAG,CAAC,GAAG,CAAC,CACL;AAEpB,IAAA,IAAI,CAAC+B,cAAa,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC;IAE3D,IAAI,IAAI,CAAC,UAAU,EAAE;MACnB,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC9B,WAAU,CAAC,OAAO,CAAC;AACzC,MAAA,SAAS,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC;AAC7C,IAAA;AAEA,IAAA,OAAO,EAAE;AACX,EAAA;;AAEA;AACF;AACA;AACA;AACA;EACUmB,qBAAoBA,CAAC,MAAe,EAAiB;AAC3D,IAAA,IAAM,SAAS,GAAG,CAAC,IAAI,CAACnB,WAAU,CAAC,MAAM,EAAE,IAAI,CAACA,WAAU,CAAC,MAAM,CAAC;IAElE,IAAI,CAAC,MAAM,EAAE;MACX,SAAS,CAAC,IAAI,CAAC,IAAI,CAACA,WAAU,CAAC,MAAM,CAAC;AACxC,IAAA;AAEA,IAAA,IAAM,EAAE,GAAG,IAAI,CAAC+B,iBAAgB,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACrD,IAAA,IAAM,GAAG,GAAG,EAAE,CAAC,UAA4B;;AAE3C;AACA;AACA,IAAA,IAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC;IAC9C,OAAO,CAAC,SAAS,GAAG,IAAI,CAACC,iBAAgB,CAAC,MAAM,CAAC;AACjD,IAAA,OAAO,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC;IAE3C,IAAM,WAAW,GAAG,MAAM,GACtB,IAAI,CAACtB,kBAAiB,GACtB,IAAI,CAACE,kBAAiB;AAE1B,IAAA,IAAI,WAAW,EAAE;MACf,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC7C,IAAA;IAEA,IAAI,IAAI,CAACb,WAAU,EAAE;AACnB,MAAA,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;AACrB,IAAA;;AAEA;AACA,IAAA,IAAM,SAAS,GAAG,IAAI,CAACkC,wBAAuB,CAAC,IAAI,CAAC;IACpD,SAAS,CAAC,YAAY,CAAC,eAAe,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;AAC9D,IAAA,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC;AAErB,IAAA,IAAI,CAAC,IAAI,CAAClC,WAAU,EAAE;AACpB,MAAA,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;AACrB,IAAA;AAEA,IAAA,OAAO,EAAE;AACX,EAAA;;AAEA;AACF;AACA;AACA;AACU2B,EAAAA,SAAQA,CAAC,IAAU,EAAE,KAAa,EAAiB;AACzD,IAAA,IAAM,UAAU,GAAG,IAAI,CAACtB,eAAc,CAAC,IAAI,CAAC;AAE5C,IAAA,IAAM,cAAc,GAClB,IAAI,CAAC,QAAQ,EAAE,IAAK,IAAI,CAAC,aAAa,IAAI,IAAI,CAACI,gBAAgB;IAEjE,IAAM,EAAE,GAAG,cAAc,GACrB,IAAI,CAACqB,eAAc,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,GAC5C,IAAI,CAACK,aAAY,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC;AAE9C,IAAA,IAAI,CAACN,eAAc,CAAC,IAAI,EAAE,EAAE,CAAC;IAE7B,IAAI,IAAI,CAACvB,WAAU,EAAE;MACnB,IAAI,CAACA,WAAU,CAAC,IAAI,EAAE,EAAE,EAAE,UAAU,CAAC;AACvC,IAAA;AAEA,IAAA,OAAO,EAAE;AACX,EAAA;;AAEA;AACF;AACA;EACU0B,iBAAgBA,CAAC,SAAiB,EAAiB;AACzD,IAAA,IAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC;IACvC,EAAE,CAAC,SAAS,GAAG,SAAS;AACxB,IAAA,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC;AAE/B,IAAA,IAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC;AACzC,IAAA,GAAG,CAAC,SAAS,GAAG,CAAA,EAAG,IAAI,CAAC/B,WAAU,CAAC,OAAO,IAAI,IAAI,CAACA,WAAU,CAAC,MAAM,CAAA,CAAE;AACtE,IAAA,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC;AAEhC,IAAA,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC;AAEd,IAAA,OAAO,EAAE;AACX,EAAA;AAEQkC,EAAAA,aAAYA,CAClB,IAAU,EACV,KAAa,EACb,UAAmB,EACJ;IACf,IAAM,EAAE,GAAG,IAAI,CAAClB,aAAY,CAAC,SAAS,CAAC,IAAI,CAAkB;AAE7D,IAAA,IAAI,UAAU,EAAE;MACd,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAChB,WAAU,CAAC,QAAQ,CAAC;AAC5C,IAAA;;AAEA;AACA,IAAA,IAAM,GAAG,GAAG,EAAE,CAAC,UAA4B;AAC3C,IAAA,IAAM,SAAS,GAAG,GAAG,CAAC,UAA6B;AAEnD,IAAA,IAAI,CAAC8B,cAAa,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC;AAE3D,IAAA,OAAO,EAAE;AACX,EAAA;;AAEA;AACF;AACA;AACUb,EAAAA,mBAAkBA,GAAkB;IAC1C,IAAM,EAAE,GAAG,IAAI,CAACc,iBAAgB,CAAC,IAAI,CAAC/B,WAAU,CAAC,MAAM,CAAC;AACxD,IAAA,IAAM,GAAG,GAAG,EAAE,CAAC,UAA4B;IAE3C,GAAG,CAAC,MAAM,CAAC,IAAI,CAACiC,wBAAuB,CAAC,KAAK,CAAC,CAAC;AAE/C,IAAA,OAAO,EAAE;AACX,EAAA;EAEQA,wBAAuBA,CAAC,QAAiB,EAAmB;AAClE,IAAA,IAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC;AAEhD,IAAA,IAAI,OAAO,GAAG,CAAA,EAAG,IAAI,CAACjC,WAAU,CAAC,KAAK,CAAA,CAAA,EAAI,IAAI,CAACA,WAAU,CAAC,MAAM,CAAA,CAAE;AAElE,IAAA,IAAI,QAAQ,EAAE;AACZ,MAAA,OAAO,IAAI,CAAA,CAAA,EAAI,IAAI,CAACA,WAAU,CAAC,WAAW,CAAA,CAAE;AAC9C,IAAA;AAEA,IAAA,OAAO,IAAI,CAAA,CAAA,EAAI,IAAI,CAACD,WAAU,GAAG,IAAI,CAACC,WAAU,CAAC,eAAe,GAAG,IAAI,CAACA,WAAU,CAAC,gBAAgB,CAAA,CAAE;IAErG,SAAS,CAAC,SAAS,GAAG,OAAO;AAC7B,IAAA,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC;AAC1C,IAAA,SAAS,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC;;AAEhD;AACA,IAAA,IAAI,IAAI,CAACS,SAAQ,KAAK,SAAS,EAAE;AAC/B,MAAA,SAAS,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC;AAC1C,IAAA;AAEA,IAAA,OAAO,SAAS;AAClB,EAAA;EAEQK,iBAAgBA,CAAC,UAAmB,EAAoB;AAC9D,IAAA,IAAI,WAAW;AACf,IAAA,IAAI,IAAI;AAER,IAAA,IAAI,UAAU,EAAE;AACd,MAAA,WAAW,GAAG,IAAI,CAACd,WAAU,CAAC,IAAI;AAClC,MAAA,IAAI,GAAG,MAAM;MAEb,IAAI,IAAI,CAACM,IAAG,EAAE;AACZ,QAAA,WAAW,IAAI,CAAA,CAAA,EAAI,IAAI,CAACN,WAAU,CAAC,GAAG,CAAA,CAAE;AAC1C,MAAA;AACF,IAAA,CAAC,MAAM;AACL,MAAA,WAAW,GAAG,EAAE;AAChB,MAAA,IAAI,GAAG,OAAO;AAChB,IAAA;IAEA,IAAI,IAAI,CAACC,YAAW,EAAE;AACpB,MAAA,WAAW,IAAI,CAAA,CAAA,EAAI,IAAI,CAACD,WAAU,CAAC,GAAG,CAAA,CAAE;AAC1C,IAAA;AAEA,IAAA,IAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC;IACvC,EAAE,CAAC,SAAS,GAAG,CAAA,EAAG,IAAI,CAACA,WAAU,CAAC,MAAM,CAAA,CAAA,EAAI,WAAW,CAAA,CAAE;AAEzD,IAAA,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC;AAE7B,IAAA,IAAI,UAAU,EAAE;AACd,MAAA,IAAI,IAAI,CAACJ,UAAS,KAAK,SAAS,EAAE;QAChC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,CAACA,UAAS,CAAC;AAC/C,MAAA;AAEA,MAAA,IAAI,IAAI,CAACC,eAAc,KAAK,SAAS,EAAE;QACrC,EAAE,CAAC,YAAY,CAAC,iBAAiB,EAAE,IAAI,CAACA,eAAc,CAAC;AACzD,MAAA;AACF,IAAA;AAEA,IAAA,OAAO,EAAE;AACX,EAAA;;AAEA;AACF;AACA;EACUiC,cAAaA,CACnB,SAA0B,EAC1B,QAAgB,EAChB,UAAmB,EACnB,KAAa,EACP;IACN,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;AAEnD,IAAA,IAAI,UAAU,EAAE;AACd,MAAA,SAAS,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC;AAE/C,MAAA,IAAM,QAAQ,GAAG,IAAI,CAACrB,SAAQ;MAE9B,IAAI,QAAQ,KAAK,SAAS,EAAE;QAC1B,SAAS,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;AACtD,MAAA;AACF,IAAA;IAEA,IAAI,IAAI,CAACX,WAAU,EAAE;MACnB,SAAS,CAAC,WAAW,GAAG,QAAQ;AAClC,IAAA,CAAC,MAAM;AACL;MACA,SAAS,CAAC,SAAS,GAAG,QAAQ;AAChC,IAAA;AACF,EAAA;EAEQkC,iBAAgBA,CAAC,MAAe,EAAU;AAChD,IAAA,IAAM,OAAO,GAAG,CAAC,IAAI,CAAChC,WAAU,CAAC,OAAO,EAAE,IAAI,CAACA,WAAU,CAAC,MAAM,CAAC;IAEjE,IAAI,CAAC,MAAM,EAAE;MACX,OAAO,CAAC,IAAI,CAAC,IAAI,CAACA,WAAU,CAAC,MAAM,CAAC;AACtC,IAAA;IAEA,IAAI,IAAI,CAACD,WAAU,EAAE;MACnB,OAAO,CAAC,IAAI,CAAC,IAAI,CAACC,WAAU,CAAC,WAAW,CAAC;AAC3C,IAAA,CAAC,MAAM;MACL,OAAO,CAAC,IAAI,CAAC,IAAI,CAACA,WAAU,CAAC,YAAY,CAAC;AAC5C,IAAA;AAEA,IAAA,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;AAC1B,EAAA;;AAEA;AACF;AACA;EACU2B,mBAAkBA,CAAC,IAAU,EAAW;IAC9C,OAAO,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;AACpD,EAAA;AACF;;"}
package/lib/events.d.ts CHANGED
@@ -82,6 +82,23 @@ export interface TreeEvents {
82
82
  node: Node;
83
83
  originalEvent: MouseEvent;
84
84
  };
85
+ /**
86
+ * Dispatched when `Enter` is pressed on the selected node, or on the
87
+ * focused node when no node is selected. Use it for what a click on a
88
+ * link would do, like opening the edit page of the node:
89
+ *
90
+ * ```js
91
+ * element.addEventListener("tree.activate", (e) => {
92
+ * window.location.href = e.detail.node.url;
93
+ * });
94
+ * ```
95
+ *
96
+ * @group Keyboard
97
+ */
98
+ "tree.activate": {
99
+ node: Node;
100
+ originalEvent: KeyboardEvent;
101
+ };
85
102
  /**
86
103
  * Dispatched when a folder is opened, after the animation.
87
104
  *
@@ -112,15 +129,19 @@ export interface TreeEvents {
112
129
  * @group Selection
113
130
  */
114
131
  "tree.select": {
115
- /** The node that was selected before, if any. */
132
+ /**
133
+ The node that was selected before, if any.
134
+ */
116
135
  deselectedNode: Node | null;
117
- /** The node that is now selected. */
136
+ /**
137
+ The node that is now selected.
138
+ */
118
139
  node: Node;
119
140
  };
120
141
  /**
121
142
  * Dispatched when the selected node is deselected, which happens when it
122
- * is clicked again or passed to `selectNode` again. No `tree.select` is
123
- * dispatched for it.
143
+ * is clicked again or passed to `selectNode` again with
144
+ * `mustToggle: true`. No `tree.select` is dispatched for it.
124
145
  *
125
146
  * ```js
126
147
  * element.addEventListener("tree.deselect", (e) => {
@@ -130,7 +151,7 @@ export interface TreeEvents {
130
151
  *
131
152
  * Selecting another node does not dispatch it — that is a `tree.select`
132
153
  * with the previous node in `deselectedNode`. It is also not dispatched
133
- * with `mustToggle: false`, or by `selectNode(null)`,
154
+ * by `selectNode` without `mustToggle: true`, `selectNode(null)`,
134
155
  * `removeFromSelection`, `removeNode`, `loadData` and restoring a saved
135
156
  * state.
136
157
  *
@@ -158,7 +179,9 @@ export interface TreeEvents {
158
179
  * @group Drag and drop
159
180
  */
160
181
  "tree.move": {
161
- /** @hidden The fields are in the table above. */
182
+ /**
183
+ @hidden The fields are in the table above.
184
+ */
162
185
  moveInfo: MoveInfo;
163
186
  };
164
187
  /**
@@ -168,7 +191,9 @@ export interface TreeEvents {
168
191
  * @group Loading data
169
192
  */
170
193
  "tree.set_data": {
171
- /** The node whose children were replaced, if it was a subtree. */
194
+ /**
195
+ The node whose children were replaced, if it was a subtree.
196
+ */
172
197
  node?: Node;
173
198
  treeData?: NodeData[];
174
199
  };
@@ -179,7 +204,9 @@ export interface TreeEvents {
179
204
  */
180
205
  "tree.loading_data": {
181
206
  element: HTMLElement;
182
- /** The node whose children are loading, if it is a subtree. */
207
+ /**
208
+ The node whose children are loading, if it is a subtree.
209
+ */
183
210
  node?: Node;
184
211
  };
185
212
  /**
@@ -190,7 +217,9 @@ export interface TreeEvents {
190
217
  */
191
218
  "tree.loaded_data": {
192
219
  element: HTMLElement;
193
- /** The node whose children were loaded, if it was a subtree. */
220
+ /**
221
+ The node whose children were loaded, if it was a subtree.
222
+ */
194
223
  node?: Node;
195
224
  };
196
225
  /**
@@ -210,9 +239,13 @@ export interface TreeEvents {
210
239
  * @group Loading data
211
240
  */
212
241
  "tree.load_failed": {
213
- /** The error thrown by `fetch`, if the request failed with a network error. */
242
+ /**
243
+ The error thrown by `fetch`, if the request failed with a network error.
244
+ */
214
245
  error?: unknown;
215
- /** The response, if the request returned an error status. */
246
+ /**
247
+ The response, if the request returned an error status.
248
+ */
216
249
  response?: Response;
217
250
  };
218
251
  }
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvD,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;IAChB,aAAa,EAAE,KAAK,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,IAAI,CAAC;CAClB;AAGD,MAAM,MAAM,SAAS,CAAC,IAAI,SAAS,aAAa,GAAG,aAAa,IAAI,WAAW,CAC7E,UAAU,CAAC,IAAI,CAAC,CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,UAAU,CAAC;AAO7C,MAAM,WAAW,UAAU;IACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,WAAW,EAAE,SAAS,CAAC;IACvB;;;;OAIG;IACH,cAAc,EAAE,SAAS,CAAC;IAC1B;;;;;;;;;;;;OAYG;IACH,YAAY,EAAE;QACZ,IAAI,EAAE,IAAI,CAAC;QACX,aAAa,EAAE,UAAU,CAAC;KAC3B,CAAC;IACF;;;;OAIG;IACH,eAAe,EAAE;QACf,IAAI,EAAE,IAAI,CAAC;QACX,aAAa,EAAE,UAAU,CAAC;KAC3B,CAAC;IACF;;;;;OAKG;IACH,kBAAkB,EAAE;QAClB,IAAI,EAAE,IAAI,CAAC;QACX,aAAa,EAAE,UAAU,CAAC;KAC3B,CAAC;IACF;;;;OAIG;IACH,WAAW,EAAE;QACX,IAAI,EAAE,IAAI,CAAC;KACZ,CAAC;IACF;;;;OAIG;IACH,YAAY,EAAE;QACZ,IAAI,EAAE,IAAI,CAAC;KACZ,CAAC;IACF;;;;;;;;;;;;OAYG;IACH,aAAa,EAAE;QACb,iDAAiD;QACjD,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;QAC5B,qCAAqC;QACrC,IAAI,EAAE,IAAI,CAAC;KACZ,CAAC;IACF;;;;;;;;;;;;;;;;;;OAkBG;IACH,eAAe,EAAE;QACf,IAAI,EAAE,IAAI,CAAC;KACZ,CAAC;IACF;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,EAAE;QACX,iDAAiD;QACjD,QAAQ,EAAE,QAAQ,CAAC;KACpB,CAAC;IACF;;;;;OAKG;IACH,eAAe,EAAE;QACf,kEAAkE;QAClE,IAAI,CAAC,EAAE,IAAI,CAAC;QACZ,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;KACvB,CAAC;IACF;;;;OAIG;IACH,mBAAmB,EAAE;QACnB,OAAO,EAAE,WAAW,CAAC;QACrB,+DAA+D;QAC/D,IAAI,CAAC,EAAE,IAAI,CAAC;KACb,CAAC;IACF;;;;;OAKG;IACH,kBAAkB,EAAE;QAClB,OAAO,EAAE,WAAW,CAAC;QACrB,gEAAgE;QAChE,IAAI,CAAC,EAAE,IAAI,CAAC;KACb,CAAC;IACF;;;;;;;;;;;;;;;OAeG;IACH,kBAAkB,EAAE;QAClB,+EAA+E;QAC/E,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,6DAA6D;QAC7D,QAAQ,CAAC,EAAE,QAAQ,CAAC;KACrB,CAAC;CACH;AAGD,KAAK,YAAY,GAAG;KACjB,IAAI,IAAI,aAAa,GAAG,SAAS,CAAC,IAAI,CAAC;CACzC,CAAC;AAGF,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,gBAAiB,SAAQ,YAAY;KAAG;IAElD,UAAU,mBAAoB,SAAQ,YAAY;KAAG;IAErD,UAAU,cAAe,SAAQ,YAAY;KAAG;CACjD"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvD,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;IAChB,aAAa,EAAE,KAAK,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,IAAI,CAAC;CAClB;AAGD,MAAM,MAAM,SAAS,CAAC,IAAI,SAAS,aAAa,GAAG,aAAa,IAAI,WAAW,CAC7E,UAAU,CAAC,IAAI,CAAC,CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,UAAU,CAAC;AAO7C,MAAM,WAAW,UAAU;IACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACH,WAAW,EAAE,SAAS,CAAC;IACvB;;;;OAIG;IACH,cAAc,EAAE,SAAS,CAAC;IAC1B;;;;;;;;;;;;OAYG;IACH,YAAY,EAAE;QACZ,IAAI,EAAE,IAAI,CAAC;QACX,aAAa,EAAE,UAAU,CAAC;KAC3B,CAAC;IACF;;;;OAIG;IACH,eAAe,EAAE;QACf,IAAI,EAAE,IAAI,CAAC;QACX,aAAa,EAAE,UAAU,CAAC;KAC3B,CAAC;IACF;;;;;OAKG;IACH,kBAAkB,EAAE;QAClB,IAAI,EAAE,IAAI,CAAC;QACX,aAAa,EAAE,UAAU,CAAC;KAC3B,CAAC;IACF;;;;;;;;;;;;OAYG;IACH,eAAe,EAAE;QACf,IAAI,EAAE,IAAI,CAAC;QACX,aAAa,EAAE,aAAa,CAAC;KAC9B,CAAC;IACF;;;;OAIG;IACH,WAAW,EAAE;QACX,IAAI,EAAE,IAAI,CAAC;KACZ,CAAC;IACF;;;;OAIG;IACH,YAAY,EAAE;QACZ,IAAI,EAAE,IAAI,CAAC;KACZ,CAAC;IACF;;;;;;;;;;;;OAYG;IACH,aAAa,EAAE;QACb;;UAEE;QACF,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;QAC5B;;UAEE;QACF,IAAI,EAAE,IAAI,CAAC;KACZ,CAAC;IACF;;;;;;;;;;;;;;;;;;OAkBG;IACH,eAAe,EAAE;QACf,IAAI,EAAE,IAAI,CAAC;KACZ,CAAC;IACF;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,EAAE;QACX;;UAEE;QACF,QAAQ,EAAE,QAAQ,CAAC;KACpB,CAAC;IACF;;;;;OAKG;IACH,eAAe,EAAE;QACf;;UAEE;QACF,IAAI,CAAC,EAAE,IAAI,CAAC;QACZ,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;KACvB,CAAC;IACF;;;;OAIG;IACH,mBAAmB,EAAE;QACnB,OAAO,EAAE,WAAW,CAAC;QACrB;;UAEE;QACF,IAAI,CAAC,EAAE,IAAI,CAAC;KACb,CAAC;IACF;;;;;OAKG;IACH,kBAAkB,EAAE;QAClB,OAAO,EAAE,WAAW,CAAC;QACrB;;UAEE;QACF,IAAI,CAAC,EAAE,IAAI,CAAC;KACb,CAAC;IACF;;;;;;;;;;;;;;;OAeG;IACH,kBAAkB,EAAE;QAClB;;UAEE;QACF,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB;;UAEE;QACF,QAAQ,CAAC,EAAE,QAAQ,CAAC;KACrB,CAAC;CACH;AAGD,KAAK,YAAY,GAAG;KACjB,IAAI,IAAI,aAAa,GAAG,SAAS,CAAC,IAAI,CAAC;CACzC,CAAC;AAGF,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,gBAAiB,SAAQ,YAAY;KAAG;IAElD,UAAU,mBAAoB,SAAQ,YAAY;KAAG;IAErD,UAAU,cAAe,SAAQ,YAAY;KAAG;CACjD"}
package/lib/index.d.ts CHANGED
@@ -1,13 +1,14 @@
1
- import type { MoveInfo, TreeEvent, TreeEventName, TreeEvents } from "./events.js";
1
+ import type { TreeEventName, TreeEvents } from "./events.js";
2
2
  import type { NodeData, NodeId, Position } from "./node.js";
3
3
  import type { TreeElementOptions } from "./options.js";
4
4
  import type { SavedState } from "./saveStateHandler.js";
5
5
  import type { SelectNodeOptions } from "./selectNodeHandler.js";
6
6
  import { Node } from "./node.js";
7
- export type { MoveInfo, Node, NodeData, NodeId, Position, SavedState, SelectNodeOptions, TreeElementOptions, TreeEvent, TreeEventName, TreeEvents, };
8
7
  export type TriggerEventProvider = (element: HTMLElement, eventName: TreeEventName, values?: TreeEvents[TreeEventName]) => boolean;
9
8
  interface TreeElementParams extends Partial<TreeElementOptions> {
10
- /** The element the tree is rendered into. Its content is replaced. */
9
+ /**
10
+ The element the tree is rendered into. Its content is replaced.
11
+ */
11
12
  htmlElement: HTMLElement;
12
13
  /** Replaces how events are dispatched. It must return whether the event
13
14
  * was not cancelled. This exists for tests and for integrating with
@@ -18,6 +19,7 @@ export default class TreeElement {
18
19
  private classNames;
19
20
  private dataLoader;
20
21
  private dndHandler;
22
+ private fallbackTabStop;
21
23
  private htmlElement;
22
24
  private isInitialized;
23
25
  private keyHandler;
@@ -30,7 +32,9 @@ export default class TreeElement {
30
32
  private selectNodeHandler;
31
33
  private tree;
32
34
  private triggerEventProvider;
33
- /** @hidden */
35
+ /**
36
+ @hidden
37
+ */
34
38
  constructor({ htmlElement, overrideTriggerEventProvider, ...options }: TreeElementParams);
35
39
  /**
36
40
  * Adds a sibling after a node.
@@ -74,12 +78,19 @@ export default class TreeElement {
74
78
  */
75
79
  appendNode(nodeData: NodeData, parentNode: Node): Node;
76
80
  /**
77
- * Closes a folder.
81
+ * Closes a folder. Await the promise when you need to know the closing
82
+ * animation has finished.
83
+ *
84
+ * @example
85
+ * ```js
86
+ * await tree.closeNode(node);
87
+ * console.log("closed");
88
+ * ```
78
89
  *
79
90
  * @param slide - Override the `slide` option for this call.
80
91
  * @group Opening and closing
81
92
  */
82
- closeNode(node: Node, slide?: boolean): void;
93
+ closeNode(node: Node, slide?: boolean): Promise<void>;
83
94
  /**
84
95
  * Empties the element and removes the tree's document-level keyboard
85
96
  * listener. Call it when you remove the tree from the page.
@@ -307,12 +318,14 @@ export default class TreeElement {
307
318
  */
308
319
  setState(state: SavedState): void;
309
320
  /**
310
- * Closes an open node and opens a closed one.
321
+ * Closes an open node and opens a closed one. Await the promise when you
322
+ * need to know the node is really open or closed, like with `openNode` and
323
+ * `closeNode`.
311
324
  *
312
325
  * @param slide - Override the `slide` option for this call.
313
326
  * @group Opening and closing
314
327
  */
315
- toggle(node: Node, slide?: boolean | null): void;
328
+ toggle(node: Node, slide?: boolean | null): Promise<void>;
316
329
  /**
317
330
  * Returns the tree as a json string, including changes made through the
318
331
  * api.
@@ -336,15 +349,19 @@ export default class TreeElement {
336
349
  * @group Changing the tree
337
350
  */
338
351
  updateNode(node: Node, data: NodeData): void;
352
+ private autoOpenNodesOnDemand;
339
353
  private createFolderElement;
340
354
  private createNodeElement;
341
355
  private createRequestUrl;
342
356
  private deselectCurrentNode;
343
357
  private deselectNodes;
344
358
  private getAutoOpenMaxLevel;
359
+ private getFirstTitleSpan;
360
+ private getFocusedNode;
345
361
  private getNodeElement;
346
362
  private getNodeElementForNode;
347
363
  private getNodeIdToBeSelected;
364
+ private hasRenderedSelectedNode;
348
365
  private initData;
349
366
  private initTree;
350
367
  private isFocusOnTree;
@@ -363,5 +380,11 @@ export default class TreeElement {
363
380
  private setInitialStateOnDemand;
364
381
  private setNodeElement;
365
382
  private triggerEvent;
383
+ private updateTabStop;
366
384
  }
385
+ export { type MoveInfo, type TreeEvent, type TreeEventName, type TreeEvents, } from "./events.js";
386
+ export { type Node, type NodeData, type NodeId, type Position } from "./node.js";
387
+ export { type TreeElementOptions } from "./options.js";
388
+ export { type SavedState } from "./saveStateHandler.js";
389
+ export { type SelectNodeOptions } from "./selectNodeHandler.js";
367
390
  //# sourceMappingURL=index.d.ts.map