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