@dxos/react-ui-list 0.8.3 → 0.8.4-main.1c7ec43d41

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 (106) hide show
  1. package/dist/lib/browser/index.mjs +1374 -739
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +1374 -739
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/components/Accordion/Accordion.d.ts +1 -1
  8. package/dist/types/src/components/Accordion/Accordion.d.ts.map +1 -1
  9. package/dist/types/src/components/Accordion/Accordion.stories.d.ts +7 -4
  10. package/dist/types/src/components/Accordion/Accordion.stories.d.ts.map +1 -1
  11. package/dist/types/src/components/Accordion/AccordionItem.d.ts +1 -1
  12. package/dist/types/src/components/Accordion/AccordionItem.d.ts.map +1 -1
  13. package/dist/types/src/components/Accordion/AccordionRoot.d.ts +1 -1
  14. package/dist/types/src/components/Accordion/AccordionRoot.d.ts.map +1 -1
  15. package/dist/types/src/components/Combobox/Combobox.d.ts +105 -0
  16. package/dist/types/src/components/Combobox/Combobox.d.ts.map +1 -0
  17. package/dist/types/src/components/Combobox/Combobox.stories.d.ts +12 -0
  18. package/dist/types/src/components/Combobox/Combobox.stories.d.ts.map +1 -0
  19. package/dist/types/src/components/Combobox/index.d.ts +2 -0
  20. package/dist/types/src/components/Combobox/index.d.ts.map +1 -0
  21. package/dist/types/src/components/List/List.d.ts +21 -10
  22. package/dist/types/src/components/List/List.d.ts.map +1 -1
  23. package/dist/types/src/components/List/List.stories.d.ts +14 -5
  24. package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
  25. package/dist/types/src/components/List/ListItem.d.ts +12 -13
  26. package/dist/types/src/components/List/ListItem.d.ts.map +1 -1
  27. package/dist/types/src/components/List/ListRoot.d.ts +2 -2
  28. package/dist/types/src/components/List/ListRoot.d.ts.map +1 -1
  29. package/dist/types/src/components/List/testing.d.ts +1 -1
  30. package/dist/types/src/components/List/testing.d.ts.map +1 -1
  31. package/dist/types/src/components/Listbox/Listbox.d.ts +27 -0
  32. package/dist/types/src/components/Listbox/Listbox.d.ts.map +1 -0
  33. package/dist/types/src/components/Listbox/Listbox.stories.d.ts +12 -0
  34. package/dist/types/src/components/Listbox/Listbox.stories.d.ts.map +1 -0
  35. package/dist/types/src/components/Listbox/index.d.ts +2 -0
  36. package/dist/types/src/components/Listbox/index.d.ts.map +1 -0
  37. package/dist/types/src/components/Picker/Picker.d.ts +49 -0
  38. package/dist/types/src/components/Picker/Picker.d.ts.map +1 -0
  39. package/dist/types/src/components/Picker/Picker.stories.d.ts +28 -0
  40. package/dist/types/src/components/Picker/Picker.stories.d.ts.map +1 -0
  41. package/dist/types/src/components/Picker/context.d.ts +29 -0
  42. package/dist/types/src/components/Picker/context.d.ts.map +1 -0
  43. package/dist/types/src/components/Picker/index.d.ts +3 -0
  44. package/dist/types/src/components/Picker/index.d.ts.map +1 -0
  45. package/dist/types/src/components/RowList/RowList.d.ts +61 -0
  46. package/dist/types/src/components/RowList/RowList.d.ts.map +1 -0
  47. package/dist/types/src/components/RowList/RowList.stories.d.ts +35 -0
  48. package/dist/types/src/components/RowList/RowList.stories.d.ts.map +1 -0
  49. package/dist/types/src/components/RowList/index.d.ts +3 -0
  50. package/dist/types/src/components/RowList/index.d.ts.map +1 -0
  51. package/dist/types/src/components/Tree/Tree.d.ts +10 -6
  52. package/dist/types/src/components/Tree/Tree.d.ts.map +1 -1
  53. package/dist/types/src/components/Tree/Tree.stories.d.ts +18 -7
  54. package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
  55. package/dist/types/src/components/Tree/TreeContext.d.ts +24 -10
  56. package/dist/types/src/components/Tree/TreeContext.d.ts.map +1 -1
  57. package/dist/types/src/components/Tree/TreeItem.d.ts +32 -10
  58. package/dist/types/src/components/Tree/TreeItem.d.ts.map +1 -1
  59. package/dist/types/src/components/Tree/TreeItemHeading.d.ts +4 -3
  60. package/dist/types/src/components/Tree/TreeItemHeading.d.ts.map +1 -1
  61. package/dist/types/src/components/Tree/TreeItemToggle.d.ts +3 -3
  62. package/dist/types/src/components/Tree/TreeItemToggle.d.ts.map +1 -1
  63. package/dist/types/src/components/Tree/helpers.d.ts.map +1 -1
  64. package/dist/types/src/components/Tree/index.d.ts +2 -0
  65. package/dist/types/src/components/Tree/index.d.ts.map +1 -1
  66. package/dist/types/src/components/Tree/testing.d.ts +3 -3
  67. package/dist/types/src/components/Tree/testing.d.ts.map +1 -1
  68. package/dist/types/src/components/index.d.ts +4 -0
  69. package/dist/types/src/components/index.d.ts.map +1 -1
  70. package/dist/types/src/util/path.d.ts.map +1 -1
  71. package/dist/types/tsconfig.tsbuildinfo +1 -1
  72. package/package.json +35 -33
  73. package/src/components/Accordion/Accordion.stories.tsx +8 -10
  74. package/src/components/Accordion/Accordion.tsx +1 -1
  75. package/src/components/Accordion/AccordionItem.tsx +7 -5
  76. package/src/components/Accordion/AccordionRoot.tsx +1 -1
  77. package/src/components/Combobox/Combobox.stories.tsx +60 -0
  78. package/src/components/Combobox/Combobox.tsx +387 -0
  79. package/src/components/Combobox/index.ts +5 -0
  80. package/src/components/List/List.stories.tsx +46 -32
  81. package/src/components/List/List.tsx +15 -14
  82. package/src/components/List/ListItem.tsx +91 -57
  83. package/src/components/List/ListRoot.tsx +4 -4
  84. package/src/components/List/testing.ts +7 -7
  85. package/src/components/Listbox/Listbox.stories.tsx +48 -0
  86. package/src/components/Listbox/Listbox.tsx +201 -0
  87. package/src/components/Listbox/index.ts +5 -0
  88. package/src/components/Picker/Picker.stories.tsx +131 -0
  89. package/src/components/Picker/Picker.tsx +368 -0
  90. package/src/components/Picker/context.ts +43 -0
  91. package/src/components/Picker/index.ts +6 -0
  92. package/src/components/RowList/RowList.stories.tsx +163 -0
  93. package/src/components/RowList/RowList.tsx +353 -0
  94. package/src/components/RowList/index.ts +6 -0
  95. package/src/components/Tree/Tree.stories.tsx +175 -83
  96. package/src/components/Tree/Tree.tsx +43 -40
  97. package/src/components/Tree/TreeContext.tsx +21 -9
  98. package/src/components/Tree/TreeItem.tsx +222 -135
  99. package/src/components/Tree/TreeItemHeading.tsx +15 -12
  100. package/src/components/Tree/TreeItemToggle.tsx +29 -19
  101. package/src/components/Tree/index.ts +2 -0
  102. package/src/components/Tree/testing.ts +10 -9
  103. package/src/components/index.ts +4 -0
  104. package/dist/lib/node/index.cjs +0 -886
  105. package/dist/lib/node/index.cjs.map +0 -7
  106. package/dist/lib/node/meta.json +0 -1
@@ -1,88 +1,66 @@
1
- // packages/ui/react-ui-list/src/components/Accordion/AccordionItem.tsx
2
- import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
1
+ // src/components/Accordion/AccordionItem.tsx
3
2
  import * as AccordionPrimitive2 from "@radix-ui/react-accordion";
4
3
  import { createContext as createContext2 } from "@radix-ui/react-context";
5
4
  import React2 from "react";
6
5
  import { Icon } from "@dxos/react-ui";
7
- import { mx as mx2 } from "@dxos/react-ui-theme";
6
+ import { mx as mx2 } from "@dxos/ui-theme";
8
7
 
9
- // packages/ui/react-ui-list/src/components/Accordion/AccordionRoot.tsx
10
- import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
8
+ // src/components/Accordion/AccordionRoot.tsx
11
9
  import * as AccordionPrimitive from "@radix-ui/react-accordion";
12
10
  import { createContext } from "@radix-ui/react-context";
13
11
  import React from "react";
14
- import { mx } from "@dxos/react-ui-theme";
12
+ import { mx } from "@dxos/ui-theme";
15
13
  var ACCORDION_NAME = "Accordion";
16
14
  var [AccordionProvider, useAccordionContext] = createContext(ACCORDION_NAME);
17
15
  var defaultGetId = (item) => item?.id;
18
16
  var AccordionRoot = ({ classNames, items, getId = defaultGetId, children, value, defaultValue, onValueChange }) => {
19
- var _effect = _useSignals();
20
- try {
21
- return /* @__PURE__ */ React.createElement(AccordionProvider, {
22
- getId
23
- }, /* @__PURE__ */ React.createElement(AccordionPrimitive.Root, {
24
- type: "multiple",
25
- value,
26
- defaultValue,
27
- onValueChange,
28
- className: mx(classNames)
29
- }, children?.({
30
- items: items ?? []
31
- })));
32
- } finally {
33
- _effect.f();
34
- }
17
+ return /* @__PURE__ */ React.createElement(AccordionProvider, {
18
+ getId
19
+ }, /* @__PURE__ */ React.createElement(AccordionPrimitive.Root, {
20
+ type: "multiple",
21
+ value,
22
+ defaultValue,
23
+ onValueChange,
24
+ className: mx(classNames)
25
+ }, children?.({
26
+ items: items ?? []
27
+ })));
35
28
  };
36
29
 
37
- // packages/ui/react-ui-list/src/components/Accordion/AccordionItem.tsx
30
+ // src/components/Accordion/AccordionItem.tsx
38
31
  var ACCORDION_ITEM_NAME = "AccordionItem";
39
- var [AccordionItemProvider, useAccordionItemContext] = createContext2(ACCORDION_ITEM_NAME);
32
+ var [AccordionItemProvider, useDxAccordionItemContext] = createContext2(ACCORDION_ITEM_NAME);
40
33
  var AccordionItem = ({ children, classNames, item }) => {
41
- var _effect = _useSignals2();
42
- try {
43
- const { getId } = useAccordionContext(ACCORDION_ITEM_NAME);
44
- return /* @__PURE__ */ React2.createElement(AccordionItemProvider, {
45
- item
46
- }, /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Item, {
47
- value: getId(item),
48
- className: mx2("overflow-hidden", classNames)
49
- }, children));
50
- } finally {
51
- _effect.f();
52
- }
34
+ const { getId } = useAccordionContext(ACCORDION_ITEM_NAME);
35
+ return /* @__PURE__ */ React2.createElement(AccordionItemProvider, {
36
+ item
37
+ }, /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Item, {
38
+ value: getId(item),
39
+ className: mx2("overflow-hidden", classNames)
40
+ }, children));
53
41
  };
54
42
  var AccordionItemHeader = ({ classNames, children, ...props }) => {
55
- var _effect = _useSignals2();
56
- try {
57
- return /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Header, {
58
- ...props,
59
- className: mx2(classNames)
60
- }, /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Trigger, {
61
- className: "group flex items-center p-2 dx-focus-ring-inset is-full text-start"
62
- }, children, /* @__PURE__ */ React2.createElement(Icon, {
63
- icon: "ph--caret-right--regular",
64
- size: 4,
65
- classNames: "transition-transform duration-200 group-data-[state=open]:rotate-90"
66
- })));
67
- } finally {
68
- _effect.f();
69
- }
43
+ return /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Header, {
44
+ ...props,
45
+ className: mx2(classNames)
46
+ }, /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Trigger, {
47
+ className: "group flex items-center p-2 dx-focus-ring-inset w-full text-start"
48
+ }, children, /* @__PURE__ */ React2.createElement(Icon, {
49
+ icon: "ph--caret-right--regular",
50
+ size: 4,
51
+ classNames: "transition-transform duration-200 group-data-[state=open]:rotate-90"
52
+ })));
70
53
  };
