@dxos/react-ui-list 0.8.3-staging.0fa589b → 0.8.4-main.03d5cd7b56

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