@mortenbrudvik/waveui 0.15.0 → 0.16.0

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 (155) hide show
  1. package/README.md +274 -24
  2. package/dist/components/data-display/List.cjs +1 -1
  3. package/dist/components/data-display/List.cjs.map +1 -1
  4. package/dist/components/data-display/List.mjs +405 -219
  5. package/dist/components/data-display/List.mjs.map +1 -1
  6. package/dist/components/data-display/List.registry.cjs +1 -1
  7. package/dist/components/data-display/List.registry.cjs.map +1 -1
  8. package/dist/components/data-display/List.registry.mjs +12 -6
  9. package/dist/components/data-display/List.registry.mjs.map +1 -1
  10. package/dist/components/input/Combobox.cjs +1 -1
  11. package/dist/components/input/Combobox.cjs.map +1 -1
  12. package/dist/components/input/Combobox.mjs +163 -148
  13. package/dist/components/input/Combobox.mjs.map +1 -1
  14. package/dist/components/input/Dropdown.cjs +1 -1
  15. package/dist/components/input/Dropdown.cjs.map +1 -1
  16. package/dist/components/input/Dropdown.mjs +132 -117
  17. package/dist/components/input/Dropdown.mjs.map +1 -1
  18. package/dist/components/input/Listbox.cjs +1 -1
  19. package/dist/components/input/Listbox.cjs.map +1 -1
  20. package/dist/components/input/Listbox.mjs +90 -78
  21. package/dist/components/input/Listbox.mjs.map +1 -1
  22. package/dist/components/input/Option.cjs +1 -1
  23. package/dist/components/input/Option.cjs.map +1 -1
  24. package/dist/components/input/Option.data.cjs +2 -0
  25. package/dist/components/input/Option.data.cjs.map +1 -0
  26. package/dist/components/input/Option.data.mjs +114 -0
  27. package/dist/components/input/Option.data.mjs.map +1 -0
  28. package/dist/components/input/Option.mjs +21 -17
  29. package/dist/components/input/Option.mjs.map +1 -1
  30. package/dist/components/layout/FlatTree.cjs +2 -0
  31. package/dist/components/layout/FlatTree.cjs.map +1 -0
  32. package/dist/components/layout/FlatTree.context.cjs +2 -0
  33. package/dist/components/layout/FlatTree.context.cjs.map +1 -0
  34. package/dist/components/layout/FlatTree.context.mjs +20 -0
  35. package/dist/components/layout/FlatTree.context.mjs.map +1 -0
  36. package/dist/components/layout/FlatTree.item.cjs +2 -0
  37. package/dist/components/layout/FlatTree.item.cjs.map +1 -0
  38. package/dist/components/layout/FlatTree.item.mjs +90 -0
  39. package/dist/components/layout/FlatTree.item.mjs.map +1 -0
  40. package/dist/components/layout/FlatTree.mjs +276 -0
  41. package/dist/components/layout/FlatTree.mjs.map +1 -0
  42. package/dist/components/layout/Tree.core.cjs +1 -1
  43. package/dist/components/layout/Tree.core.cjs.map +1 -1
  44. package/dist/components/layout/Tree.core.mjs +166 -165
  45. package/dist/components/layout/Tree.core.mjs.map +1 -1
  46. package/dist/components/layout/Tree.selection.cjs +1 -1
  47. package/dist/components/layout/Tree.selection.cjs.map +1 -1
  48. package/dist/components/layout/Tree.selection.mjs +11 -57
  49. package/dist/components/layout/Tree.selection.mjs.map +1 -1
  50. package/dist/components/layout/useFlatTree.cjs +2 -0
  51. package/dist/components/layout/useFlatTree.cjs.map +1 -0
  52. package/dist/components/layout/useFlatTree.mjs +83 -0
  53. package/dist/components/layout/useFlatTree.mjs.map +1 -0
  54. package/dist/components/table/DataGrid.cjs +1 -1
  55. package/dist/components/table/DataGrid.cjs.map +1 -1
  56. package/dist/components/table/DataGrid.context.cjs +2 -0
  57. package/dist/components/table/DataGrid.context.cjs.map +1 -0
  58. package/dist/components/table/DataGrid.context.mjs +74 -0
  59. package/dist/components/table/DataGrid.context.mjs.map +1 -0
  60. package/dist/components/table/DataGrid.header.cjs +2 -0
  61. package/dist/components/table/DataGrid.header.cjs.map +1 -0
  62. package/dist/components/table/DataGrid.header.mjs +168 -0
  63. package/dist/components/table/DataGrid.header.mjs.map +1 -0
  64. package/dist/components/table/DataGrid.mjs +488 -591
  65. package/dist/components/table/DataGrid.mjs.map +1 -1
  66. package/dist/components/table/DataGrid.sizing.cjs +2 -0
  67. package/dist/components/table/DataGrid.sizing.cjs.map +1 -0
  68. package/dist/components/table/DataGrid.sizing.mjs +187 -0
  69. package/dist/components/table/DataGrid.sizing.mjs.map +1 -0
  70. package/dist/components/table/DataGrid.store.cjs +2 -0
  71. package/dist/components/table/DataGrid.store.cjs.map +1 -0
  72. package/dist/components/table/DataGrid.store.mjs +108 -0
  73. package/dist/components/table/DataGrid.store.mjs.map +1 -0
  74. package/dist/components/table/DataGrid.window.cjs +2 -0
  75. package/dist/components/table/DataGrid.window.cjs.map +1 -0
  76. package/dist/components/table/DataGrid.window.mjs +165 -0
  77. package/dist/components/table/DataGrid.window.mjs.map +1 -0
  78. package/dist/components/table/Table.cjs +1 -1
  79. package/dist/components/table/Table.cjs.map +1 -1
  80. package/dist/components/table/Table.mjs +74 -72
  81. package/dist/components/table/Table.mjs.map +1 -1
  82. package/dist/components/table/Table.resize.cjs +2 -0
  83. package/dist/components/table/Table.resize.cjs.map +1 -0
  84. package/dist/components/table/Table.resize.mjs +98 -0
  85. package/dist/components/table/Table.resize.mjs.map +1 -0
  86. package/dist/components/table/useGridNavigation.cjs +1 -1
  87. package/dist/components/table/useGridNavigation.cjs.map +1 -1
  88. package/dist/components/table/useGridNavigation.mjs +343 -140
  89. package/dist/components/table/useGridNavigation.mjs.map +1 -1
  90. package/dist/components/table/useTableColumnSizing.cjs +2 -0
  91. package/dist/components/table/useTableColumnSizing.cjs.map +1 -0
  92. package/dist/components/table/useTableColumnSizing.mjs +76 -0
  93. package/dist/components/table/useTableColumnSizing.mjs.map +1 -0
  94. package/dist/components/table/useTableFeatures.cjs +2 -0
  95. package/dist/components/table/useTableFeatures.cjs.map +1 -0
  96. package/dist/components/table/useTableFeatures.mjs +110 -0
  97. package/dist/components/table/useTableFeatures.mjs.map +1 -0
  98. package/dist/components/table/useTableSelection.cjs +2 -0
  99. package/dist/components/table/useTableSelection.cjs.map +1 -0
  100. package/dist/components/table/useTableSelection.mjs +39 -0
  101. package/dist/components/table/useTableSelection.mjs.map +1 -0
  102. package/dist/components/table/useTableSort.cjs +2 -0
  103. package/dist/components/table/useTableSort.cjs.map +1 -0
  104. package/dist/components/table/useTableSort.mjs +58 -0
  105. package/dist/components/table/useTableSort.mjs.map +1 -0
  106. package/dist/hooks/useActiveDescendant.cjs +1 -1
  107. package/dist/hooks/useActiveDescendant.cjs.map +1 -1
  108. package/dist/hooks/useActiveDescendant.mjs +33 -25
  109. package/dist/hooks/useActiveDescendant.mjs.map +1 -1
  110. package/dist/hooks/useListbox.cjs +1 -1
  111. package/dist/hooks/useListbox.cjs.map +1 -1
  112. package/dist/hooks/useListbox.mjs +140 -130
  113. package/dist/hooks/useListbox.mjs.map +1 -1
  114. package/dist/hooks/useRovingTabIndex.cjs +1 -1
  115. package/dist/hooks/useRovingTabIndex.cjs.map +1 -1
  116. package/dist/hooks/useRovingTabIndex.mjs +1 -1
  117. package/dist/hooks/useRovingTabIndex.mjs.map +1 -1
  118. package/dist/hooks/useSelection.cjs +2 -0
  119. package/dist/hooks/useSelection.cjs.map +1 -0
  120. package/dist/hooks/useSelection.mjs +57 -0
  121. package/dist/hooks/useSelection.mjs.map +1 -0
  122. package/dist/hooks/useVirtualWindow.cjs +2 -0
  123. package/dist/hooks/useVirtualWindow.cjs.map +1 -0
  124. package/dist/hooks/useVirtualWindow.mjs +102 -0
  125. package/dist/hooks/useVirtualWindow.mjs.map +1 -0
  126. package/dist/index.cjs +1 -1
  127. package/dist/index.d.cts +1542 -53
  128. package/dist/index.d.ts +1542 -53
  129. package/dist/index.mjs +147 -136
  130. package/dist/lib/classNames.cjs +1 -1
  131. package/dist/lib/classNames.cjs.map +1 -1
  132. package/dist/lib/classNames.mjs +68 -49
  133. package/dist/lib/classNames.mjs.map +1 -1
  134. package/dist/lib/columnSizing.cjs +2 -0
  135. package/dist/lib/columnSizing.cjs.map +1 -0
  136. package/dist/lib/columnSizing.mjs +27 -0
  137. package/dist/lib/columnSizing.mjs.map +1 -0
  138. package/dist/lib/flatTree.cjs +2 -0
  139. package/dist/lib/flatTree.cjs.map +1 -0
  140. package/dist/lib/flatTree.mjs +118 -0
  141. package/dist/lib/flatTree.mjs.map +1 -0
  142. package/dist/lib/selection.cjs +2 -0
  143. package/dist/lib/selection.cjs.map +1 -0
  144. package/dist/lib/selection.mjs +28 -0
  145. package/dist/lib/selection.mjs.map +1 -0
  146. package/dist/lib/treeCascade.cjs +2 -0
  147. package/dist/lib/treeCascade.cjs.map +1 -0
  148. package/dist/lib/treeCascade.mjs +52 -0
  149. package/dist/lib/treeCascade.mjs.map +1 -0
  150. package/dist/lib/virtual.cjs +2 -0
  151. package/dist/lib/virtual.cjs.map +1 -0
  152. package/dist/lib/virtual.mjs +54 -0
  153. package/dist/lib/virtual.mjs.map +1 -0
  154. package/dist/styles.css +1 -1
  155. package/package.json +1 -1
