@ixfx/components 0.2.6 → 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 (141) hide show
  1. package/bundle/index.d.ts +213 -117
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +1438 -686
  4. package/bundle/index.js.map +1 -1
  5. package/dist/ac-text.js +3 -3
  6. package/dist/ac-text.js.map +1 -1
  7. package/dist/{button-B9ztaKyl.js → button-DMt5XWUK.js} +4 -4
  8. package/dist/{button-B9ztaKyl.js.map → button-DMt5XWUK.js.map} +1 -1
  9. package/dist/button.js +1 -1
  10. package/dist/checkbox.d.ts +2 -3
  11. package/dist/checkbox.d.ts.map +1 -1
  12. package/dist/checkbox.js +1 -1
  13. package/dist/checkbox.js.map +1 -1
  14. package/dist/{colour-C3MQIjFJ-BJV-QC-3.js → colour-C3MQIjFJ-BLXg8W3U.js} +2 -2
  15. package/dist/{colour-C3MQIjFJ-BJV-QC-3.js.map → colour-C3MQIjFJ-BLXg8W3U.js.map} +1 -1
  16. package/dist/{colour-picker-BNqDz4wK.js → colour-picker-K6zu82lm.js} +5 -5
  17. package/dist/{colour-picker-BNqDz4wK.js.map → colour-picker-K6zu82lm.js.map} +1 -1
  18. package/dist/colour-picker.js +1 -1
  19. package/dist/crumbs.d.ts +2 -3
  20. package/dist/crumbs.d.ts.map +1 -1
  21. package/dist/crumbs.js +10 -10
  22. package/dist/crumbs.js.map +1 -1
  23. package/dist/data-display.js +3 -3
  24. package/dist/{decorate-O4m1U4l3.js → decorate-D7rC1gLP.js} +10 -8
  25. package/dist/decorate-D7rC1gLP.js.map +1 -0
  26. package/dist/{defaults-FEZaGiYZ.js → defaults-C7elhuyJ.js} +2 -2
  27. package/dist/{defaults-FEZaGiYZ.js.map → defaults-C7elhuyJ.js.map} +1 -1
  28. package/dist/{dist-By5URG0Y.js → dist-BX0OVIm7.js} +2 -2
  29. package/dist/{dist-By5URG0Y.js.map → dist-BX0OVIm7.js.map} +1 -1
  30. package/dist/{dist-D7kJgnSE.js → dist-TAGYwaju.js} +1 -1
  31. package/dist/{dist-D7kJgnSE.js.map → dist-TAGYwaju.js.map} +1 -1
  32. package/dist/editable-label.d.ts +6 -1
  33. package/dist/editable-label.d.ts.map +1 -1
  34. package/dist/editable-label.js +49 -2
  35. package/dist/editable-label.js.map +1 -1
  36. package/dist/{hex-editor-gH3mteMr.js → hex-editor-CsN_ySkH.js} +85 -85
  37. package/dist/hex-editor-CsN_ySkH.js.map +1 -0
  38. package/dist/{hex-editor-2_s0Ua5t.d.ts → hex-editor-DlfoA65y.d.ts} +5 -5
  39. package/dist/{hex-editor-2_s0Ua5t.d.ts.map → hex-editor-DlfoA65y.d.ts.map} +1 -1
  40. package/dist/hex.d.ts +1 -1
  41. package/dist/hex.js +1 -1
  42. package/dist/{highlight-CAjwQ4GE.js → highlight-TPbSHruI.js} +3 -3
  43. package/dist/highlight-TPbSHruI.js.map +1 -0
  44. package/dist/{icon-CYACf6o8.js → icon-9NWTXtE1.js} +4 -5
  45. package/dist/icon-9NWTXtE1.js.map +1 -0
  46. package/dist/icon-CeTDJhC7.d.ts.map +1 -1
  47. package/dist/icons.js +3 -3
  48. package/dist/{incr-search-BZawvrfl.js → incr-search-DSKKsk6w.js} +12 -10
  49. package/dist/incr-search-DSKKsk6w.js.map +1 -0
  50. package/dist/incr-search.d.ts +1 -1
  51. package/dist/incr-search.js +2 -2
  52. package/dist/{index-CwGkb9s1.d.ts → index--hrxPBkQ.d.ts} +69 -69
  53. package/dist/index--hrxPBkQ.d.ts.map +1 -0
  54. package/dist/{index-kY5gxbkI.d.ts → index-DSlPeWLK.d.ts} +15 -15
  55. package/dist/{index-kY5gxbkI.d.ts.map → index-DSlPeWLK.d.ts.map} +1 -1
  56. package/dist/{index-V2cJorlA.d.ts → index-hXFn14tM.d.ts} +4 -4
  57. package/dist/index-hXFn14tM.d.ts.map +1 -0
  58. package/dist/index.d.ts +109 -13
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +748 -52
  61. package/dist/index.js.map +1 -1
  62. package/dist/keyboard-De_vOHLg.js.map +1 -1
  63. package/dist/{labelled-input-base-BvgH7ldm.js → labelled-input-base-CqPL5rKm.js} +2 -2
  64. package/dist/labelled-input-base-CqPL5rKm.js.map +1 -0
  65. package/dist/labelled-radial-input.js +3 -3
  66. package/dist/labelled-radial-input.js.map +1 -1
  67. package/dist/labelled-range-input.js +2 -2
  68. package/dist/led.js +1 -1
  69. package/dist/{menu-C3eANB5M.js → menu-DJJuCm-5.js} +48 -48
  70. package/dist/menu-DJJuCm-5.js.map +1 -0
  71. package/dist/{menu-item-6IU5weHi.js → menu-item-CKRfP0pN.js} +10 -10
  72. package/dist/menu-item-CKRfP0pN.js.map +1 -0
  73. package/dist/menu.d.ts +1 -1
  74. package/dist/menu.js +2 -2
  75. package/dist/miller.d.ts +5 -7
  76. package/dist/miller.d.ts.map +1 -1
  77. package/dist/miller.js +14 -14
  78. package/dist/miller.js.map +1 -1
  79. package/dist/narrowed-text.d.ts.map +1 -1
  80. package/dist/narrowed-text.js +4 -4
  81. package/dist/narrowed-text.js.map +1 -1
  82. package/dist/panel.js +2 -2
  83. package/dist/panel.js.map +1 -1
  84. package/dist/plots.js +1 -1
  85. package/dist/polar-pad.d.ts.map +1 -1
  86. package/dist/polar-pad.js +1 -1
  87. package/dist/polar-pad.js.map +1 -1
  88. package/dist/{popup-Ddx9LCzY.js → popup-ImtS9KnS.js} +1 -1
  89. package/dist/{popup-Ddx9LCzY.js.map → popup-ImtS9KnS.js.map} +1 -1
  90. package/dist/{prominence-CreDBdCs.js → prominence--ic9uWBl.js} +1 -1
  91. package/dist/{prominence-CreDBdCs.js.map → prominence--ic9uWBl.js.map} +1 -1
  92. package/dist/{radial-input-Dbc6fgCK.js → radial-input-DZA6WaFu.js} +14 -14
  93. package/dist/radial-input-DZA6WaFu.js.map +1 -0
  94. package/dist/radial-input.js +1 -1
  95. package/dist/range-input.js +1 -1
  96. package/dist/range.js +2 -2
  97. package/dist/{registry-CZEB1YI9.js → registry-Q2gYQCHM.js} +1 -1
  98. package/dist/{registry-CZEB1YI9.js.map → registry-Q2gYQCHM.js.map} +1 -1
  99. package/dist/selecthorizontal.js +1 -1
  100. package/dist/snap-container.js +1 -1
  101. package/dist/split-layout.js +4 -4
  102. package/dist/split-layout.js.map +1 -1
  103. package/dist/swipe.d.ts +1 -2
  104. package/dist/swipe.d.ts.map +1 -1
  105. package/dist/swipe.js +2 -2
  106. package/dist/swipe.js.map +1 -1
  107. package/dist/tab-list-BnqISNvO.d.ts.map +1 -1
  108. package/dist/tabs.js +2 -2
  109. package/dist/tabs.js.map +1 -1
  110. package/dist/{timeline-B62Sz6J_.js → timeline-Cv75Th2U.js} +120 -116
  111. package/dist/timeline-Cv75Th2U.js.map +1 -0
  112. package/dist/timeline.d.ts +1 -1
  113. package/dist/timeline.js +1 -1
  114. package/dist/tooltip-CwGfb4lp.d.ts.map +1 -1
  115. package/dist/tree-CvvKbO-f.js +1330 -0
  116. package/dist/tree-CvvKbO-f.js.map +1 -0
  117. package/dist/{tree-component-CQpoPo4s.d.ts → tree-component-D8Bg48tt.d.ts} +12 -12
  118. package/dist/{tree-component-CQpoPo4s.d.ts.map → tree-component-D8Bg48tt.d.ts.map} +1 -1
  119. package/dist/tree.d.ts +1 -1
  120. package/dist/tree.js +1 -1143
  121. package/dist/xy-axis-D9uwpGTT.d.ts.map +1 -1
  122. package/dist/{xy-axis-C7fNxDwY.js → xy-axis-DL0tfJDr.js} +10 -10
  123. package/dist/{xy-axis-C7fNxDwY.js.map → xy-axis-DL0tfJDr.js.map} +1 -1
  124. package/dist/xy-pad.js +2 -2
  125. package/package.json +3 -3
  126. package/dist/decorate-O4m1U4l3.js.map +0 -1
  127. package/dist/hex-editor-gH3mteMr.js.map +0 -1
  128. package/dist/highlight-CAjwQ4GE.js.map +0 -1
  129. package/dist/icon-CYACf6o8.js.map +0 -1
  130. package/dist/incr-search-BZawvrfl.js.map +0 -1
  131. package/dist/index-CwGkb9s1.d.ts.map +0 -1
  132. package/dist/index-V2cJorlA.d.ts.map +0 -1
  133. package/dist/labelled-input-base-BvgH7ldm.js.map +0 -1
  134. package/dist/menu-C3eANB5M.js.map +0 -1
  135. package/dist/menu-item-6IU5weHi.js.map +0 -1
  136. package/dist/radial-input-Dbc6fgCK.js.map +0 -1
  137. package/dist/timeline-B62Sz6J_.js.map +0 -1
  138. package/dist/tree-data-model-DGvRVOFY.js +0 -190
  139. package/dist/tree-data-model-DGvRVOFY.js.map +0 -1
  140. package/dist/tree.js.map +0 -1
  141. /package/dist/{interaction-CQDQJf2Q.js → interaction-DG7X1rhI.js} +0 -0