71
54
  var AccordionItemBody = ({ children, classNames }) => {
72
- var _effect = _useSignals2();
73
- try {
74
- return /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Content, {
75
- className: "overflow-hidden data-[state=closed]:animate-slideUp data-[state=open]:animate-slideDown"
76
- }, /* @__PURE__ */ React2.createElement("div", {
77
- role: "none",
78
- className: mx2("p-2", classNames)
79
- }, children));
80
- } finally {
81
- _effect.f();
82
- }
55
+ return /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Content, {
56
+ className: "overflow-hidden data-[state=closed]:animate-slide-up data-[state=open]:animate-slide-down"
57
+ }, /* @__PURE__ */ React2.createElement("div", {
58
+ role: "none",
59
+ className: mx2("p-2", classNames)
60
+ }, children));
83
61
  };
84
62
 
85
- // packages/ui/react-ui-list/src/components/Accordion/Accordion.tsx
63
+ // src/components/Accordion/Accordion.tsx
86
64
  var Accordion = {
87
65
  Root: AccordionRoot,
88
66
  Item: AccordionItem,
@@ -90,96 +68,526 @@ var Accordion = {
90
68
  ItemBody: AccordionItemBody
91
69
  };
92
70
 
93
- // packages/ui/react-ui-list/src/components/List/ListItem.tsx
94
- import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
71
+ // src/components/Combobox/Combobox.tsx
72
+ import { createContext as createContext4 } from "@radix-ui/react-context";
73
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
74
+ import React4, { forwardRef as forwardRef2, useCallback as useCallback2 } from "react";
75
+ import { Button, Icon as Icon2, Popover, ScrollArea, useId } from "@dxos/react-ui";
76
+ import { composable, composableProps, mx as mx4 } from "@dxos/ui-theme";
77
+
78
+ // src/components/Picker/Picker.tsx
79
+ import { Slot } from "@radix-ui/react-slot";
80
+ import React3, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react";
81
+ import { Input, useThemeContext } from "@dxos/react-ui";
82
+ import { mx as mx3 } from "@dxos/ui-theme";
83
+
84
+ // src/components/Picker/context.ts
85
+ import { createContext as createContext3 } from "@radix-ui/react-context";
86
+ var [PickerItemContextProvider, usePickerItemContext] = createContext3("PickerItem");
87
+ var [PickerInputContextProvider, usePickerInputContext] = createContext3("PickerInput");
88
+
89
+ // src/components/Picker/Picker.tsx
90
+ var PickerRoot = ({ children }) => {
91
+ const [selectedValue, setSelectedValue] = useState(void 0);
92
+ const itemsRef = useRef(/* @__PURE__ */ new Map());
93
+ const [itemVersion, setItemVersion] = useState(0);
94
+ useEffect(() => {
95
+ const current = selectedValue !== void 0 ? itemsRef.current.get(selectedValue) : void 0;
96
+ const isValid = current !== void 0 && !current.disabled;
97
+ if (!isValid && itemsRef.current.size > 0) {
98
+ const entries = Array.from(itemsRef.current.entries()).filter(([, data]) => !data.disabled);
99
+ if (entries.length > 0) {
100
+ entries.sort(([, a], [, b]) => {
101
+ const position = a.element.compareDocumentPosition(b.element);
102
+ if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
103
+ return -1;
104
+ }
105
+ if (position & Node.DOCUMENT_POSITION_PRECEDING) {
106
+ return 1;
107
+ }
108
+ return 0;
109
+ });
110
+ const firstValue = entries[0]?.[0];
111
+ if (firstValue !== void 0 && firstValue !== selectedValue) {
112
+ setSelectedValue(firstValue);
113
+ }
114
+ } else if (selectedValue !== void 0) {
115
+ setSelectedValue(void 0);
116
+ }
117
+ }
118
+ }, [
119
+ itemVersion,
120
+ selectedValue
121
+ ]);
122
+ const registerItem = useCallback((value, element, onSelect, disabled) => {
123
+ if (element) {
124
+ itemsRef.current.set(value, {
125
+ element,
126
+ onSelect,
127
+ disabled
128
+ });
129
+ setItemVersion((v) => v + 1);
130
+ }
131
+ }, []);
132
+ const unregisterItem = useCallback((value) => {
133
+ itemsRef.current.delete(value);
134
+ setItemVersion((v) => v + 1);
135
+ }, []);
136
+ const getItemValues = useCallback(() => {
137
+ return Array.from(itemsRef.current.entries()).filter(([, data]) => !data.disabled).sort(([, a], [, b]) => {
138
+ const position = a.element.compareDocumentPosition(b.element);
139
+ return position & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : position & Node.DOCUMENT_POSITION_PRECEDING ? 1 : 0;
140
+ }).map(([value]) => value);
141
+ }, []);
142
+ const triggerSelect = useCallback(() => {
143
+ if (selectedValue !== void 0) {
144
+ const item = itemsRef.current.get(selectedValue);
145
+ item?.onSelect?.();
146
+ }
147
+ }, [
148
+ selectedValue
149
+ ]);
150
+ const itemContextValue = useMemo(() => ({
151
+ selectedValue,
152
+ onSelectedValueChange: setSelectedValue,
153
+ registerItem,
154
+ unregisterItem
155
+ }), [
156
+ selectedValue,
157
+ registerItem,
158
+ unregisterItem
159
+ ]);
160
+ const inputContextValue = useMemo(() => ({
161
+ selectedValue,
162
+ onSelectedValueChange: setSelectedValue,
163
+ getItemValues,
164
+ triggerSelect
165
+ }), [
166
+ selectedValue,
167
+ getItemValues,
168
+ triggerSelect
169
+ ]);
170
+ return /* @__PURE__ */ React3.createElement(PickerInputContextProvider, inputContextValue, /* @__PURE__ */ React3.createElement(PickerItemContextProvider, itemContextValue, children));
171
+ };
172
+ PickerRoot.displayName = "Picker.Root";
173
+ var PickerInput = /* @__PURE__ */ forwardRef(({ value, onValueChange, onChange, onKeyDown, autoFocus, ...props }, forwardedRef) => {
174
+ const { hasIosKeyboard } = useThemeContext();
175
+ const { selectedValue, onSelectedValueChange, getItemValues, triggerSelect } = usePickerInputContext("Picker.Input");
176
+ const handleChange = useCallback((event) => {
177
+ onValueChange?.(event.target.value);
178
+ onChange?.(event);
179
+ }, [
180
+ onValueChange,
181
+ onChange
182
+ ]);
183
+ const handleKeyDown = useCallback((event) => {
184
+ onKeyDown?.(event);
185
+ if (event.defaultPrevented) {
186
+ return;
187
+ }
188
+ const values = getItemValues();
189
+ if (values.length === 0) {
190
+ if (event.key === "Escape") {
191
+ onValueChange?.("");
192
+ }
193
+ return;
194
+ }
195
+ const currentIndex = selectedValue !== void 0 ? values.indexOf(selectedValue) : -1;
196
+ switch (event.key) {
197
+ case "ArrowDown": {
198
+ event.preventDefault();
199
+ const nextIndex = currentIndex === -1 ? 0 : Math.min(currentIndex + 1, values.length - 1);
200
+ const nextValue = values[nextIndex];
201
+ if (nextValue !== void 0) {
202
+ onSelectedValueChange(nextValue);
203
+ }
204
+ break;
205
+ }
206
+ case "ArrowUp": {
207
+ event.preventDefault();
208
+ const prevIndex = currentIndex === -1 ? values.length - 1 : Math.max(currentIndex - 1, 0);
209
+ const prevValue = values[prevIndex];
210
+ if (prevValue !== void 0) {
211
+ onSelectedValueChange(prevValue);
212
+ }
213
+ break;
214
+ }
215
+ case "Enter": {
216
+ if (selectedValue !== void 0) {
217
+ event.preventDefault();
218
+ triggerSelect();
219
+ }
220
+ break;
221
+ }
222
+ case "Home": {
223
+ event.preventDefault();
224
+ const firstValue = values[0];
225
+ if (firstValue !== void 0) {
226
+ onSelectedValueChange(firstValue);
227
+ }
228
+ break;
229
+ }
230
+ case "End": {
231
+ event.preventDefault();
232
+ const lastValue = values[values.length - 1];
233
+ if (lastValue !== void 0) {
234
+ onSelectedValueChange(lastValue);
235
+ }
236
+ break;
237
+ }
238
+ case "Escape": {
239
+ event.preventDefault();
240
+ if (selectedValue !== void 0) {
241
+ onSelectedValueChange(void 0);
242
+ } else {
243
+ onValueChange?.("");
244
+ }
245
+ break;
246
+ }
247
+ }
248
+ }, [
249
+ selectedValue,
250
+ onSelectedValueChange,
251
+ getItemValues,
252
+ triggerSelect,
253
+ onValueChange,
254
+ onKeyDown
255
+ ]);
256
+ return /* @__PURE__ */ React3.createElement(Input.Root, null, /* @__PURE__ */ React3.createElement(Input.TextInput, {
257
+ ...props,
258
+ autoFocus: autoFocus && !hasIosKeyboard,
259
+ ...value !== void 0 && {
260
+ value
261
+ },
262
+ onChange: handleChange,
263
+ onKeyDown: handleKeyDown,
264
+ ref: forwardedRef
265
+ }));
266
+ });
267
+ PickerInput.displayName = "Picker.Input";
268
+ var PickerItem = /* @__PURE__ */ forwardRef(({ classNames, value, onSelect, disabled, asChild, children, ...props }, forwardedRef) => {
269
+ const { selectedValue, onSelectedValueChange, registerItem, unregisterItem } = usePickerItemContext("Picker.Item");
270
+ const internalRef = useRef(null);
271
+ const isSelected = selectedValue === value && !disabled;
272
+ useEffect(() => {
273
+ const element = internalRef.current;
274
+ if (element) {
275
+ registerItem(value, element, onSelect, disabled);
276
+ }
277
+ return () => unregisterItem(value);
278
+ }, [
279
+ value,
280
+ onSelect,
281
+ disabled,
282
+ registerItem,
283
+ unregisterItem
284
+ ]);
285
+ useEffect(() => {
286
+ if (isSelected && internalRef.current) {
287
+ internalRef.current.scrollIntoView({
288
+ block: "nearest",
289
+ behavior: "smooth"
290
+ });
291
+ }
292
+ }, [
293
+ isSelected
294
+ ]);
295
+ const handleClick = useCallback(() => {
296
+ if (disabled) {
297
+ return;
298
+ }
299
+ onSelectedValueChange(value);
300
+ onSelect?.();
301
+ }, [
302
+ disabled,
303
+ value,
304
+ onSelectedValueChange,
305
+ onSelect
306
+ ]);
307
+ const handleMouseDown = useCallback((event) => {
308
+ event.preventDefault();
309
+ }, []);
310
+ const Comp = asChild ? Slot : "div";
311
+ return /* @__PURE__ */ React3.createElement(Comp, {
312
+ ...props,
313
+ ref: (node) => {
314
+ internalRef.current = node;
315
+ if (typeof forwardedRef === "function") {
316
+ forwardedRef(node);
317
+ } else if (forwardedRef) {
318
+ forwardedRef.current = node;
319
+ }
320
+ },
321
+ role: "option",
322
+ "aria-selected": isSelected,
323
+ "aria-disabled": disabled,
324
+ "data-selected": isSelected,
325
+ "data-disabled": disabled,
326
+ "data-value": value,
327
+ // Browser focus stays on the input; highlight is via `aria-selected`.
328
+ tabIndex: -1,
329
+ className: mx3("dx-hover dx-selected px-[var(--gutter,0.75rem)] py-1 cursor-pointer select-none", disabled && "opacity-50 cursor-not-allowed", classNames),
330
+ onMouseDown: handleMouseDown,
331
+ onClick: handleClick
332
+ }, children);
333
+ });
334
+ PickerItem.displayName = "Picker.Item";
335
+ var Picker = {
336
+ Root: PickerRoot,
337
+ Input: PickerInput,
338
+ Item: PickerItem
339
+ };
340
+
341
+ // src/components/Combobox/Combobox.tsx
342
+ var COMBOBOX_NAME = "Combobox";
343
+ var COMBOBOX_CONTENT_NAME = "ComboboxContent";
344
+ var COMBOBOX_ITEM_NAME = "ComboboxItem";
345
+ var COMBOBOX_TRIGGER_NAME = "ComboboxTrigger";
346
+ var [ComboboxProvider, useComboboxContext] = createContext4(COMBOBOX_NAME, {});
347
+ var ComboboxRoot = ({ children, modal, modalId: modalIdProp, open: openProp, defaultOpen, onOpenChange: propsOnOpenChange, value: valueProp, defaultValue, onValueChange: propsOnValueChange, placeholder }) => {
348
+ const modalId = useId(COMBOBOX_NAME, modalIdProp);
349
+ const [open = false, onOpenChange] = useControllableState({
350
+ prop: openProp,
351
+ defaultProp: defaultOpen,
352
+ onChange: propsOnOpenChange
353
+ });
354
+ const [value = "", onValueChange] = useControllableState({
355
+ prop: valueProp,
356
+ defaultProp: defaultValue,
357
+ onChange: propsOnValueChange
358
+ });
359
+ return /* @__PURE__ */ React4.createElement(Popover.Root, {
360
+ open,
361
+ onOpenChange,
362
+ modal
363
+ }, /* @__PURE__ */ React4.createElement(ComboboxProvider, {
364
+ isCombobox: true,
365
+ modalId,
366
+ placeholder,
367
+ open,
368
+ onOpenChange,
369
+ value,
370
+ onValueChange
371
+ }, children));
372
+ };
373
+ var ComboboxContent = composable(({ children, ...props }, forwardedRef) => {
374
+ const { modalId } = useComboboxContext(COMBOBOX_CONTENT_NAME);
375
+ return /* @__PURE__ */ React4.createElement(Popover.Content, {
376
+ ...composableProps(props, {
377
+ id: modalId
378
+ }),
379
+ ref: forwardedRef
380
+ }, /* @__PURE__ */ React4.createElement(Popover.Viewport, {
381
+ classNames: "w-(--radix-popover-trigger-width)"
382
+ }, /* @__PURE__ */ React4.createElement(Picker.Root, null, children)));
383
+ });
384
+ ComboboxContent.displayName = COMBOBOX_CONTENT_NAME;
385
+ var ComboboxTrigger = /* @__PURE__ */ forwardRef2(({ children, onClick, ...props }, forwardedRef) => {
386
+ const { modalId, open, onOpenChange, placeholder, value } = useComboboxContext(COMBOBOX_TRIGGER_NAME);
387
+ const handleClick = useCallback2((event) => {
388
+ onClick?.(event);
389
+ onOpenChange?.(true);
390
+ }, [
391
+ onClick,
392
+ onOpenChange
393
+ ]);
394
+ return /* @__PURE__ */ React4.createElement(Popover.Trigger, {
395
+ asChild: true
396
+ }, /* @__PURE__ */ React4.createElement(Button, {
397
+ ...props,
398
+ role: "combobox",
399
+ "aria-expanded": open,
400
+ "aria-controls": modalId,
401
+ "aria-haspopup": "dialog",
402
+ onClick: handleClick,
403
+ ref: forwardedRef
404
+ }, children ?? /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement("span", {
405
+ className: mx4("font-normal text-start flex-1 min-w-0 truncate me-2", !value && "text-subdued")
406
+ }, value || placeholder), /* @__PURE__ */ React4.createElement(Icon2, {
407
+ icon: "ph--caret-down--bold",
408
+ size: 3
409
+ }))));
410
+ });
411
+ ComboboxTrigger.displayName = COMBOBOX_TRIGGER_NAME;
412
+ var ComboboxVirtualTrigger = Popover.VirtualTrigger;
413
+ var ComboboxInput = /* @__PURE__ */ forwardRef2(({ classNames, ...props }, forwardedRef) => {
414
+ return /* @__PURE__ */ React4.createElement(Picker.Input, {
415
+ ...props,
416
+ classNames: [
417
+ "m-form-chrome mb-0 w-[calc(100%-2*var(--spacing-form-chrome))]",
418
+ classNames
419
+ ],
420
+ ref: forwardedRef
421
+ });
422
+ });
423
+ ComboboxInput.displayName = "Combobox.Input";
424
+ var ComboboxList = /* @__PURE__ */ forwardRef2(({ classNames, children, ...props }, forwardedRef) => {
425
+ return /* @__PURE__ */ React4.createElement(ScrollArea.Root, {
426
+ ...composableProps(props, {
427
+ classNames: [
428
+ "py-form-chrome",
429
+ classNames
430
+ ]
431
+ }),
432
+ role: "listbox",
433
+ centered: true,
434
+ padding: true,
435
+ thin: true,
436
+ ref: forwardedRef
437
+ }, /* @__PURE__ */ React4.createElement(ScrollArea.Viewport, null, children));
438
+ });
439
+ ComboboxList.displayName = "Combobox.List";
440
+ var ComboboxItem = /* @__PURE__ */ forwardRef2(({ classNames, onSelect, value, label, icon, iconClassNames, checked, suffix, disabled, closeOnSelect = true, children }, forwardedRef) => {
441
+ const { onValueChange, onOpenChange } = useComboboxContext(COMBOBOX_ITEM_NAME);
442
+ const handleSelect = useCallback2(() => {
443
+ onSelect?.();
444
+ if (value !== void 0) {
445
+ onValueChange?.(value);
446
+ }
447
+ if (closeOnSelect) {
448
+ onOpenChange?.(false);
449
+ }
450
+ }, [
451
+ onSelect,
452
+ onValueChange,
453
+ onOpenChange,
454
+ value,
455
+ closeOnSelect
456
+ ]);
457
+ return /* @__PURE__ */ React4.createElement(Picker.Item, {
458
+ value,
459
+ disabled,
460
+ onSelect: handleSelect,
461
+ ref: forwardedRef,
462
+ classNames: [
463
+ // Full width inside the viewport (no horizontal margin).
464
+ // `px-3 py-1`, `cursor-pointer`, `select-none` and the
465
+ // `dx-hover` / `dx-selected` pairing come from `Picker.Item`'s
466
+ // defaults; we only add the row-shape (flex / icons + label)
467
+ // and the disabled overrides on top.
468
+ "flex w-full gap-2 items-center",
469
+ disabled && "hover:bg-transparent data-[selected=true]:bg-transparent",
470
+ classNames
471
+ ]
472
+ }, children ?? /* @__PURE__ */ React4.createElement(React4.Fragment, null, icon && /* @__PURE__ */ React4.createElement(Icon2, {
473
+ icon,
474
+ classNames: iconClassNames
475
+ }), /* @__PURE__ */ React4.createElement("span", {
476
+ className: "w-0 grow truncate"
477
+ }, label), suffix && /* @__PURE__ */ React4.createElement("span", {
478
+ className: "shrink-0 text-description"
479
+ }, suffix), checked && /* @__PURE__ */ React4.createElement(Icon2, {
480
+ icon: "ph--check--regular"
481
+ })));
482
+ });
483
+ ComboboxItem.displayName = COMBOBOX_ITEM_NAME;
484
+ var ComboboxArrow = Popover.Arrow;
485
+ var ComboboxEmpty = /* @__PURE__ */ forwardRef2(({ classNames, children }, forwardedRef) => {
486
+ return /* @__PURE__ */ React4.createElement("div", {
487
+ ref: forwardedRef,
488
+ role: "status",
489
+ className: mx4(classNames)
490
+ }, children);
491
+ });
492
+ ComboboxEmpty.displayName = "Combobox.Empty";
493
+ var ComboboxPortal = Popover.Portal;
494
+ var Combobox = {
495
+ Root: ComboboxRoot,
496
+ Portal: ComboboxPortal,
497
+ Content: ComboboxContent,
498
+ Trigger: ComboboxTrigger,
499
+ VirtualTrigger: ComboboxVirtualTrigger,
500
+ Input: ComboboxInput,
501
+ List: ComboboxList,
502
+ Item: ComboboxItem,
503
+ Arrow: ComboboxArrow,
504
+ Empty: ComboboxEmpty
505
+ };
506
+
507
+ // src/components/List/ListItem.tsx
508
+ import { attachClosestEdge, extractClosestEdge as extractClosestEdge2 } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
95
509
  import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
