@krollins/blueprint 0.1.11 → 0.1.13
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.
- package/dist/components/accordion.js +393 -0
- package/dist/components/accordion.js.map +1 -0
- package/dist/components/alert.js +213 -0
- package/dist/components/alert.js.map +1 -0
- package/dist/components/avatar.js +237 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.js +144 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/breadcrumb.js +481 -0
- package/dist/components/breadcrumb.js.map +1 -0
- package/dist/components/button.js +192 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/card.js +223 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/checkbox.js +337 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/color-picker.js +1660 -0
- package/dist/components/color-picker.js.map +1 -0
- package/dist/components/combobox.js +595 -0
- package/dist/components/combobox.js.map +1 -0
- package/dist/components/date-picker.js +726 -0
- package/dist/components/date-picker.js.map +1 -0
- package/dist/components/divider.js +214 -0
- package/dist/components/divider.js.map +1 -0
- package/dist/components/drawer.js +568 -0
- package/dist/components/drawer.js.map +1 -0
- package/dist/components/dropdown.js +377 -0
- package/dist/components/dropdown.js.map +1 -0
- package/dist/components/file-upload.js +669 -0
- package/dist/components/file-upload.js.map +1 -0
- package/dist/components/heading.js +161 -0
- package/dist/components/heading.js.map +1 -0
- package/dist/components/icon.js +599 -0
- package/dist/components/icon.js.map +1 -0
- package/dist/components/input.js +363 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/link.js +178 -0
- package/dist/components/link.js.map +1 -0
- package/dist/components/menu.js +331 -0
- package/dist/components/menu.js.map +1 -0
- package/dist/components/modal.js +317 -0
- package/dist/components/modal.js.map +1 -0
- package/dist/components/multi-select.js +642 -0
- package/dist/components/multi-select.js.map +1 -0
- package/dist/components/notification.js +429 -0
- package/dist/components/notification.js.map +1 -0
- package/dist/components/number-input.js +556 -0
- package/dist/components/number-input.js.map +1 -0
- package/dist/components/pagination.js +320 -0
- package/dist/components/pagination.js.map +1 -0
- package/dist/components/popover.js +597 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/progress.js +219 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/radio.js +321 -0
- package/dist/components/radio.js.map +1 -0
- package/dist/components/select.js +498 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/skeleton.js +240 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/slider.js +9 -0
- package/dist/components/slider.js.map +1 -0
- package/dist/components/spinner.js +133 -0
- package/dist/components/spinner.js.map +1 -0
- package/dist/components/stepper.js +812 -0
- package/dist/components/stepper.js.map +1 -0
- package/dist/components/switch.js +380 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/table.js +642 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/tabs.js +547 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/tag.js +291 -0
- package/dist/components/tag.js.map +1 -0
- package/dist/components/text.js +278 -0
- package/dist/components/text.js.map +1 -0
- package/dist/components/textarea.js +380 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/time-picker.js +457 -0
- package/dist/components/time-picker.js.map +1 -0
- package/dist/components/tooltip.js +239 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/tree.js +582 -0
- package/dist/components/tree.js.map +1 -0
- package/dist/index.js +93 -17799
- package/dist/index.js.map +1 -1
- package/dist/shared/boolean-converter-XDGfS9LC.js +12 -0
- package/dist/shared/boolean-converter-XDGfS9LC.js.map +1 -0
- package/dist/shared/debounce-BckY30Sf.js +23 -0
- package/dist/shared/debounce-BckY30Sf.js.map +1 -0
- package/dist/shared/memoize-DlOFy-92.js +16 -0
- package/dist/shared/memoize-DlOFy-92.js.map +1 -0
- package/dist/shared/slider-BNt5TITl.js +484 -0
- package/dist/shared/slider-BNt5TITl.js.map +1 -0
- package/package.json +49 -3
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
import { css as g, LitElement as v, nothing as b, html as a } from "lit";
|
|
2
|
+
import { property as d, state as m, customElement as x } from "lit/decorators.js";
|
|
3
|
+
import { ifDefined as h } from "lit/directives/if-defined.js";
|
|
4
|
+
import { repeat as f } from "lit/directives/repeat.js";
|
|
5
|
+
import { m as y } from "../shared/memoize-DlOFy-92.js";
|
|
6
|
+
const w = g`
|
|
7
|
+
/* Base styles */
|
|
8
|
+
:host {
|
|
9
|
+
display: block;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.tree {
|
|
13
|
+
font-family: var(--bp-font-family);
|
|
14
|
+
font-size: var(--bp-font-size-base);
|
|
15
|
+
color: var(--bp-color-text);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* Node structure */
|
|
19
|
+
.node {
|
|
20
|
+
position: relative;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.node-content {
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
gap: var(--bp-spacing-2);
|
|
27
|
+
padding: var(--bp-spacing-2) var(--bp-spacing-3);
|
|
28
|
+
padding-left: calc(
|
|
29
|
+
var(--bp-spacing-3) + var(--node-level, 0) * var(--bp-spacing-5)
|
|
30
|
+
);
|
|
31
|
+
border-radius: var(--bp-border-radius-sm);
|
|
32
|
+
cursor: pointer;
|
|
33
|
+
user-select: none;
|
|
34
|
+
transition:
|
|
35
|
+
background-color var(--bp-transition-fast),
|
|
36
|
+
color var(--bp-transition-fast);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.node-content:hover {
|
|
40
|
+
background-color: var(--bp-color-surface-subdued);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.node-content:focus {
|
|
44
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
|
|
45
|
+
outline-offset: var(--bp-focus-offset);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.node-content:focus:not(:focus-visible) {
|
|
49
|
+
outline: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.node-content:focus-visible {
|
|
53
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
|
|
54
|
+
outline-offset: var(--bp-focus-offset);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Selected state */
|
|
58
|
+
.node-content--selected {
|
|
59
|
+
background-color: oklch(from var(--bp-color-primary) l c h / 0.15);
|
|
60
|
+
color: var(--bp-color-primary);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.node-content--selected:hover {
|
|
64
|
+
background-color: oklch(from var(--bp-color-primary) l c h / 0.2);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Active state */
|
|
68
|
+
.node-content:active {
|
|
69
|
+
background-color: var(--bp-color-surface-subdued);
|
|
70
|
+
transform: translateY(1px);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.node-content--selected:active {
|
|
74
|
+
background-color: oklch(from var(--bp-color-primary) l c h / 0.25);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Toggle icon */
|
|
78
|
+
.node-toggle {
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
justify-content: center;
|
|
82
|
+
width: var(--bp-spacing-5);
|
|
83
|
+
height: var(--bp-spacing-5);
|
|
84
|
+
flex-shrink: 0;
|
|
85
|
+
visibility: hidden;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.node-toggle--visible {
|
|
89
|
+
visibility: visible;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.node-toggle--visible:hover {
|
|
93
|
+
background-color: var(--bp-color-surface-subdued);
|
|
94
|
+
border-radius: var(--bp-border-radius-sm);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.toggle-icon {
|
|
98
|
+
width: var(--bp-spacing-4);
|
|
99
|
+
height: var(--bp-spacing-4);
|
|
100
|
+
transition: transform var(--bp-transition-fast) ease-out;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.toggle-icon--expanded {
|
|
104
|
+
transform: rotate(90deg);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* Node custom icon */
|
|
108
|
+
.node-icon {
|
|
109
|
+
flex-shrink: 0;
|
|
110
|
+
color: var(--bp-color-text-muted);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Node label */
|
|
114
|
+
.node-label {
|
|
115
|
+
flex: 1;
|
|
116
|
+
overflow: hidden;
|
|
117
|
+
text-overflow: ellipsis;
|
|
118
|
+
white-space: nowrap;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Children container */
|
|
122
|
+
.node-children {
|
|
123
|
+
position: relative;
|
|
124
|
+
content-visibility: auto;
|
|
125
|
+
contain-intrinsic-size: auto 200px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Expanded state visual cue */
|
|
129
|
+
.node--expanded > .node-content {
|
|
130
|
+
background-color: var(--bp-color-surface);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* Disabled state */
|
|
134
|
+
.node--disabled .node-content {
|
|
135
|
+
cursor: not-allowed;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.node--disabled .node-label {
|
|
139
|
+
opacity: var(--bp-opacity-disabled);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.node--disabled .node-content:hover {
|
|
143
|
+
background-color: transparent;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* Show lines variant */
|
|
147
|
+
.tree--lines .node-children {
|
|
148
|
+
margin-left: calc(var(--bp-spacing-4) + var(--bp-spacing-4));
|
|
149
|
+
padding-left: var(--bp-spacing-4);
|
|
150
|
+
border-left: var(--bp-border-width) solid var(--bp-color-border);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Sizes */
|
|
154
|
+
.tree--sm {
|
|
155
|
+
font-size: var(--bp-font-size-sm);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.tree--sm .node-content {
|
|
159
|
+
padding: var(--bp-spacing-1) var(--bp-spacing-2);
|
|
160
|
+
padding-left: calc(
|
|
161
|
+
var(--bp-spacing-2) + var(--node-level, 0) * var(--bp-spacing-4)
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.tree--sm .node-toggle {
|
|
166
|
+
width: var(--bp-spacing-4);
|
|
167
|
+
height: var(--bp-spacing-4);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.tree--sm .toggle-icon {
|
|
171
|
+
width: var(--bp-spacing-3);
|
|
172
|
+
height: var(--bp-spacing-3);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.tree--lg {
|
|
176
|
+
font-size: var(--bp-font-size-lg);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.tree--lg .node-content {
|
|
180
|
+
padding: var(--bp-spacing-3) var(--bp-spacing-4);
|
|
181
|
+
padding-left: calc(
|
|
182
|
+
var(--bp-spacing-4) + var(--node-level, 0) * var(--bp-spacing-6)
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.tree--lg .node-toggle {
|
|
187
|
+
width: var(--bp-spacing-6);
|
|
188
|
+
height: var(--bp-spacing-6);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.tree--lg .toggle-icon {
|
|
192
|
+
width: var(--bp-spacing-5);
|
|
193
|
+
height: var(--bp-spacing-5);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* Link nodes — reset anchor styles so links look like regular nodes */
|
|
197
|
+
a.node-content {
|
|
198
|
+
text-decoration: none;
|
|
199
|
+
color: inherit;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
a.node-content:visited {
|
|
203
|
+
color: inherit;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* Reduced motion */
|
|
207
|
+
@media (prefers-reduced-motion: reduce) {
|
|
208
|
+
.node-content,
|
|
209
|
+
.toggle-icon {
|
|
210
|
+
transition: none;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.node-content:active {
|
|
214
|
+
transform: none;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
`;
|
|
218
|
+
var $ = Object.defineProperty, k = Object.getOwnPropertyDescriptor, l = (e, t, s, i) => {
|
|
219
|
+
for (var o = i > 1 ? void 0 : i ? k(t, s) : t, c = e.length - 1, p; c >= 0; c--)
|
|
220
|
+
(p = e[c]) && (o = (i ? p(t, s, o) : p(o)) || o);
|
|
221
|
+
return i && o && $(t, s, o), o;
|
|
222
|
+
};
|
|
223
|
+
let r = class extends v {
|
|
224
|
+
constructor() {
|
|
225
|
+
super(), this.selectedIds = [], this.computeExpandedSet = y(
|
|
226
|
+
(e) => new Set(e)
|
|
227
|
+
), this.nodes = [], this.selectedId = null, this.expandedIds = [], this.multiSelect = !1, this.showLines = !1, this.selectable = !0, this.size = "md";
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Get the memoized expanded set for fast lookups during rendering.
|
|
231
|
+
*/
|
|
232
|
+
get expandedSet() {
|
|
233
|
+
return this.computeExpandedSet(this.expandedIds);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Expand a node by ID.
|
|
237
|
+
* Adds the node to expandedIds and dispatches bp-expand event.
|
|
238
|
+
*
|
|
239
|
+
* @param nodeId - The ID of the node to expand
|
|
240
|
+
*/
|
|
241
|
+
expand(e) {
|
|
242
|
+
if (!this.expandedSet.has(e)) {
|
|
243
|
+
this.expandedIds = [...this.expandedIds, e];
|
|
244
|
+
const t = this.findNode(e, this.nodes);
|
|
245
|
+
t && this.dispatchEvent(
|
|
246
|
+
new CustomEvent("bp-expand", {
|
|
247
|
+
detail: { node: t, expanded: !0 },
|
|
248
|
+
bubbles: !0,
|
|
249
|
+
composed: !0
|
|
250
|
+
})
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Collapse a node by ID.
|
|
256
|
+
* Removes the node from expandedIds and dispatches bp-collapse event.
|
|
257
|
+
*
|
|
258
|
+
* @param nodeId - The ID of the node to collapse
|
|
259
|
+
*/
|
|
260
|
+
collapse(e) {
|
|
261
|
+
if (this.expandedSet.has(e)) {
|
|
262
|
+
this.expandedIds = this.expandedIds.filter((s) => s !== e);
|
|
263
|
+
const t = this.findNode(e, this.nodes);
|
|
264
|
+
t && this.dispatchEvent(
|
|
265
|
+
new CustomEvent("bp-collapse", {
|
|
266
|
+
detail: { node: t, expanded: !1 },
|
|
267
|
+
bubbles: !0,
|
|
268
|
+
composed: !0
|
|
269
|
+
})
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Toggle a node's expanded state.
|
|
275
|
+
* Calls expand() if collapsed, collapse() if expanded.
|
|
276
|
+
*
|
|
277
|
+
* @param nodeId - The ID of the node to toggle
|
|
278
|
+
*/
|
|
279
|
+
toggle(e) {
|
|
280
|
+
this.expandedSet.has(e) ? this.collapse(e) : this.expand(e);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Expand all nodes in the tree.
|
|
284
|
+
* Sets expandedIds to include all nodes with children.
|
|
285
|
+
*/
|
|
286
|
+
expandAll() {
|
|
287
|
+
const e = this.getAllNodeIds(this.nodes);
|
|
288
|
+
this.expandedIds = e;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Collapse all nodes in the tree.
|
|
292
|
+
* Clears the expandedIds array.
|
|
293
|
+
*/
|
|
294
|
+
collapseAll() {
|
|
295
|
+
this.expandedIds = [];
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Select a node by ID.
|
|
299
|
+
* Respects multiSelect setting and disabled state.
|
|
300
|
+
* Dispatches bp-select event with node, selectedIds, and path.
|
|
301
|
+
*
|
|
302
|
+
* @param nodeId - The ID of the node to select
|
|
303
|
+
*/
|
|
304
|
+
selectNode(e) {
|
|
305
|
+
const t = this.findNode(e, this.nodes);
|
|
306
|
+
!t || t.disabled || (this.multiSelect ? this.selectedIds.includes(e) ? this.selectedIds = this.selectedIds.filter((s) => s !== e) : this.selectedIds = [...this.selectedIds, e] : this.selectedId = e, this.dispatchEvent(
|
|
307
|
+
new CustomEvent("bp-select", {
|
|
308
|
+
detail: {
|
|
309
|
+
node: t,
|
|
310
|
+
selectedIds: this.multiSelect ? this.selectedIds : [e],
|
|
311
|
+
path: this.getNodePath(e, this.nodes)
|
|
312
|
+
},
|
|
313
|
+
bubbles: !0,
|
|
314
|
+
composed: !0
|
|
315
|
+
})
|
|
316
|
+
));
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Clear all selections.
|
|
320
|
+
* Resets both selectedId and selectedIds.
|
|
321
|
+
*/
|
|
322
|
+
clearSelection() {
|
|
323
|
+
this.selectedId = null, this.selectedIds = [];
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Recursively finds a node by ID in the tree structure.
|
|
327
|
+
*
|
|
328
|
+
* @param nodeId - The ID to search for
|
|
329
|
+
* @param nodes - The array of nodes to search within
|
|
330
|
+
* @returns The found node or null if not found
|
|
331
|
+
*/
|
|
332
|
+
findNode(e, t) {
|
|
333
|
+
for (const s of t) {
|
|
334
|
+
if (s.id === e) return s;
|
|
335
|
+
if (s.children) {
|
|
336
|
+
const i = this.findNode(e, s.children);
|
|
337
|
+
if (i) return i;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Recursively collects all node IDs that have children.
|
|
344
|
+
* Used for expandAll functionality.
|
|
345
|
+
*
|
|
346
|
+
* @param nodes - The array of nodes to collect IDs from
|
|
347
|
+
* @returns Array of node IDs that have children
|
|
348
|
+
*/
|
|
349
|
+
getAllNodeIds(e) {
|
|
350
|
+
const t = [];
|
|
351
|
+
for (const s of e)
|
|
352
|
+
s.children && s.children.length > 0 && (t.push(s.id), t.push(...this.getAllNodeIds(s.children)));
|
|
353
|
+
return t;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Gets the path from root to a specific node.
|
|
357
|
+
* Returns an array of node IDs representing the path.
|
|
358
|
+
*
|
|
359
|
+
* @param nodeId - The target node ID
|
|
360
|
+
* @param nodes - The array of nodes to search within
|
|
361
|
+
* @param path - Accumulator for the current path (used in recursion)
|
|
362
|
+
* @returns Array of node IDs from root to target
|
|
363
|
+
*/
|
|
364
|
+
getNodePath(e, t, s = []) {
|
|
365
|
+
for (const i of t) {
|
|
366
|
+
if (i.id === e)
|
|
367
|
+
return [...s, i.id];
|
|
368
|
+
if (i.children) {
|
|
369
|
+
const o = this.getNodePath(e, i.children, [
|
|
370
|
+
...s,
|
|
371
|
+
i.id
|
|
372
|
+
]);
|
|
373
|
+
if (o.length > s.length + 1)
|
|
374
|
+
return o;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return s;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Handles click events on tree nodes.
|
|
381
|
+
* For nodes with href, dispatches bp-navigate and follows the link unless prevented.
|
|
382
|
+
* For other nodes, selects the node if selectable and not disabled.
|
|
383
|
+
*
|
|
384
|
+
* @param event - The click event
|
|
385
|
+
* @param node - The node that was clicked
|
|
386
|
+
*/
|
|
387
|
+
handleNodeClick(e, t) {
|
|
388
|
+
if (e.stopPropagation(), t.href && !t.disabled) {
|
|
389
|
+
const s = new CustomEvent("bp-navigate", {
|
|
390
|
+
detail: {
|
|
391
|
+
node: t,
|
|
392
|
+
href: t.href,
|
|
393
|
+
path: this.getNodePath(t.id, this.nodes)
|
|
394
|
+
},
|
|
395
|
+
bubbles: !0,
|
|
396
|
+
composed: !0,
|
|
397
|
+
cancelable: !0
|
|
398
|
+
});
|
|
399
|
+
if (this.dispatchEvent(s))
|
|
400
|
+
return;
|
|
401
|
+
e.preventDefault();
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
this.selectable && !t.disabled && this.selectNode(t.id);
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Handles click events on the expand/collapse toggle icon.
|
|
408
|
+
* Prevents event propagation to avoid triggering node selection.
|
|
409
|
+
*
|
|
410
|
+
* @param event - The click event
|
|
411
|
+
* @param node - The node whose toggle was clicked
|
|
412
|
+
*/
|
|
413
|
+
handleToggleClick(e, t) {
|
|
414
|
+
e.stopPropagation(), e.preventDefault(), this.toggle(t.id);
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Handles keyboard navigation on tree nodes.
|
|
418
|
+
* Enter/Space: select node
|
|
419
|
+
* ArrowRight: expand node (if has children and collapsed)
|
|
420
|
+
* ArrowLeft: collapse node (if has children and expanded)
|
|
421
|
+
*
|
|
422
|
+
* @param event - The keyboard event
|
|
423
|
+
* @param node - The node that received the keyboard event
|
|
424
|
+
*/
|
|
425
|
+
handleKeyDown(e, t) {
|
|
426
|
+
const s = t.children && t.children.length > 0, i = this.expandedSet.has(t.id);
|
|
427
|
+
switch (e.key) {
|
|
428
|
+
case "Enter":
|
|
429
|
+
case " ":
|
|
430
|
+
e.preventDefault(), t.href && !t.disabled ? this.handleNodeClick(e, t) : this.selectable && !t.disabled && this.selectNode(t.id);
|
|
431
|
+
break;
|
|
432
|
+
case "ArrowRight":
|
|
433
|
+
e.preventDefault(), s && !i && this.expand(t.id);
|
|
434
|
+
break;
|
|
435
|
+
case "ArrowLeft":
|
|
436
|
+
e.preventDefault(), s && i && this.collapse(t.id);
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Checks if a node is currently selected.
|
|
442
|
+
* Handles both single and multi-select modes.
|
|
443
|
+
*
|
|
444
|
+
* @param nodeId - The node ID to check
|
|
445
|
+
* @returns True if the node is selected
|
|
446
|
+
*/
|
|
447
|
+
isSelected(e) {
|
|
448
|
+
return this.multiSelect ? this.selectedIds.includes(e) : this.selectedId === e;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Recursively renders a tree node and its children.
|
|
452
|
+
* Handles expand/collapse state, selection, and disabled state.
|
|
453
|
+
*
|
|
454
|
+
* @param node - The node to render
|
|
455
|
+
* @param level - The nesting level (0 for root)
|
|
456
|
+
* @returns Lit template result
|
|
457
|
+
*/
|
|
458
|
+
renderNode(e, t = 0) {
|
|
459
|
+
const s = e.children && e.children.length > 0, i = this.expandedSet.has(e.id), o = this.isSelected(e.id), c = `node-content ${o ? "node-content--selected" : ""} ${e.href ? "node-content--link" : ""}`, p = a`
|
|
460
|
+
<span
|
|
461
|
+
class="node-toggle ${s ? "node-toggle--visible" : ""}"
|
|
462
|
+
part="node-icon"
|
|
463
|
+
@click=${(n) => this.handleToggleClick(n, e)}
|
|
464
|
+
>
|
|
465
|
+
${s ? a`<bp-icon
|
|
466
|
+
class="toggle-icon ${i ? "toggle-icon--expanded" : ""}"
|
|
467
|
+
name="chevron-right"
|
|
468
|
+
size="sm"
|
|
469
|
+
></bp-icon>` : b}
|
|
470
|
+
</span>
|
|
471
|
+
${e.icon ? a`<bp-icon
|
|
472
|
+
class="node-icon"
|
|
473
|
+
part="node-custom-icon"
|
|
474
|
+
name=${e.icon}
|
|
475
|
+
size="sm"
|
|
476
|
+
></bp-icon>` : b}
|
|
477
|
+
<span class="node-label" part="node-label">${e.label}</span>
|
|
478
|
+
`, u = e.href ? a`
|
|
479
|
+
<a
|
|
480
|
+
class=${c}
|
|
481
|
+
part="node-content"
|
|
482
|
+
href=${e.href}
|
|
483
|
+
tabindex=${e.disabled ? -1 : 0}
|
|
484
|
+
@click=${(n) => this.handleNodeClick(n, e)}
|
|
485
|
+
@keydown=${(n) => this.handleKeyDown(n, e)}
|
|
486
|
+
>
|
|
487
|
+
${p}
|
|
488
|
+
</a>
|
|
489
|
+
` : a`
|
|
490
|
+
<div
|
|
491
|
+
class=${c}
|
|
492
|
+
part="node-content"
|
|
493
|
+
tabindex=${e.disabled ? -1 : 0}
|
|
494
|
+
@click=${(n) => this.handleNodeClick(n, e)}
|
|
495
|
+
@keydown=${(n) => this.handleKeyDown(n, e)}
|
|
496
|
+
>
|
|
497
|
+
${p}
|
|
498
|
+
</div>
|
|
499
|
+
`;
|
|
500
|
+
return a`
|
|
501
|
+
<div
|
|
502
|
+
class="node ${e.disabled ? "node--disabled" : ""} ${s && i ? "node--expanded" : ""}"
|
|
503
|
+
part="node"
|
|
504
|
+
role="treeitem"
|
|
505
|
+
aria-expanded=${h(
|
|
506
|
+
s ? i ? "true" : "false" : void 0
|
|
507
|
+
)}
|
|
508
|
+
aria-selected=${h(
|
|
509
|
+
this.selectable ? o ? "true" : "false" : void 0
|
|
510
|
+
)}
|
|
511
|
+
aria-disabled=${h(e.disabled ? "true" : void 0)}
|
|
512
|
+
style="--node-level: ${t}"
|
|
513
|
+
>
|
|
514
|
+
${u}
|
|
515
|
+
${s && i ? a`
|
|
516
|
+
<div class="node-children" part="node-children" role="group">
|
|
517
|
+
${f(
|
|
518
|
+
e.children,
|
|
519
|
+
(n) => n.id,
|
|
520
|
+
(n) => this.renderNode(n, t + 1)
|
|
521
|
+
)}
|
|
522
|
+
</div>
|
|
523
|
+
` : b}
|
|
524
|
+
</div>
|
|
525
|
+
`;
|
|
526
|
+
}
|
|
527
|
+
render() {
|
|
528
|
+
const e = this.nodes && this.nodes.length > 0;
|
|
529
|
+
return a`
|
|
530
|
+
<div
|
|
531
|
+
class="tree tree--${this.size} ${this.showLines ? "tree--lines" : ""}"
|
|
532
|
+
part="tree"
|
|
533
|
+
role="tree"
|
|
534
|
+
aria-multiselectable=${h(this.multiSelect ? "true" : void 0)}
|
|
535
|
+
>
|
|
536
|
+
${e ? f(
|
|
537
|
+
this.nodes,
|
|
538
|
+
(t) => t.id,
|
|
539
|
+
(t) => this.renderNode(t, 0)
|
|
540
|
+
) : a`<slot></slot>`}
|
|
541
|
+
</div>
|
|
542
|
+
`;
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
r.styles = [w];
|
|
546
|
+
l([
|
|
547
|
+
d({ type: Array })
|
|
548
|
+
], r.prototype, "nodes", 2);
|
|
549
|
+
l([
|
|
550
|
+
d({ type: String, reflect: !0 })
|
|
551
|
+
], r.prototype, "selectedId", 2);
|
|
552
|
+
l([
|
|
553
|
+
d({ type: Array })
|
|
554
|
+
], r.prototype, "expandedIds", 2);
|
|
555
|
+
l([
|
|
556
|
+
d({ type: Boolean, reflect: !0, attribute: "multi-select" })
|
|
557
|
+
], r.prototype, "multiSelect", 2);
|
|
558
|
+
l([
|
|
559
|
+
d({ type: Boolean, reflect: !0, attribute: "show-lines" })
|
|
560
|
+
], r.prototype, "showLines", 2);
|
|
561
|
+
l([
|
|
562
|
+
d({ type: Boolean, reflect: !0 })
|
|
563
|
+
], r.prototype, "selectable", 2);
|
|
564
|
+
l([
|
|
565
|
+
d({
|
|
566
|
+
type: String,
|
|
567
|
+
reflect: !0,
|
|
568
|
+
converter: {
|
|
569
|
+
fromAttribute: (e) => e && ["sm", "md", "lg"].includes(e) ? e : "md"
|
|
570
|
+
}
|
|
571
|
+
})
|
|
572
|
+
], r.prototype, "size", 2);
|
|
573
|
+
l([
|
|
574
|
+
m()
|
|
575
|
+
], r.prototype, "selectedIds", 2);
|
|
576
|
+
r = l([
|
|
577
|
+
x("bp-tree")
|
|
578
|
+
], r);
|
|
579
|
+
export {
|
|
580
|
+
r as BpTree
|
|
581
|
+
};
|
|
582
|
+
//# sourceMappingURL=tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree.js","sources":["../../source/components/tree/tree.style.ts","../../source/components/tree/tree.ts"],"sourcesContent":["import { css } from 'lit';\r\n\r\nexport const treeStyles = css`\r\n /* Base styles */\r\n :host {\r\n display: block;\r\n }\r\n\r\n .tree {\r\n font-family: var(--bp-font-family);\r\n font-size: var(--bp-font-size-base);\r\n color: var(--bp-color-text);\r\n }\r\n\r\n /* Node structure */\r\n .node {\r\n position: relative;\r\n }\r\n\r\n .node-content {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--bp-spacing-2);\r\n padding: var(--bp-spacing-2) var(--bp-spacing-3);\r\n padding-left: calc(\r\n var(--bp-spacing-3) + var(--node-level, 0) * var(--bp-spacing-5)\r\n );\r\n border-radius: var(--bp-border-radius-sm);\r\n cursor: pointer;\r\n user-select: none;\r\n transition:\r\n background-color var(--bp-transition-fast),\r\n color var(--bp-transition-fast);\r\n }\r\n\r\n .node-content:hover {\r\n background-color: var(--bp-color-surface-subdued);\r\n }\r\n\r\n .node-content:focus {\r\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\r\n outline-offset: var(--bp-focus-offset);\r\n }\r\n\r\n .node-content:focus:not(:focus-visible) {\r\n outline: none;\r\n }\r\n\r\n .node-content:focus-visible {\r\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\r\n outline-offset: var(--bp-focus-offset);\r\n }\r\n\r\n /* Selected state */\r\n .node-content--selected {\r\n background-color: oklch(from var(--bp-color-primary) l c h / 0.15);\r\n color: var(--bp-color-primary);\r\n }\r\n\r\n .node-content--selected:hover {\r\n background-color: oklch(from var(--bp-color-primary) l c h / 0.2);\r\n }\r\n\r\n /* Active state */\r\n .node-content:active {\r\n background-color: var(--bp-color-surface-subdued);\r\n transform: translateY(1px);\r\n }\r\n\r\n .node-content--selected:active {\r\n background-color: oklch(from var(--bp-color-primary) l c h / 0.25);\r\n }\r\n\r\n /* Toggle icon */\r\n .node-toggle {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: var(--bp-spacing-5);\r\n height: var(--bp-spacing-5);\r\n flex-shrink: 0;\r\n visibility: hidden;\r\n }\r\n\r\n .node-toggle--visible {\r\n visibility: visible;\r\n }\r\n\r\n .node-toggle--visible:hover {\r\n background-color: var(--bp-color-surface-subdued);\r\n border-radius: var(--bp-border-radius-sm);\r\n }\r\n\r\n .toggle-icon {\r\n width: var(--bp-spacing-4);\r\n height: var(--bp-spacing-4);\r\n transition: transform var(--bp-transition-fast) ease-out;\r\n }\r\n\r\n .toggle-icon--expanded {\r\n transform: rotate(90deg);\r\n }\r\n\r\n /* Node custom icon */\r\n .node-icon {\r\n flex-shrink: 0;\r\n color: var(--bp-color-text-muted);\r\n }\r\n\r\n /* Node label */\r\n .node-label {\r\n flex: 1;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n\r\n /* Children container */\r\n .node-children {\r\n position: relative;\r\n content-visibility: auto;\r\n contain-intrinsic-size: auto 200px;\r\n }\r\n\r\n /* Expanded state visual cue */\r\n .node--expanded > .node-content {\r\n background-color: var(--bp-color-surface);\r\n }\r\n\r\n /* Disabled state */\r\n .node--disabled .node-content {\r\n cursor: not-allowed;\r\n }\r\n\r\n .node--disabled .node-label {\r\n opacity: var(--bp-opacity-disabled);\r\n }\r\n\r\n .node--disabled .node-content:hover {\r\n background-color: transparent;\r\n }\r\n\r\n /* Show lines variant */\r\n .tree--lines .node-children {\r\n margin-left: calc(var(--bp-spacing-4) + var(--bp-spacing-4));\r\n padding-left: var(--bp-spacing-4);\r\n border-left: var(--bp-border-width) solid var(--bp-color-border);\r\n }\r\n\r\n /* Sizes */\r\n .tree--sm {\r\n font-size: var(--bp-font-size-sm);\r\n }\r\n\r\n .tree--sm .node-content {\r\n padding: var(--bp-spacing-1) var(--bp-spacing-2);\r\n padding-left: calc(\r\n var(--bp-spacing-2) + var(--node-level, 0) * var(--bp-spacing-4)\r\n );\r\n }\r\n\r\n .tree--sm .node-toggle {\r\n width: var(--bp-spacing-4);\r\n height: var(--bp-spacing-4);\r\n }\r\n\r\n .tree--sm .toggle-icon {\r\n width: var(--bp-spacing-3);\r\n height: var(--bp-spacing-3);\r\n }\r\n\r\n .tree--lg {\r\n font-size: var(--bp-font-size-lg);\r\n }\r\n\r\n .tree--lg .node-content {\r\n padding: var(--bp-spacing-3) var(--bp-spacing-4);\r\n padding-left: calc(\r\n var(--bp-spacing-4) + var(--node-level, 0) * var(--bp-spacing-6)\r\n );\r\n }\r\n\r\n .tree--lg .node-toggle {\r\n width: var(--bp-spacing-6);\r\n height: var(--bp-spacing-6);\r\n }\r\n\r\n .tree--lg .toggle-icon {\r\n width: var(--bp-spacing-5);\r\n height: var(--bp-spacing-5);\r\n }\r\n\r\n /* Link nodes — reset anchor styles so links look like regular nodes */\r\n a.node-content {\r\n text-decoration: none;\r\n color: inherit;\r\n }\r\n\r\n a.node-content:visited {\r\n color: inherit;\r\n }\r\n\r\n /* Reduced motion */\r\n @media (prefers-reduced-motion: reduce) {\r\n .node-content,\r\n .toggle-icon {\r\n transition: none;\r\n }\r\n\r\n .node-content:active {\r\n transform: none;\r\n }\r\n }\r\n`;\r\n","import { LitElement, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\nimport { ifDefined } from 'lit/directives/if-defined.js';\r\nimport { repeat } from 'lit/directives/repeat.js';\r\nimport { treeStyles } from './tree.style.js';\r\nimport { memoizeOne } from '../../utilities/memoize.js';\r\nimport '../icon/icon.js';\r\n\r\n/**\r\n * Tree node data structure\r\n */\r\nexport interface TreeNode {\r\n /** Unique identifier for the node */\r\n id: string;\r\n /** Display label */\r\n label: string;\r\n /** Optional icon name */\r\n icon?: string;\r\n /** URL to navigate to when the node is clicked */\r\n href?: string;\r\n /** Child nodes */\r\n children?: TreeNode[];\r\n /** Whether the node is disabled */\r\n disabled?: boolean;\r\n /** Custom data attached to the node */\r\n data?: unknown;\r\n}\r\n\r\n/**\r\n * A hierarchical tree component for displaying nested data structures.\r\n *\r\n * @fires bp-select - Fired when a node is selected. Detail: { node: TreeNode, path: string[] }\r\n * @fires bp-expand - Fired when a node is expanded. Detail: { node: TreeNode, expanded: boolean }\r\n * @fires bp-collapse - Fired when a node is collapsed. Detail: { node: TreeNode, expanded: boolean }\r\n * @fires bp-navigate - Fired when a node with href is clicked. Detail: { node: TreeNode, href: string, path: string[] }. Call preventDefault() to handle navigation yourself.\r\n *\r\n * @slot - Default slot for custom tree items (when not using data prop)\r\n *\r\n * @csspart tree - The tree container\r\n * @csspart node - Individual tree nodes\r\n * @csspart node-content - The clickable content area of a node\r\n * @csspart node-icon - The expand/collapse icon\r\n * @csspart node-label - The node label text\r\n * @csspart node-children - Container for child nodes\r\n */\r\n@customElement('bp-tree')\r\nexport class BpTree extends LitElement {\r\n /** Array of tree nodes to render */\r\n @property({ type: Array }) declare nodes: TreeNode[];\r\n\r\n /** Currently selected node ID */\r\n @property({ type: String, reflect: true }) declare selectedId: string | null;\r\n\r\n /** Array of expanded node IDs */\r\n @property({ type: Array }) declare expandedIds: string[];\r\n\r\n /** Whether multiple nodes can be selected */\r\n @property({ type: Boolean, reflect: true, attribute: 'multi-select' })\r\n declare multiSelect: boolean;\r\n\r\n /** Whether to show connecting lines between nodes */\r\n @property({ type: Boolean, reflect: true, attribute: 'show-lines' })\r\n declare showLines: boolean;\r\n\r\n /** Whether nodes can be selected */\r\n @property({ type: Boolean, reflect: true }) declare selectable: boolean;\r\n\r\n /** Size variant */\r\n @property({\r\n type: String,\r\n reflect: true,\r\n converter: {\r\n fromAttribute: (value: string | null) => {\r\n const valid = ['sm', 'md', 'lg'];\r\n return value && valid.includes(value) ? value : 'md';\r\n },\r\n },\r\n })\r\n declare size: 'sm' | 'md' | 'lg';\r\n\r\n /** Selected node IDs when multiSelect is true */\r\n @state() private selectedIds: string[] = [];\r\n\r\n /**\r\n * Memoized computation of expanded IDs as a Set for O(1) lookups.\r\n * Only recomputes when expandedIds reference changes.\r\n */\r\n private computeExpandedSet = memoizeOne(\r\n (expandedIds: string[]): Set<string> => new Set(expandedIds)\r\n );\r\n\r\n /**\r\n * Get the memoized expanded set for fast lookups during rendering.\r\n */\r\n private get expandedSet(): Set<string> {\r\n return this.computeExpandedSet(this.expandedIds);\r\n }\r\n\r\n static styles = [treeStyles];\r\n\r\n constructor() {\r\n super();\r\n this.nodes = [];\r\n this.selectedId = null;\r\n this.expandedIds = [];\r\n this.multiSelect = false;\r\n this.showLines = false;\r\n this.selectable = true;\r\n this.size = 'md';\r\n }\r\n\r\n /**\r\n * Expand a node by ID.\r\n * Adds the node to expandedIds and dispatches bp-expand event.\r\n *\r\n * @param nodeId - The ID of the node to expand\r\n */\r\n expand(nodeId: string): void {\r\n if (!this.expandedSet.has(nodeId)) {\r\n this.expandedIds = [...this.expandedIds, nodeId];\r\n const node = this.findNode(nodeId, this.nodes);\r\n if (node) {\r\n this.dispatchEvent(\r\n new CustomEvent('bp-expand', {\r\n detail: { node, expanded: true },\r\n bubbles: true,\r\n composed: true,\r\n })\r\n );\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Collapse a node by ID.\r\n * Removes the node from expandedIds and dispatches bp-collapse event.\r\n *\r\n * @param nodeId - The ID of the node to collapse\r\n */\r\n collapse(nodeId: string): void {\r\n if (this.expandedSet.has(nodeId)) {\r\n this.expandedIds = this.expandedIds.filter((id) => id !== nodeId);\r\n const node = this.findNode(nodeId, this.nodes);\r\n if (node) {\r\n this.dispatchEvent(\r\n new CustomEvent('bp-collapse', {\r\n detail: { node, expanded: false },\r\n bubbles: true,\r\n composed: true,\r\n })\r\n );\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Toggle a node's expanded state.\r\n * Calls expand() if collapsed, collapse() if expanded.\r\n *\r\n * @param nodeId - The ID of the node to toggle\r\n */\r\n toggle(nodeId: string): void {\r\n if (this.expandedSet.has(nodeId)) {\r\n this.collapse(nodeId);\r\n } else {\r\n this.expand(nodeId);\r\n }\r\n }\r\n\r\n /**\r\n * Expand all nodes in the tree.\r\n * Sets expandedIds to include all nodes with children.\r\n */\r\n expandAll(): void {\r\n const allIds = this.getAllNodeIds(this.nodes);\r\n this.expandedIds = allIds;\r\n }\r\n\r\n /**\r\n * Collapse all nodes in the tree.\r\n * Clears the expandedIds array.\r\n */\r\n collapseAll(): void {\r\n this.expandedIds = [];\r\n }\r\n\r\n /**\r\n * Select a node by ID.\r\n * Respects multiSelect setting and disabled state.\r\n * Dispatches bp-select event with node, selectedIds, and path.\r\n *\r\n * @param nodeId - The ID of the node to select\r\n */\r\n selectNode(nodeId: string): void {\r\n const node = this.findNode(nodeId, this.nodes);\r\n if (!node || node.disabled) return;\r\n\r\n if (this.multiSelect) {\r\n if (this.selectedIds.includes(nodeId)) {\r\n this.selectedIds = this.selectedIds.filter((id) => id !== nodeId);\r\n } else {\r\n this.selectedIds = [...this.selectedIds, nodeId];\r\n }\r\n } else {\r\n this.selectedId = nodeId;\r\n }\r\n\r\n this.dispatchEvent(\r\n new CustomEvent('bp-select', {\r\n detail: {\r\n node,\r\n selectedIds: this.multiSelect ? this.selectedIds : [nodeId],\r\n path: this.getNodePath(nodeId, this.nodes),\r\n },\r\n bubbles: true,\r\n composed: true,\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * Clear all selections.\r\n * Resets both selectedId and selectedIds.\r\n */\r\n clearSelection(): void {\r\n this.selectedId = null;\r\n this.selectedIds = [];\r\n }\r\n\r\n /**\r\n * Recursively finds a node by ID in the tree structure.\r\n *\r\n * @param nodeId - The ID to search for\r\n * @param nodes - The array of nodes to search within\r\n * @returns The found node or null if not found\r\n */\r\n private findNode(nodeId: string, nodes: TreeNode[]): TreeNode | null {\r\n for (const node of nodes) {\r\n if (node.id === nodeId) return node;\r\n if (node.children) {\r\n const found = this.findNode(nodeId, node.children);\r\n if (found) return found;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Recursively collects all node IDs that have children.\r\n * Used for expandAll functionality.\r\n *\r\n * @param nodes - The array of nodes to collect IDs from\r\n * @returns Array of node IDs that have children\r\n */\r\n private getAllNodeIds(nodes: TreeNode[]): string[] {\r\n const ids: string[] = [];\r\n for (const node of nodes) {\r\n if (node.children && node.children.length > 0) {\r\n ids.push(node.id);\r\n ids.push(...this.getAllNodeIds(node.children));\r\n }\r\n }\r\n return ids;\r\n }\r\n\r\n /**\r\n * Gets the path from root to a specific node.\r\n * Returns an array of node IDs representing the path.\r\n *\r\n * @param nodeId - The target node ID\r\n * @param nodes - The array of nodes to search within\r\n * @param path - Accumulator for the current path (used in recursion)\r\n * @returns Array of node IDs from root to target\r\n */\r\n private getNodePath(\r\n nodeId: string,\r\n nodes: TreeNode[],\r\n path: string[] = []\r\n ): string[] {\r\n for (const node of nodes) {\r\n if (node.id === nodeId) {\r\n return [...path, node.id];\r\n }\r\n if (node.children) {\r\n const foundPath = this.getNodePath(nodeId, node.children, [\r\n ...path,\r\n node.id,\r\n ]);\r\n if (foundPath.length > path.length + 1) {\r\n return foundPath;\r\n }\r\n }\r\n }\r\n return path;\r\n }\r\n\r\n /**\r\n * Handles click events on tree nodes.\r\n * For nodes with href, dispatches bp-navigate and follows the link unless prevented.\r\n * For other nodes, selects the node if selectable and not disabled.\r\n *\r\n * @param event - The click event\r\n * @param node - The node that was clicked\r\n */\r\n private handleNodeClick(event: Event, node: TreeNode): void {\r\n event.stopPropagation();\r\n\r\n if (node.href && !node.disabled) {\r\n const navigateEvent = new CustomEvent('bp-navigate', {\r\n detail: {\r\n node,\r\n href: node.href,\r\n path: this.getNodePath(node.id, this.nodes),\r\n },\r\n bubbles: true,\r\n composed: true,\r\n cancelable: true,\r\n });\r\n const allowed = this.dispatchEvent(navigateEvent);\r\n if (allowed) {\r\n // Default navigation — let the <a> handle it naturally\r\n return;\r\n }\r\n // Consumer called preventDefault(); suppress default link behavior\r\n event.preventDefault();\r\n return;\r\n }\r\n\r\n if (this.selectable && !node.disabled) {\r\n this.selectNode(node.id);\r\n }\r\n }\r\n\r\n /**\r\n * Handles click events on the expand/collapse toggle icon.\r\n * Prevents event propagation to avoid triggering node selection.\r\n *\r\n * @param event - The click event\r\n * @param node - The node whose toggle was clicked\r\n */\r\n private handleToggleClick(event: Event, node: TreeNode): void {\r\n event.stopPropagation();\r\n event.preventDefault();\r\n this.toggle(node.id);\r\n }\r\n\r\n /**\r\n * Handles keyboard navigation on tree nodes.\r\n * Enter/Space: select node\r\n * ArrowRight: expand node (if has children and collapsed)\r\n * ArrowLeft: collapse node (if has children and expanded)\r\n *\r\n * @param event - The keyboard event\r\n * @param node - The node that received the keyboard event\r\n */\r\n private handleKeyDown(event: KeyboardEvent, node: TreeNode): void {\r\n const hasChildren = node.children && node.children.length > 0;\r\n const isExpanded = this.expandedSet.has(node.id);\r\n\r\n switch (event.key) {\r\n case 'Enter':\r\n case ' ':\r\n event.preventDefault();\r\n if (node.href && !node.disabled) {\r\n this.handleNodeClick(event, node);\r\n } else if (this.selectable && !node.disabled) {\r\n this.selectNode(node.id);\r\n }\r\n break;\r\n case 'ArrowRight':\r\n event.preventDefault();\r\n if (hasChildren && !isExpanded) {\r\n this.expand(node.id);\r\n }\r\n break;\r\n case 'ArrowLeft':\r\n event.preventDefault();\r\n if (hasChildren && isExpanded) {\r\n this.collapse(node.id);\r\n }\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Checks if a node is currently selected.\r\n * Handles both single and multi-select modes.\r\n *\r\n * @param nodeId - The node ID to check\r\n * @returns True if the node is selected\r\n */\r\n private isSelected(nodeId: string): boolean {\r\n if (this.multiSelect) {\r\n return this.selectedIds.includes(nodeId);\r\n }\r\n return this.selectedId === nodeId;\r\n }\r\n\r\n /**\r\n * Recursively renders a tree node and its children.\r\n * Handles expand/collapse state, selection, and disabled state.\r\n *\r\n * @param node - The node to render\r\n * @param level - The nesting level (0 for root)\r\n * @returns Lit template result\r\n */\r\n private renderNode(node: TreeNode, level: number = 0): unknown {\r\n const hasChildren = node.children && node.children.length > 0;\r\n const isExpanded = this.expandedSet.has(node.id);\r\n const isSelected = this.isSelected(node.id);\r\n\r\n const contentClasses = `node-content ${isSelected ? 'node-content--selected' : ''} ${node.href ? 'node-content--link' : ''}`;\r\n\r\n const contentInner = html`\r\n <span\r\n class=\"node-toggle ${hasChildren ? 'node-toggle--visible' : ''}\"\r\n part=\"node-icon\"\r\n @click=${(e: Event) => this.handleToggleClick(e, node)}\r\n >\r\n ${hasChildren\r\n ? html`<bp-icon\r\n class=\"toggle-icon ${isExpanded ? 'toggle-icon--expanded' : ''}\"\r\n name=\"chevron-right\"\r\n size=\"sm\"\r\n ></bp-icon>`\r\n : nothing}\r\n </span>\r\n ${node.icon\r\n ? html`<bp-icon\r\n class=\"node-icon\"\r\n part=\"node-custom-icon\"\r\n name=${node.icon}\r\n size=\"sm\"\r\n ></bp-icon>`\r\n : nothing}\r\n <span class=\"node-label\" part=\"node-label\">${node.label}</span>\r\n `;\r\n\r\n const nodeContent = node.href\r\n ? html`\r\n <a\r\n class=${contentClasses}\r\n part=\"node-content\"\r\n href=${node.href}\r\n tabindex=${node.disabled ? -1 : 0}\r\n @click=${(e: Event) => this.handleNodeClick(e, node)}\r\n @keydown=${(e: KeyboardEvent) => this.handleKeyDown(e, node)}\r\n >\r\n ${contentInner}\r\n </a>\r\n `\r\n : html`\r\n <div\r\n class=${contentClasses}\r\n part=\"node-content\"\r\n tabindex=${node.disabled ? -1 : 0}\r\n @click=${(e: Event) => this.handleNodeClick(e, node)}\r\n @keydown=${(e: KeyboardEvent) => this.handleKeyDown(e, node)}\r\n >\r\n ${contentInner}\r\n </div>\r\n `;\r\n\r\n return html`\r\n <div\r\n class=\"node ${node.disabled ? 'node--disabled' : ''} ${hasChildren &&\r\n isExpanded\r\n ? 'node--expanded'\r\n : ''}\"\r\n part=\"node\"\r\n role=\"treeitem\"\r\n aria-expanded=${ifDefined(\r\n hasChildren ? (isExpanded ? 'true' : 'false') : undefined\r\n )}\r\n aria-selected=${ifDefined(\r\n this.selectable ? (isSelected ? 'true' : 'false') : undefined\r\n )}\r\n aria-disabled=${ifDefined(node.disabled ? 'true' : undefined)}\r\n style=\"--node-level: ${level}\"\r\n >\r\n ${nodeContent}\r\n ${hasChildren && isExpanded\r\n ? html`\r\n <div class=\"node-children\" part=\"node-children\" role=\"group\">\r\n ${repeat(\r\n node.children!,\r\n (child) => child.id,\r\n (child) => this.renderNode(child, level + 1)\r\n )}\r\n </div>\r\n `\r\n : nothing}\r\n </div>\r\n `;\r\n }\r\n\r\n render() {\r\n const hasNodes = this.nodes && this.nodes.length > 0;\r\n\r\n return html`\r\n <div\r\n class=\"tree tree--${this.size} ${this.showLines ? 'tree--lines' : ''}\"\r\n part=\"tree\"\r\n role=\"tree\"\r\n aria-multiselectable=${ifDefined(this.multiSelect ? 'true' : undefined)}\r\n >\r\n ${hasNodes\r\n ? repeat(\r\n this.nodes,\r\n (node) => node.id,\r\n (node) => this.renderNode(node, 0)\r\n )\r\n : html`<slot></slot>`}\r\n </div>\r\n `;\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'bp-tree': BpTree;\r\n }\r\n}\r\n"],"names":["treeStyles","css","BpTree","LitElement","memoizeOne","expandedIds","nodeId","node","id","allIds","nodes","found","ids","path","foundPath","event","navigateEvent","hasChildren","isExpanded","level","isSelected","contentClasses","contentInner","html","e","nothing","nodeContent","ifDefined","repeat","child","hasNodes","__decorateClass","property","value","state","customElement"],"mappings":"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"}
|