package/dist/tree.js CHANGED
@@ -1,1144 +1,2 @@
1
- import { n as tickledStyles, r as TickledController, t as tickledItemStyles } from "./tickled-styles-Bg3QbcrD.js";
2
- import { n as safeCustomElement, t as __decorate } from "./decorate-O4m1U4l3.js";
3
- import "./interaction-CQDQJf2Q.js";
4
- import { t as TreeDataModel } from "./tree-data-model-DGvRVOFY.js";
5
- import { LitElement, css, html, nothing } from "lit";
6
- import { property, state } from "lit/decorators.js";
7
- //#region src/tree/tree-base.ts
8
- let TreeBaseElement = class TreeBaseElement extends LitElement {
9
- constructor(..._args) {
10
- super(..._args);
11
- this.exclusivity = `none`;
12
- this.selectionFilter = `all`;
13
- this.interactionMode = `standard`;
14
- this._selectedNodes = /* @__PURE__ */ new Set();
15
- this.disableKeyboardNavigation = false;
16
- this._expandedKeys = /* @__PURE__ */ new Set();
17
- this.tickled = new TickledController(this, {
18
- getItems: () => {
19
- return this.#getAllNodes().map(({ node }) => ({
20
- id: node.item.key,
21
- enabled: true
22
- }));
23
- },
24
- onStateChange: () => {
25
- this.setAttribute(`data-input-mode`, this.tickled.inputMode);
26
- }
27
- });
28
- this._focusedDepth = 0;
29
- this.#config = { indent: 20 };
30
- this.#onKeyDown = (event) => {
31
- const nodes = this.#getAllNodes();
32
- if (nodes.length === 0) return;
33
- if ([
34
- `ArrowDown`,
35
- `ArrowUp`,
36
- `ArrowLeft`,
37
- `ArrowRight`,
38
- `Enter`,
39
- ` `
40
- ].includes(event.key)) this.tickled.setInputMode(`keyboard`);
41
- const currentIdx = this.#getFocusedIndex();
42
- switch (event.key) {
43
- case `ArrowDown`: {
44
- event.preventDefault();
45
- const nextIdx = Math.min(currentIdx + 1, nodes.length - 1);
46
- if (this.interactionMode === `implicit`) this.select(nodes[nextIdx].node);
47
- this.#setFocusedIndex(nextIdx);
48
- if (event.shiftKey && (this.interactionMode === `standard` || this.interactionMode === `vscode`)) this.#extendRangeSelection(nodes, currentIdx, nextIdx);
49
- else if (this.interactionMode === `vscode`) this.#anchor = void 0;
50
- this.requestUpdate();
51
- break;
52
- }
53
- case `ArrowUp`: {
54
- event.preventDefault();
55
- const prevIdx = Math.max(currentIdx - 1, 0);
56
- if (this.interactionMode === `implicit`) this.select(nodes[prevIdx].node);
57
- this.#setFocusedIndex(prevIdx);
58
- if (event.shiftKey && (this.interactionMode === `standard` || this.interactionMode === `vscode`)) this.#extendRangeSelection(nodes, currentIdx, prevIdx);
59
- else if (this.interactionMode === `vscode`) this.#anchor = void 0;
60
- this.requestUpdate();
61
- break;
62
- }
63
- case `ArrowRight`: {
64
- event.preventDefault();
65
- const current = nodes[currentIdx];
66
- if (current && current.node.item.isLeaf !== true) {
67
- if (!this._expandedKeys.has(current.node.item.key)) this.#toggleExpand(current.node, current.depth);
68
- else if (currentIdx + 1 < nodes.length) this.#setFocusedIndex(currentIdx + 1);
69
- }
70
- this.requestUpdate();
71
- break;
72
- }
73
- case `ArrowLeft`: {
74
- event.preventDefault();
75
- const current = nodes[currentIdx];
76
- if (current && this._expandedKeys.has(current.node.item.key)) {
77
- this._expandedKeys.delete(current.node.item.key);
78
- this.dispatchEvent(new CustomEvent(`collapse`, {
79
- detail: {
80
- node: current.node,
81
- depth: current.depth
82
- },
83
- bubbles: true,
84
- composed: true
85
- }));
86
- } else if (current.depth > 1) {
87
- const parentDepth = current.depth - 1;
88
- for (let i = currentIdx - 1; i >= 0; i--) if (nodes[i].depth === parentDepth) {
89
- this.#setFocusedIndex(i);
90
- break;
91
- }
92
- }
93
- this.requestUpdate();
94
- break;
95
- }
96
- case `Enter`: {
97
- event.preventDefault();
98
- const current = nodes[currentIdx];
99
- if (current) {
100
- if (this.interactionMode !== `manual` && this.interactionMode !== `checked`) this.select(current.node);
101
- this.dispatchEvent(new CustomEvent(`activate`, {
102
- detail: {
103
- node: current.node,
104
- depth: current.depth
105
- },
106
- bubbles: true,
107
- composed: true
108
- }));
109
- this.requestUpdate();
110
- }
111
- break;
112
- }
113
- case ` `: {
114
- event.preventDefault();
115
- const current = nodes[currentIdx];
116
- if (!current) break;
117
- if (this.interactionMode === `checked`) this._handleCheckboxClick(new MouseEvent("click"), current.node, current.depth);
118
- else if (this.interactionMode === `standard` || this.interactionMode === `vscode` || this.interactionMode === `manual`) this.#toggleSelection(current.node, current.depth);
119
- break;
120
- }
121
- case `Escape`:
122
- event.preventDefault();
123
- this.#abortPending();
124
- break;
125
- }
126
- };
127
- this.#onDblClick = (e) => {
128
- const li = e.target.closest(`li`);
129
- if (!li) return;
130
- const key = li.dataset.key;
131
- if (!key) return;
132
- const node = this.#getAllNodes().find((n) => n.node.item.key === key);
133
- if (!node) return;
134
- this.dispatchEvent(new CustomEvent(`activate`, {
135
- detail: {
136
- node: node.node,
137
- depth: node.depth
138
- },
139
- bubbles: true,
140
- composed: true
141
- }));
142
- };
143
- }
144
- get selectedNodes() {
145
- return this._selectedNodes;
146
- }
147
- #pendingNode;
148
- #pendingController;
149
- #modelUnsubscribe;
150
- #anchor;
151
- #config;
152
- updated(changedProps) {
153
- if (changedProps.has(`root`) && this.root) {
154
- this.#abortPending();
155
- this._expandedKeys.clear();
156
- this.#clearSelectionInternal();
157
- this.tickled.clearTickled();
158
- this._focusedDepth = 0;
159
- }
160
- if (changedProps.has(`model`)) {
161
- this.#modelUnsubscribe?.();
162
- this.#modelUnsubscribe = void 0;
163
- const model = this.model;
164
- if (model) {
165
- this.root = model.root;
166
- this.#modelUnsubscribe = model._subscribe((event) => {
167
- if (event.type === `root`) {
168
- this.root = event.root;
169
- this.requestUpdate();
170
- } else if (event.type === `invalidate`) {
171
- if (this._expandedKeys.has(event.key)) {
172
- this._expandedKeys.delete(event.key);
173
- this.requestUpdate();
174
- }
175
- }
176
- });
177
- }
178
- }
179
- if (changedProps.has(`interactionMode`)) {
180
- this.#anchor = void 0;
181
- this.clearSelection();
182
- }
183
- if (changedProps.has(`selectedNode`) && this.selectedNode) {
184
- if (changedProps.get(`selectedNode`) !== this.selectedNode) this.tickled.setTickled(this.selectedNode.item.key);
185
- }
186
- }
187
- connectedCallback() {
188
- super.connectedCallback();
189
- this.setAttribute(`data-input-mode`, `mouse`);
190
- }
191
- disconnectedCallback() {
192
- super.disconnectedCallback();
193
- this.#modelUnsubscribe?.();
194
- this.#modelUnsubscribe = void 0;
195
- }
196
- getConfig() {
197
- return { ...this.#config };
198
- }
199
- setConfig(config) {
200
- this.#config = {
201
- ...this.#config,
202
- ...config
203
- };
204
- this.requestUpdate();
205
- }
206
- select(node) {
207
- if (!this.#canSelect(node)) return;
208
- const prev = new Set(this._selectedNodes);
209
- this._selectedNodes.clear();
210
- this._selectedNodes.add(node);
211
- this.selectedNode = node;
212
- this.#dispatchSelect(prev);
213
- this.requestUpdate();
214
- }
215
- deselect(node) {
216
- if (!this._selectedNodes.has(node)) return;
217
- const prev = new Set(this._selectedNodes);
218
- this._selectedNodes.delete(node);
219
- if (this.selectedNode === node) this.selectedNode = [...this._selectedNodes].at(-1);
220
- this.#dispatchSelect(prev);
221
- this.requestUpdate();
222
- }
223
- clearSelection() {
224
- if (this._selectedNodes.size === 0) return;
225
- const prev = new Set(this._selectedNodes);
226
- this.#clearSelectionInternal();
227
- this.#dispatchSelect(prev);
228
- this.requestUpdate();
229
- }
230
- navigateTo(keys) {
231
- if (!this.root?.children) return false;
232
- this.#abortPending();
233
- this.#clearSelectionInternal();
234
- this.tickled.clearTickled();
235
- this._focusedDepth = 0;
236
- let currentNode = this.root;
237
- for (const key of keys) {
238
- const children = currentNode?.children;
239
- if (!children) return false;
240
- const found = children.find((n) => n.item.key === key);
241
- if (!found) return false;
242
- this.#applyExclusivity(found.item.key);
243
- this._expandedKeys.add(found.item.key);
244
- if (key === keys.at(-1)) {
245
- this.select(found);
246
- this.tickled.setTickled(found.item.key);
247
- }
248
- currentNode = found;
249
- }
250
- this.requestUpdate();
251
- this.#scrollKeyIntoView(keys.at(-1));
252
- return true;
253
- }
254
- navigateToNode(predicate) {
255
- if (!this.root?.children) return false;
256
- const keyPath = this.#findNodePath(this.root.children, predicate);
257
- if (!keyPath) return false;
258
- return this.navigateTo(keyPath);
259
- }
260
- getNodes() {
261
- if (!this.root?.children) return [];
262
- const result = [];
263
- const visit = (node, depth) => {
264
- result.push({
265
- node,
266
- depth
267
- });
268
- if (node.children) for (const child of node.children) visit(child, depth + 1);
269
- };
270
- for (const child of this.root.children) visit(child, 0);
271
- return result;
272
- }
273
- #canSelect(node) {
274
- if (this.selectionFilter === `none`) return false;
275
- if (this.selectionFilter === `leaf`) return node.item.isLeaf === true;
276
- if (this.selectionFilter === `branch`) return node.item.isLeaf === false || node.children !== void 0 && node.children.length > 0;
277
- return true;
278
- }
279
- #clearSelectionInternal() {
280
- this._selectedNodes.clear();
281
- this.selectedNode = void 0;
282
- }
283
- #dispatchSelect(previous) {
284
- const detail = {
285
- selected: new Set(this._selectedNodes),
286
- previous
287
- };
288
- this.dispatchEvent(new CustomEvent(`select`, {
289
- detail,
290
- bubbles: true,
291
- composed: true
292
- }));
293
- }
294
- #findNodePath(nodes, predicate, prefix = []) {
295
- for (const node of nodes) {
296
- const path = [...prefix, node.item.key];
297
- if (predicate(node)) return path;
298
- if (node.children?.length) {
299
- const result = this.#findNodePath(node.children, predicate, path);
300
- if (result) return result;
301
- }
302
- }
303
- }
304
- renderNodeContent(node, _depth) {
305
- const isBranch = node.item.isLeaf !== true;
306
- const isExpanded = this._isExpanded(node);
307
- return html`
308
- <span class="tree-caret">
309
- ${isBranch ? html`<ixfx-icon class="caret-icon" name="chevron-down" .rotate=${isExpanded ? nothing : `-90deg`}></ixfx-icon>` : ``}
310
- </span>
311
- <span class="tree-label">${node.item.label}</span>
312
- `;
313
- }
314
- _handleItemClick(node, depth, event) {
315
- if (this.#pendingNode && this._expandedKeys.has(this.#pendingNode.item.key)) this.#abortPending();
316
- this.tickled.handlePointerEnter(node.item.key);
317
- this._focusedDepth = depth;
318
- this.dispatchEvent(new CustomEvent(`item-click`, {
319
- detail: {
320
- node,
321
- depth
322
- },
323
- bubbles: true,
324
- composed: true
325
- }));
326
- switch (this.interactionMode) {
327
- case `implicit`:
328
- this.#handleImplicitClick(node, depth);
329
- break;
330
- case `standard`:
331
- this.#handleStandardClick(node, depth, event);
332
- break;
333
- case `vscode`:
334
- this.#handleStandardClick(node, depth, event);
335
- break;
336
- case `manual`:
337
- this.#handleManualClick(node, depth, event);
338
- break;
339
- case `checked`:
340
- this.#handleExpandOnly(node, depth);
341
- break;
342
- }
343
- this.requestUpdate();
344
- }
345
- #handleImplicitClick(node, depth) {
346
- if (this.#canSelect(node)) {
347
- const prev = new Set(this._selectedNodes);
348
- this._selectedNodes.clear();
349
- this._selectedNodes.add(node);
350
- this.selectedNode = node;
351
- if (!prev.has(node) || prev.size !== 1) this.#dispatchSelect(prev);
352
- }
353
- this.#toggleExpand(node, depth);
354
- }
355
- #handleStandardClick(node, depth, event) {
356
- const isMeta = event ? event.metaKey || event.ctrlKey : false;
357
- const isShift = event ? event.shiftKey : false;
358
- if (isMeta) {
359
- if (this.#canSelect(node)) {
360
- const prev = new Set(this._selectedNodes);
361
- if (this._selectedNodes.has(node)) {
362
- this._selectedNodes.delete(node);
363
- if (this.selectedNode === node) this.selectedNode = [...this._selectedNodes].at(-1);
364
- } else {
365
- this._selectedNodes.add(node);
366
- this.selectedNode = node;
367
- this.#anchor = {
368
- node,
369
- flatIndex: this.#getFlatIndexOf(node)
370
- };
371
- }
372
- this.#dispatchSelect(prev);
373
- }
374
- return;
375
- }
376
- if (isShift && this.#anchor) {
377
- const visible = this.#getAllNodes();
378
- const anchorIdx = visible.findIndex((n) => n.node === this.#anchor.node);
379
- const targetIdx = visible.findIndex((n) => n.node === node);
380
- if (anchorIdx >= 0 && targetIdx >= 0) {
381
- const prev = new Set(this._selectedNodes);
382
- const from = Math.min(anchorIdx, targetIdx);
383
- const to = Math.max(anchorIdx, targetIdx);
384
- const rangeNodes = visible.slice(from, to + 1).map((n) => n.node).filter((n) => this.#canSelect(n));
385
- this._selectedNodes = new Set(rangeNodes);
386
- this.selectedNode = node;
387
- this.#dispatchSelect(prev);
388
- }
389
- return;
390
- }
391
- if (this.#canSelect(node)) {
392
- const prev = new Set(this._selectedNodes);
393
- this._selectedNodes.clear();
394
- this._selectedNodes.add(node);
395
- this.selectedNode = node;
396
- this.#anchor = {
397
- node,
398
- flatIndex: this.#getFlatIndexOf(node)
399
- };
400
- if (!prev.has(node) || prev.size !== 1) this.#dispatchSelect(prev);
401
- }
402
- this.#toggleExpand(node, depth);
403
- }
404
- #handleExpandOnly(node, depth) {
405
- this.#toggleExpand(node, depth);
406
- }
407
- #handleManualClick(node, depth, event) {
408
- const isMeta = event ? event.metaKey || event.ctrlKey : false;
409
- const isShift = event ? event.shiftKey : false;
410
- if (isMeta) {
411
- if (this.#canSelect(node)) {
412
- const prev = new Set(this._selectedNodes);
413
- if (this._selectedNodes.has(node)) {
414
- this._selectedNodes.delete(node);
415
- if (this.selectedNode === node) this.selectedNode = [...this._selectedNodes].at(-1);
416
- } else {
417
- this._selectedNodes.add(node);
418
- this.selectedNode = node;
419
- this.#anchor = {
420
- node,
421
- flatIndex: this.#getFlatIndexOf(node)
422
- };
423
- }
424
- this.#dispatchSelect(prev);
425
- }
426
- return;
427
- }
428
- if (isShift && this.#anchor) {
429
- const visible = this.#getAllNodes();
430
- const anchorIdx = visible.findIndex((n) => n.node === this.#anchor.node);
431
- const targetIdx = visible.findIndex((n) => n.node === node);
432
- if (anchorIdx >= 0 && targetIdx >= 0) {
433
- const prev = new Set(this._selectedNodes);
434
- const from = Math.min(anchorIdx, targetIdx);
435
- const to = Math.max(anchorIdx, targetIdx);
436
- const rangeNodes = visible.slice(from, to + 1).map((n) => n.node).filter((n) => this.#canSelect(n));
437
- this._selectedNodes = new Set(rangeNodes);
438
- this.selectedNode = node;
439
- this.#dispatchSelect(prev);
440
- }
441
- return;
442
- }
443
- this.#toggleExpand(node, depth);
444
- }
445
- #toggleSelection(node, _depth) {
446
- if (!this.#canSelect(node)) return;
447
- const prev = new Set(this._selectedNodes);
448
- if (this._selectedNodes.has(node)) {
449
- this._selectedNodes.delete(node);
450
- if (this.selectedNode === node) this.selectedNode = [...this._selectedNodes].at(-1);
451
- } else {
452
- this._selectedNodes.add(node);
453
- this.selectedNode = node;
454
- this.#anchor = {
455
- node,
456
- flatIndex: this.#getFlatIndexOf(node)
457
- };
458
- }
459
- this.#dispatchSelect(prev);
460
- }
461
- _handleCheckboxClick(event, node, _depth) {
462
- event.stopPropagation();
463
- const prev = new Set(this._selectedNodes);
464
- const allSelected = this.#allDescendantsSelected(node);
465
- this.#applyCheckedToggle(node, !allSelected);
466
- if (this.selectedNode === void 0 || !this._selectedNodes.has(this.selectedNode)) this.selectedNode = [...this._selectedNodes].at(-1);
467
- this.#dispatchSelect(prev);
468
- this.requestUpdate();
469
- }
470
- #toggleExpand(node, depth) {
471
- if (this._expandedKeys.has(node.item.key)) {
472
- this._expandedKeys.delete(node.item.key);
473
- this.dispatchEvent(new CustomEvent(`collapse`, {
474
- detail: {
475
- node,
476
- depth
477
- },
478
- bubbles: true,
479
- composed: true
480
- }));
481
- } else if (node.children === void 0) {
482
- if (node.item.isLeaf !== false) return;
483
- if (this.model ?? (this.loadChildren ? this : void 0)) {
484
- this.#pendingNode = node;
485
- const controller = new AbortController();
486
- this.#pendingController = controller;
487
- this.#invokeLoadChildren(node, depth, controller).catch(() => {});
488
- }
489
- } else {
490
- this.#applyExclusivity(node.item.key);
491
- this._expandedKeys.add(node.item.key);
492
- this.dispatchEvent(new CustomEvent(`expand`, {
493
- detail: {
494
- node,
495
- depth
496
- },
497
- bubbles: true,
498
- composed: true
499
- }));
500
- }
501
- }
502
- #allDescendantsSelected(node) {
503
- if (!this._selectedNodes.has(node)) return false;
504
- if (!node.children?.length) return true;
505
- return node.children.every((child) => this.#allDescendantsSelected(child));
506
- }
507
- #applyCheckedToggle(node, selected) {
508
- if (this.#canSelect(node)) if (selected) this._selectedNodes.add(node);
509
- else this._selectedNodes.delete(node);
510
- if (node.children) for (const child of node.children) this.#applyCheckedToggle(child, selected);
511
- }
512
- #getFlatIndexOf(node) {
513
- return this.#getAllNodes().findIndex((n) => n.node === node);
514
- }
515
- #extendRangeSelection(nodes, fromIdx, toIdx) {
516
- if (!this.#anchor) {
517
- const anchorNode = nodes[fromIdx]?.node;
518
- if (anchorNode) this.#anchor = {
519
- node: anchorNode,
520
- flatIndex: fromIdx
521
- };
522
- }
523
- if (!this.#anchor) return;
524
- const anchorIdx = nodes.findIndex((n) => n.node === this.#anchor.node);
525
- if (anchorIdx < 0) return;
526
- const from = Math.min(anchorIdx, toIdx);
527
- const to = Math.max(anchorIdx, toIdx);
528
- if (this.interactionMode === `vscode`) {
529
- if (!this.#anchor.selectionSnapshot) this.#anchor = {
530
- ...this.#anchor,
531
- selectionSnapshot: new Set(this._selectedNodes)
532
- };
533
- const snap = this.#anchor.selectionSnapshot;
534
- const rangeNodes = nodes.slice(from, to + 1).map((n) => n.node).filter((n) => this.#canSelect(n));
535
- const next = new Set(snap);
536
- for (const n of rangeNodes) if (snap.has(n)) next.delete(n);
537
- else next.add(n);
538
- const prev = new Set(this._selectedNodes);
539
- this._selectedNodes = next;
540
- this.selectedNode = nodes[toIdx]?.node ?? this.selectedNode;
541
- this.#dispatchSelect(prev);
542
- } else {
543
- const prev = new Set(this._selectedNodes);
544
- const rangeNodes = nodes.slice(from, to + 1).map((n) => n.node).filter((n) => this.#canSelect(n));
545
- this._selectedNodes = new Set(rangeNodes);
546
- this.selectedNode = nodes[toIdx]?.node ?? this.selectedNode;
547
- this.#dispatchSelect(prev);
548
- }
549
- }
550
- async #invokeLoadChildren(node, depth, controller) {
551
- try {
552
- let children;
553
- if (this.model) children = await this.model.getChildren(node, depth, controller.signal);
554
- else {
555
- const result = this.loadChildren(node, depth, controller.signal);
556
- children = result instanceof Promise ? await result : result;
557
- }
558
- if (controller.signal.aborted) return;
559
- node.children = children;
560
- this.#applyExclusivity(node.item.key);
561
- this._expandedKeys.add(node.item.key);
562
- this.#pendingNode = void 0;
563
- this.#pendingController = void 0;
564
- this.dispatchEvent(new CustomEvent(`expand`, {
565
- detail: {
566
- node,
567
- depth
568
- },
569
- bubbles: true,
570
- composed: true
571
- }));
572
- this.requestUpdate();
573
- } catch (err) {
574
- if (controller.signal.aborted) return;
575
- node.children = [];
576
- this.#pendingNode = void 0;
577
- this.#pendingController = void 0;
578
- this.requestUpdate();
579
- }
580
- }
581
- _isSelected(node) {
582
- return this._selectedNodes.has(node);
583
- }
584
- _isFocused(node) {
585
- return this.tickled.isTickled(node.item.key);
586
- }
587
- _isExpanded(node) {
588
- if (this._expandedKeys.has(node.item.key)) return true;
589
- if (this.filterPredicate && node.children) return node.children.some((child) => this.#matchesFilter(child, 0));
590
- return false;
591
- }
592
- #matchesFilter(node, depth) {
593
- if (!this.filterPredicate) return true;
594
- if (this.filterPredicate(node, depth)) return true;
595
- return node.children?.some((child) => this.#matchesFilter(child, depth + 1)) ?? false;
596
- }
597
- get _pendingNode() {
598
- return this.#pendingNode;
599
- }
600
- #scrollKeyIntoView(key) {
601
- requestAnimationFrame(() => {
602
- const el = this.shadowRoot?.querySelector(`[data-key="${CSS.escape(key)}"]`);
603
- if (!el) return;
604
- const elRect = el.getBoundingClientRect();
605
- const hostRect = this.getBoundingClientRect();
606
- const relativeTop = elRect.top - hostRect.top;
607
- const relativeBottom = relativeTop + elRect.height;
608
- if (relativeTop < 0) this.scrollTop += relativeTop;
609
- else if (relativeBottom > this.clientHeight) this.scrollTop += relativeBottom - this.clientHeight;
610
- });
611
- }
612
- #abortPending() {
613
- if (this.#pendingController) {
614
- this.#pendingController.abort();
615
- this.#pendingController = void 0;
616
- this.#pendingNode = void 0;
617
- }
618
- }
619
- /** Apply exclusivity rules when a node is about to be expanded. */
620
- #applyExclusivity(expandKey) {
621
- if (this.exclusivity === `none`) return;
622
- if (this.exclusivity === `depth`) this.#collapseSiblingsAtDepth(expandKey);
623
- else if (this.exclusivity === `global`) {
624
- const ancestorKeys = this.#findAncestorKeys(expandKey);
625
- for (const key of [...this._expandedKeys]) if (!ancestorKeys.has(key) && key !== expandKey) this._expandedKeys.delete(key);
626
- }
627
- }
628
- #collapseSiblingsAtDepth(expandKey) {
629
- if (!this.root) return;
630
- const parent = this.#findParent(this.root, expandKey);
631
- if (!parent?.children) return;
632
- for (const child of parent.children) if (child.item.key !== expandKey && this._expandedKeys.has(child.item.key)) this._expandedKeys.delete(child.item.key);
633
- }
634
- #findAncestorKeys(targetKey) {
635
- const keys = /* @__PURE__ */ new Set();
636
- const walk = (node) => {
637
- if (node.item.key === targetKey) return true;
638
- if (!node.children) return false;
639
- for (const child of node.children) if (walk(child)) {
640
- keys.add(node.item.key);
641
- return true;
642
- }
643
- return false;
644
- };
645
- if (this.root) walk(this.root);
646
- return keys;
647
- }
648
- #findParent(node, targetKey, parent = void 0) {
649
- if (!node.children) return void 0;
650
- for (const child of node.children) {
651
- if (child.item.key === targetKey) return parent ?? node;
652
- const found = this.#findParent(child, targetKey, child);
653
- if (found) return found;
654
- }
655
- }
656
- #getVisibleNodes(node, depth) {
657
- const result = [];
658
- const visit = (n, d) => {
659
- result.push({
660
- node: n,
661
- depth: d
662
- });
663
- if (this._expandedKeys.has(n.item.key) && n.children) for (const child of n.children) visit(child, d + 1);
664
- };
665
- if (node.children) for (const child of node.children) visit(child, depth + 1);
666
- return result;
667
- }
668
- #getAllNodes() {
669
- if (!this.root) return [];
670
- return this.#getVisibleNodes(this.root, 0);
671
- }
672
- #getFocusedIndex() {
673
- const nodes = this.#getAllNodes();
674
- const tickledKey = this.tickled.tickledId;
675
- if (!tickledKey) return 0;
676
- return nodes.findIndex((n) => n.node.item.key === tickledKey);
677
- }
678
- #setFocusedIndex(index) {
679
- const nodes = this.#getAllNodes();
680
- if (index < 0 || index >= nodes.length) return;
681
- const { node, depth } = nodes[index];
682
- this.tickled.setTickled(node.item.key);
683
- this._focusedDepth = depth;
684
- this.dispatchEvent(new CustomEvent(`tickle`, {
685
- detail: {
686
- node,
687
- depth
688
- },
689
- bubbles: true,
690
- composed: true
691
- }));
692
- this.requestUpdate();
693
- this.updateComplete.then(() => this.#scrollTickledIntoView());
694
- }
695
- #scrollTickledIntoView() {
696
- const tickledKey = this.tickled.tickledId;
697
- if (tickledKey === void 0) return;
698
- (this.shadowRoot?.querySelector(`[data-key="${tickledKey}"]`))?.scrollIntoView({
699
- block: `nearest`,
700
- behavior: `smooth`
701
- });
702
- }
703
- #onKeyDown;
704
- renderLoadingIndicator() {
705
- return html`<span class="loading-spinner"></span>`;
706
- }
707
- render() {
708
- const nodes = this.#getAllNodes();
709
- return html`
710
- <div
711
- id="container"
712
- data-input-mode=${this.tickled.inputMode}
713
- @keydown=${this.#onKeyDown}
714
- @dblclick=${this.#onDblClick}
715
- @pointerleave=${(e) => this.tickled.handlePointerLeave(e)}
716
- tabindex="0"
717
- >
718
- ${this.root ? this.#renderNodes(nodes) : nothing}
719
- </div>
720
- `;
721
- }
722
- #onDblClick;
723
- #renderNodes(nodes) {
724
- if (nodes.length === 0 && this.#pendingNode) return html`
725
- <div class="tree-loading">
726
- ${this.renderLoadingIndicator()}
727
- </div>
728
- `;
729
- return html`
730
- <ul class="tree-list" role="tree">
731
- ${nodes.map(({ node, depth }) => this._renderNode(node, depth))}
732
- </ul>
733
- `;
734
- }
735
- _renderNode(node, depth) {
736
- const selected = this._isSelected(node);
737
- const tickled = this._isFocused(node);
738
- const isBranch = node.item.isLeaf !== true;
739
- const isExpanded = this._isExpanded(node);
740
- const isPending = this.#pendingNode === node;
741
- const isFiltered = this.filterPredicate !== void 0 && !this.#matchesFilter(node, depth);
742
- return html`
743
- <li
744
- class="item ${selected ? `selected` : ``} ${tickled ? `tickled` : ``} ${isBranch ? `branch` : `leaf`} ${isFiltered ? `filtered` : ``}"
745
- role="treeitem"
746
- aria-selected=${selected}
747
- aria-expanded=${isBranch ? isExpanded : nothing}
748
- aria-level=${depth + 1}
749
- data-key=${node.item.key}
750
- style=${`--depth: ${depth}`}
751
- @click=${(e) => this._handleItemClick(node, depth, e)}
752
- @pointerenter=${() => {
753
- this.tickled.handlePointerEnter(node.item.key);
754
- this.dispatchEvent(new CustomEvent(`tickle`, {
755
- detail: {
756
- node,
757
- depth
758
- },
759
- bubbles: true,
760
- composed: true
761
- }));
762
- }}
763
- >
764
- ${this.renderNodeContent(node, depth)}
765
- ${isPending ? this.renderLoadingIndicator() : nothing}
766
- </li>
767
- `;
768
- }
769
- static {
770
- this.styles = [
771
- tickledStyles,
772
- tickledItemStyles,
773
- css`
774
- :host {
775
- --tree-bg: var(--surface-3);
776
- --tree-text: var(--surface-3-text);
777
- --tree-muted-text: var(--surface-muted-text);
778
- --tree-indent: 1ch;
779
- --tree-item-height: 28px;
780
- --tree-caret-size: 10px;
781
- --tree-radius: var(--radius-s);
782
-
783
- display: block;
784
- overflow: auto;
785
- box-sizing: border-box;
786
- background: var(--tree-bg);
787
- color: var(--tree-text);
788
- }
789
-
790
- #container {
791
- outline: none;
792
- min-height: 100%;
793
- }
794
-
795
- .tree-list {
796
- list-style: none;
797
- margin: 0;
798
- padding: var(--space-xs);
799
- }
800
-
801
- .item {
802
- display: flex;
803
- align-items: center;
804
- height: var(--tree-item-height);
805
- padding-left: calc(var(--tree-indent) * var(--depth, 0));
806
- cursor: pointer;
807
- user-select: none;
808
- font-family: var(--font-family);
809
- font-size: var(--text-m);
810
- border-radius: var(--tree-radius);
811
- transition: background var(--transition, 0.15s ease-out);
812
- margin: 1px 0;
813
- }
814
-
815
- .tree-caret {
816
- display: inline-flex;
817
- align-items: center;
818
- justify-content: center;
819
- width: var(--tree-caret-size);
820
- height: var(--tree-caret-size);
821
- flex-shrink: 0;
822
- margin-right: var(--space-xs);
823
- }
824
-
825
- .caret-icon {
826
- width: var(--tree-caret-size);
827
- height: var(--tree-caret-size);
828
- color: var(--tree-muted-text);
829
- transition: transform var(--transition, 0.15s ease-out);
830
- }
831
-
832
- .item.selected .caret-icon {
833
- color: var(--accent-text);
834
- }
835
-
836
- .tree-label {
837
- flex: 1;
838
- overflow: hidden;
839
- text-overflow: ellipsis;
840
- white-space: nowrap;
841
- }
842
-
843
- .tree-loading {
844
- display: flex;
845
- align-items: center;
846
- justify-content: center;
847
- padding: var(--space-m);
848
- }
849
-
850
- .loading-spinner {
851
- width: 16px;
852
- height: 16px;
853
- border: 2px solid var(--surface-5);
854
- border-top-color: var(--accent);
855
- border-radius: 50%;
856
- animation: tree-spin 0.7s linear infinite;
857
- }
858
-
859
- @keyframes tree-spin {
860
- to { transform: rotate(360deg); }
861
- }
862
-
863
- .item.filtered {
864
- display: none;
865
- }
866
-
867
- ::highlight(incr-search-highlight) {
868
- background: var(--search-highlight-bg, var(--accent));
869
- color: var(--search-highlight-color, var(--accent-text, #fff));
870
- border-radius: 2px;
871
- padding: 0 1px;
872
- }
873
- `
874
- ];
875
- }
876
- };
877
- __decorate([property({ type: Object })], TreeBaseElement.prototype, "root", void 0);
878
- __decorate([property({ attribute: false })], TreeBaseElement.prototype, "model", void 0);
879
- __decorate([property({ attribute: false })], TreeBaseElement.prototype, "loadChildren", void 0);
880
- __decorate([property({
881
- reflect: true,
882
- attribute: `exclusivity`
883
- })], TreeBaseElement.prototype, "exclusivity", void 0);
884
- __decorate([property({
885
- reflect: true,
886
- attribute: `selection-filter`
887
- })], TreeBaseElement.prototype, "selectionFilter", void 0);
888
- __decorate([property({
889
- type: String,
890
- attribute: `interaction-mode`
891
- })], TreeBaseElement.prototype, "interactionMode", void 0);
892
- __decorate([property({ attribute: false })], TreeBaseElement.prototype, "selectedNode", void 0);
893
- __decorate([state()], TreeBaseElement.prototype, "_selectedNodes", void 0);
894
- __decorate([property({ attribute: false })], TreeBaseElement.prototype, "filterPredicate", void 0);
895
- __decorate([property({
896
- type: Boolean,
897
- attribute: `disable-keyboard-navigation`
898
- })], TreeBaseElement.prototype, "disableKeyboardNavigation", void 0);
899
- __decorate([state()], TreeBaseElement.prototype, "_expandedKeys", void 0);
900
- __decorate([state()], TreeBaseElement.prototype, "_focusedDepth", void 0);
901
- TreeBaseElement = __decorate([safeCustomElement(`ixfx-tree-base`)], TreeBaseElement);
902
- //#endregion
903
- //#region src/tree/tree-controller.ts
904
- var TreeController = class {
905
- #root;
906
- #element;
907
- #options;
908
- #nodeToTree = /* @__PURE__ */ new WeakMap();
909
- #identityToTreeNode = /* @__PURE__ */ new Map();
910
- #connectSignal;
911
- constructor(root, element, options) {
912
- this.#root = root;
913
- this.#element = element;
914
- this.#options = options;
915
- }
916
- connect() {
917
- this.disconnect();
918
- this.#connectSignal = new AbortController();
919
- const { signal } = this.#connectSignal;
920
- const rootValue = this.#root.getValue();
921
- const rootItem = this.#options.valueToItem(rootValue, this.#root);
922
- const rootChildren = this.#childrenOf(this.#root);
923
- this.#element.root = {
924
- item: rootItem,
925
- children: rootChildren
926
- };
927
- this.#element.addEventListener(`expand`, (e) => {
928
- const { node } = e.detail;
929
- const treeNode = this.#nodeToTree.get(node);
930
- if (!treeNode) return;
931
- node.children = this.#childrenOf(treeNode);
932
- this.#element.requestUpdate();
933
- }, { signal });
934
- this.#element.addEventListener(`collapse`, (_e) => {}, { signal });
935
- }
936
- disconnect() {
937
- this.#connectSignal?.abort();
938
- this.#connectSignal = void 0;
939
- }
940
- navigateToValue(predicate) {
941
- const treePath = this.#findTreePath(this.#root, predicate);
942
- if (!treePath) return false;
943
- const keys = [];
944
- for (let i = 1; i < treePath.length; i++) {
945
- const treeNode = treePath[i];
946
- const key = this.#options.valueToItem(treeNode.getValue(), treeNode).key;
947
- keys.push(key);
948
- if (i < treePath.length - 1) {
949
- const currentChildren = i === 1 ? this.#element.root?.children ?? [] : this.#findInChildren(this.#element.root?.children ?? [], keys);
950
- const treeNodeMap = this.#nodeToTree;
951
- const node = currentChildren.find((n) => n.item.key === key);
952
- if (!node) return false;
953
- if (node.children === void 0) {
954
- const mapped = treeNodeMap.get(node);
955
- if (mapped) node.children = this.#childrenOf(mapped);
956
- }
957
- }
958
- }
959
- return this.#element.navigateTo(keys);
960
- }
961
- #findInChildren(children, keys) {
962
- if (keys.length === 0) return children;
963
- const key = keys[0];
964
- return children.find((n) => n.item.key === key)?.children ?? [];
965
- }
966
- #childrenOf(treeNode) {
967
- return Array.from(treeNode.children(), (child) => this.#toTreeNode(child));
968
- }
969
- #toTreeNode(treeNode) {
970
- const value = treeNode.getValue();
971
- const childList = [...treeNode.children()];
972
- const userItem = this.#options.valueToItem(value, treeNode);
973
- const isLeaf = userItem.isLeaf ?? childList.length === 0;
974
- const treeNodeMap = { item: {
975
- ...userItem,
976
- isLeaf
977
- } };
978
- this.#nodeToTree.set(treeNodeMap, treeNode);
979
- this.#identityToTreeNode.set(treeNode.getIdentity(), treeNode);
980
- return treeNodeMap;
981
- }
982
- #findTreePath(node, predicate, ancestors = []) {
983
- const path = [...ancestors, node];
984
- if (predicate(node.getValue())) return path;
985
- for (const child of node.children()) {
986
- const result = this.#findTreePath(child, predicate, path);
987
- if (result) return result;
988
- }
989
- }
990
- };
991
- //#endregion
992
- //#region src/tree/tree-list.ts
993
- function computeCheckboxState(node, selectedNodes) {
994
- if (node.item.isLeaf || !node.children?.length) return selectedNodes.has(node) ? `checked` : `unchecked`;
995
- const childStates = node.children.map((c) => computeCheckboxState(c, selectedNodes));
996
- const allChecked = childStates.every((s) => s === `checked`);
997
- const allUnchecked = childStates.every((s) => s === `unchecked`);
998
- if (allChecked) return `checked`;
999
- if (allUnchecked) return `unchecked`;
1000
- return `indeterminate`;
1001
- }
1002
- let TreeListElement = class TreeListElement extends TreeBaseElement {
1003
- #depthsWithIcons = /* @__PURE__ */ new Set();
1004
- render() {
1005
- this.#detectIcons();
1006
- return super.render();
1007
- }
1008
- #detectIcons() {
1009
- this.#depthsWithIcons.clear();
1010
- const visit = (node, depth) => {
1011
- if (node.item.icon) this.#depthsWithIcons.add(depth);
1012
- if (node.children) for (const child of node.children) visit(child, depth + 1);
1013
- };
1014
- if (this.root) visit(this.root, 0);
1015
- }
1016
- renderNodeContent(node, depth) {
1017
- const isBranch = node.item.isLeaf !== true;
1018
- const isExpanded = this._isExpanded(node);
1019
- const icon = node.item.icon;
1020
- const tooltip = node.item.tooltip;
1021
- const caretAndLabel = html`
1022
- <span class="tree-caret">
1023
- ${isBranch ? html`<ixfx-icon class="caret-icon" name="chevron-down" .rotate=${isExpanded ? nothing : `-90deg`}></ixfx-icon>` : ``}
1024
- </span>
1025
- ${icon ? html`<ixfx-icon class="tree-icon" name="${icon}"></ixfx-icon>` : nothing}
1026
- <span class="tree-label">
1027
- ${node.item.label}
1028
- ${tooltip ? html`<ixfx-tooltip class="tree-tooltip" anchor="--tooltip-tree-${node.item.key}" .value=${tooltip}></ixfx-tooltip>` : nothing}
1029
- </span>
1030
- `;
1031
- if (this.interactionMode === `checked`) {
1032
- const state = computeCheckboxState(node, this._selectedNodes);
1033
- return html`
1034
- <input
1035
- type="checkbox"
1036
- class="tree-checkbox"
1037
- .checked=${state === `checked`}
1038
- .indeterminate=${state === `indeterminate`}
1039
- aria-label="Select ${node.item.label}"
1040
- @click=${(e) => this._handleCheckboxClick(e, node, depth)}
1041
- />${caretAndLabel}`;
1042
- }
1043
- return caretAndLabel;
1044
- }
1045
- _renderNode(node, depth) {
1046
- const selected = this._isSelected(node);
1047
- const tickled = this._isFocused(node);
1048
- const isBranch = node.item.isLeaf !== true;
1049
- const isExpanded = this._isExpanded(node);
1050
- const isPending = this._pendingNode === node;
1051
- const hasIconAtDepth = this.#depthsWithIcons.has(depth);
1052
- return html`
1053
- <li
1054
- class="item ${selected ? `selected` : ``} ${tickled ? `tickled` : ``} ${isBranch ? `branch` : `leaf`} ${hasIconAtDepth ? `has-icon-at-depth` : ``}"
1055
- data-key=${node.item.key}
1056
- role="treeitem"
1057
- aria-selected=${selected}
1058
- aria-expanded=${isBranch ? isExpanded : nothing}
1059
- aria-level=${depth + 1}
1060
- style=${`--depth: ${depth}`}
1061
- @click=${(e) => this._handleItemClick(node, depth, e)}
1062
- @pointerenter=${() => this.tickled.handlePointerEnter(node.item.key)}
1063
- >
1064
- ${this.renderNodeContent(node, depth)}
1065
- ${isPending ? this.renderLoadingIndicator() : nothing}
1066
- </li>
1067
- `;
1068
- }
1069
- static {
1070
- this.styles = [...TreeBaseElement.styles, css`
1071
- .tree-caret {
1072
- display: inline-flex;
1073
- align-items: center;
1074
- justify-content: center;
1075
- width: var(--tree-caret-size);
1076
- height: var(--tree-caret-size);
1077
- flex-shrink: 0;
1078
- margin-right: var(--space-xs);
1079
- }
1080
-
1081
- .caret-icon {
1082
- width: var(--tree-caret-size);
1083
- height: var(--tree-caret-size);
1084
- color: var(--tree-muted-text);
1085
- transition: transform var(--transition, 0.15s ease-out);
1086
- }
1087
-
1088
- .item.selected .caret-icon {
1089
- color: var(--accent-text);
1090
- }
1091
-
1092
- .tree-icon {
1093
- flex-shrink: 0;
1094
- width: var(--icon-size, 1em);
1095
- height: var(--icon-size, 1em);
1096
- margin-right: var(--icon-spacing, 0.3em);
1097
- }
1098
-
1099
- .item:not(.has-icon-at-depth) .tree-icon {
1100
- display: none;
1101
- }
1102
-
1103
- .item.has-icon-at-depth .tree-label {
1104
- margin-left: var(--icon-size, 1em);
1105
- }
1106
-
1107
- .tree-tooltip {
1108
- position: absolute;
1109
- anchor-name: --tooltip-tree;
1110
- }
1111
-
1112
- .tree-checkbox {
1113
- flex-shrink: 0;
1114
- margin-right: var(--space-xs, 3px);
1115
- cursor: pointer;
1116
- accent-color: var(--accent);
1117
- pointer-events: auto;
1118
- }
1119
-
1120
- /* In checked mode the checkbox communicates selection state —
1121
- suppress the row highlight so it doesn't double-signal */
1122
- :host([interaction-mode="checked"]) .item.selected {
1123
- background: transparent;
1124
- color: inherit;
1125
- outline: none;
1126
- }
1127
-
1128
-
1129
-
1130
- .tree-label {
1131
- flex: 1;
1132
- overflow: hidden;
1133
- text-overflow: ellipsis;
1134
- white-space: nowrap;
1135
- position: relative;
1136
- }
1137
- `];
1138
- }
1139
- };
1140
- TreeListElement = __decorate([safeCustomElement(`ixfx-tree-list`)], TreeListElement);
1141
- //#endregion
1
+ import { i as TreeDataModel, n as TreeController, r as TreeBaseElement, t as TreeListElement } from "./tree-CvvKbO-f.js";
1142
2
  export { TreeBaseElement, TreeController, TreeDataModel, TreeListElement };
1143
-
1144
- //# sourceMappingURL=tree.js.map