96
510
  import { draggable, dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
97
511
  import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview";
98
- import { attachClosestEdge, extractClosestEdge as extractClosestEdge2 } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
99
- import { createContext as createContext4 } from "@radix-ui/react-context";
100
- import React4, { forwardRef, useEffect as useEffect2, useRef, useState as useState2 } from "react";
512
+ import { createContext as createContext6 } from "@radix-ui/react-context";
513
+ import { Slot as Slot2 } from "@radix-ui/react-slot";
514
+ import React6, { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
101
515
  import { createPortal } from "react-dom";
102
516
  import { invariant } from "@dxos/invariant";
103
- import { Icon as Icon2, ListItem as NaturalListItem } from "@dxos/react-ui";
104
- import { mx as mx3 } from "@dxos/react-ui-theme";
517
+ import { IconButton, ListItem as NaturalListItem, useTranslation } from "@dxos/react-ui";
518
+ import { mx as mx5, osTranslations } from "@dxos/ui-theme";
105
519
 
106
- // packages/ui/react-ui-list/src/components/List/ListRoot.tsx
107
- import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
108
- import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
520
+ // src/components/List/ListRoot.tsx
109
521
  import { extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
110
522
  import { getReorderDestinationIndex } from "@atlaskit/pragmatic-drag-and-drop-hitbox/util/get-reorder-destination-index";
111
- import { createContext as createContext3 } from "@radix-ui/react-context";
112
- import React3, { useCallback, useEffect, useState } from "react";
523
+ import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
524
+ import { createContext as createContext5 } from "@radix-ui/react-context";
525
+ import React5, { useCallback as useCallback3, useEffect as useEffect2, useState as useState2 } from "react";
113
526
  var LIST_NAME = "List";
114
- var [ListProvider, useListContext] = createContext3(LIST_NAME);
527
+ var [ListProvider, useListContext] = createContext5(LIST_NAME);
115
528
  var defaultGetId2 = (item) => item?.id;
116
529
  var ListRoot = ({ children, items, isItem, getId = defaultGetId2, onMove, ...props }) => {
117
- var _effect = _useSignals3();
118
- try {
119
- const isEqual = useCallback((a, b) => {
120
- const idA = getId?.(a);
121
- const idB = getId?.(b);
122
- if (idA !== void 0 && idB !== void 0) {
123
- return idA === idB;
124
- } else {
125
- return a === b;
126
- }
127
- }, [
128
- getId
129
- ]);
130
- const [state, setState] = useState(idle);
131
- useEffect(() => {
132
- if (!items) {
133
- return;
134
- }
135
- return monitorForElements({
136
- canMonitor: ({ source }) => isItem?.(source.data) ?? false,
137
- onDrop: ({ location, source }) => {
138
- const target = location.current.dropTargets[0];
139
- if (!target) {
140
- return;
141
- }
142
- const sourceData = source.data;
143
- const targetData = target.data;
144
- if (!isItem?.(sourceData) || !isItem?.(targetData)) {
145
- return;
146
- }
147
- const sourceIdx = items.findIndex((item) => isEqual(item, sourceData));
148
- const targetIdx = items.findIndex((item) => isEqual(item, targetData));
149
- if (targetIdx < 0 || sourceIdx < 0) {
150
- return;
151
- }
152
- const closestEdgeOfTarget = extractClosestEdge(targetData);
153
- const destinationIndex = getReorderDestinationIndex({
154
- closestEdgeOfTarget,
155
- startIndex: sourceIdx,
156
- indexOfTarget: targetIdx,
157
- axis: "vertical"
158
- });
159
- onMove?.(sourceIdx, destinationIndex);
530
+ const isEqual = useCallback3((a, b) => {
531
+ const idA = getId?.(a);
532
+ const idB = getId?.(b);
533
+ if (idA !== void 0 && idB !== void 0) {
534
+ return idA === idB;
535
+ } else {
536
+ return a === b;
537
+ }
538
+ }, [
539
+ getId
540
+ ]);
541
+ const [state, setState] = useState2(idle);
542
+ useEffect2(() => {
543
+ if (!items) {
544
+ return;
545
+ }
546
+ return monitorForElements({
547
+ canMonitor: ({ source }) => isItem?.(source.data) ?? false,
548
+ onDrop: ({ location, source }) => {
549
+ const target = location.current.dropTargets[0];
550
+ if (!target) {
551
+ return;
160
552
  }
161
- });
162
- }, [
163
- items,
164
- isEqual,
165
- onMove
166
- ]);
167
- return /* @__PURE__ */ React3.createElement(ListProvider, {
168
- state,
169
- setState,
170
- isItem,
171
- ...props
172
- }, children?.({
173
- state,
174
- items: items ?? []
175
- }));
176
- } finally {
177
- _effect.f();
178
- }
553
+ const sourceData = source.data;
554
+ const targetData = target.data;
555
+ if (!isItem?.(sourceData) || !isItem?.(targetData)) {
556
+ return;
557
+ }
558
+ const sourceIdx = items.findIndex((item) => isEqual(item, sourceData));
559
+ const targetIdx = items.findIndex((item) => isEqual(item, targetData));
560
+ if (targetIdx < 0 || sourceIdx < 0) {
561
+ return;
562
+ }
563
+ const closestEdgeOfTarget = extractClosestEdge(targetData);
564
+ const destinationIndex = getReorderDestinationIndex({
565
+ closestEdgeOfTarget,
566
+ startIndex: sourceIdx,
567
+ indexOfTarget: targetIdx,
568
+ axis: "vertical"
569
+ });
570
+ onMove?.(sourceIdx, destinationIndex);
571
+ }
572
+ });
573
+ }, [
574
+ items,
575
+ isEqual,
576
+ onMove
577
+ ]);
578
+ return /* @__PURE__ */ React5.createElement(ListProvider, {
579
+ state,
580
+ setState,
581
+ isItem,
582
+ ...props
583
+ }, children?.({
584
+ state,
585
+ items: items ?? []
586
+ }));
179
587
  };
180
588
 
181
- // packages/ui/react-ui-list/src/components/List/ListItem.tsx
182
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-list/src/components/List/ListItem.tsx";
589
+ // src/components/List/ListItem.tsx
590
+ var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-list/src/components/List/ListItem.tsx";
183
591
  var idle = {
184
592
  type: "idle"
185
593
  };
@@ -188,205 +596,170 @@ var stateStyles = {
188
596
  };
189
597
  var defaultContext = {};
190
598
  var LIST_ITEM_NAME = "ListItem";
191
- var [ListItemProvider, useListItemContext] = createContext4(LIST_ITEM_NAME, defaultContext);
192
- var ListItem = ({ children, classNames, item, ...props }) => {
193
- var _effect = _useSignals4();
194
- try {
195
- const { isItem, readonly, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
196
- const ref = useRef(null);
197
- const dragHandleRef = useRef(null);
198
- const [state, setState] = useState2(idle);
199
- useEffect2(() => {
200
- const element = ref.current;
201
- invariant(element, void 0, {
202
- F: __dxlog_file,
203
- L: 91,
204
- S: void 0,
205
- A: [
206
- "element",
207
- ""
208
- ]
209
- });
210
- return combine(
211
- //
212
- // https://atlassian.design/components/pragmatic-drag-and-drop/core-package/adapters/element/about#draggable
213
- //
214
- draggable({
215
- element,
216
- dragHandle: dragHandleRef.current,
217
- canDrag: () => !readonly,
218
- getInitialData: () => item,
219
- onGenerateDragPreview: dragPreview ? ({ nativeSetDragImage, source }) => {
220
- const rect = source.element.getBoundingClientRect();
221
- setCustomNativeDragPreview({
222
- nativeSetDragImage,
223
- getOffset: ({ container }) => {
224
- const { height } = container.getBoundingClientRect();
225
- return {
226
- x: 20,
227
- y: height / 2
228
- };
229
- },
230
- render: ({ container }) => {
231
- container.style.width = rect.width + "px";
232
- setState({
233
- type: "preview",
234
- container
235
- });
236
- setRootState({
237
- type: "preview",
238
- container,
239
- item
240
- });
241
- return () => {
242
- };
243
- }
244
- });
245
- } : void 0,
246
- onDragStart: () => {
247
- setState({
248
- type: "is-dragging"
249
- });
250
- setRootState({
251
- type: "is-dragging",
252
- item
253
- });
254
- },
255
- onDrop: () => {
256
- setState(idle);
257
- setRootState(idle);
258
- }
259
- }),
260
- //
261
- // https://atlassian.design/components/pragmatic-drag-and-drop/core-package/adapters/element/about#drop-target-for-elements
262
- //
263
- dropTargetForElements({
264
- element,
265
- canDrop: ({ source }) => {
266
- return (source.element !== element && isItem?.(source.data)) ?? false;
267
- },
268
- getData: ({ input }) => {
269
- return attachClosestEdge(item, {
270
- element,
271
- input,
272
- allowedEdges: [
273
- "top",
274
- "bottom"
275
- ]
276
- });
277
- },
278
- getIsSticky: () => true,
279
- onDragEnter: ({ self }) => {
280
- const closestEdge = extractClosestEdge2(self.data);
281
- setState({
282
- type: "is-dragging-over",
283
- closestEdge
284
- });
285
- },
286
- onDrag: ({ self }) => {
287
- const closestEdge = extractClosestEdge2(self.data);
288
- setState((current) => {
289
- if (current.type === "is-dragging-over" && current.closestEdge === closestEdge) {
290
- return current;
291
- }
599
+ var [ListItemProvider, useListItemContext] = createContext6(LIST_ITEM_NAME, defaultContext);
600
+ var ListItem = ({ children, classNames, item, asChild, selected, ...props }) => {
601
+ const Comp = asChild ? Slot2 : "div";
602
+ const { isItem, readonly, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
603
+ const rootRef = useRef2(null);
604
+ const dragHandleRef = useRef2(null);
605
+ const [state, setState] = useState3(idle);
606
+ useEffect3(() => {
607
+ const element = rootRef.current;
608
+ invariant(element, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 37, S: void 0, A: ["element", ""] });
609
+ return combine(
610
+ //
611
+ // https://atlassian.design/components/pragmatic-drag-and-drop/core-package/adapters/element/about#draggable
612
+ //
613
+ draggable({
614
+ element,
615
+ dragHandle: dragHandleRef.current,
616
+ canDrag: () => !readonly,
617
+ getInitialData: () => item,
618
+ onGenerateDragPreview: dragPreview ? ({ nativeSetDragImage, source }) => {
619
+ const rect = source.element.getBoundingClientRect();
620
+ setCustomNativeDragPreview({
621
+ nativeSetDragImage,
622
+ getOffset: ({ container }) => {
623
+ const { height } = container.getBoundingClientRect();
292
624
  return {
293
- type: "is-dragging-over",
294
- closestEdge
625
+ x: 20,
626
+ y: height / 2
295
627
  };
296
- });
297
- },
298
- onDragLeave: () => {
299
- setState(idle);
300
- },
301
- onDrop: () => {
302
- setState(idle);
303
- }
304
- })
305
- );
306
- }, [
307
- item
308
- ]);
309
- return /* @__PURE__ */ React4.createElement(ListItemProvider, {
310
- item,
311
- dragHandleRef
312
- }, /* @__PURE__ */ React4.createElement("div", {
313
- role: "none",
314
- className: "relative"
315
- }, /* @__PURE__ */ React4.createElement("div", {
316
- ref,
317
- role: "listitem",
318
- className: mx3("flex overflow-hidden", classNames, stateStyles[state.type]),
319
- ...props
320
- }, children), state.type === "is-dragging-over" && state.closestEdge && /* @__PURE__ */ React4.createElement(NaturalListItem.DropIndicator, {
321
- edge: state.closestEdge
322
- })));
323
- } finally {
324
- _effect.f();
325
- }
628
+ },
629
+ render: ({ container }) => {
630
+ container.style.width = rect.width + "px";
631
+ setState({
632
+ type: "preview",
633
+ container
634
+ });
635
+ setRootState({
636
+ type: "preview",
637
+ container,
638
+ item
639
+ });
640
+ return () => {
641
+ };
642
+ }
643
+ });
644
+ } : void 0,
645
+ onDragStart: () => {
646
+ setState({
647
+ type: "is-dragging"
648
+ });
649
+ setRootState({
650
+ type: "is-dragging",
651
+ item
652
+ });
653
+ },
654
+ onDrop: () => {
655
+ setState(idle);
656
+ setRootState(idle);
657
+ }
658
+ }),
659
+ //
660
+ // https://atlassian.design/components/pragmatic-drag-and-drop/core-package/adapters/element/about#drop-target-for-elements
661
+ //
662
+ dropTargetForElements({
663
+ element,
664
+ canDrop: ({ source }) => {
665
+ return (source.element !== element && isItem?.(source.data)) ?? false;
666
+ },
667
+ getData: ({ input }) => {
668
+ return attachClosestEdge(item, {
669
+ element,
670
+ input,
671
+ allowedEdges: [
672
+ "top",
673
+ "bottom"
674
+ ]
675
+ });
676
+ },
677
+ getIsSticky: () => true,
678
+ onDragEnter: ({ self }) => {
679
+ const closestEdge = extractClosestEdge2(self.data);
680
+ setState({
681
+ type: "is-dragging-over",
682
+ closestEdge
683
+ });
684
+ },
685
+ onDragLeave: () => {
686
+ setState(idle);
687
+ },
688
+ onDrag: ({ self }) => {
689
+ const closestEdge = extractClosestEdge2(self.data);
690
+ setState((current) => {
691
+ if (current.type === "is-dragging-over" && current.closestEdge === closestEdge) {
692
+ return current;
693
+ }
694
+ return {
695
+ type: "is-dragging-over",
696
+ closestEdge
697
+ };
698
+ });
699
+ },
700
+ onDrop: () => {
701
+ setState(idle);
702
+ }
703
+ })
704
+ );
705
+ }, [
706
+ item
707
+ ]);
708
+ return /* @__PURE__ */ React6.createElement(ListItemProvider, {
709
+ item,
710
+ dragHandleRef
711
+ }, /* @__PURE__ */ React6.createElement(Comp, {
712
+ ...props,
713
+ role: "listitem",
714
+ "aria-selected": selected,
715
+ className: mx5("relative p-1 dx-selected dx-hover", classNames, stateStyles[state.type]),
716
+ ref: rootRef
717
+ }, children), state.type === "is-dragging-over" && state.closestEdge && /* @__PURE__ */ React6.createElement(NaturalListItem.DropIndicator, {
718
+ edge: state.closestEdge
719
+ }));
326
720
  };
327
- var IconButton = /* @__PURE__ */ forwardRef(({ classNames, icon, ...props }, forwardedRef) => {
328
- var _effect = _useSignals4();
329
- try {
330
- return /* @__PURE__ */ React4.createElement("button", {
331
- ref: forwardedRef,
332
- className: mx3("flex items-center justify-center", classNames),
333
- ...props
334
- }, /* @__PURE__ */ React4.createElement(Icon2, {
335
- icon,
336
- classNames: "cursor-pointer",
337
- size: 4
338
- }));
339
- } finally {
340
- _effect.f();
341
- }
342
- });
343
- var ListItemDeleteButton = ({ autoHide = true, classNames, disabled, icon = "ph--x--regular", ...props }) => {
344
- var _effect = _useSignals4();
345
- try {
346
- const { state } = useListContext("DELETE_BUTTON");
347
- const isDisabled = state.type !== "idle" || disabled;
348
- return /* @__PURE__ */ React4.createElement(IconButton, {
349
- icon,
350
- disabled: isDisabled,
351
- classNames: [
352
- classNames,
353
- autoHide && disabled && "hidden"
354
- ],
355
- ...props
356
- });
357
- } finally {
358
- _effect.f();
359
- }
721
+ var ListItemIconButton = ({ autoHide = true, iconOnly = true, variant = "ghost", classNames, disabled, ...props }) => {
722
+ const { state } = useListContext("ITEM_BUTTON");
723
+ const isDisabled = state.type !== "idle" || disabled;
724
+ return /* @__PURE__ */ React6.createElement(IconButton, {
725
+ ...props,
726
+ disabled: isDisabled,
727
+ iconOnly,
728
+ variant,
729
+ classNames: [
730
+ classNames,
731
+ autoHide && disabled && "hidden"
732
+ ]
733
+ });
360
734
  };
361
- var ListItemButton = ({ autoHide = true, classNames, disabled, ...props }) => {
362
- var _effect = _useSignals4();
363
- try {
364
- const { state } = useListContext("ITEM_BUTTON");
365
- const isDisabled = state.type !== "idle" || disabled;
366
- return /* @__PURE__ */ React4.createElement(IconButton, {
367
- disabled: isDisabled,
368
- classNames: [
369
- classNames,
370
- autoHide && disabled && "hidden"
371
- ],
372
- ...props
373
- });
374
- } finally {
375
- _effect.f();
376
- }
735
+ var ListItemDeleteButton = ({ autoHide = true, classNames, disabled, icon = "ph--x--regular", label, ...props }) => {
736
+ const { state } = useListContext("DELETE_BUTTON");
737
+ const isDisabled = state.type !== "idle" || disabled;
738
+ const { t } = useTranslation(osTranslations);
739
+ return /* @__PURE__ */ React6.createElement(IconButton, {
740
+ ...props,
741
+ variant: "ghost",
742
+ disabled: isDisabled,
743
+ icon,
744
+ iconOnly: true,
745
+ label: label ?? t("delete.label"),
746
+ classNames: [
747
+ classNames,
748
+ autoHide && disabled && "hidden"
749
+ ]
750
+ });
377
751
  };
378
752
  var ListItemDragHandle = ({ disabled }) => {
379
- var _effect = _useSignals4();
380
- try {
381
- const { dragHandleRef } = useListItemContext("DRAG_HANDLE");
382
- return /* @__PURE__ */ React4.createElement(IconButton, {
383
- ref: dragHandleRef,
384
- icon: "ph--dots-six-vertical--regular",
385
- disabled
386
- });
387
- } finally {
388
- _effect.f();
389
- }
753
+ const { dragHandleRef } = useListItemContext("DRAG_HANDLE");
754
+ const { t } = useTranslation(osTranslations);
755
+ return /* @__PURE__ */ React6.createElement(IconButton, {
756
+ variant: "ghost",
757
+ disabled,
758
+ icon: "ph--dots-six-vertical--regular",
759
+ iconOnly: true,
760
+ label: t("drag-handle.label"),
761
+ ref: dragHandleRef
762
+ });
390
763
  };
391
764
  var ListItemDragPreview = ({ children }) => {
392
765
  const { state } = useListContext("DRAG_PREVIEW");
@@ -394,153 +767,362 @@ var ListItemDragPreview = ({ children }) => {
394
767
  item: state.item
395
768
  }), state.container) : null;
396
769
  };
397
- var ListItemWrapper = ({ classNames, children }) => {
398
- var _effect = _useSignals4();
399
- try {
400
- return /* @__PURE__ */ React4.createElement("div", {
401
- className: mx3("flex is-full gap-2", classNames)
402
- }, children);
403
- } finally {
404
- _effect.f();
405
- }
406
- };
407
- var ListItemTitle = ({ classNames, children, ...props }) => {
408
- var _effect = _useSignals4();
409
- try {
410
- return /* @__PURE__ */ React4.createElement("div", {
411
- className: mx3("flex grow items-center truncate", classNames),
412
- ...props
413
- }, children);
414
- } finally {
415
- _effect.f();
416
- }
417
- };
770
+ var ListItemWrapper = ({ classNames, children }) => /* @__PURE__ */ React6.createElement("div", {
771
+ role: "none",
772
+ className: mx5("flex w-full gap-2", classNames)
773
+ }, children);
774
+ var ListItemTitle = ({ classNames, children, ...props }) => /* @__PURE__ */ React6.createElement("div", {
775
+ role: "none",
776
+ className: mx5("flex grow items-center truncate", classNames),
777
+ ...props
778
+ }, children);
418
779
 
419
- // packages/ui/react-ui-list/src/components/List/List.tsx
780
+ // src/components/List/List.tsx
420
781
  var List = {
421
782
  Root: ListRoot,
422
783
  Item: ListItem,
423
784
  ItemDragPreview: ListItemDragPreview,
424
785
  ItemWrapper: ListItemWrapper,
425
786
  ItemDragHandle: ListItemDragHandle,
787
+ ItemIconButton: ListItemIconButton,
426
788
  ItemDeleteButton: ListItemDeleteButton,
427
- ItemButton: ListItemButton,
428
- ItemTitle: ListItemTitle,
429
- IconButton
789
+ ItemTitle: ListItemTitle
790
+ };
791
+
792
+ // src/components/Listbox/Listbox.tsx
793
+ import { createContextScope as createContextScope2 } from "@radix-ui/react-context";
794
+ import React8, { forwardRef as forwardRef3 } from "react";
795
+ import { Icon as Icon3 } from "@dxos/react-ui";
796
+ import { mx as mx6 } from "@dxos/ui-theme";
797
+
798
+ // src/components/RowList/RowList.tsx
799
+ import { useArrowNavigationGroup } from "@fluentui/react-tabster";
800
+ import { createContextScope } from "@radix-ui/react-context";
801
+ import { useControllableState as useControllableState2 } from "@radix-ui/react-use-controllable-state";
802
+ import React7, { useCallback as useCallback4 } from "react";
803
+ import { List as List2, ListItem as ListItem2 } from "@dxos/react-list";
804
+ import { ScrollArea as ScrollArea2 } from "@dxos/react-ui";
805
+ import { composable as composable2, composableProps as composableProps2 } from "@dxos/ui-theme";
806
+ var ROW_LIST_NAME = "RowList";
807
+ var ROW_LIST_ROOT_NAME = "RowList.Root";
808
+ var ROW_LIST_VIEWPORT_NAME = "RowList.Viewport";
809
+ var ROW_LIST_CONTENT_NAME = "RowList.Content";
810
+ var ROW_NAME = "List.Row";
811
+ var [createRowListContext, createRowListScope] = createContextScope(ROW_LIST_NAME, []);
812
+ var [RowListProvider, useRowListContext] = createRowListContext(ROW_LIST_NAME);
813
+ var Root2 = ({ selectedId, defaultSelectedId, onSelectChange, children }) => {
814
+ const [resolved, setResolved] = useControllableState2({
815
+ prop: selectedId,
816
+ defaultProp: defaultSelectedId,
817
+ onChange: (next) => {
818
+ if (next !== void 0) {
819
+ onSelectChange?.(next);
820
+ }
821
+ }
822
+ });
823
+ const setSelected = useCallback4((id) => setResolved(id), [
824
+ setResolved
825
+ ]);
826
+ return /* @__PURE__ */ React7.createElement(RowListProvider, {
827
+ scope: void 0,
828
+ selectedId: resolved,
829
+ setSelected
830
+ }, children);
831
+ };
832
+ Root2.displayName = ROW_LIST_ROOT_NAME;
833
+ var Viewport = composable2((props, forwardedRef) => {
834
+ const { thin, padding, centered, children, ...rest } = props;
835
+ const composed = composableProps2(rest, {
836
+ classNames: "dx-container"
837
+ });
838
+ return /* @__PURE__ */ React7.createElement(ScrollArea2.Root, {
839
+ orientation: "vertical",
840
+ thin,
841
+ padding,
842
+ centered,
843
+ ...composed,
844
+ ref: forwardedRef
845
+ }, /* @__PURE__ */ React7.createElement(ScrollArea2.Viewport, null, children));
846
+ });
847
+ Viewport.displayName = ROW_LIST_VIEWPORT_NAME;
848
+ var firstEnabledOption = (ul) => {
849
+ if (!ul) {
850
+ return null;
851
+ }
852
+ return ul.querySelector('[role="option"]:not([aria-disabled="true"])');
853
+ };
854
+ var Content2 = composable2((props, forwardedRef) => {
855
+ useRowListContext(ROW_LIST_CONTENT_NAME, void 0);
856
+ const arrowGroup = useArrowNavigationGroup({
857
+ axis: "vertical",
858
+ memorizeCurrent: true
859
+ });
860
+ const { children, ...rest } = props;
861
+ const handleFocus = useCallback4((event) => {
862
+ if (event.target !== event.currentTarget) {
863
+ return;
864
+ }
865
+ const ul = event.currentTarget;
866
+ const selected = ul.querySelector('[role="option"][aria-selected="true"]:not([aria-disabled="true"])');
867
+ const target = selected ?? firstEnabledOption(ul);
868
+ target?.focus();
869
+ }, []);
870
+ const composed = composableProps2(rest, {
871
+ classNames: "flex flex-col"
872
+ });
873
+ return /* @__PURE__ */ React7.createElement(List2, {
874
+ variant: "unordered",
875
+ ...composed,
876
+ ...arrowGroup,
877
+ role: "listbox",
878
+ onFocus: handleFocus,
879
+ ref: forwardedRef
880
+ }, children);
881
+ });
882
+ Content2.displayName = ROW_LIST_CONTENT_NAME;
883
+ var ROW_BASE = "dx-hover dx-selected px-3 py-2 cursor-pointer outline-none border-b border-separator last:border-b-0";
884
+ var Row = composable2((props, forwardedRef) => {
885
+ const { id, disabled, onClick, onFocus, children, ...rest } = props;
886
+ const { selectedId, setSelected } = useRowListContext(ROW_NAME, void 0);
887
+ const isSelected = selectedId === id;
888
+ const handleClick = useCallback4((event) => {
889
+ if (disabled) {
890
+ return;
891
+ }
892
+ setSelected(id);
893
+ onClick?.(event);
894
+ }, [
895
+ disabled,
896
+ id,
897
+ setSelected,
898
+ onClick
899
+ ]);
900
+ const handleFocus = useCallback4((event) => {
901
+ if (!disabled && selectedId !== id) {
902
+ setSelected(id);
903
+ }
904
+ onFocus?.(event);
905
+ }, [
906
+ disabled,
907
+ selectedId,
908
+ id,
909
+ setSelected,
910
+ onFocus
911
+ ]);
912
+ const composed = composableProps2(rest, {
913
+ classNames: [
914
+ ROW_BASE,
915
+ disabled && "opacity-50 cursor-not-allowed"
916
+ ]
917
+ });
918
+ return /* @__PURE__ */ React7.createElement(ListItem2, {
919
+ ...composed,
920
+ role: "option",
921
+ tabIndex: 0,
922
+ "aria-selected": isSelected,
923
+ "aria-disabled": disabled || void 0,
924
+ onClick: handleClick,
925
+ onFocus: handleFocus,
926
+ ref: forwardedRef
927
+ }, children);
928
+ });
929
+ Row.displayName = ROW_NAME;
930
+ var useRowListSelection = (id) => {
931
+ const { selectedId } = useRowListContext("useRowListSelection", void 0);
932
+ return selectedId === id;
933
+ };
934
+ var RowList = {
935
+ Root: Root2,
936
+ Viewport,
937
+ Content: Content2
430
938
  };
431
939
 
432
- // packages/ui/react-ui-list/src/components/Tree/Tree.tsx
433
- import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
434
- import React8, { useMemo as useMemo2 } from "react";
940
+ // src/components/Listbox/Listbox.tsx
941
+ var commandItem = "flex items-center overflow-hidden";
942
+ var LISTBOX_NAME = "Listbox";
943
+ var LISTBOX_OPTION_NAME = "ListboxOption";
944
+ var LISTBOX_OPTION_LABEL_NAME = "ListboxOptionLabel";
945
+ var LISTBOX_OPTION_INDICATOR_NAME = "ListboxOptionIndicator";
946
+ var [createListboxContext, createListboxScope] = createContextScope2(LISTBOX_NAME, [
947
+ createRowListScope
948
+ ]);
949
+ var [createListboxOptionContext, createListboxOptionScope] = createContextScope2(LISTBOX_OPTION_NAME, [
950
+ createListboxScope
951
+ ]);
952
+ var [ListboxOptionProvider, useListboxOptionContext] = createListboxOptionContext(LISTBOX_OPTION_NAME);
953
+ var ListboxRoot = /* @__PURE__ */ forwardRef3((props, forwardedRef) => {
954
+ const { __listboxScope: _scope, children, classNames, value, defaultValue, onValueChange, autoFocus: _autoFocus, ...rootProps } = props;
955
+ return /* @__PURE__ */ React8.createElement(RowList.Root, {
956
+ selectedId: value,
957
+ defaultSelectedId: defaultValue,
958
+ onSelectChange: onValueChange
959
+ }, /* @__PURE__ */ React8.createElement(RowList.Content, {
960
+ ...rootProps,
961
+ classNames: mx6("w-full", classNames),
962
+ ref: forwardedRef
963
+ }, children));
964
+ });
965
+ ListboxRoot.displayName = LISTBOX_NAME;
966
+ var ListboxOption = /* @__PURE__ */ forwardRef3((props, forwardedRef) => {
967
+ const { __listboxScope, children, classNames, value, ...rootProps } = props;
968
+ return /* @__PURE__ */ React8.createElement(Row, {
969
+ id: value,
970
+ ...rootProps,
971
+ classNames: mx6("dx-focus-ring rounded-xs", commandItem, classNames),
972
+ ref: forwardedRef
973
+ }, /* @__PURE__ */ React8.createElement(ListboxOptionProviderHost, {
974
+ value
975
+ }, children));
976
+ });
977
+ ListboxOption.displayName = LISTBOX_OPTION_NAME;
978
+ var ListboxOptionProviderHost = ({ value, children }) => {
979
+ const isSelected = useRowListSelection(value);
980
+ return /* @__PURE__ */ React8.createElement(ListboxOptionProvider, {
981
+ scope: void 0,
982
+ value,
983
+ isSelected
984
+ }, children);
985
+ };
986
+ var ListboxOptionLabel = /* @__PURE__ */ forwardRef3(({ children, classNames, ...rootProps }, forwardedRef) => {
987
+ return /* @__PURE__ */ React8.createElement("span", {
988
+ ...rootProps,
989
+ className: mx6("grow truncate", classNames),
990
+ ref: forwardedRef
991
+ }, children);
992
+ });
993
+ ListboxOptionLabel.displayName = LISTBOX_OPTION_LABEL_NAME;
994
+ var ListboxOptionIndicator = /* @__PURE__ */ forwardRef3((props, forwardedRef) => {
995
+ const { __listboxOptionScope, classNames, ...rootProps } = props;
996
+ const { isSelected } = useListboxOptionContext(LISTBOX_OPTION_INDICATOR_NAME, __listboxOptionScope);
997
+ return /* @__PURE__ */ React8.createElement(Icon3, {
998
+ icon: "ph--check--regular",
999
+ ...rootProps,
1000
+ classNames: mx6(!isSelected && "invisible", classNames),
1001
+ ref: forwardedRef
1002
+ });
1003
+ });
1004
+ ListboxOptionIndicator.displayName = LISTBOX_OPTION_INDICATOR_NAME;
1005
+ var Listbox = {
1006
+ Root: ListboxRoot,
1007
+ Option: ListboxOption,
1008
+ OptionLabel: ListboxOptionLabel,
1009
+ OptionIndicator: ListboxOptionIndicator
1010
+ };
1011
+
1012
+ // src/components/Tree/Tree.tsx
1013
+ import { useAtomValue as useAtomValue2 } from "@effect-atom/atom-react";
1014
+ import React12, { useMemo as useMemo3 } from "react";
435
1015
  import { Treegrid as Treegrid2 } from "@dxos/react-ui";
436
1016
 
437
- // packages/ui/react-ui-list/src/components/Tree/TreeContext.tsx
438
- import { createContext as createContext5, useContext } from "react";
1017
+ // src/components/Tree/TreeContext.tsx
1018
+ import { createContext as createContext7, useContext } from "react";
439
1019
  import { raise } from "@dxos/debug";
440
- var TreeContext = /* @__PURE__ */ createContext5(null);
1020
+ var TreeContext = /* @__PURE__ */ createContext7(null);
441
1021
  var TreeProvider = TreeContext.Provider;
442
1022
  var useTree = () => useContext(TreeContext) ?? raise(new Error("TreeContext not found"));
443
1023
 
444
- // packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx
445
- import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
1024
+ // src/components/Tree/TreeItem.tsx
1025
+ import { attachInstruction, extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item";
446
1026
  import { combine as combine2 } from "@atlaskit/pragmatic-drag-and-drop/combine";
447
1027
  import { draggable as draggable2, dropTargetForElements as dropTargetForElements2 } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
448
- import { attachInstruction, extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item";
449
- import { Schema } from "effect";
450
- import React7, { memo as memo3, useCallback as useCallback3, useEffect as useEffect3, useMemo, useRef as useRef2, useState as useState3 } from "react";
1028
+ import { useAtomValue } from "@effect-atom/atom-react";
1029
+ import * as Schema from "effect/Schema";
1030
+ import React11, { memo as memo3, useCallback as useCallback6, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef3, useState as useState4 } from "react";
451
1031
  import { invariant as invariant2 } from "@dxos/invariant";
452
- import { Treegrid, TreeItem as NaturalTreeItem } from "@dxos/react-ui";
453
- import { ghostHover, hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, mx as mx6 } from "@dxos/react-ui-theme";
1032
+ import { TreeItem as NaturalTreeItem, Treegrid, TREEGRID_PARENT_OF_SEPARATOR } from "@dxos/react-ui";
1033
+ import { ghostFocusWithin, ghostHover, hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, mx as mx7 } from "@dxos/ui-theme";
454
1034
 
455
- // packages/ui/react-ui-list/src/components/Tree/TreeItemHeading.tsx
456
- import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
457
- import React5, { forwardRef as forwardRef2, memo, useCallback as useCallback2 } from "react";
458
- import { Button, Icon as Icon3, toLocalizedString, useTranslation } from "@dxos/react-ui";
1035
+ // src/components/Tree/helpers.ts
1036
+ var DEFAULT_INDENTATION = 8;
1037
+ var paddingIndentation = (level, indentation = DEFAULT_INDENTATION) => ({
1038
+ paddingInlineStart: `${(level - 1) * indentation}px`
1039
+ });
1040
+
1041
+ // src/components/Tree/TreeItemHeading.tsx
1042
+ import React9, { forwardRef as forwardRef4, memo, useCallback as useCallback5 } from "react";
1043
+ import { Button as Button2, Icon as Icon4, toLocalizedString, useTranslation as useTranslation2 } from "@dxos/react-ui";
459
1044
  import { TextTooltip } from "@dxos/react-ui-text-tooltip";
460
- import { mx as mx4 } from "@dxos/react-ui-theme";
461
- var TreeItemHeading = /* @__PURE__ */ memo(/* @__PURE__ */ forwardRef2(({ label, icon, className, disabled, current, onSelect }, forwardedRef) => {
462
- var _effect = _useSignals5();
463
- try {
464
- const { t } = useTranslation();
465
- const handleSelect = useCallback2((event) => {
1045
+ import { getStyles } from "@dxos/ui-theme";
1046
+ var TreeItemHeading = /* @__PURE__ */ memo(/* @__PURE__ */ forwardRef4(({ label, className, icon, iconHue, disabled, current, onSelect }, forwardedRef) => {
1047
+ const { t } = useTranslation2();
1048
+ const styles = iconHue ? getStyles(iconHue) : void 0;
1049
+ const handleSelect = useCallback5((event) => {
1050
+ onSelect?.(event.altKey);
1051
+ }, [
1052
+ onSelect
1053
+ ]);
1054
+ const handleButtonKeydown = useCallback5((event) => {
1055
+ if (event.key === " " || event.key === "Enter") {
1056
+ event.preventDefault();
1057
+ event.stopPropagation();
466
1058
  onSelect?.(event.altKey);
467
- }, [
468
- onSelect
469
- ]);
470
- const handleButtonKeydown = useCallback2((event) => {
471
- if (event.key === " " || event.key === "Enter") {
472
- event.preventDefault();
473
- event.stopPropagation();
474
- onSelect?.(event.altKey);
475
- }
476
- }, [
477
- onSelect
478
- ]);
479
- return /* @__PURE__ */ React5.createElement(TextTooltip, {
480
- text: toLocalizedString(label, t),
481
- side: "bottom",
482
- truncateQuery: "span[data-tooltip]",
483
- onlyWhenTruncating: true,
484
- asChild: true,
485
- ref: forwardedRef
486
- }, /* @__PURE__ */ React5.createElement(Button, {
487
- "data-testid": "treeItem.heading",
488
- variant: "ghost",
489
- density: "fine",
490
- classNames: mx4("grow gap-2 pis-0.5 hover:bg-transparent dark:hover:bg-transparent", "disabled:cursor-default disabled:opacity-100", className),
491
- disabled,
492
- onClick: handleSelect,
493
- onKeyDown: handleButtonKeydown,
494
- ...current && {
495
- "aria-current": "location"
496
- }
497
- }, icon && /* @__PURE__ */ React5.createElement(Icon3, {
498
- icon: icon ?? "ph--placeholder--regular",
499
- size: 5,
500
- classNames: "mlb-1"
501
- }), /* @__PURE__ */ React5.createElement("span", {
502
- className: "flex-1 is-0 truncate text-start text-sm font-normal",
503
- "data-tooltip": true
504
- }, toLocalizedString(label, t))));
505
- } finally {
506
- _effect.f();
507
- }
1059
+ }
1060
+ }, [
1061
+ onSelect
1062
+ ]);
1063
+ return /* @__PURE__ */ React9.createElement(TextTooltip, {
1064
+ text: toLocalizedString(label, t),
1065
+ side: "bottom",
1066
+ truncateQuery: "span[data-tooltip]",
1067
+ onlyWhenTruncating: true,
1068
+ asChild: true,
1069
+ ref: forwardedRef
1070
+ }, /* @__PURE__ */ React9.createElement(Button2, {
1071
+ "data-testid": "treeItem.heading",
1072
+ variant: "ghost",
1073
+ classNames: [
1074
+ "grow gap-2 ps-0.5 hover:bg-transparent dark:hover:bg-transparent",
1075
+ "disabled:cursor-default disabled:opacity-100",
1076
+ className
1077
+ ],
1078
+ disabled,
1079
+ onClick: handleSelect,
1080
+ onKeyDown: handleButtonKeydown,
1081
+ ...current && {
1082
+ "aria-current": "location"
1083
+ }
1084
+ }, icon && /* @__PURE__ */ React9.createElement(Icon4, {
1085
+ size: 5,
1086
+ icon: icon ?? "ph--placeholder--regular",
1087
+ classNames: [
1088
+ "my-1",
1089
+ styles?.surfaceText
1090
+ ]
1091
+ }), /* @__PURE__ */ React9.createElement("span", {
1092
+ className: "flex-1 w-0 truncate text-start font-normal",
1093
+ "data-tooltip": true
1094
+ }, toLocalizedString(label, t))));
508
1095
  }));
509
1096
 
510
- // packages/ui/react-ui-list/src/components/Tree/TreeItemToggle.tsx
511
- import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
512
- import React6, { forwardRef as forwardRef3, memo as memo2 } from "react";
513
- import { Button as Button2, Icon as Icon4 } from "@dxos/react-ui";
514
- import { mx as mx5 } from "@dxos/react-ui-theme";
515
- var TreeItemToggle = /* @__PURE__ */ memo2(/* @__PURE__ */ forwardRef3(({ open, isBranch, hidden, onToggle }, forwardedRef) => {
516
- var _effect = _useSignals6();
517
- try {
518
- return /* @__PURE__ */ React6.createElement(Button2, {
519
- ref: forwardedRef,
520
- "data-testid": "treeItem.toggle",
521
- "aria-expanded": open,
522
- variant: "ghost",
523
- density: "fine",
524
- classNames: mx5("is-6 pli-0 dx-focus-ring-inset", hidden ? "hidden" : !isBranch && "invisible"),
525
- onClick: onToggle
526
- }, /* @__PURE__ */ React6.createElement(Icon4, {
527
- icon: "ph--caret-right--bold",
528
- size: 3,
529
- classNames: mx5("transition duration-200", open && "rotate-90")
530
- }));
531
- } finally {
532
- _effect.f();
533
- }
1097
+ // src/components/Tree/TreeItemToggle.tsx
1098
+ import React10, { forwardRef as forwardRef5, memo as memo2 } from "react";
1099
+ import { IconButton as IconButton2 } from "@dxos/react-ui";
1100
+ var TreeItemToggle = /* @__PURE__ */ memo2(/* @__PURE__ */ forwardRef5(({ classNames, open, isBranch, hidden, ...props }, forwardedRef) => {
1101
+ return /* @__PURE__ */ React10.createElement(IconButton2, {
1102
+ ref: forwardedRef,
1103
+ "data-testid": "treeItem.toggle",
1104
+ "aria-expanded": open,
1105
+ variant: "ghost",
1106
+ density: "fine",
1107
+ classNames: [
1108
+ "h-full w-6 px-0",
1109
+ "[&_svg]:transition-transform [&_svg]:duration-200",
1110
+ open ? "[&_svg]:rotate-90" : "[&_svg]:rotate-0",
1111
+ hidden ? "hidden" : !isBranch && "invisible",
1112
+ classNames
1113
+ ],
1114
+ size: 3,
1115
+ icon: "ph--caret-right--bold",
1116
+ iconOnly: true,
1117
+ noTooltip: true,
1118
+ label: open ? "Click to close" : "Click to open",
1119
+ tabIndex: -1,
1120
+ ...props
1121
+ });
534
1122
  }));
535
1123
 
536
- // packages/ui/react-ui-list/src/components/Tree/helpers.ts
537
- var DEFAULT_INDENTATION = 8;
538
- var paddingIndentation = (level, indentation = DEFAULT_INDENTATION) => ({
539
- paddingInlineStart: `${(level - 1) * indentation}px`
540
- });
541
-
542
- // packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx
543
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx";
1124
+ // src/components/Tree/TreeItem.tsx
1125
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx";
544
1126
  var hoverableDescriptionIcons = "[--icons-color:inherit] hover-hover:[--icons-color:var(--description-text)] hover-hover:hover:[--icons-color:inherit] focus-within:[--icons-color:inherit]";
545
1127
  var TreeDataSchema = Schema.Struct({
546
1128
  id: Schema.String,
@@ -548,307 +1130,346 @@ var TreeDataSchema = Schema.Struct({
548
1130
  item: Schema.Any
549
1131
  });
550
1132
  var isTreeData = (data) => Schema.is(TreeDataSchema)(data);
551
- var RawTreeItem = ({ item, path: _path, last, draggable: _draggable, renderColumns: Columns, canDrop, onOpenChange, onSelect, levelOffset = 2 }) => {
552
- var _effect = _useSignals7();
553
- try {
554
- const rowRef = useRef2(null);
555
- const buttonRef = useRef2(null);
556
- const openRef = useRef2(false);
557
- const cancelExpandRef = useRef2(null);
558
- const [_state, setState] = useState3("idle");
559
- const [instruction, setInstruction] = useState3(null);
560
- const [menuOpen, setMenuOpen] = useState3(false);
561
- const { useItems, getProps, isOpen, isCurrent } = useTree();
562
- const items = useItems(item);
563
- const { id, label, parentOf, icon, disabled, className, headingClassName, testId } = getProps(item, _path);
564
- const path = useMemo(() => [
565
- ..._path,
566
- id
567
- ], [
568
- _path,
569
- id
570
- ]);
571
- const open = isOpen(path, item);
572
- const current = isCurrent(path, item);
573
- const level = path.length - levelOffset;
574
- const isBranch = !!parentOf;
575
- const mode = last ? "last-in-group" : open ? "expanded" : "standard";
576
- const cancelExpand = useCallback3(() => {
577
- if (cancelExpandRef.current) {
578
- clearTimeout(cancelExpandRef.current);
579
- cancelExpandRef.current = null;
580
- }
581
- }, []);
582
- useEffect3(() => {
583
- if (!_draggable) {
584
- return;
1133
+ var RawTreeItem = ({ item, path: pathProp, levelOffset = 2, last, draggable: draggableProp, renderColumns: Columns, blockInstruction, canDrop, canSelect, onOpenChange, onSelect, onItemHover }) => {
1134
+ const rowRef = useRef3(null);
1135
+ const buttonRef = useRef3(null);
1136
+ const openRef = useRef3(false);
1137
+ const cancelExpandRef = useRef3(null);
1138
+ const [_state, setState] = useState4("idle");
1139
+ const [instruction, setInstruction] = useState4(null);
1140
+ const [menuOpen, setMenuOpen] = useState4(false);
1141
+ const { itemProps: itemPropsAtom, childIds: childIdsAtom, itemOpen: itemOpenAtom, itemCurrent: itemCurrentAtom } = useTree();
1142
+ const path = useMemo2(() => [
1143
+ ...pathProp,
1144
+ item.id
1145
+ ], [
1146
+ pathProp,
1147
+ item.id
1148
+ ]);
1149
+ const { id, parentOf, draggable: itemDraggable, droppable: itemDroppable, label, className, headingClassName, icon, iconHue, disabled, testId } = useAtomValue(itemPropsAtom(path));
1150
+ const childIds = useAtomValue(childIdsAtom(item.id));
1151
+ const open = useAtomValue(itemOpenAtom(path));
1152
+ const current = useAtomValue(itemCurrentAtom(path));
1153
+ const level = path.length - levelOffset;
1154
+ const isBranch = !!parentOf;
1155
+ const mode = last ? "last-in-group" : open ? "expanded" : "standard";
1156
+ const canSelectItem = canSelect?.({
1157
+ item,
1158
+ path
1159
+ }) ?? true;
1160
+ const data = {
1161
+ id,
1162
+ path,
1163
+ item
1164
+ };
1165
+ const shouldSeedNativeDragData = typeof document !== "undefined" && document.body.hasAttribute("data-platform");
1166
+ const cancelExpand = useCallback6(() => {
1167
+ if (cancelExpandRef.current) {
1168
+ clearTimeout(cancelExpandRef.current);
1169
+ cancelExpandRef.current = null;
1170
+ }
1171
+ }, []);
1172
+ const isItemDraggable = draggableProp && itemDraggable !== false;
1173
+ const isItemDroppable = itemDroppable !== false;
1174
+ const nativeDragText = id;
1175
+ useEffect4(() => {
1176
+ if (!draggableProp) {
1177
+ return;
1178
+ }
1179
+ invariant2(buttonRef.current, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 70, S: void 0, A: ["buttonRef.current", ""] });
1180
+ const makeDraggable = () => draggable2({
1181
+ element: buttonRef.current,
1182
+ getInitialData: () => data,
1183
+ getInitialDataForExternal: () => {
1184
+ if (!shouldSeedNativeDragData) {
1185
+ return {};
1186
+ }
1187
+ return {
1188
+ "text/plain": nativeDragText
1189
+ };
1190
+ },
1191
+ onDragStart: () => {
1192
+ setState("dragging");
1193
+ if (open) {
1194
+ openRef.current = true;
1195
+ onOpenChange?.({
1196
+ item,
1197
+ path,
1198
+ open: false
1199
+ });
1200
+ }
1201
+ },
1202
+ onDrop: () => {
1203
+ setState("idle");
1204
+ if (openRef.current) {
1205
+ onOpenChange?.({
1206
+ item,
1207
+ path,
1208
+ open: true
1209
+ });
1210
+ }
585
1211
  }
586
- invariant2(buttonRef.current, void 0, {
587
- F: __dxlog_file2,
588
- L: 106,
589
- S: void 0,
590
- A: [
591
- "buttonRef.current",
592
- ""
593
- ]
594
- });
595
- const data = {
596
- id,
597
- path,
598
- item
599
- };
600
- return combine2(
601
- draggable2({
602
- element: buttonRef.current,
603
- getInitialData: () => data,
604
- onDragStart: () => {
605
- setState("dragging");
606
- if (open) {
607
- openRef.current = true;
608
- onOpenChange?.({
609
- item,
610
- path,
611
- open: false
612
- });
613
- }
614
- },
615
- onDrop: () => {
616
- setState("idle");
617
- if (openRef.current) {
1212
+ });
1213
+ if (!isItemDroppable) {
1214
+ return isItemDraggable ? makeDraggable() : void 0;
1215
+ }
1216
+ const dropTarget = dropTargetForElements2({
1217
+ element: buttonRef.current,
1218
+ getData: ({ input, element }) => {
1219
+ return attachInstruction(data, {
1220
+ input,
1221
+ element,
1222
+ indentPerLevel: DEFAULT_INDENTATION,
1223
+ currentLevel: level,
1224
+ mode,
1225
+ block: isBranch ? [] : [
1226
+ "make-child"
1227
+ ]
1228
+ });
1229
+ },
1230
+ canDrop: ({ source }) => {
1231
+ const _canDrop = canDrop ?? (() => true);
1232
+ return source.element !== buttonRef.current && _canDrop({
1233
+ source: source.data,
1234
+ target: data
1235
+ });
1236
+ },
1237
+ getIsSticky: () => true,
1238
+ onDrag: ({ self, source }) => {
1239
+ const desired = extractInstruction(self.data);
1240
+ const block = desired && blockInstruction?.({
1241
+ instruction: desired,
1242
+ source: source.data,
1243
+ target: data
1244
+ });
1245
+ const instruction2 = block && desired.type !== "instruction-blocked" ? {
1246
+ type: "instruction-blocked",
1247
+ desired
1248
+ } : desired;
1249
+ if (source.data.id !== id) {
1250
+ if (instruction2?.type === "make-child" && isBranch && !open && !cancelExpandRef.current) {
1251
+ cancelExpandRef.current = setTimeout(() => {
618
1252
  onOpenChange?.({
619
1253
  item,
620
1254
  path,
621
1255
  open: true
622
1256
  });
623
- }
1257
+ }, 500);
624
1258
  }
625
- }),
626
- // https://github.com/atlassian/pragmatic-drag-and-drop/blob/main/packages/hitbox/constellation/index/about.mdx
627
- dropTargetForElements2({
628
- element: buttonRef.current,
629
- getData: ({ input, element }) => {
630
- return attachInstruction(data, {
631
- input,
632
- element,
633
- indentPerLevel: DEFAULT_INDENTATION,
634
- currentLevel: level,
635
- mode,
636
- block: isBranch ? [] : [
637
- "make-child"
638
- ]
639
- });
640
- },
641
- canDrop: ({ source }) => {
642
- const _canDrop = canDrop ?? (() => true);
643
- return source.element !== buttonRef.current && _canDrop({
644
- source: source.data,
645
- target: data
646
- });
647
- },
648
- getIsSticky: () => true,
649
- onDrag: ({ self, source }) => {
650
- const instruction2 = extractInstruction(self.data);
651
- if (source.data.id !== id) {
652
- if (instruction2?.type === "make-child" && isBranch && !open && !cancelExpandRef.current) {
653
- cancelExpandRef.current = setTimeout(() => {
654
- onOpenChange?.({
655
- item,
656
- path,
657
- open: true
658
- });
659
- }, 500);
660
- }
661
- if (instruction2?.type !== "make-child") {
662
- cancelExpand();
663
- }
664
- setInstruction(instruction2);
665
- } else if (instruction2?.type === "reparent") {
666
- setInstruction(instruction2);
667
- } else {
668
- setInstruction(null);
669
- }
670
- },
671
- onDragLeave: () => {
672
- cancelExpand();
673
- setInstruction(null);
674
- },
675
- onDrop: () => {
1259
+ if (instruction2?.type !== "make-child") {
676
1260
  cancelExpand();
677
- setInstruction(null);
678
1261
  }
679
- })
680
- );
681
- }, [
682
- _draggable,
683
- item,
684
- id,
685
- mode,
686
- path,
687
- open,
688
- canDrop
689
- ]);
690
- useEffect3(() => () => cancelExpand(), [
691
- cancelExpand
692
- ]);
693
- const handleOpenChange = useCallback3(() => onOpenChange?.({
694
- item,
695
- path,
696
- open: !open
697
- }), [
698
- onOpenChange,
699
- item,
700
- path,
701
- open
702
- ]);
703
- const handleSelect = useCallback3((option = false) => {
704
- if (isBranch) {
705
- handleOpenChange();
706
- } else {
707
- rowRef.current?.focus();
708
- onSelect?.({
709
- item,
710
- path,
711
- current: !current,
712
- option
713
- });
714
- }
715
- }, [
716
- item,
717
- path,
718
- current,
719
- isBranch,
720
- handleOpenChange,
721
- onSelect
722
- ]);
723
- const handleKeyDown = useCallback3((event) => {
724
- switch (event.key) {
725
- case "ArrowRight":
726
- isBranch && !open && handleOpenChange();
727
- break;
728
- case "ArrowLeft":
729
- isBranch && open && handleOpenChange();
730
- break;
731
- case " ":
732
- handleSelect(event.altKey);
733
- break;
734
- }
735
- }, [
736
- isBranch,
737
- open,
738
- handleOpenChange,
739
- handleSelect
740
- ]);
741
- return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(Treegrid.Row, {
742
- ref: rowRef,
743
- key: id,
744
- id,
745
- "aria-labelledby": `${id}__label`,
746
- parentOf: parentOf?.join(Treegrid.PARENT_OF_SEPARATOR),
747
- classNames: mx6("grid grid-cols-subgrid col-[tree-row] mbs-0.5 aria-[current]:bg-activeSurface", hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, hoverableDescriptionIcons, ghostHover, className),
748
- "data-itemid": id,
749
- "data-testid": testId,
750
- // NOTE(thure): This is intentionally an empty string to for descendents to select by in the CSS
751
- // without alerting the user (except for in the correct link element). See also:
752
- // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current#description
753
- "aria-current": current ? "" : void 0,
754
- onKeyDown: handleKeyDown,
755
- onContextMenu: (event) => {
756
- event.preventDefault();
757
- setMenuOpen(true);
1262
+ setInstruction(instruction2);
1263
+ } else if (instruction2?.type === "reparent") {
1264
+ setInstruction(instruction2);
1265
+ } else {
1266
+ setInstruction(null);
1267
+ }
1268
+ },
1269
+ onDragLeave: () => {
1270
+ cancelExpand();
1271
+ setInstruction(null);
1272
+ },
1273
+ onDrop: () => {
1274
+ cancelExpand();
1275
+ setInstruction(null);
758
1276
  }
759
- }, /* @__PURE__ */ React7.createElement(Treegrid.Cell, {
760
- indent: true,
761
- classNames: "relative grid grid-cols-subgrid col-[tree-row]",
762
- style: paddingIndentation(level)
763
- }, /* @__PURE__ */ React7.createElement("div", {
764
- role: "none",
765
- className: "flex items-center"
766
- }, /* @__PURE__ */ React7.createElement(TreeItemToggle, {
767
- isBranch,
768
- open,
769
- onToggle: handleOpenChange
770
- }), /* @__PURE__ */ React7.createElement(TreeItemHeading, {
771
- ref: buttonRef,
772
- label,
773
- icon,
774
- className: headingClassName,
775
- disabled,
776
- current,
777
- onSelect: handleSelect
778
- })), Columns && /* @__PURE__ */ React7.createElement(Columns, {
779
- item,
780
- path,
781
- open,
782
- menuOpen,
783
- setMenuOpen
784
- }), instruction && /* @__PURE__ */ React7.createElement(NaturalTreeItem.DropIndicator, {
785
- instruction,
786
- gap: 2
787
- }))), open && items.map((item2, index) => /* @__PURE__ */ React7.createElement(TreeItem, {
788
- key: item2.id,
789
- item: item2,
790
- path,
791
- last: index === items.length - 1,
792
- draggable: _draggable,
793
- renderColumns: Columns,
794
- canDrop,
795
- onOpenChange,
796
- onSelect
797
- })));
798
- } finally {
799
- _effect.f();
800
- }
1277
+ });
1278
+ if (!isItemDraggable) {
1279
+ return dropTarget;
1280
+ }
1281
+ return combine2(makeDraggable(), dropTarget);
1282
+ }, [
1283
+ draggableProp,
1284
+ isItemDraggable,
1285
+ isItemDroppable,
1286
+ item,
1287
+ id,
1288
+ mode,
1289
+ path,
1290
+ open,
1291
+ blockInstruction,
1292
+ canDrop
1293
+ ]);
1294
+ useEffect4(() => () => cancelExpand(), [
1295
+ cancelExpand
1296
+ ]);
1297
+ const handleOpenToggle = useCallback6(() => onOpenChange?.({
1298
+ item,
1299
+ path,
1300
+ open: !open
1301
+ }), [
1302
+ onOpenChange,
1303
+ item,
1304
+ path,
1305
+ open
1306
+ ]);
1307
+ const handleSelect = useCallback6((option = false) => {
1308
+ if (isBranch && (option || current)) {
1309
+ handleOpenToggle();
1310
+ } else if (canSelectItem) {
1311
+ canSelect?.({
1312
+ item,
1313
+ path
1314
+ });
1315
+ rowRef.current?.focus();
1316
+ onSelect?.({
1317
+ item,
1318
+ path,
1319
+ current: !current,
1320
+ option
1321
+ });
1322
+ }
1323
+ }, [
1324
+ item,
1325
+ path,
1326
+ current,
1327
+ isBranch,
1328
+ canSelectItem,
1329
+ handleOpenToggle,
1330
+ onSelect
1331
+ ]);
1332
+ const handleKeyDown = useCallback6((event) => {
1333
+ switch (event.key) {
1334
+ case "ArrowRight":
1335
+ case "ArrowLeft":
1336
+ isBranch && handleOpenToggle();
1337
+ break;
1338
+ }
1339
+ }, [
1340
+ isBranch,
1341
+ open,
1342
+ handleOpenToggle,
1343
+ handleSelect
1344
+ ]);
1345
+ const handleItemHover = useCallback6(() => {
1346
+ onItemHover?.({
1347
+ item
1348
+ });
1349
+ }, [
1350
+ onItemHover,
1351
+ item
1352
+ ]);
1353
+ const handleContextMenu = useCallback6((event) => {
1354
+ event.preventDefault();
1355
+ setMenuOpen(true);
1356
+ }, [
1357
+ setMenuOpen
1358
+ ]);
1359
+ const childProps = {
1360
+ draggable: draggableProp,
1361
+ renderColumns: Columns,
1362
+ blockInstruction,
1363
+ canDrop,
1364
+ canSelect,
1365
+ onItemHover,
1366
+ onOpenChange,
1367
+ onSelect
1368
+ };
1369
+ return /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Treegrid.Row, {
1370
+ ref: rowRef,
1371
+ key: id,
1372
+ id,
1373
+ "aria-labelledby": `${id}__label`,
1374
+ parentOf: parentOf?.join(TREEGRID_PARENT_OF_SEPARATOR),
1375
+ "data-object-id": id,
1376
+ "data-testid": testId,
1377
+ // NOTE(thure): This is intentionally an empty string to for descendents to select by in the CSS
1378
+ // without alerting the user (except for in the correct link element). See also:
1379
+ // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current#description
1380
+ "aria-current": current ? "" : void 0,
1381
+ classNames: mx7("grid grid-cols-subgrid col-[tree-row] mt-0.5 is-current:bg-active-surface", hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, hoverableDescriptionIcons, ghostFocusWithin, ghostHover, className),
1382
+ onKeyDown: handleKeyDown,
1383
+ onMouseEnter: handleItemHover,
1384
+ onContextMenu: handleContextMenu
1385
+ }, /* @__PURE__ */ React11.createElement("div", {
1386
+ role: "none",
1387
+ className: "indent relative grid grid-cols-subgrid col-[tree-row]",
1388
+ style: paddingIndentation(level)
1389
+ }, /* @__PURE__ */ React11.createElement(Treegrid.Cell, {
1390
+ classNames: "flex items-center"
1391
+ }, /* @__PURE__ */ React11.createElement(TreeItemToggle, {
1392
+ isBranch,
1393
+ open,
1394
+ onClick: handleOpenToggle
1395
+ }), /* @__PURE__ */ React11.createElement(TreeItemHeading, {
1396
+ disabled,
1397
+ current,
1398
+ label,
1399
+ className: headingClassName,
1400
+ icon,
1401
+ iconHue,
1402
+ onSelect: handleSelect,
1403
+ ref: buttonRef
1404
+ })), Columns && /* @__PURE__ */ React11.createElement(Columns, {
1405
+ item,
1406
+ path,
1407
+ open,
1408
+ menuOpen,
1409
+ setMenuOpen
1410
+ }), instruction && /* @__PURE__ */ React11.createElement(NaturalTreeItem.DropIndicator, {
1411
+ instruction,
1412
+ gap: 2
1413
+ }))), open && childIds.map((childId, index) => /* @__PURE__ */ React11.createElement(TreeItemById, {
1414
+ key: childId,
1415
+ id: childId,
1416
+ path,
1417
+ last: index === childIds.length - 1,
1418
+ ...childProps
1419
+ })));
801
1420
  };
802
1421
  var TreeItem = /* @__PURE__ */ memo3(RawTreeItem);
803
-
804
- // packages/ui/react-ui-list/src/components/Tree/Tree.tsx
805
- var Tree = ({ root, path, id, useItems, getProps, isOpen, isCurrent, draggable: draggable3 = false, gridTemplateColumns = "[tree-row-start] 1fr min-content [tree-row-end]", classNames, levelOffset, renderColumns, canDrop, onOpenChange, onSelect }) => {
806
- var _effect = _useSignals8();
807
- try {
808
- const context = useMemo2(() => ({
809
- useItems,
810
- getProps,
811
- isOpen,
812
- isCurrent
813
- }), [
814
- useItems,
815
- getProps,
816
- isOpen,
817
- isCurrent
818
- ]);
819
- const items = useItems(root);
820
- const treePath = useMemo2(() => path ? [
821
- ...path,
822
- id
823
- ] : [
824
- id
825
- ], [
826
- id,
827
- path
828
- ]);
829
- return /* @__PURE__ */ React8.createElement(Treegrid2.Root, {
830
- gridTemplateColumns,
831
- classNames
832
- }, /* @__PURE__ */ React8.createElement(TreeProvider, {
833
- value: context
834
- }, items.map((item, index) => /* @__PURE__ */ React8.createElement(TreeItem, {
835
- key: item.id,
836
- item,
837
- last: index === items.length - 1,
838
- path: treePath,
839
- levelOffset,
840
- draggable: draggable3,
841
- renderColumns,
842
- canDrop,
843
- onOpenChange,
844
- onSelect
845
- }))));
846
- } finally {
847
- _effect.f();
1422
+ var RawTreeItemById = ({ id, ...props }) => {
1423
+ const { item: itemAtom } = useTree();
1424
+ const item = useAtomValue(itemAtom(id));
1425
+ if (!item) {
1426
+ return null;
848
1427
  }
1428
+ return /* @__PURE__ */ React11.createElement(TreeItem, {
1429
+ item,
1430
+ ...props
1431
+ });
1432
+ };
1433
+ var TreeItemById = /* @__PURE__ */ memo3(RawTreeItemById);
1434
+
1435
+ // src/components/Tree/Tree.tsx
1436
+ var Tree = ({ model, rootId, path, id, draggable: draggable3 = false, gridTemplateColumns = "[tree-row-start] 1fr min-content [tree-row-end]", classNames, levelOffset, renderColumns, blockInstruction, canDrop, canSelect, onOpenChange, onSelect, onItemHover }) => {
1437
+ const childIds = useAtomValue2(model.childIds(rootId));
1438
+ const treePath = useMemo3(() => path ? [
1439
+ ...path,
1440
+ id
1441
+ ] : [
1442
+ id
1443
+ ], [
1444
+ id,
1445
+ path
1446
+ ]);
1447
+ const childProps = {
1448
+ path: treePath,
1449
+ levelOffset,
1450
+ draggable: draggable3,
1451
+ renderColumns,
1452
+ blockInstruction,
1453
+ canDrop,
1454
+ canSelect,
1455
+ onOpenChange,
1456
+ onSelect,
1457
+ onItemHover
1458
+ };
1459
+ return /* @__PURE__ */ React12.createElement(Treegrid2.Root, {
1460
+ gridTemplateColumns,
1461
+ classNames
1462
+ }, /* @__PURE__ */ React12.createElement(TreeProvider, {
1463
+ value: model
1464
+ }, childIds.map((childId, index) => /* @__PURE__ */ React12.createElement(TreeItemById, {
1465
+ key: childId,
1466
+ id: childId,
1467
+ last: index === childIds.length - 1,
1468
+ ...childProps
1469
+ }))));
849
1470
  };
850
1471
 
851
- // packages/ui/react-ui-list/src/util/path.ts
1472
+ // src/util/path.ts
852
1473
  var SEPARATOR = "+";
853
1474
  var Path = {
854
1475
  create: (...args) => args.join(SEPARATOR),
@@ -865,13 +1486,27 @@ var Path = {
865
1486
  };
866
1487
  export {
867
1488
  Accordion,
1489
+ Combobox,
1490
+ DEFAULT_INDENTATION,
868
1491
  List,
1492
+ Listbox,
869
1493
  Path,
1494
+ Picker,
1495
+ Row,
1496
+ RowList,
870
1497
  Tree,
871
1498
  TreeDataSchema,
872
1499
  TreeItem,
1500
+ TreeItemById,
1501
+ TreeItemToggle,
873
1502
  TreeProvider,
1503
+ createListboxScope,
1504
+ createRowListScope,
874
1505
  isTreeData,
1506
+ paddingIndentation,
1507
+ usePickerInputContext,
1508
+ usePickerItemContext,
1509
+ useRowListSelection,
875
1510
  useTree
876
1511
  };
877
1512
  //# sourceMappingURL=index.mjs.map