@@ -0,0 +1,276 @@
1
+ "use client";
2
+ import { cn as e } from "../../lib/cn.mjs";
3
+ import { warnOnce as t } from "../../lib/dev.mjs";
4
+ import { composeEventHandlers as n } from "../../lib/composeEventHandlers.mjs";
5
+ import { flatTreeClassNames as r } from "../../lib/classNames.mjs";
6
+ import { useEventCallback as i } from "../../hooks/useEventCallback.mjs";
7
+ import { getArrowIntent as a, getDirection as o } from "../../lib/direction.mjs";
8
+ import { useTypeahead as s } from "../../hooks/useTypeahead.mjs";
9
+ import { useMergedRefs as c } from "../../hooks/useMergedRefs.mjs";
10
+ import { isEditableTarget as l, isOwnEvent as u } from "../../lib/events.mjs";
11
+ import { FlatTreeContext as d } from "./FlatTree.context.mjs";
12
+ import { FlatTreeItem as f } from "./FlatTree.item.mjs";
13
+ import * as p from "react";
14
+ import { jsx as m } from "react/jsx-runtime";
15
+ //#region src/components/layout/FlatTree.tsx
16
+ var h = {
17
+ focused: null,
18
+ pending: null
19
+ }, ee = class {
20
+ state = h;
21
+ listeners = /* @__PURE__ */ new Set();
22
+ subscribe = (e) => (this.listeners.add(e), () => {
23
+ this.listeners.delete(e);
24
+ });
25
+ getSnapshot = () => this.state;
26
+ getServerSnapshot = () => h;
27
+ update(e) {
28
+ let t = {
29
+ ...this.state,
30
+ ...e
31
+ };
32
+ if (t.focused !== this.state.focused || t.pending !== this.state.pending) {
33
+ this.state = t;
34
+ for (let e of this.listeners) e();
35
+ }
36
+ }
37
+ };
38
+ function g({ size: e }) {
39
+ return /* @__PURE__ */ m("div", {
40
+ role: "none",
41
+ "aria-hidden": "true",
42
+ "data-virtual-spacer": "",
43
+ className: r.spacer,
44
+ style: { height: e }
45
+ });
46
+ }
47
+ g.displayName = "FlatTreeSpacer";
48
+ function _(e, t) {
49
+ let n = t instanceof Element ? t : null;
50
+ for (; n && n.parentElement !== e;) n = n.parentElement;
51
+ return n instanceof HTMLElement && n.getAttribute("role") === "treeitem" ? n : null;
52
+ }
53
+ function v(e) {
54
+ let t = e.getAttribute("data-index");
55
+ return t !== null && /^\d+$/.test(t) ? Number(t) : null;
56
+ }
57
+ function y(e, t) {
58
+ return e.querySelector(`:scope > [data-index="${t}"]`);
59
+ }
60
+ function b(e, t, n) {
61
+ for (let r = t + n; r >= 0 && r < e.length; r += n) if (!e[r].item.disabled) return r;
62
+ }
63
+ function te(e, t) {
64
+ let { level: n } = e[t];
65
+ for (let r = t + 1; r < e.length && e[r].level > n; r += 1) if (e[r].level === n + 1 && !e[r].item.disabled) return r;
66
+ }
67
+ var ne = "FlatTree: a tree needs an accessible name. Pass `aria-label` or `aria-labelledby`.", re = "FlatTree: selectionMode=\"multiple\" needs a model that holds the check states: pass `selectionMode: 'multiple'` to `useFlatTree` as well; until then every item shows unchecked.", ie = "FlatTree: `selected` has no effect with selectionMode=\"multiple\"; use the model's `checkedItems`, and `current` for the item the user is on.", ae = "FlatTree: selectionMode=\"single\" draws a radio on every item for `selected`; pass `selected` (null while nothing is selected) and update it from `onItemSelect`.", x = ({ model: h, virtualWindow: x, renderItem: S, selectionMode: oe, selected: C, current: w, onItemSelect: se, className: T, onKeyDown: ce, onFocus: le, onBlur: ue, onPointerDownCapture: de, ref: fe, ...E }) => {
68
+ let D = h.getTreeProps().selectionMode, O = oe ?? D, k = h.visibleItems, A = k.length, j = x !== void 0, M = O === "multiple" ? void 0 : O === "single" ? C ?? null : C, [N] = p.useState(() => new ee()), { focused: P, pending: F } = p.useSyncExternalStore(N.subscribe, N.getSnapshot, N.getServerSnapshot), pe = p.useMemo(() => k.find((e) => !e.item.disabled), [k]), I = P === null ? void 0 : h.getItem(P), L = M == null ? void 0 : h.getItem(M), R = I ?? (L && !L.item.disabled ? L : pe), z = R?.index, B = F === null ? void 0 : h.getItem(F)?.index, me = p.useMemo(() => [z, B].filter((e) => e !== void 0), [z, B]), V = i((e) => {
69
+ e.item.disabled || (e.isBranch && h.toggle(e.item.value), se?.(e.item.value));
70
+ }), H = i((e, t) => {
71
+ e.item.disabled || h.setChecked(e.item.value, e.checked !== "checked", t);
72
+ }), U = x?.itemSize, W = R?.item.value ?? null, he = p.useMemo(() => ({
73
+ selectionMode: O,
74
+ selected: M,
75
+ current: w,
76
+ tabStop: W,
77
+ itemSize: U,
78
+ activate: V,
79
+ toggleChecked: H
80
+ }), [
81
+ O,
82
+ M,
83
+ w,
84
+ W,
85
+ U,
86
+ V,
87
+ H
88
+ ]), G = p.useRef(null), ge = c(fe, G, x?.scrollRef), K = (e, t) => {
89
+ let n = k[t];
90
+ if (!n) return;
91
+ x?.scrollToIndex(t, { align: "auto" });
92
+ let r = y(e, t);
93
+ r ? (N.update({ pending: null }), r.focus()) : N.update({ pending: n.item.value });
94
+ }, { onTypeahead: _e, isSearching: ve } = s({
95
+ getItems: () => k.map((e) => ({
96
+ value: e.item.value,
97
+ text: e.item.label ?? e.item.value,
98
+ disabled: e.item.disabled
99
+ })),
100
+ onMatch: (e) => {
101
+ let t = G.current, n = h.getItem(e);
102
+ t && n && K(t, n.index);
103
+ }
104
+ }), q = p.useRef(null), J = p.useRef(!1), ye = i((e) => {
105
+ j && u(e) && (J.current = !0);
106
+ });
107
+ p.useEffect(() => {
108
+ let e = G.current?.ownerDocument;
109
+ if (!j || !e) return;
110
+ let t = () => {
111
+ J.current = !1;
112
+ };
113
+ return e.addEventListener("keydown", t, !0), () => e.removeEventListener("keydown", t, !0);
114
+ }, [j]);
115
+ let Y = p.useRef(!1), be = i((e) => {
116
+ let t = J.current;
117
+ J.current = !1, Y.current = !e.currentTarget.contains(e.target);
118
+ let n = _(e.currentTarget, e.target), r = n ? v(n) : null, i = r === null ? void 0 : k[r];
119
+ if (!i || r === null) return;
120
+ N.update({
121
+ focused: i.item.value,
122
+ pending: null
123
+ });
124
+ let a = [];
125
+ for (let e = i.parentValue; e !== void 0;) a.push(e), e = h.getItem(e)?.parentValue;
126
+ q.current = {
127
+ path: a,
128
+ index: r
129
+ }, x && !t && x.scrollToIndex(r, { align: "auto" });
130
+ }), xe = i((e) => {
131
+ let t = e.currentTarget, n = e.relatedTarget;
132
+ if (n && t.contains(n)) return;
133
+ Y.current = !1;
134
+ let r = e.target;
135
+ queueMicrotask(() => {
136
+ if (!t.isConnected || Y.current) return;
137
+ let e = t.ownerDocument.activeElement;
138
+ e && t.contains(e) || r.isConnected && N.update({ focused: null });
139
+ });
140
+ }), Se = i((e) => {
141
+ let t = e.currentTarget, n = _(t, e.target), r = n ? v(n) : null;
142
+ if (r === null || r >= A || l(e.target)) return;
143
+ let i = k[r], s = N.getSnapshot().pending, c = (s === null ? void 0 : h.getItem(s)?.index) ?? r;
144
+ if (e.key.length === 1 && (e.key !== "*" || ve()) && _e(e, k[c].item.value)) {
145
+ e.preventDefault();
146
+ return;
147
+ }
148
+ if (e.altKey || e.ctrlKey || e.metaKey) return;
149
+ let u;
150
+ switch (e.key) {
151
+ case "ArrowDown":
152
+ u = b(k, c, 1);
153
+ break;
154
+ case "ArrowUp":
155
+ u = b(k, c, -1);
156
+ break;
157
+ case "Home":
158
+ u = b(k, -1, 1);
159
+ break;
160
+ case "End":
161
+ u = b(k, A, -1);
162
+ break;
163
+ case "Enter":
164
+ e.preventDefault(), V(i);
165
+ return;
166
+ case " ":
167
+ e.preventDefault(), O === "multiple" ? H(i, e.nativeEvent) : V(i);
168
+ return;
169
+ case "*": {
170
+ e.preventDefault();
171
+ let t = k.filter((e) => e.parentValue === i.parentValue && e.isBranch && !e.expanded && !e.item.disabled).map((e) => e.item.value);
172
+ t.length > 0 && h.expand(t);
173
+ return;
174
+ }
175
+ default: {
176
+ let n = a(e.key, {
177
+ orientation: "horizontal",
178
+ dir: o(t)
179
+ });
180
+ if (n === null) return;
181
+ if (n === "next") {
182
+ if (i.isBranch && !i.expanded) {
183
+ e.preventDefault(), i.item.disabled || h.expand(i.item.value);
184
+ return;
185
+ }
186
+ i.expanded && (u = te(k, r));
187
+ } else {
188
+ if (i.isBranch && i.expanded && !i.item.disabled) {
189
+ e.preventDefault(), h.collapse(i.item.value);
190
+ return;
191
+ }
192
+ for (let e = i.parentValue; e !== void 0 && u === void 0;) {
193
+ let t = h.getItem(e);
194
+ if (!t) break;
195
+ t.item.disabled || (u = t.index), e = t.parentValue;
196
+ }
197
+ }
198
+ if (u === void 0) {
199
+ e.preventDefault();
200
+ return;
201
+ }
202
+ }
203
+ }
204
+ e.preventDefault();
205
+ let d = u ?? c;
206
+ if (d === r) {
207
+ N.update({ pending: null }), x?.scrollToIndex(d, { align: "auto" });
208
+ return;
209
+ }
210
+ K(t, d);
211
+ }), X = p.useRef(null);
212
+ p.useLayoutEffect(() => {
213
+ let e = G.current, t = N.getSnapshot().focused, n = t === null ? void 0 : h.getItem(t)?.index, r = X.current;
214
+ if (X.current = null, !x || !e || t === null || n === void 0) return;
215
+ let i = x.itemSize, a = e.scrollTop;
216
+ if (r?.value === t && n !== r.index && e.contains(e.ownerDocument.activeElement)) {
217
+ let t = Math.floor(a / i) === Math.floor(r.top / i) ? a : r.top, o = r.index * i;
218
+ o + i > t && o < t + e.clientHeight && (e.scrollTop = t + (n - r.index) * i, x.scrollToIndex(n, { align: "auto" }), a = e.scrollTop);
219
+ }
220
+ X.current = {
221
+ value: t,
222
+ index: n,
223
+ top: a
224
+ };
225
+ }), p.useLayoutEffect(() => {
226
+ let e = G.current;
227
+ if (!e) return;
228
+ let t = e.ownerDocument, n = t.activeElement, r = !n || n === t.body || !n.isConnected, i = N.getSnapshot();
229
+ if (i.pending !== null) {
230
+ N.update({ pending: null });
231
+ let t = h.getItem(i.pending), a = t ? y(e, t.index) : null;
232
+ a && (r || e.contains(n)) && a.focus();
233
+ return;
234
+ }
235
+ if (i.focused === null || h.getItem(i.focused) || (N.update({ focused: null }), !r || A === 0)) return;
236
+ let a = q.current, o = a?.path.map((e) => h.getItem(e)).find((e) => e)?.index;
237
+ o ??= Math.min(a?.index ?? 0, A - 1), K(e, o);
238
+ });
239
+ let Z = !E["aria-label"] && !E["aria-labelledby"];
240
+ p.useEffect(() => {
241
+ Z && t("FlatTree:name", ne);
242
+ }, [Z]);
243
+ let Q = O === "multiple" && D !== "multiple";
244
+ p.useEffect(() => {
245
+ Q && t("FlatTree:selection-mode", re);
246
+ }, [Q]), p.useEffect(() => {
247
+ O === "multiple" && C !== void 0 && t("FlatTree:selected-with-multiple", ie), O === "single" && C === void 0 && t("FlatTree:single-without-selected", ae);
248
+ }, [O, C]);
249
+ let $ = (e) => /* @__PURE__ */ m(f, {
250
+ item: e,
251
+ children: S ? S(e) : e.item.label ?? e.item.value
252
+ }, `item:${e.item.value}`), Ce = x ? x.layout(A, { keep: me }).map((e) => e.kind === "item" ? $(k[e.index]) : /* @__PURE__ */ m(g, { size: e.size }, `spacer:${e.key}`)) : k.map($);
253
+ return /* @__PURE__ */ m(d.Provider, {
254
+ value: he,
255
+ children: /* @__PURE__ */ m("div", {
256
+ role: "tree",
257
+ "aria-multiselectable": O === "multiple" || void 0,
258
+ "data-selection-mode": O,
259
+ tabIndex: j && W !== null ? -1 : void 0,
260
+ className: e(r.root, "text-body-1", j && "overflow-y-auto [overflow-anchor:none]", T),
261
+ ...E,
262
+ onKeyDown: n(ce, Se),
263
+ onFocus: n(le, be, { checkDefaultPrevented: !1 }),
264
+ onBlur: n(ue, xe, { checkDefaultPrevented: !1 }),
265
+ onPointerDownCapture: n(de, ye),
266
+ ref: ge,
267
+ children: Ce
268
+ })
269
+ });
270
+ };
271
+ x.displayName = "FlatTree";
272
+ var S = /* @__PURE__ */ Object.assign(x, { Item: f });
273
+ //#endregion
274
+ export { S as FlatTree, f as FlatTreeItem };
275
+
276
+ //# sourceMappingURL=FlatTree.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FlatTree.mjs","names":["React","NO_FOCUS","FlatTreeFocusStore","listener","state","next","FlatTreeSpacer","flatTreeClassNames","size","getOwnItem","el","target","root","getIndex","value","getRenderedItem","index","nextEnabled","at","from","step","rows","firstEnabledChild","level","NAME_MESSAGE","SELECTION_MODE_MESSAGE","SELECTED_WITH_MULTIPLE_MESSAGE","SINGLE_WITHOUT_SELECTED_MESSAGE","FlatTreeRoot","selectionModeProp","rest","modelMode","model","selectionMode","count","windowed","virtualWindow","effectiveSelected","selected","focusStore","firstEnabled","row","focusedRow","focused","selectedRow","tabStopRow","tabStopIndex","pendingIndex","pending","keep","activate","useEventCallback","onItemSelect","toggleChecked","event","itemSize","tabStop","context","current","rootRef","mergedRef","useMergedRefs","ref","moveTo","useTypeahead","focusPathRef","pointerPressRef","handlePointerDownCapture","isOwnEvent","doc","clear","focusInPopupRef","handleFocus","pointerFocus","path","parent","handleBlur","blurred","active","handleKeyDown","isEditableTarget","awaited","isSearching","onTypeahead","siblings","other","intent","getArrowIntent","getDirection","parentRow","goal","focusPlaceRef","last","top","before","lastTop","lost","snapshot","record","unnamed","warnOnce","missingChecks","renderRow","FlatTreeItem","renderItem","content","entry","FlatTreeContext","cn","className","composeEventHandlers","onKeyDown","onFocus","onBlur","onPointerDownCapture","FlatTree"],"sources":["../../../src/components/layout/FlatTree.tsx"],"sourcesContent":["import * as React from 'react';\nimport { flatTreeClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport { getArrowIntent, getDirection } from '../../lib/direction';\nimport { isEditableTarget, isOwnEvent } from '../../lib/events';\nimport type { VisibleFlatItem } from '../../lib/flatTree';\nimport type { CheckState } from '../../lib/treeCascade';\nimport type { SelectionMode } from '../../lib/types';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useTypeahead } from '../../hooks/useTypeahead';\nimport type { VirtualWindow } from '../../hooks/useVirtualWindow';\nimport { FlatTreeContext, type FlatTreeContextValue, type FlatTreeRow } from './FlatTree.context';\nimport { FlatTreeItem } from './FlatTree.item';\nimport type { FlatTreeModel } from './useFlatTree';\n\nexport type { FlatTreeItemProps } from './FlatTree.item';\n\n/** Properties for the FlatTree component. */\nexport interface FlatTreeProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'children' | 'onSelect'\n> {\n /** The tree's model, from `useFlatTree`: the visible rows, the expanded and the checked state. */\n model: FlatTreeModel;\n /**\n * Renders only the items in view (and a few beyond), from `useVirtualWindow({ itemSize })`. The\n * tree is then the scrolling element: give it a bounded height (a class or a style). Every item\n * is exactly `itemSize` pixels tall, so its content must fit in one row. Without it every visible\n * item is rendered.\n *\n * The tree element is then no tab stop of its own while an item is (`tabIndex` -1, as Firefox\n * would stop on a scroller; a `tabIndex` you pass wins), and the browser's scroll anchoring is\n * off on it (the window lays the items out): when rows are inserted or removed above the focused\n * item while it is in view (`*`, or a change of the model from code), the tree moves the view\n * with it, so it stays where it was.\n */\n virtualWindow?: VirtualWindow;\n /**\n * The content of an item, from its row: the item data with its level, position, set size,\n * expanded state and, in multiple mode, its check state. Called for the rendered items only.\n * @default the item's `label`, else its `value`\n */\n renderItem?: (item: VisibleFlatItem & { checked?: CheckState }) => React.ReactNode;\n /**\n * How items are selected, as the nested `Tree`'s `selectionMode`. `'multiple'` draws a checkbox\n * on every item, bound to the model's checked items (create the model with\n * `selectionMode: 'multiple'`); `'single'` draws a radio for `selected`. Spread\n * `model.getTreeProps()` on the tree to pass the model's mode.\n * @default the model's mode (`model.getTreeProps().selectionMode`)\n */\n selectionMode?: 'none' | SelectionMode;\n /**\n * Value of the selected item. When set (also to `null`), every item carries `aria-selected`, and\n * the selected item is where keyboard focus enters the tree while it is visible. It has no effect\n * with `selectionMode=\"multiple\"` (a development warning). With `selectionMode=\"single\"` every\n * item carries `aria-selected` even while it is not set (a development warning: the radios need\n * it).\n */\n selected?: string | null;\n /** Value of the current item (for example the open page): it gets `aria-current=\"true\"`. */\n current?: string | null;\n /**\n * Called with an item's value every time it is activated (a click on its row, Enter, or Space\n * unless the tree has checkboxes), also when the same item is activated again.\n */\n onItemSelect?: (value: string) => void;\n /** Ref to the `role=\"tree\"` element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** The focused and the awaited item of a FlatTree, by value (see {@link FlatTreeFocusStore}). */\ninterface FlatTreeFocus {\n /** The item that has focus while focus is inside the tree: kept rendered, and the tab stop. */\n focused: string | null;\n /** The item a key moved to that was not rendered: kept rendered, focused after the commit. */\n pending: string | null;\n}\n\nconst NO_FOCUS: FlatTreeFocus = { focused: null, pending: null };\n\n/**\n * The focused and the awaited item of a FlatTree, read during render through\n * `useSyncExternalStore` and written by the tree's handlers and layout effect (C-HOOKS: no state\n * set in an effect, no ref read during render).\n */\nclass FlatTreeFocusStore {\n private state: FlatTreeFocus = NO_FOCUS;\n private readonly listeners = new Set<() => void>();\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): FlatTreeFocus => this.state;\n\n getServerSnapshot = (): FlatTreeFocus => NO_FOCUS;\n\n /** Changes the given fields; notifies only when one of them changed. */\n update(next: Partial<FlatTreeFocus>): void {\n const state = { ...this.state, ...next };\n if (state.focused === this.state.focused && state.pending === this.state.pending) return;\n this.state = state;\n for (const listener of this.listeners) listener();\n }\n}\n\n/** The element that stands in for the items of a windowed tree that are not rendered. */\nfunction FlatTreeSpacer({ size }: { size: number }) {\n return (\n <div\n role=\"none\"\n aria-hidden=\"true\"\n data-virtual-spacer=\"\"\n className={flatTreeClassNames.spacer}\n style={{ height: size }}\n />\n );\n}\nFlatTreeSpacer.displayName = 'FlatTreeSpacer';\n\n/** The item element (a treeitem child of `root`) that holds `target`; `null` for a portal's. */\nfunction getOwnItem(root: Element, target: EventTarget | null): HTMLElement | null {\n let el = target instanceof Element ? target : null;\n while (el && el.parentElement !== root) el = el.parentElement;\n return el instanceof HTMLElement && el.getAttribute('role') === 'treeitem' ? el : null;\n}\n\n/** The place of an item element in the visible rows (`data-index`). */\nfunction getIndex(el: Element): number | null {\n const value = el.getAttribute('data-index');\n return value !== null && /^\\d+$/.test(value) ? Number(value) : null;\n}\n\n/** The rendered item at `index` of the visible rows, or `null` while it is not rendered. */\nfunction getRenderedItem(root: Element, index: number): HTMLElement | null {\n return root.querySelector<HTMLElement>(`:scope > [data-index=\"${index}\"]`);\n}\n\n/** The next enabled row from `from` (exclusive) in the direction of `step`, or `undefined`. */\nfunction nextEnabled(rows: readonly FlatTreeRow[], from: number, step: 1 | -1): number | undefined {\n for (let at = from + step; at >= 0 && at < rows.length; at += step) {\n if (!rows[at].item.disabled) return at;\n }\n return undefined;\n}\n\n/** The first enabled child row of the expanded row at `index`, or `undefined`. */\nfunction firstEnabledChild(rows: readonly FlatTreeRow[], index: number): number | undefined {\n const { level } = rows[index];\n for (let at = index + 1; at < rows.length && rows[at].level > level; at += 1) {\n if (rows[at].level === level + 1 && !rows[at].item.disabled) return at;\n }\n return undefined;\n}\n\nconst NAME_MESSAGE =\n 'FlatTree: a tree needs an accessible name. Pass `aria-label` or `aria-labelledby`.';\n\nconst SELECTION_MODE_MESSAGE =\n 'FlatTree: selectionMode=\"multiple\" needs a model that holds the check states: pass ' +\n \"`selectionMode: 'multiple'` to `useFlatTree` as well; until then every item shows unchecked.\";\n\nconst SELECTED_WITH_MULTIPLE_MESSAGE =\n 'FlatTree: `selected` has no effect with selectionMode=\"multiple\"; use the model\\'s ' +\n '`checkedItems`, and `current` for the item the user is on.';\n\nconst SINGLE_WITHOUT_SELECTED_MESSAGE =\n 'FlatTree: selectionMode=\"single\" draws a radio on every item for `selected`; pass `selected` ' +\n '(null while nothing is selected) and update it from `onItemSelect`.';\n\n// The FlatTree root, documented on the exported `FlatTree` const.\nconst FlatTreeRoot = ({\n model,\n virtualWindow,\n renderItem,\n selectionMode: selectionModeProp,\n selected,\n current,\n onItemSelect,\n className,\n onKeyDown,\n onFocus,\n onBlur,\n onPointerDownCapture,\n ref,\n ...rest\n}: FlatTreeProps) => {\n const modelMode = model.getTreeProps().selectionMode;\n const selectionMode = selectionModeProp ?? modelMode;\n const rows = model.visibleItems;\n const count = rows.length;\n const windowed = virtualWindow !== undefined;\n\n // An item carries aria-checked or aria-selected, never both (APG); in single mode every item\n // carries aria-selected from the first render, so the radios and the state agree.\n const effectiveSelected =\n selectionMode === 'multiple'\n ? undefined\n : selectionMode === 'single'\n ? (selected ?? null)\n : selected;\n\n const [focusStore] = React.useState(() => new FlatTreeFocusStore());\n const { focused, pending } = React.useSyncExternalStore(\n focusStore.subscribe,\n focusStore.getSnapshot,\n focusStore.getServerSnapshot,\n );\n\n // The tab stop follows the model, not the DOM (most items are not rendered): the focused item,\n // else the selected item while it is visible and enabled, else the first enabled item.\n const firstEnabled = React.useMemo(() => rows.find((row) => !row.item.disabled), [rows]);\n const focusedRow = focused === null ? undefined : model.getItem(focused);\n const selectedRow =\n effectiveSelected === undefined || effectiveSelected === null\n ? undefined\n : model.getItem(effectiveSelected);\n const tabStopRow =\n focusedRow ?? (selectedRow && !selectedRow.item.disabled ? selectedRow : firstEnabled);\n const tabStopIndex = tabStopRow?.index;\n const pendingIndex = pending === null ? undefined : model.getItem(pending)?.index;\n // The tab stop and the awaited item stay rendered outside the window (a focused item scrolled\n // away keeps focus and its tab stop).\n const keep = React.useMemo(\n () => [tabStopIndex, pendingIndex].filter((index): index is number => index !== undefined),\n [tabStopIndex, pendingIndex],\n );\n\n const activate = useEventCallback((row: FlatTreeRow) => {\n if (row.item.disabled) return;\n if (row.isBranch) model.toggle(row.item.value);\n onItemSelect?.(row.item.value);\n });\n const toggleChecked = useEventCallback((row: FlatTreeRow, event: Event) => {\n if (row.item.disabled) return;\n model.setChecked(row.item.value, row.checked !== 'checked', event);\n });\n\n const itemSize = virtualWindow?.itemSize;\n const tabStop = tabStopRow?.item.value ?? null;\n const context = React.useMemo<FlatTreeContextValue>(\n () => ({\n selectionMode,\n selected: effectiveSelected,\n current,\n tabStop,\n itemSize,\n activate,\n toggleChecked,\n }),\n [selectionMode, effectiveSelected, current, tabStop, itemSize, activate, toggleChecked],\n );\n\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n // The tree is the window's scroller.\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, rootRef, virtualWindow?.scrollRef);\n\n /**\n * Focuses the row at `index`, moving the window to it first (in the same update, so no frame\n * shows the spacer); a row that is not rendered is awaited and focused after the commit that\n * renders it.\n */\n const moveTo = (root: HTMLElement, index: number) => {\n const row = rows[index];\n if (!row) return;\n virtualWindow?.scrollToIndex(index, { align: 'auto' });\n const el = getRenderedItem(root, index);\n if (el) {\n focusStore.update({ pending: null });\n el.focus();\n } else {\n focusStore.update({ pending: row.item.value });\n }\n };\n\n // Typeahead over the visible items' labels (disabled items are skipped).\n const { onTypeahead, isSearching } = useTypeahead({\n getItems: () =>\n rows.map((row) => ({\n value: row.item.value,\n text: row.item.label ?? row.item.value,\n disabled: row.item.disabled,\n })),\n onMatch: (value) => {\n const root = rootRef.current;\n const row = model.getItem(value);\n if (root && row) moveTo(root, row.index);\n },\n });\n\n /** The visible item, its ancestors from the parent up, and its place, of the focused item. */\n const focusPathRef = React.useRef<{ path: string[]; index: number } | null>(null);\n\n /**\n * Set by a pointer press in a windowed tree until the focus it gives, or until a key press:\n * keyboard focus always follows one, so a press that gave no focus never keeps a later keyboard\n * focus from being scrolled into view. A press in a popup an item opened is the popup's.\n */\n const pointerPressRef = React.useRef(false);\n const handlePointerDownCapture = useEventCallback((event: React.PointerEvent<HTMLDivElement>) => {\n if (windowed && isOwnEvent(event)) pointerPressRef.current = true;\n });\n React.useEffect(() => {\n const doc = rootRef.current?.ownerDocument;\n if (!windowed || !doc) return;\n const clear = () => {\n pointerPressRef.current = false;\n };\n doc.addEventListener('keydown', clear, true);\n return () => doc.removeEventListener('keydown', clear, true);\n }, [windowed]);\n\n /**\n * Whether focus is in a popup that an item opened (an element outside the tree's DOM whose focus\n * React bubbles through the tree): the focused item stays kept. Written by the focus and blur\n * handlers.\n */\n const focusInPopupRef = React.useRef(false);\n\n // Focus moving onto an item makes it the focused item (the tab stop, kept rendered). Unless a\n // pointer press gave the focus, the window moves to it in the same update (a browser's own focus\n // scrolling moves the view a frame before the window would follow).\n const handleFocus = useEventCallback((event: React.FocusEvent<HTMLDivElement>) => {\n const pointerFocus = pointerPressRef.current;\n pointerPressRef.current = false;\n focusInPopupRef.current = !event.currentTarget.contains(event.target as Node);\n const el = getOwnItem(event.currentTarget, event.target);\n const index = el ? getIndex(el) : null;\n const row = index === null ? undefined : rows[index];\n if (!row || index === null) return;\n focusStore.update({ focused: row.item.value, pending: null });\n const path: string[] = [];\n for (let parent = row.parentValue; parent !== undefined;) {\n path.push(parent);\n parent = model.getItem(parent)?.parentValue;\n }\n focusPathRef.current = { path, index };\n if (virtualWindow && !pointerFocus) virtualWindow.scrollToIndex(index, { align: 'auto' });\n });\n\n // Focus leaving the tree (for an element outside it, or for nothing) ends the focused item; the\n // tab stop then returns to the selected or the first item. Decided once focus has landed: a\n // popup an item opened takes focus in the same task (`focusInPopupRef`).\n const handleBlur = useEventCallback((event: React.FocusEvent<HTMLDivElement>) => {\n const root = event.currentTarget;\n const next = event.relatedTarget as Node | null;\n if (next && root.contains(next)) return;\n focusInPopupRef.current = false;\n const blurred = event.target as Node;\n queueMicrotask(() => {\n if (!root.isConnected || focusInPopupRef.current) return;\n const active = root.ownerDocument.activeElement;\n if (active && root.contains(active)) return;\n // A focused item that left the document (a branch collapsed around it): the commit's check\n // below has moved focus, or decided that it cannot.\n if (!blurred.isConnected) return;\n focusStore.update({ focused: null });\n });\n });\n\n const handleKeyDown = useEventCallback((event: React.KeyboardEvent<HTMLDivElement>) => {\n const root = event.currentTarget;\n // A key from a portal is the portal's; a text field in the content keeps its keys.\n const el = getOwnItem(root, event.target);\n const current = el ? getIndex(el) : null;\n if (current === null || current >= count || isEditableTarget(event.target)) return;\n const row = rows[current];\n // Keys pressed before an awaited item renders move from it (possible only within one task).\n const awaited = focusStore.getSnapshot().pending;\n const from = (awaited === null ? undefined : model.getItem(awaited)?.index) ?? current;\n\n // Typeahead; a Space continues a search, and `*` starts none.\n if (event.key.length === 1 && (event.key !== '*' || isSearching())) {\n if (onTypeahead(event, rows[from].item.value)) {\n event.preventDefault();\n return;\n }\n }\n if (event.altKey || event.ctrlKey || event.metaKey) return;\n\n let target: number | undefined;\n switch (event.key) {\n case 'ArrowDown':\n target = nextEnabled(rows, from, 1);\n break;\n case 'ArrowUp':\n target = nextEnabled(rows, from, -1);\n break;\n case 'Home':\n target = nextEnabled(rows, -1, 1);\n break;\n case 'End':\n target = nextEnabled(rows, count, -1);\n break;\n case 'Enter':\n event.preventDefault();\n activate(row);\n return;\n case ' ':\n event.preventDefault();\n // A checkbox tree toggles the focused item's check (APG); the other modes activate.\n if (selectionMode === 'multiple') toggleChecked(row, event.nativeEvent);\n else activate(row);\n return;\n case '*': {\n event.preventDefault();\n // The siblings of a visible item are all visible (their parent is expanded).\n const siblings = rows\n .filter(\n (other) =>\n other.parentValue === row.parentValue &&\n other.isBranch &&\n !other.expanded &&\n !other.item.disabled,\n )\n .map((other) => other.item.value);\n if (siblings.length > 0) model.expand(siblings);\n return;\n }\n default: {\n const intent = getArrowIntent(event.key, {\n orientation: 'horizontal',\n dir: getDirection(root),\n });\n if (intent === null) return;\n if (intent === 'next') {\n // Expand a collapsed branch (focus stays), else move to the first child.\n if (row.isBranch && !row.expanded) {\n event.preventDefault();\n if (!row.item.disabled) model.expand(row.item.value);\n return;\n }\n if (row.expanded) target = firstEnabledChild(rows, current);\n } else {\n // Collapse an expanded branch (focus stays), else move to the nearest enabled ancestor.\n if (row.isBranch && row.expanded && !row.item.disabled) {\n event.preventDefault();\n model.collapse(row.item.value);\n return;\n }\n for (let parent = row.parentValue; parent !== undefined && target === undefined;) {\n const parentRow = model.getItem(parent);\n if (!parentRow) break;\n if (!parentRow.item.disabled) target = parentRow.index;\n parent = parentRow.parentValue;\n }\n }\n if (target === undefined) {\n event.preventDefault();\n return;\n }\n }\n }\n event.preventDefault();\n // No item to move to: the focused item stays, and is brought into view.\n const goal = target ?? from;\n if (goal === current) {\n focusStore.update({ pending: null });\n virtualWindow?.scrollToIndex(goal, { align: 'auto' });\n return;\n }\n moveTo(root, goal);\n });\n\n /**\n * The focused item of a windowed tree, its place in the visible rows and the scroll offset, at\n * the last commit (written by the layout effect below).\n */\n const focusPlaceRef = React.useRef<{ value: string; index: number; top: number } | null>(null);\n\n // After every commit of a windowed tree: rows inserted or removed above the focused item while\n // it was in view (`*`, a model change from code) move the view with it, so it stays where it\n // was, and the window follows in the same update. The browser's scroll anchoring would do the\n // same a frame before the window follows; it is off (the window lays the rows out).\n React.useLayoutEffect(() => {\n const root = rootRef.current;\n const value = focusStore.getSnapshot().focused;\n const index = value === null ? undefined : model.getItem(value)?.index;\n const last = focusPlaceRef.current;\n focusPlaceRef.current = null;\n if (!virtualWindow || !root || value === null || index === undefined) return;\n const size = virtualWindow.itemSize;\n let top = root.scrollTop;\n if (\n last?.value === value &&\n index !== last.index &&\n root.contains(root.ownerDocument.activeElement)\n ) {\n // Rows removed above may leave less content than the offset, which the browser has clamped\n // by now: an offset in another row than the one recorded (the tree commits at every row the\n // view enters) stands for that, and the recorded one is where the view was.\n const before = Math.floor(top / size) === Math.floor(last.top / size) ? top : last.top;\n const lastTop = last.index * size;\n if (lastTop + size > before && lastTop < before + root.clientHeight) {\n root.scrollTop = before + (index - last.index) * size;\n virtualWindow.scrollToIndex(index, { align: 'auto' });\n top = root.scrollTop;\n }\n }\n focusPlaceRef.current = { value, index, top };\n });\n\n // After every commit: focus the awaited item, which the commit rendered (it is kept), unless\n // focus went outside the tree meanwhile; and when the focused item is no longer visible (a\n // branch collapsed around it, or the items changed) while focus is lost with it, move focus to\n // its nearest visible ancestor, else to the visible item nearest to its place. Never to the body.\n React.useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n const doc = root.ownerDocument;\n const active = doc.activeElement;\n const lost = !active || active === doc.body || !active.isConnected;\n const snapshot = focusStore.getSnapshot();\n if (snapshot.pending !== null) {\n focusStore.update({ pending: null });\n const row = model.getItem(snapshot.pending);\n const el = row ? getRenderedItem(root, row.index) : null;\n if (el && (lost || root.contains(active))) el.focus();\n return;\n }\n if (snapshot.focused === null || model.getItem(snapshot.focused)) return;\n focusStore.update({ focused: null });\n if (!lost || count === 0) return;\n const record = focusPathRef.current;\n let target = record?.path.map((value) => model.getItem(value)).find((row) => row)?.index;\n target ??= Math.min(record?.index ?? 0, count - 1);\n moveTo(root, target);\n });\n\n // Development diagnostics (C-DEV): emitted from effects, once per page.\n const unnamed = !rest['aria-label'] && !rest['aria-labelledby'];\n React.useEffect(() => {\n if (unnamed) warnOnce('FlatTree:name', NAME_MESSAGE);\n }, [unnamed]);\n const missingChecks = selectionMode === 'multiple' && modelMode !== 'multiple';\n React.useEffect(() => {\n if (missingChecks) warnOnce('FlatTree:selection-mode', SELECTION_MODE_MESSAGE);\n }, [missingChecks]);\n React.useEffect(() => {\n if (selectionMode === 'multiple' && selected !== undefined) {\n warnOnce('FlatTree:selected-with-multiple', SELECTED_WITH_MULTIPLE_MESSAGE);\n }\n if (selectionMode === 'single' && selected === undefined) {\n warnOnce('FlatTree:single-without-selected', SINGLE_WITHOUT_SELECTED_MESSAGE);\n }\n }, [selectionMode, selected]);\n\n const renderRow = (row: FlatTreeRow) => (\n <FlatTreeItem key={`item:${row.item.value}`} item={row}>\n {renderItem ? renderItem(row) : (row.item.label ?? row.item.value)}\n </FlatTreeItem>\n );\n const content = virtualWindow\n ? virtualWindow\n .layout(count, { keep })\n .map((entry) =>\n entry.kind === 'item' ? (\n renderRow(rows[entry.index])\n ) : (\n <FlatTreeSpacer key={`spacer:${entry.key}`} size={entry.size} />\n ),\n )\n : rows.map(renderRow);\n\n return (\n <FlatTreeContext.Provider value={context}>\n <div\n role=\"tree\"\n aria-multiselectable={selectionMode === 'multiple' ? true : undefined}\n data-selection-mode={selectionMode}\n // A windowed tree's tab stop is an item: the scroller is none of its own (Firefox makes a\n // scroller a tab stop). The consumer's `tabIndex` wins.\n tabIndex={windowed && tabStop !== null ? -1 : undefined}\n className={cn(\n flatTreeClassNames.root,\n 'text-body-1',\n // The window lays the rows out: the browser's scroll anchoring only fights it.\n windowed && 'overflow-y-auto [overflow-anchor:none]',\n className,\n )}\n {...rest}\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n onFocus={composeEventHandlers(onFocus, handleFocus, { checkDefaultPrevented: false })}\n onBlur={composeEventHandlers(onBlur, handleBlur, { checkDefaultPrevented: false })}\n onPointerDownCapture={composeEventHandlers(onPointerDownCapture, handlePointerDownCapture)}\n ref={mergedRef}\n >\n {content}\n </div>\n </FlatTreeContext.Provider>\n );\n};\nFlatTreeRoot.displayName = 'FlatTree';\n\n/**\n * A tree built from flat data (WAI-ARIA Tree View pattern) that can render only the items in\n * view, for trees of thousands of items. Its model comes from `useFlatTree(items, options)`: items\n * listed with a `parentValue`, in any order, the expanded and the checked state. The tree renders\n * the visible items (the roots and the children of every expanded branch) as sibling\n * `role=\"treeitem\"` elements with `aria-level`, `aria-setsize` and `aria-posinset` from the data,\n * `aria-expanded` on branches, and the nested `Tree`'s chevron, checkbox and radio.\n *\n * ```tsx\n * const model = useFlatTree(items, { defaultExpandedItems: ['docs'] });\n * const virtualWindow = useVirtualWindow({ itemSize: 28 });\n * <FlatTree aria-label=\"Files\" model={model} {...model.getTreeProps()} virtualWindow={virtualWindow} style={{ height: 400 }} />\n * ```\n *\n * Windowing: with `virtualWindow` the tree is the scrolling element (it needs a bounded height),\n * renders the items in view plus the window's overscan and spacers for the others, and every item\n * is exactly the window's `itemSize` tall. The server renders the first window. Keys move over the\n * whole visible list, scrolling an item that is not rendered into view before focusing it, and the\n * focused item stays rendered (and focused) while it is scrolled away.\n *\n * Keyboard: a single tab stop, on the focused item while focus is inside, else on the `selected`\n * item while it is visible, else on the first enabled item; Tab leaves the tree. Up/Down move\n * between the visible items, Home/End to the first and last, Right expands a collapsed branch or\n * moves to its first child, Left collapses an expanded branch or moves to the parent (both\n * mirrored in right-to-left layouts), Enter activates (and toggles a branch), and so does Space\n * unless the tree has checkboxes, `*` expands the sibling branches, and typing moves to the next\n * visible item whose label starts with the typed text (items under a collapsed branch are not\n * searched). The focused item stays the focused item (rendered, and the tab stop) while focus is\n * in a popup that its content opened, such as a menu in a portal, so the popup can return focus\n * to it.\n *\n * Selection, as the nested `Tree`: `selected` and `onItemSelect` (single selection and activation,\n * with radios in `selectionMode=\"single\"`), `current`, and with `selectionMode=\"multiple\"` a\n * checkbox on every item bound to the model's `checkedItems` (Space or a click on the checkbox\n * toggles it, and checks cascade). An item whose data is `disabled` is `aria-disabled`, is skipped\n * by the keys and typeahead, never holds the tab stop (except while a pointer press has focused\n * it), and is neither activated, expanded nor checked by the user (a check of its parent still\n * includes it).\n *\n * When a branch collapses around the focused item (from code), focus moves to that branch, so it\n * never falls to the page. Items expand and collapse at once, without motion: there is no child\n * group to animate. A selected item under a collapsed branch is not the tab stop until it is\n * visible again.\n *\n * `FlatTree.Item` is the row the tree renders for each visible item (it is not written by hand);\n * it is also exported as `FlatTreeItem` for React Server Components, which cannot use the dotted\n * form.\n */\nexport const FlatTree = /* @__PURE__ */ Object.assign(FlatTreeRoot, { Item: FlatTreeItem });\n\nexport { FlatTreeItem };\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/children.cjs"),r=require("../../lib/dev.cjs"),i=require("../../lib/slot.cjs"),a=require("../../lib/composeEventHandlers.cjs"),o=require("../../lib/classNames.cjs"),s=require("../../hooks/useEventCallback.cjs"),c=require("../../hooks/useControllable.cjs"),l=require("../../hooks/useId.cjs"),u=require("../../lib/direction.cjs"),d=require("../../lib/focus.cjs"),f=require("../../hooks/useRovingTabIndex.cjs"),p=require("../../hooks/useMergedRefs.cjs"),m=require("../../lib/aria.cjs"),h=require("../../lib/styles.cjs"),g=require("../../lib/icons.cjs"),_=require("../../lib/events.cjs"),ee=require("../../hooks/useCollapsePresence.cjs"),v=require("./Tree.context.cjs"),te=require("./Tree.selection.cjs");let y=require("react");y=e.__toESM(y,1);let b=require("react/jsx-runtime");var x=[],S="Tree.Item was rendered inside the label of another Tree.Item, so it is not part of that item's child group: the parent cannot expand, its name includes the nested text, and a treeitem sits inside a label (axe aria-required-parent). A Tree.Item finds its nested items among its own children (written directly, in Fragments, or returned by a render function such as `children.map(renderNode)`), but not inside a component that renders Tree.Item itself. Build a data-driven tree with a render function instead of a recursive component.";function ne(e){r.warnOnce(`Tree:duplicate:${e}`,`Tree: several items share the value "${e}". Item values must be unique within a Tree; items with the same value share their expanded, selected and focus state.`)}var C='Tree: `selected` has no effect with selectionMode="multiple"; use `checkedItems`, and `current` for the item the user is on.',re='Tree: `checkedItems` and `defaultCheckedItems` need selectionMode="multiple"; without it the tree draws no checkboxes and ignores them.',ie='Tree: selectionMode="single" draws a radio on every item for `selected`; pass `selected` (null while nothing is selected) and update it from `onItemSelect`.';function ae(e){return e?Array.from(e,e=>e.current).filter(e=>e!==null).sort((e,t)=>!e.element||!t.element||e.element===t.element?0:e.element.compareDocumentPosition(t.element)&Node.DOCUMENT_POSITION_FOLLOWING?-1:1).map(e=>e.node):[]}var oe=`[role="treeitem"]`,w=`button, [href], input, select, textarea, [role="button"], [tabindex]`,se=`[&:focus-within:not(:has(>*>[role=group]_:focus))>[data-tree-row]_[data-tree-actions]]:visible`,ce=`[@media(hover:hover)]:not-forced-colors:[&:focus-within:not(:has(>*>[role=group]_:focus))>[data-tree-row]_[data-tree-aside]]:invisible`,le=`invisible group-hover/row:visible focus-within:visible forced-colors:visible [@media(hover:none)]:visible has-[[aria-expanded=true]]:visible data-[focus-in-popup]:visible`,ue=`not-forced-colors:group-hover/row:invisible [@media(hover:hover)]:not-forced-colors:group-focus-within/end:invisible [@media(hover:hover)]:not-forced-colors:group-has-[[aria-expanded=true]]/end:invisible [@media(hover:hover)]:not-forced-colors:group-has-[[data-focus-in-popup]]/end:invisible`,de=`[&>*]:[grid-area:1/1] forced-colors:flex [@media(hover:none)]:flex`;function fe(e){let t=e.querySelector(`:scope > [data-tree-row] [data-tree-actions]`);if(!t)return!1;let n=new Map;for(let e of Array.from(t.querySelectorAll(w))){if(d.isHiddenInput(e)||e.matches(`:disabled`))continue;let r=e.closest(`[hidden], [inert]`);if(r&&t.contains(r))continue;let i=e.getAttribute(`data-roving-disabled`);if((i===null||i===`false`)&&(e.getAttribute(`aria-disabled`)!==`true`||e.hasAttribute(`data-disabled-focusable`))&&!f.isHiddenByCss(e,t,n)&&(e.focus(),e.ownerDocument.activeElement===e))return!0}return!1}var T=({expandedItems:e,defaultExpandedItems:n,onExpandedItemsChange:i,onItemSelect:l,selected:u,current:d,selectionMode:m=`none`,navigationMode:h=`tree`,checkedItems:g,defaultCheckedItems:_,onCheckedItemsChange:ee,motion:S,className:w,children:se,onKeyDown:ce,onKeyDownCapture:le,onFocus:ue,onBlur:de,ref:fe,...T})=>{let[me]=y.useState(()=>n??x),[he,E]=c.useControllable(e,me,e=>i?.([...e])),D=y.useMemo(()=>new Set(he),[he]),O=y.useCallback(e=>{E(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e])},[E]),k=y.useCallback(e=>{E(t=>{let n=e.filter(e=>!t.includes(e));return n.length>0?[...t,...n]:t})},[E]),A=s.useEventCallback(e=>{l?.(e)}),[j]=y.useState(()=>_??x),M=y.useRef(void 0),[N,ge]=c.useControllable(g,j,e=>ee?.([...e],M.current)),P=y.useMemo(()=>new Set(N),[N]),F=y.useRef(null),_e=y.useCallback(e=>{F.current??=new Set;let t=F.current;return t.add(e),()=>{t.delete(e)}},[]),I=s.useEventCallback((e,t)=>{let n=ae(F.current);ge(r=>{let i=te.toggleCheck(n,r,e);return M.current={value:e,checked:i.includes(e),event:t},i}),M.current=void 0}),L=m===`multiple`?void 0:m===`single`?u??null:u;y.useEffect(()=>{m===`multiple`&&u!==void 0&&r.warnOnce(`Tree:selected-with-multiple`,C)},[m,u]),y.useEffect(()=>{m===`single`&&u===void 0&&r.warnOnce(`Tree:single-without-selected`,ie)},[m,u]);let R=g!==void 0||_!==void 0;y.useEffect(()=>{m!==`multiple`&&R&&r.warnOnce(`Tree:checked-without-multiple`,re)},[m,R]);let[z,B]=y.useState(null),V=y.useRef(null),H=y.useCallback(e=>{if(!r.isDev)return()=>{};V.current??=new Map;let t=V.current,n=(t.get(e)??0)+1;return t.set(e,n),n>1&&ne(e),()=>{let n=(t.get(e)??1)-1;n>0?t.set(e,n):t.delete(e)}},[]),{containerProps:U,getTabIndex:W,focusValue:G}=f.useRovingTabIndex({activeValue:z??L??null,itemSelector:oe,orientation:`vertical`,loop:!1,typeahead:!0}),ve=y.useMemo(()=>({expanded:D,toggle:O,expand:k,activate:A,selected:L,current:d,getTabIndex:W,focusValue:G,onItemFocus:B,focusedItem:z,navigationMode:h,registerValue:H,selectionMode:m,checked:P,toggleChecked:I,registerTopLevel:_e,motion:S}),[D,O,k,A,L,d,W,G,z,h,H,m,P,I,_e,S]),ye=p.useMergedRefs(fe,U.ref),K=e=>{e.key.length===1&&pe(e.currentTarget),U.onKeyDown(e)},q=e=>{e.key===` `&&pe(e.currentTarget),U.onKeyDownCapture(e)},J=e=>{let t=e.relatedTarget;(!t||!e.currentTarget.contains(t))&&B(null)};return(0,b.jsx)(v.TreeContext.Provider,{value:ve,children:(0,b.jsx)(v.TreeParentContext.Provider,{value:null,children:(0,b.jsx)(v.TreeCheckForcedContext.Provider,{value:!1,children:(0,b.jsx)(`div`,{role:`tree`,"data-selection-mode":m,"aria-multiselectable":m===`multiple`||void 0,className:t.cn(o.treeClassNames.root,`text-body-1`,w),...T,"data-roving-container":``,onKeyDown:a.composeEventHandlers(ce,K),onKeyDownCapture:a.composeEventHandlers(le,q),onFocus:a.composeEventHandlers(ue,U.onFocus,{checkDefaultPrevented:!1}),onBlur:a.composeEventHandlers(de,J,{checkDefaultPrevented:!1}),ref:ye,children:(0,b.jsx)(v.TreeLabelContext.Provider,{value:!1,children:se})})})})})};T.displayName=`Tree`;function pe(e){e.querySelectorAll(`[role="treeitem"]`).forEach(e=>{let t=e.querySelector(`:scope > [data-tree-row] > [data-tree-label]`);if(!t)return;let n=t.querySelector(`[data-tree-persona-name]`),r=t.getAttribute(`data-roving-text`)??n?.textContent??t.textContent??``;e.getAttribute(`data-roving-text`)!==r&&e.setAttribute(`data-roving-text`,r)})}function me(e){let t=e.target;return!t?.closest?.(`[data-tree-actions]`)&&t?.closest?.(`[role="treeitem"]`)===e.currentTarget}function he(e){let t=e.target;return t===e.currentTarget?e.detail===0||!e.currentTarget.querySelector(`:scope > [inert]`):!t?.closest?.(`[data-tree-checkbox], [data-tree-actions]`)&&t?.closest?.(`[data-tree-row]`)?.parentElement===e.currentTarget}var E=({labelledBy:e,tabStop:n,navigationMode:r,onReturn:i,children:a})=>{let s=r===`treegrid`,{containerProps:{ref:c},handleKeyDown:l,handleFocus:d}=f.useRovingTabIndex({itemSelector:w,manageTabIndex:!0,orientation:`horizontal`,loop:!s,tabStop:n}),[p,m]=y.useState(null);y.useEffect(()=>{if(p!==`leaving`)return;let e=requestAnimationFrame(()=>m(null));return()=>cancelAnimationFrame(e)},[p]);let h=e=>{d(e),m(e.currentTarget.contains(e.target)?null:`inside`)},g=e=>{if(e.currentTarget.contains(e.target))return;let t=e.relatedTarget;t instanceof Node&&e.currentTarget.contains(t)||m(`leaving`)},ee=e=>{if(e.defaultPrevented||!_.isOwnEvent(e))return!1;let t=e.target,n=t.getAttribute(`aria-haspopup`);return(e.key===`ArrowDown`||e.key===`ArrowUp`)&&n!==null&&n!==`false`?(e.preventDefault(),!1):!s||e.altKey||e.ctrlKey||e.metaKey||_.isEditableTarget(t)?!1:u.getArrowIntent(e.key,{orientation:`horizontal`,dir:u.getDirection(e.currentTarget)})===`prev`};return(0,b.jsx)(`span`,{role:`toolbar`,"aria-labelledby":e,"aria-orientation":`horizontal`,"data-tree-actions":``,"data-roving-container":``,ref:c,"data-focus-in-popup":p===null?void 0:``,onKeyDown:e=>{let t=ee(e);e.defaultPrevented||(l(e),t&&e.target===document.activeElement&&(e.preventDefault(),i()))},onFocus:h,onBlur:g,className:t.cn(o.treeItemClassNames.actions,`inline-flex items-center gap-1`,le),children:a})};E.displayName=`TreeItemActions`;var D=({value:e,icon:s,iconAfter:c,expandIcon:d,aside:f,actions:_,leaf:x=!1,className:ne,children:C,onClick:re,onKeyDown:ie,onFocus:ae,onBlur:oe,ref:w,...le})=>{let{"data-roving-text":pe,...O}=le,k=v.useTreeContext(`Tree.Item`),A=y.useContext(v.TreeParentContext),j=y.useContext(v.TreeLabelContext),M=k.expanded.has(e),N=l.useId(`tree-item-label`),ge=l.useId(`tree-item-aside`),P=y.useContext(v.TreeCheckForcedContext),F=y.useRef(null),_e=p.useMergedRefs(w,F),[I,L]=y.useState(null),R=y.useCallback(e=>(L(e),()=>L(t=>t===e?null:t)),[]),z=y.useMemo(()=>({registerLayout:R}),[R]),B=I?.nameId??N,{registerValue:V,registerTopLevel:H}=k;y.useEffect(()=>V(e),[V,e]),y.useEffect(()=>{j&&r.warnOnce(`Tree.Item:inside-label`,S)},[j]);let U=[],W=[],G;n.flattenChildren(C).forEach(({key:e,node:t})=>{let r=(0,b.jsx)(y.Fragment,{children:t},e);n.isElementOfType(t,D)?(G??=t.props.value,U.push(r)):n.isElementOfType(t,T)?U.push(r):W.push(r)});let ve=s&&i.slotRendersContent(s)?i.renderSlot(s,`span`,t.cn(o.treeItemClassNames.icon,`inline-flex shrink-0`),{"aria-hidden":!0}):null,ye=c&&i.slotRendersContent(c)?i.renderSlot(c,`span`,t.cn(o.treeItemClassNames.iconAfter,`inline-flex shrink-0`),{"aria-hidden":!0}):null,K=i.slotRendersContent(f),q=i.slotRendersContent(_),J=U.length>0&&!x,be=y.useRef(null),{isMounted:xe,wrapperRef:Se,presenceProps:Ce,className:we}=ee.useCollapsePresence(J&&M,{motion:k.motion,partRef:be,getTrigger:()=>F.current}),Te=(0,b.jsx)(`span`,{className:`w-3 shrink-0`,"aria-hidden":`true`});J&&d==null?Te=(0,b.jsx)(g.ChevronRightIcon,{className:t.cn(o.treeItemClassNames.expandIcon,`shrink-0 transition-transform motion-reduce:transition-none`,M?`rotate-90`:`wave-rtl:-scale-x-100`)}):J&&i.slotRendersContent(d)&&(Te=i.renderSlot(d,`span`,t.cn(o.treeItemClassNames.expandIcon,`inline-flex shrink-0`),{"aria-hidden":!0}));let Y=k.selectionMode===`multiple`,X=y.useMemo(()=>Y?{value:e,children:x?[]:te.collectItems(C,{item:D,tree:T})}:null,[Y,e,x,C]),Z=X?te.computeCheckStates([X],k.checked,P).get(e):void 0,Ee=y.useRef(null);y.useLayoutEffect(()=>{Ee.current=X?{node:X,element:F.current}:null});let De=A===null&&!j;y.useLayoutEffect(()=>Y&&De?H(Ee):void 0,[Y,De,H]);let Q=k.selected===void 0?void 0:k.selected===e,Oe=k.current!==void 0&&k.current!==null&&k.current===e,ke=()=>{J&&k.toggle(e),k.activate(e)},Ae=e=>{he(e)&&(re?.(e),e.defaultPrevented||ke())},je=t=>{if(!me(t)||(ie?.(t),t.defaultPrevented||t.altKey||t.ctrlKey||t.metaKey))return;switch(t.key){case`Enter`:t.preventDefault(),ke();return;case` `:t.preventDefault(),Z===void 0?ke():k.toggleChecked(e,t.nativeEvent);return;case`*`:{t.preventDefault();let e=t.currentTarget.parentElement?.querySelectorAll(`:scope > [role="treeitem"][aria-expanded="false"][data-roving-value]`);k.expand(Array.from(e??[],e=>e.getAttribute(`data-roving-value`)??``).filter(Boolean));return}}let n=u.getArrowIntent(t.key,{orientation:`horizontal`,dir:u.getDirection(t.currentTarget)});if(n===`next`){if(t.preventDefault(),J&&!M){k.toggle(e);return}if(k.navigationMode===`treegrid`&&fe(t.currentTarget))return;J&&G!==void 0&&k.focusValue(G)}else n===`prev`&&(t.preventDefault(),J&&M?k.toggle(e):A!==null&&k.focusValue(A))},$=y.useRef(null),Me=e=>e.target.closest(`[data-tree-actions]`)?.closest(`[role="treeitem"]`)===e.currentTarget,Ne=t=>{(t.target===t.currentTarget||Me(t))&&k.onItemFocus(e),Me(t)&&($.current=t.target)},Pe=e=>{Me(e)&&(e.relatedTarget!==null||e.target.isConnected)&&($.current=null)};y.useLayoutEffect(()=>{let e=$.current;if(!e)return;let t=F.current,n=t?.ownerDocument.activeElement;n&&n!==t.ownerDocument.body?$.current=null:t&&!e.isConnected&&($.current=null,t.focus({preventScroll:!0}))});let Fe=Z===void 0?null:(0,b.jsx)(`span`,{role:`checkbox`,"aria-checked":Z===`mixed`?`mixed`:Z===`checked`,"aria-labelledby":B,tabIndex:-1,"data-tree-checkbox":``,onMouseDown:e=>{e.preventDefault(),F.current?.focus({preventScroll:!0})},onClick:t=>{k.toggleChecked(e,t.nativeEvent)},className:t.cn(o.treeItemClassNames.indicator,`relative inline-flex size-4 shrink-0 items-center justify-center rounded-xs border transition-colors motion-reduce:transition-none`,`before:absolute before:-inset-1`,Z===`unchecked`?t.cn(`border-stroke-accessible bg-transparent`,h.forcedColors.control):`border-primary bg-primary text-primary-foreground forced-colors:border-[Highlight] forced-colors:bg-[Highlight]`),children:Z===`mixed`?(0,b.jsx)(g.SubtractIcon,{size:12,className:h.forcedColors.selectedLeaf}):Z===`checked`?(0,b.jsx)(g.CheckIcon,{size:12,className:h.forcedColors.selectedLeaf}):null}),Ie=k.selectionMode===`single`?(0,b.jsx)(`span`,{"aria-hidden":`true`,className:t.cn(o.treeItemClassNames.indicator,`inline-flex size-4 shrink-0 items-center justify-center rounded-full border transition-colors motion-reduce:transition-none`,Q?`border-2 border-primary forced-colors:border-[Highlight]`:t.cn(`border-stroke-accessible`,h.forcedColors.control)),children:Q&&(0,b.jsx)(`span`,{className:t.cn(`block size-2 rounded-full bg-primary`,h.forcedColors.selectedLeaf)})}):null,Le=Fe??Ie,Re=P||Y&&k.checked.has(e);return(0,b.jsxs)(`div`,{role:`treeitem`,"aria-selected":Q,"aria-current":Oe?!0:void 0,"data-checked":Z===`checked`?``:void 0,"data-mixed":Z===`mixed`?``:void 0,className:t.cn(o.treeItemClassNames.root,`block outline-none`,`[&:focus-visible>[data-tree-row]]:outline-2 [&:focus-visible>[data-tree-row]]:-outline-offset-2 [&:focus-visible>[data-tree-row]]:outline-ring`,q&&se,q&&K&&ce,ne),...O,"aria-labelledby":O[`aria-labelledby`]??(O[`aria-label`]===void 0?B:void 0),"aria-describedby":m.joinIds(O[`aria-describedby`],K?ge:void 0,I?.descriptionId),"aria-expanded":J?M:void 0,"aria-checked":Z===void 0?void 0:Z===`mixed`?`mixed`:Z===`checked`,tabIndex:k.getTabIndex(e),"data-roving-value":e,"data-selected":Q?``:void 0,"data-current":Oe?``:void 0,onClick:Ae,onKeyDown:je,onFocus:e=>a.composeEventHandlers(ae,Ne,{checkDefaultPrevented:!1})(e),onBlur:e=>a.composeEventHandlers(oe,Pe,{checkDefaultPrevented:!1})(e),ref:_e,children:[(0,b.jsxs)(`div`,{"data-tree-row":``,className:t.cn(o.treeItemClassNames.row,`flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 hover:bg-subtle-hover`,q&&`group/row`,Q&&t.cn(`bg-subtle-selected font-semibold`,h.forcedColors.selectedContainer)),children:[Te,Le,ve,(0,b.jsx)(`span`,{id:N,"data-tree-label":``,"data-roving-text":pe,className:t.cn(o.treeItemClassNames.label,`truncate`,(ye||K||q)&&`min-w-0`),children:(0,b.jsx)(v.TreeCheckForcedContext.Provider,{value:!1,children:(0,b.jsx)(v.TreeLabelContext.Provider,{value:!0,children:(0,b.jsx)(v.TreeItemContext.Provider,{value:z,children:W})})})}),ye,(K||q)&&(0,b.jsxs)(`span`,{"data-tree-end":``,className:t.cn(`group/end ms-auto inline-grid shrink-0 items-center gap-1`,K&&q&&de),children:[K&&(0,b.jsx)(`span`,{id:ge,"data-tree-aside":``,className:t.cn(o.treeItemClassNames.aside,`inline-flex items-center text-caption-1 text-muted-foreground`,q&&ue),children:i.materialiseSlotContent(f)}),q&&(0,b.jsx)(E,{labelledBy:B,tabStop:k.navigationMode===`tree`&&k.focusedItem===e?`last-focused`:`none`,navigationMode:k.navigationMode,onReturn:()=>k.focusValue(e),children:i.materialiseSlotContent(_)})]})]}),xe&&(0,b.jsx)(v.TreeParentContext.Provider,{value:e,children:(0,b.jsx)(v.TreeCheckForcedContext.Provider,{value:Re,children:(0,b.jsx)(v.TreeLabelContext.Provider,{value:!1,children:(0,b.jsx)(`div`,{ref:Se,...Ce,className:t.cn(o.treeItemClassNames.collapse,we),children:(0,b.jsx)(`div`,{ref:be,role:`group`,className:t.cn(o.treeItemClassNames.group,`ps-4`),children:U})})})})})]})};D.displayName=`TreeItem`,exports.TreeItem=D,exports.TreeRoot=T;
1
+ "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/children.cjs"),r=require("../../lib/dev.cjs"),i=require("../../lib/slot.cjs"),a=require("../../lib/composeEventHandlers.cjs"),o=require("../../lib/classNames.cjs"),s=require("../../hooks/useEventCallback.cjs"),c=require("../../hooks/useControllable.cjs"),l=require("../../hooks/useId.cjs"),u=require("../../lib/direction.cjs"),d=require("../../lib/focus.cjs"),f=require("../../hooks/useRovingTabIndex.cjs"),p=require("../../hooks/useMergedRefs.cjs"),m=require("../../lib/aria.cjs"),h=require("../../lib/styles.cjs"),g=require("../../lib/icons.cjs"),_=require("../../lib/events.cjs"),ee=require("../../hooks/useCollapsePresence.cjs"),v=require("./Tree.context.cjs"),te=require("../../lib/treeCascade.cjs"),ne=require("./Tree.selection.cjs");let y=require("react");y=e.__toESM(y,1);let b=require("react/jsx-runtime");var x=[],re="Tree.Item was rendered inside the label of another Tree.Item, so it is not part of that item's child group: the parent cannot expand, its name includes the nested text, and a treeitem sits inside a label (axe aria-required-parent). A Tree.Item finds its nested items among its own children (written directly, in Fragments, or returned by a render function such as `children.map(renderNode)`), but not inside a component that renders Tree.Item itself. Build a data-driven tree with a render function instead of a recursive component.";function ie(e){r.warnOnce(`Tree:duplicate:${e}`,`Tree: several items share the value "${e}". Item values must be unique within a Tree; items with the same value share their expanded, selected and focus state.`)}var S='Tree: `selected` has no effect with selectionMode="multiple"; use `checkedItems`, and `current` for the item the user is on.',ae='Tree: `checkedItems` and `defaultCheckedItems` need selectionMode="multiple"; without it the tree draws no checkboxes and ignores them.',oe='Tree: selectionMode="single" draws a radio on every item for `selected`; pass `selected` (null while nothing is selected) and update it from `onItemSelect`.';function se(e){return e?Array.from(e,e=>e.current).filter(e=>e!==null).sort((e,t)=>!e.element||!t.element||e.element===t.element?0:e.element.compareDocumentPosition(t.element)&Node.DOCUMENT_POSITION_FOLLOWING?-1:1).map(e=>e.node):[]}var ce=`[role="treeitem"]`,C=`button, [href], input, select, textarea, [role="button"], [tabindex]`,le=`[&:focus-within:not(:has(>*>[role=group]_:focus))>[data-tree-row]_[data-tree-actions]]:visible`,ue=`[@media(hover:hover)]:not-forced-colors:[&:focus-within:not(:has(>*>[role=group]_:focus))>[data-tree-row]_[data-tree-aside]]:invisible`,de=`invisible group-hover/row:visible focus-within:visible forced-colors:visible [@media(hover:none)]:visible has-[[aria-expanded=true]]:visible data-[focus-in-popup]:visible`,fe=`not-forced-colors:group-hover/row:invisible [@media(hover:hover)]:not-forced-colors:group-focus-within/end:invisible [@media(hover:hover)]:not-forced-colors:group-has-[[aria-expanded=true]]/end:invisible [@media(hover:hover)]:not-forced-colors:group-has-[[data-focus-in-popup]]/end:invisible`,pe=`[&>*]:[grid-area:1/1] forced-colors:flex [@media(hover:none)]:flex`;function me(e){let t=e.querySelector(`:scope > [data-tree-row] [data-tree-actions]`);if(!t)return!1;let n=new Map;for(let e of Array.from(t.querySelectorAll(C))){if(d.isHiddenInput(e)||e.matches(`:disabled`))continue;let r=e.closest(`[hidden], [inert]`);if(r&&t.contains(r))continue;let i=e.getAttribute(`data-roving-disabled`);if((i===null||i===`false`)&&(e.getAttribute(`aria-disabled`)!==`true`||e.hasAttribute(`data-disabled-focusable`))&&!f.isHiddenByCss(e,t,n)&&(e.focus(),e.ownerDocument.activeElement===e))return!0}return!1}var w=({expandedItems:e,defaultExpandedItems:n,onExpandedItemsChange:i,onItemSelect:l,selected:u,current:d,selectionMode:m=`none`,navigationMode:h=`tree`,checkedItems:g,defaultCheckedItems:_,onCheckedItemsChange:ee,motion:ne,className:re,children:C,onKeyDown:le,onKeyDownCapture:ue,onFocus:de,onBlur:fe,ref:pe,...me})=>{let[w]=y.useState(()=>n??x),[ge,T]=c.useControllable(e,w,e=>i?.([...e])),E=y.useMemo(()=>new Set(ge),[ge]),D=y.useCallback(e=>{T(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e])},[T]),O=y.useCallback(e=>{T(t=>{let n=e.filter(e=>!t.includes(e));return n.length>0?[...t,...n]:t})},[T]),k=s.useEventCallback(e=>{l?.(e)}),[A]=y.useState(()=>_??x),j=y.useRef(void 0),[M,N]=c.useControllable(g,A,e=>ee?.([...e],j.current)),P=y.useMemo(()=>new Set(M),[M]),F=y.useRef(null),I=y.useCallback(e=>{F.current??=new Set;let t=F.current;return t.add(e),()=>{t.delete(e)}},[]),_e=s.useEventCallback((e,t)=>{let n=se(F.current);N(r=>{let i=te.toggleCheck(n,r,e);return j.current={value:e,checked:i.includes(e),event:t},i}),j.current=void 0}),L=m===`multiple`?void 0:m===`single`?u??null:u;y.useEffect(()=>{m===`multiple`&&u!==void 0&&r.warnOnce(`Tree:selected-with-multiple`,S)},[m,u]),y.useEffect(()=>{m===`single`&&u===void 0&&r.warnOnce(`Tree:single-without-selected`,oe)},[m,u]);let R=g!==void 0||_!==void 0;y.useEffect(()=>{m!==`multiple`&&R&&r.warnOnce(`Tree:checked-without-multiple`,ae)},[m,R]);let[z,ve]=y.useState(null),B=y.useRef(null),V=y.useCallback(e=>{if(!r.isDev)return()=>{};B.current??=new Map;let t=B.current,n=(t.get(e)??0)+1;return t.set(e,n),n>1&&ie(e),()=>{let n=(t.get(e)??1)-1;n>0?t.set(e,n):t.delete(e)}},[]),{containerProps:H,getTabIndex:U,focusValue:W}=f.useRovingTabIndex({activeValue:z??L??null,itemSelector:ce,orientation:`vertical`,loop:!1,typeahead:!0}),G=y.useMemo(()=>({expanded:E,toggle:D,expand:O,activate:k,selected:L,current:d,getTabIndex:U,focusValue:W,onItemFocus:ve,focusedItem:z,navigationMode:h,registerValue:V,selectionMode:m,checked:P,toggleChecked:_e,registerTopLevel:I,motion:ne}),[E,D,O,k,L,d,U,W,z,h,V,m,P,_e,I,ne]),ye=p.useMergedRefs(pe,H.ref),be=e=>{e.key.length===1&&he(e.currentTarget),H.onKeyDown(e)},K=e=>{e.key===` `&&he(e.currentTarget),H.onKeyDownCapture(e)},q=e=>{let t=e.relatedTarget;(!t||!e.currentTarget.contains(t))&&ve(null)};return(0,b.jsx)(v.TreeContext.Provider,{value:G,children:(0,b.jsx)(v.TreeParentContext.Provider,{value:null,children:(0,b.jsx)(v.TreeCheckForcedContext.Provider,{value:!1,children:(0,b.jsx)(`div`,{role:`tree`,"data-selection-mode":m,"aria-multiselectable":m===`multiple`||void 0,className:t.cn(o.treeClassNames.root,`text-body-1`,re),...me,"data-roving-container":``,onKeyDown:a.composeEventHandlers(le,be),onKeyDownCapture:a.composeEventHandlers(ue,K),onFocus:a.composeEventHandlers(de,H.onFocus,{checkDefaultPrevented:!1}),onBlur:a.composeEventHandlers(fe,q,{checkDefaultPrevented:!1}),ref:ye,children:(0,b.jsx)(v.TreeLabelContext.Provider,{value:!1,children:C})})})})})};w.displayName=`Tree`;function he(e){e.querySelectorAll(`[role="treeitem"]`).forEach(e=>{let t=e.querySelector(`:scope > [data-tree-row] > [data-tree-label]`);if(!t)return;let n=t.querySelector(`[data-tree-persona-name]`),r=t.getAttribute(`data-roving-text`)??n?.textContent??t.textContent??``;e.getAttribute(`data-roving-text`)!==r&&e.setAttribute(`data-roving-text`,r)})}function ge(e){let t=e.target;return!t?.closest?.(`[data-tree-actions]`)&&t?.closest?.(`[role="treeitem"]`)===e.currentTarget}function T(e){let t=e.target;return t===e.currentTarget?e.detail===0||!e.currentTarget.querySelector(`:scope > [inert]`):!t?.closest?.(`[data-tree-checkbox], [data-tree-actions]`)&&t?.closest?.(`[data-tree-row]`)?.parentElement===e.currentTarget}var E=({labelledBy:e,tabStop:n,navigationMode:r,onReturn:i,children:a})=>{let s=r===`treegrid`,{containerProps:{ref:c},handleKeyDown:l,handleFocus:d}=f.useRovingTabIndex({itemSelector:C,manageTabIndex:!0,orientation:`horizontal`,loop:!s,tabStop:n}),[p,m]=y.useState(null);y.useEffect(()=>{if(p!==`leaving`)return;let e=requestAnimationFrame(()=>m(null));return()=>cancelAnimationFrame(e)},[p]);let h=e=>{d(e),m(e.currentTarget.contains(e.target)?null:`inside`)},g=e=>{if(e.currentTarget.contains(e.target))return;let t=e.relatedTarget;t instanceof Node&&e.currentTarget.contains(t)||m(`leaving`)},ee=e=>{if(e.defaultPrevented||!_.isOwnEvent(e))return!1;let t=e.target,n=t.getAttribute(`aria-haspopup`);return(e.key===`ArrowDown`||e.key===`ArrowUp`)&&n!==null&&n!==`false`?(e.preventDefault(),!1):!s||e.altKey||e.ctrlKey||e.metaKey||_.isEditableTarget(t)?!1:u.getArrowIntent(e.key,{orientation:`horizontal`,dir:u.getDirection(e.currentTarget)})===`prev`};return(0,b.jsx)(`span`,{role:`toolbar`,"aria-labelledby":e,"aria-orientation":`horizontal`,"data-tree-actions":``,"data-roving-container":``,ref:c,"data-focus-in-popup":p===null?void 0:``,onKeyDown:e=>{let t=ee(e);e.defaultPrevented||(l(e),t&&e.target===document.activeElement&&(e.preventDefault(),i()))},onFocus:h,onBlur:g,className:t.cn(o.treeItemClassNames.actions,`inline-flex items-center gap-1`,de),children:a})};E.displayName=`TreeItemActions`;var D=({value:e,icon:s,iconAfter:c,expandIcon:d,aside:f,actions:_,leaf:x=!1,className:ie,children:S,onClick:ae,onKeyDown:oe,onFocus:se,onBlur:ce,ref:C,...de})=>{let{"data-roving-text":he,...O}=de,k=v.useTreeContext(`Tree.Item`),A=y.useContext(v.TreeParentContext),j=y.useContext(v.TreeLabelContext),M=k.expanded.has(e),N=l.useId(`tree-item-label`),P=l.useId(`tree-item-aside`),F=y.useContext(v.TreeCheckForcedContext),I=y.useRef(null),_e=p.useMergedRefs(C,I),[L,R]=y.useState(null),z=y.useCallback(e=>(R(e),()=>R(t=>t===e?null:t)),[]),ve=y.useMemo(()=>({registerLayout:z}),[z]),B=L?.nameId??N,{registerValue:V,registerTopLevel:H}=k;y.useEffect(()=>V(e),[V,e]),y.useEffect(()=>{j&&r.warnOnce(`Tree.Item:inside-label`,re)},[j]);let U=[],W=[],G;n.flattenChildren(S).forEach(({key:e,node:t})=>{let r=(0,b.jsx)(y.Fragment,{children:t},e);n.isElementOfType(t,D)?(G??=t.props.value,U.push(r)):n.isElementOfType(t,w)?U.push(r):W.push(r)});let ye=s&&i.slotRendersContent(s)?i.renderSlot(s,`span`,t.cn(o.treeItemClassNames.icon,`inline-flex shrink-0`),{"aria-hidden":!0}):null,be=c&&i.slotRendersContent(c)?i.renderSlot(c,`span`,t.cn(o.treeItemClassNames.iconAfter,`inline-flex shrink-0`),{"aria-hidden":!0}):null,K=i.slotRendersContent(f),q=i.slotRendersContent(_),J=U.length>0&&!x,xe=y.useRef(null),{isMounted:Se,wrapperRef:Ce,presenceProps:we,className:Te}=ee.useCollapsePresence(J&&M,{motion:k.motion,partRef:xe,getTrigger:()=>I.current}),Ee=(0,b.jsx)(`span`,{className:`w-3 shrink-0`,"aria-hidden":`true`});J&&d==null?Ee=(0,b.jsx)(g.ChevronRightIcon,{className:t.cn(o.treeItemClassNames.expandIcon,`shrink-0 transition-transform motion-reduce:transition-none`,M?`rotate-90`:`wave-rtl:-scale-x-100`)}):J&&i.slotRendersContent(d)&&(Ee=i.renderSlot(d,`span`,t.cn(o.treeItemClassNames.expandIcon,`inline-flex shrink-0`),{"aria-hidden":!0}));let Y=k.selectionMode===`multiple`,X=y.useMemo(()=>Y?{value:e,children:x?[]:ne.collectItems(S,{item:D,tree:w})}:null,[Y,e,x,S]),Z=X?te.computeCheckStates([X],k.checked,F).get(e):void 0,De=y.useRef(null);y.useLayoutEffect(()=>{De.current=X?{node:X,element:I.current}:null});let Oe=A===null&&!j;y.useLayoutEffect(()=>Y&&Oe?H(De):void 0,[Y,Oe,H]);let Q=k.selected===void 0?void 0:k.selected===e,ke=k.current!==void 0&&k.current!==null&&k.current===e,Ae=()=>{J&&k.toggle(e),k.activate(e)},je=e=>{T(e)&&(ae?.(e),e.defaultPrevented||Ae())},Me=t=>{if(!ge(t)||(oe?.(t),t.defaultPrevented||t.altKey||t.ctrlKey||t.metaKey))return;switch(t.key){case`Enter`:t.preventDefault(),Ae();return;case` `:t.preventDefault(),Z===void 0?Ae():k.toggleChecked(e,t.nativeEvent);return;case`*`:{t.preventDefault();let e=t.currentTarget.parentElement?.querySelectorAll(`:scope > [role="treeitem"][aria-expanded="false"][data-roving-value]`);k.expand(Array.from(e??[],e=>e.getAttribute(`data-roving-value`)??``).filter(Boolean));return}}let n=u.getArrowIntent(t.key,{orientation:`horizontal`,dir:u.getDirection(t.currentTarget)});if(n===`next`){if(t.preventDefault(),J&&!M){k.toggle(e);return}if(k.navigationMode===`treegrid`&&me(t.currentTarget))return;J&&G!==void 0&&k.focusValue(G)}else n===`prev`&&(t.preventDefault(),J&&M?k.toggle(e):A!==null&&k.focusValue(A))},$=y.useRef(null),Ne=e=>e.target.closest(`[data-tree-actions]`)?.closest(`[role="treeitem"]`)===e.currentTarget,Pe=t=>{(t.target===t.currentTarget||Ne(t))&&k.onItemFocus(e),Ne(t)&&($.current=t.target)},Fe=e=>{Ne(e)&&(e.relatedTarget!==null||e.target.isConnected)&&($.current=null)};y.useLayoutEffect(()=>{let e=$.current;if(!e)return;let t=I.current,n=t?.ownerDocument.activeElement;n&&n!==t.ownerDocument.body?$.current=null:t&&!e.isConnected&&($.current=null,t.focus({preventScroll:!0}))});let Ie=Z===void 0?null:(0,b.jsx)(`span`,{role:`checkbox`,"aria-checked":Z===`mixed`?`mixed`:Z===`checked`,"aria-labelledby":B,tabIndex:-1,"data-tree-checkbox":``,onMouseDown:e=>{e.preventDefault(),I.current?.focus({preventScroll:!0})},onClick:t=>{k.toggleChecked(e,t.nativeEvent)},className:t.cn(o.treeItemClassNames.indicator,`relative inline-flex size-4 shrink-0 items-center justify-center rounded-xs border transition-colors motion-reduce:transition-none`,`before:absolute before:-inset-1`,Z===`unchecked`?t.cn(`border-stroke-accessible bg-transparent`,h.forcedColors.control):`border-primary bg-primary text-primary-foreground forced-colors:border-[Highlight] forced-colors:bg-[Highlight]`),children:Z===`mixed`?(0,b.jsx)(g.SubtractIcon,{size:12,className:h.forcedColors.selectedLeaf}):Z===`checked`?(0,b.jsx)(g.CheckIcon,{size:12,className:h.forcedColors.selectedLeaf}):null}),Le=k.selectionMode===`single`?(0,b.jsx)(`span`,{"aria-hidden":`true`,className:t.cn(o.treeItemClassNames.indicator,`inline-flex size-4 shrink-0 items-center justify-center rounded-full border transition-colors motion-reduce:transition-none`,Q?`border-2 border-primary forced-colors:border-[Highlight]`:t.cn(`border-stroke-accessible`,h.forcedColors.control)),children:Q&&(0,b.jsx)(`span`,{className:t.cn(`block size-2 rounded-full bg-primary`,h.forcedColors.selectedLeaf)})}):null,Re=Ie??Le,ze=F||Y&&k.checked.has(e);return(0,b.jsxs)(`div`,{role:`treeitem`,"aria-selected":Q,"aria-current":ke?!0:void 0,"data-checked":Z===`checked`?``:void 0,"data-mixed":Z===`mixed`?``:void 0,className:t.cn(o.treeItemClassNames.root,`block outline-none`,`[&:focus-visible>[data-tree-row]]:outline-2 [&:focus-visible>[data-tree-row]]:-outline-offset-2 [&:focus-visible>[data-tree-row]]:outline-ring`,q&&le,q&&K&&ue,ie),...O,"aria-labelledby":O[`aria-labelledby`]??(O[`aria-label`]===void 0?B:void 0),"aria-describedby":m.joinIds(O[`aria-describedby`],K?P:void 0,L?.descriptionId),"aria-expanded":J?M:void 0,"aria-checked":Z===void 0?void 0:Z===`mixed`?`mixed`:Z===`checked`,tabIndex:k.getTabIndex(e),"data-roving-value":e,"data-selected":Q?``:void 0,"data-current":ke?``:void 0,onClick:je,onKeyDown:Me,onFocus:e=>a.composeEventHandlers(se,Pe,{checkDefaultPrevented:!1})(e),onBlur:e=>a.composeEventHandlers(ce,Fe,{checkDefaultPrevented:!1})(e),ref:_e,children:[(0,b.jsxs)(`div`,{"data-tree-row":``,className:t.cn(o.treeItemClassNames.row,`flex cursor-pointer items-center gap-1.5 rounded px-2 py-1 hover:bg-subtle-hover`,q&&`group/row`,Q&&t.cn(`bg-subtle-selected font-semibold`,h.forcedColors.selectedContainer)),children:[Ee,Re,ye,(0,b.jsx)(`span`,{id:N,"data-tree-label":``,"data-roving-text":he,className:t.cn(o.treeItemClassNames.label,`truncate`,(be||K||q)&&`min-w-0`),children:(0,b.jsx)(v.TreeCheckForcedContext.Provider,{value:!1,children:(0,b.jsx)(v.TreeLabelContext.Provider,{value:!0,children:(0,b.jsx)(v.TreeItemContext.Provider,{value:ve,children:W})})})}),be,(K||q)&&(0,b.jsxs)(`span`,{"data-tree-end":``,className:t.cn(`group/end ms-auto inline-grid shrink-0 items-center gap-1`,K&&q&&pe),children:[K&&(0,b.jsx)(`span`,{id:P,"data-tree-aside":``,className:t.cn(o.treeItemClassNames.aside,`inline-flex items-center text-caption-1 text-muted-foreground`,q&&fe),children:i.materialiseSlotContent(f)}),q&&(0,b.jsx)(E,{labelledBy:B,tabStop:k.navigationMode===`tree`&&k.focusedItem===e?`last-focused`:`none`,navigationMode:k.navigationMode,onReturn:()=>k.focusValue(e),children:i.materialiseSlotContent(_)})]})]}),Se&&(0,b.jsx)(v.TreeParentContext.Provider,{value:e,children:(0,b.jsx)(v.TreeCheckForcedContext.Provider,{value:ze,children:(0,b.jsx)(v.TreeLabelContext.Provider,{value:!1,children:(0,b.jsx)(`div`,{ref:Ce,...we,className:t.cn(o.treeItemClassNames.collapse,Te),children:(0,b.jsx)(`div`,{ref:xe,role:`group`,className:t.cn(o.treeItemClassNames.group,`ps-4`),children:U})})})})})]})};D.displayName=`TreeItem`,exports.TreeItem=D,exports.TreeRoot=w;
2
2
  //# sourceMappingURL=Tree.core.cjs.map