@dxos/react-ui-list 0.8.4-main.3f58842 → 0.8.4-main.4a85c3132b

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 (55) hide show
  1. package/dist/lib/browser/index.mjs +676 -729
  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 +676 -729
  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.stories.d.ts +7 -4
  8. package/dist/types/src/components/Accordion/Accordion.stories.d.ts.map +1 -1
  9. package/dist/types/src/components/Accordion/AccordionItem.d.ts +1 -1
  10. package/dist/types/src/components/Accordion/AccordionItem.d.ts.map +1 -1
  11. package/dist/types/src/components/List/List.d.ts +8 -8
  12. package/dist/types/src/components/List/List.d.ts.map +1 -1
  13. package/dist/types/src/components/List/List.stories.d.ts +14 -5
  14. package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
  15. package/dist/types/src/components/List/ListItem.d.ts +6 -9
  16. package/dist/types/src/components/List/ListItem.d.ts.map +1 -1
  17. package/dist/types/src/components/List/ListRoot.d.ts +2 -2
  18. package/dist/types/src/components/List/ListRoot.d.ts.map +1 -1
  19. package/dist/types/src/components/List/testing.d.ts +1 -1
  20. package/dist/types/src/components/List/testing.d.ts.map +1 -1
  21. package/dist/types/src/components/Tree/Tree.d.ts +10 -6
  22. package/dist/types/src/components/Tree/Tree.d.ts.map +1 -1
  23. package/dist/types/src/components/Tree/Tree.stories.d.ts +18 -7
  24. package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
  25. package/dist/types/src/components/Tree/TreeContext.d.ts +20 -10
  26. package/dist/types/src/components/Tree/TreeContext.d.ts.map +1 -1
  27. package/dist/types/src/components/Tree/TreeItem.d.ts +32 -10
  28. package/dist/types/src/components/Tree/TreeItem.d.ts.map +1 -1
  29. package/dist/types/src/components/Tree/TreeItemHeading.d.ts +4 -3
  30. package/dist/types/src/components/Tree/TreeItemHeading.d.ts.map +1 -1
  31. package/dist/types/src/components/Tree/TreeItemToggle.d.ts +3 -3
  32. package/dist/types/src/components/Tree/TreeItemToggle.d.ts.map +1 -1
  33. package/dist/types/src/components/Tree/index.d.ts +2 -0
  34. package/dist/types/src/components/Tree/index.d.ts.map +1 -1
  35. package/dist/types/src/components/Tree/testing.d.ts +3 -3
  36. package/dist/types/src/components/Tree/testing.d.ts.map +1 -1
  37. package/dist/types/tsconfig.tsbuildinfo +1 -1
  38. package/package.json +31 -28
  39. package/src/components/Accordion/Accordion.stories.tsx +5 -7
  40. package/src/components/Accordion/Accordion.tsx +1 -1
  41. package/src/components/Accordion/AccordionItem.tsx +8 -5
  42. package/src/components/Accordion/AccordionRoot.tsx +1 -1
  43. package/src/components/List/List.stories.tsx +40 -26
  44. package/src/components/List/List.tsx +2 -5
  45. package/src/components/List/ListItem.tsx +50 -38
  46. package/src/components/List/ListRoot.tsx +3 -3
  47. package/src/components/List/testing.ts +3 -3
  48. package/src/components/Tree/Tree.stories.tsx +172 -79
  49. package/src/components/Tree/Tree.tsx +43 -40
  50. package/src/components/Tree/TreeContext.tsx +17 -9
  51. package/src/components/Tree/TreeItem.tsx +141 -83
  52. package/src/components/Tree/TreeItemHeading.tsx +13 -8
  53. package/src/components/Tree/TreeItemToggle.tsx +29 -18
  54. package/src/components/Tree/index.ts +2 -0
  55. package/src/components/Tree/testing.ts +5 -4
@@ -1,85 +1,63 @@
1
1
  // src/components/Accordion/AccordionItem.tsx
2
- import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
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
8
  // src/components/Accordion/AccordionRoot.tsx
10
- import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
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
30
  // src/components/Accordion/AccordionItem.tsx
38
31
  var ACCORDION_ITEM_NAME = "AccordionItem";
39
- var [AccordionItemProvider, useAccordionItemContext] = createContext2(ACCORDION_ITEM_NAME);
32
+ var [AccordionItemProvider, useDxAccordionItemContext] = createContext2(ACCORDION_ITEM_NAME);
40
33
  var AccordionItem = ({ children, classNames, item }) => {
41
- var _effect = _useSignals2();
42
- try {
43
- const { getId } = useAccordionContext(ACCORDION_ITEM_NAME);
44
- return /* @__PURE__ */ React2.createElement(AccordionItemProvider, {
45
- item
46
- }, /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Item, {
47
- value: getId(item),
48
- className: mx2("overflow-hidden", classNames)
49
- }, children));
50
- } finally {
51
- _effect.f();
52
- }
34
+ const { getId } = useAccordionContext(ACCORDION_ITEM_NAME);
35
+ return /* @__PURE__ */ React2.createElement(AccordionItemProvider, {
36
+ item
37
+ }, /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Item, {
38
+ value: getId(item),
39
+ className: mx2("overflow-hidden", classNames)
40
+ }, children));
53
41
  };
54
42
  var AccordionItemHeader = ({ classNames, children, ...props }) => {
55
- var _effect = _useSignals2();
56
- try {
57
- return /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Header, {
58
- ...props,
59
- className: mx2(classNames)
60
- }, /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Trigger, {
61
- className: "group flex items-center p-2 dx-focus-ring-inset is-full text-start"
62
- }, children, /* @__PURE__ */ React2.createElement(Icon, {
63
- icon: "ph--caret-right--regular",
64
- size: 4,
65
- classNames: "transition-transform duration-200 group-data-[state=open]:rotate-90"
66
- })));
67
- } finally {
68
- _effect.f();
69
- }
43
+ return /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Header, {
44
+ ...props,
45
+ className: mx2(classNames)
46
+ }, /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Trigger, {
47
+ className: "group flex items-center p-2 dx-focus-ring-inset w-full text-start"
48
+ }, children, /* @__PURE__ */ React2.createElement(Icon, {
49
+ icon: "ph--caret-right--regular",
50
+ size: 4,
51
+ classNames: "transition-transform duration-200 group-data-[state=open]:rotate-90"
52
+ })));
70
53
  };
71
54
  var AccordionItemBody = ({ children, classNames }) => {
72
- var _effect = _useSignals2();
73
- try {
74
- return /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Content, {
75
- className: "overflow-hidden data-[state=closed]:animate-slideUp data-[state=open]:animate-slideDown"
76
- }, /* @__PURE__ */ React2.createElement("div", {
77
- role: "none",
78
- className: mx2("p-2", classNames)
79
- }, children));
80
- } finally {
81
- _effect.f();
82
- }
55
+ return /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Content, {
56
+ className: "overflow-hidden data-[state=closed]:animate-slide-up data-[state=open]:animate-slide-down"
57
+ }, /* @__PURE__ */ React2.createElement("div", {
58
+ role: "none",
59
+ className: mx2("p-2", classNames)
60
+ }, children));
83
61
  };
84
62
 
85
63
  // src/components/Accordion/Accordion.tsx
@@ -91,20 +69,18 @@ var Accordion = {
91
69
  };
92
70
 
93
71
  // src/components/List/ListItem.tsx
94
- import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
95
72
  import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
96
73
  import { draggable, dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
97
74
  import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview";
98
75
  import { attachClosestEdge, extractClosestEdge as extractClosestEdge2 } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
99
76
  import { createContext as createContext4 } from "@radix-ui/react-context";
100
- import React4, { forwardRef, useEffect as useEffect2, useRef, useState as useState2 } from "react";
77
+ import React4, { useEffect as useEffect2, useRef, useState as useState2 } from "react";
101
78
  import { createPortal } from "react-dom";
102
79
  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";
80
+ import { IconButton, ListItem as NaturalListItem, useTranslation } from "@dxos/react-ui";
81
+ import { mx as mx3, osTranslations } from "@dxos/ui-theme";
105
82
 
106
83
  // src/components/List/ListRoot.tsx
107
- import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
108
84
  import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
109
85
  import { extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
110
86
  import { getReorderDestinationIndex } from "@atlaskit/pragmatic-drag-and-drop-hitbox/util/get-reorder-destination-index";
@@ -114,68 +90,63 @@ var LIST_NAME = "List";
114
90
  var [ListProvider, useListContext] = createContext3(LIST_NAME);
115
91
  var defaultGetId2 = (item) => item?.id;
116
92
  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);
93
+ const isEqual = useCallback((a, b) => {
94
+ const idA = getId?.(a);
95
+ const idB = getId?.(b);
96
+ if (idA !== void 0 && idB !== void 0) {
97
+ return idA === idB;
98
+ } else {
99
+ return a === b;
100
+ }
101
+ }, [
102
+ getId
103
+ ]);
104
+ const [state, setState] = useState(idle);
105
+ useEffect(() => {
106
+ if (!items) {
107
+ return;
108
+ }
109
+ return monitorForElements({
110
+ canMonitor: ({ source }) => isItem?.(source.data) ?? false,
111
+ onDrop: ({ location, source }) => {
112
+ const target = location.current.dropTargets[0];
113
+ if (!target) {
114
+ return;
160
115
  }
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
- }
116
+ const sourceData = source.data;
117
+ const targetData = target.data;
118
+ if (!isItem?.(sourceData) || !isItem?.(targetData)) {
119
+ return;
120
+ }
121
+ const sourceIdx = items.findIndex((item) => isEqual(item, sourceData));
122
+ const targetIdx = items.findIndex((item) => isEqual(item, targetData));
123
+ if (targetIdx < 0 || sourceIdx < 0) {
124
+ return;
125
+ }
126
+ const closestEdgeOfTarget = extractClosestEdge(targetData);
127
+ const destinationIndex = getReorderDestinationIndex({
128
+ closestEdgeOfTarget,
129
+ startIndex: sourceIdx,
130
+ indexOfTarget: targetIdx,
131
+ axis: "vertical"
132
+ });
133
+ onMove?.(sourceIdx, destinationIndex);
134
+ }
135
+ });
136
+ }, [
137
+ items,
138
+ isEqual,
139
+ onMove
140
+ ]);
141
+ return /* @__PURE__ */ React3.createElement(ListProvider, {
142
+ state,
143
+ setState,
144
+ isItem,
145
+ ...props
146
+ }, children?.({
147
+ state,
148
+ items: items ?? []
149
+ }));
179
150
  };
180
151
 
181
152
  // src/components/List/ListItem.tsx
@@ -184,209 +155,180 @@ var idle = {
184
155
  type: "idle"
185
156
  };
186
157
  var stateStyles = {
187
- "is-dragging": "opacity-50"
158
+ "w-dragging": "opacity-50"
188
159
  };
189
160
  var defaultContext = {};
190
161
  var LIST_ITEM_NAME = "ListItem";
191
162
  var [ListItemProvider, useListItemContext] = createContext4(LIST_ITEM_NAME, defaultContext);
192
163
  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: 93,
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
- onDragLeave: () => {
287
- setState(idle);
288
- },
289
- onDrag: ({ self }) => {
290
- const closestEdge = extractClosestEdge2(self.data);
291
- setState((current) => {
292
- if (current.type === "is-dragging-over" && current.closestEdge === closestEdge) {
293
- return current;
294
- }
164
+ const { isItem, readonly, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
165
+ const ref = useRef(null);
166
+ const dragHandleRef = useRef(null);
167
+ const [state, setState] = useState2(idle);
168
+ useEffect2(() => {
169
+ const element = ref.current;
170
+ invariant(element, void 0, {
171
+ F: __dxlog_file,
172
+ L: 98,
173
+ S: void 0,
174
+ A: [
175
+ "element",
176
+ ""
177
+ ]
178
+ });
179
+ return combine(
180
+ //
181
+ // https://atlassian.design/components/pragmatic-drag-and-drop/core-package/adapters/element/about#draggable
182
+ //
183
+ draggable({
184
+ element,
185
+ dragHandle: dragHandleRef.current,
186
+ canDrag: () => !readonly,
187
+ getInitialData: () => item,
188
+ onGenerateDragPreview: dragPreview ? ({ nativeSetDragImage, source }) => {
189
+ const rect = source.element.getBoundingClientRect();
190
+ setCustomNativeDragPreview({
191
+ nativeSetDragImage,
192
+ getOffset: ({ container }) => {
193
+ const { height } = container.getBoundingClientRect();
295
194
  return {
296
- type: "is-dragging-over",
297
- closestEdge
195
+ x: 20,
196
+ y: height / 2
298
197
  };
299
- });
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
- }
198
+ },
199
+ render: ({ container }) => {
200
+ container.style.width = rect.width + "px";
201
+ setState({
202
+ type: "preview",
203
+ container
204
+ });
205
+ setRootState({
206
+ type: "preview",
207
+ container,
208
+ item
209
+ });
210
+ return () => {
211
+ };
212
+ }
213
+ });
214
+ } : void 0,
215
+ onDragStart: () => {
216
+ setState({
217
+ type: "w-dragging"
218
+ });
219
+ setRootState({
220
+ type: "w-dragging",
221
+ item
222
+ });
223
+ },
224
+ onDrop: () => {
225
+ setState(idle);
226
+ setRootState(idle);
227
+ }
228
+ }),
229
+ //
230
+ // https://atlassian.design/components/pragmatic-drag-and-drop/core-package/adapters/element/about#drop-target-for-elements
231
+ //
232
+ dropTargetForElements({
233
+ element,
234
+ canDrop: ({ source }) => {
235
+ return (source.element !== element && isItem?.(source.data)) ?? false;
236
+ },
237
+ getData: ({ input }) => {
238
+ return attachClosestEdge(item, {
239
+ element,
240
+ input,
241
+ allowedEdges: [
242
+ "top",
243
+ "bottom"
244
+ ]
245
+ });
246
+ },
247
+ getIsSticky: () => true,
248
+ onDragEnter: ({ self }) => {
249
+ const closestEdge = extractClosestEdge2(self.data);
250
+ setState({
251
+ type: "w-dragging-over",
252
+ closestEdge
253
+ });
254
+ },
255
+ onDragLeave: () => {
256
+ setState(idle);
257
+ },
258
+ onDrag: ({ self }) => {
259
+ const closestEdge = extractClosestEdge2(self.data);
260
+ setState((current) => {
261
+ if (current.type === "w-dragging-over" && current.closestEdge === closestEdge) {
262
+ return current;
263
+ }
264
+ return {
265
+ type: "w-dragging-over",
266
+ closestEdge
267
+ };
268
+ });
269
+ },
270
+ onDrop: () => {
271
+ setState(idle);
272
+ }
273
+ })
274
+ );
275
+ }, [
276
+ item
277
+ ]);
278
+ return /* @__PURE__ */ React4.createElement(ListItemProvider, {
279
+ item,
280
+ dragHandleRef
281
+ }, /* @__PURE__ */ React4.createElement("div", {
282
+ ref,
283
+ role: "listitem",
284
+ className: mx3("flex relative", classNames, stateStyles[state.type]),
285
+ ...props
286
+ }, children, state.type === "w-dragging-over" && state.closestEdge && /* @__PURE__ */ React4.createElement(NaturalListItem.DropIndicator, {
287
+ edge: state.closestEdge
288
+ })));
326
289
  };
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
- }
290
+ var ListItemDeleteButton = ({ autoHide = true, classNames, disabled, icon = "ph--x--regular", label, ...props }) => {
291
+ const { state } = useListContext("DELETE_BUTTON");
292
+ const isDisabled = state.type !== "idle" || disabled;
293
+ const { t } = useTranslation(osTranslations);
294
+ return /* @__PURE__ */ React4.createElement(IconButton, {
295
+ iconOnly: true,
296
+ variant: "ghost",
297
+ ...props,
298
+ icon,
299
+ disabled: isDisabled,
300
+ label: label ?? t("delete label"),
301
+ classNames: [
302
+ classNames,
303
+ autoHide && disabled && "hidden"
304
+ ]
305
+ });
360
306
  };
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
- }
307
+ var ListItemButton = ({ autoHide = true, iconOnly = true, variant = "ghost", classNames, disabled, ...props }) => {
308
+ const { state } = useListContext("ITEM_BUTTON");
309
+ const isDisabled = state.type !== "idle" || disabled;
310
+ return /* @__PURE__ */ React4.createElement(IconButton, {
311
+ ...props,
312
+ disabled: isDisabled,
313
+ iconOnly,
314
+ variant,
315
+ classNames: [
316
+ classNames,
317
+ autoHide && disabled && "hidden"
318
+ ]
319
+ });
377
320
  };
378
321
  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
- }
322
+ const { dragHandleRef } = useListItemContext("DRAG_HANDLE");
323
+ const { t } = useTranslation(osTranslations);
324
+ return /* @__PURE__ */ React4.createElement(IconButton, {
325
+ iconOnly: true,
326
+ variant: "ghost",
327
+ label: t("drag handle label"),
328
+ ref: dragHandleRef,
329
+ icon: "ph--dots-six-vertical--regular",
330
+ disabled
331
+ });
390
332
  };
391
333
  var ListItemDragPreview = ({ children }) => {
392
334
  const { state } = useListContext("DRAG_PREVIEW");
@@ -394,27 +336,13 @@ var ListItemDragPreview = ({ children }) => {
394
336
  item: state.item
395
337
  }), state.container) : null;
396
338
  };
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
- };
339
+ var ListItemWrapper = ({ classNames, children }) => /* @__PURE__ */ React4.createElement("div", {
340
+ className: mx3("flex w-full gap-2", classNames)
341
+ }, children);
342
+ var ListItemTitle = ({ classNames, children, ...props }) => /* @__PURE__ */ React4.createElement("div", {
343
+ className: mx3("flex grow items-center truncate", classNames),
344
+ ...props
345
+ }, children);
418
346
 
419
347
  // src/components/List/List.tsx
420
348
  var List = {
@@ -425,12 +353,11 @@ var List = {
425
353
  ItemDragHandle: ListItemDragHandle,
426
354
  ItemDeleteButton: ListItemDeleteButton,
427
355
  ItemButton: ListItemButton,
428
- ItemTitle: ListItemTitle,
429
- IconButton
356
+ ItemTitle: ListItemTitle
430
357
  };
431
358
 
432
359
  // src/components/Tree/Tree.tsx
433
- import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
360
+ import { useAtomValue as useAtomValue2 } from "@effect-atom/atom-react";
434
361
  import React8, { useMemo as useMemo2 } from "react";
435
362
  import { Treegrid as Treegrid2 } from "@dxos/react-ui";
436
363
 
@@ -442,111 +369,106 @@ var TreeProvider = TreeContext.Provider;
442
369
  var useTree = () => useContext(TreeContext) ?? raise(new Error("TreeContext not found"));
443
370
 
444
371
  // src/components/Tree/TreeItem.tsx
445
- import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
446
372
  import { combine as combine2 } from "@atlaskit/pragmatic-drag-and-drop/combine";
447
373
  import { draggable as draggable2, dropTargetForElements as dropTargetForElements2 } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
448
374
  import { attachInstruction, extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item";
449
- import { Schema } from "effect";
375
+ import { useAtomValue } from "@effect-atom/atom-react";
376
+ import * as Schema from "effect/Schema";
450
377
  import React7, { memo as memo3, useCallback as useCallback3, useEffect as useEffect3, useMemo, useRef as useRef2, useState as useState3 } from "react";
451
378
  import { invariant as invariant2 } from "@dxos/invariant";
452
- import { Treegrid, TreeItem as NaturalTreeItem } from "@dxos/react-ui";
453
- import { ghostHover, hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls } from "@dxos/react-ui-theme";
379
+ import { TreeItem as NaturalTreeItem, Treegrid } from "@dxos/react-ui";
380
+ import { ghostFocusWithin, ghostHover, hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, mx as mx4 } from "@dxos/ui-theme";
381
+
382
+ // src/components/Tree/helpers.ts
383
+ var DEFAULT_INDENTATION = 8;
384
+ var paddingIndentation = (level, indentation = DEFAULT_INDENTATION) => ({
385
+ paddingInlineStart: `${(level - 1) * indentation}px`
386
+ });
454
387
 
455
388
  // 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";
389
+ import React5, { forwardRef, memo, useCallback as useCallback2 } from "react";
390
+ import { Button, Icon as Icon2, toLocalizedString, useTranslation as useTranslation2 } from "@dxos/react-ui";
459
391
  import { TextTooltip } from "@dxos/react-ui-text-tooltip";
460
- var TreeItemHeading = /* @__PURE__ */ memo(/* @__PURE__ */ forwardRef2(({ label, icon, className, disabled, current, onSelect }, forwardedRef) => {
461
- var _effect = _useSignals5();
462
- try {
463
- const { t } = useTranslation();
464
- const handleSelect = useCallback2((event) => {
392
+ import { getStyles } from "@dxos/ui-theme";
393
+ var TreeItemHeading = /* @__PURE__ */ memo(/* @__PURE__ */ forwardRef(({ label, className, icon, iconHue, disabled, current, onSelect }, forwardedRef) => {
394
+ const { t } = useTranslation2();
395
+ const styles = iconHue ? getStyles(iconHue) : void 0;
396
+ const handleSelect = useCallback2((event) => {
397
+ onSelect?.(event.altKey);
398
+ }, [
399
+ onSelect
400
+ ]);
401
+ const handleButtonKeydown = useCallback2((event) => {
402
+ if (event.key === " " || event.key === "Enter") {
403
+ event.preventDefault();
404
+ event.stopPropagation();
465
405
  onSelect?.(event.altKey);
466
- }, [
467
- onSelect
468
- ]);
469
- const handleButtonKeydown = useCallback2((event) => {
470
- if (event.key === " " || event.key === "Enter") {
471
- event.preventDefault();
472
- event.stopPropagation();
473
- onSelect?.(event.altKey);
474
- }
475
- }, [
476
- onSelect
477
- ]);
478
- return /* @__PURE__ */ React5.createElement(TextTooltip, {
479
- text: toLocalizedString(label, t),
480
- side: "bottom",
481
- truncateQuery: "span[data-tooltip]",
482
- onlyWhenTruncating: true,
483
- asChild: true,
484
- ref: forwardedRef
485
- }, /* @__PURE__ */ React5.createElement(Button, {
486
- "data-testid": "treeItem.heading",
487
- variant: "ghost",
488
- density: "fine",
489
- classNames: [
490
- "grow gap-2 pis-0.5 hover:bg-transparent dark:hover:bg-transparent",
491
- "disabled:cursor-default disabled:opacity-100",
492
- className
493
- ],
494
- disabled,
495
- onClick: handleSelect,
496
- onKeyDown: handleButtonKeydown,
497
- ...current && {
498
- "aria-current": "location"
499
- }
500
- }, icon && /* @__PURE__ */ React5.createElement(Icon3, {
501
- icon: icon ?? "ph--placeholder--regular",
502
- size: 5,
503
- classNames: "mlb-1"
504
- }), /* @__PURE__ */ React5.createElement("span", {
505
- className: "flex-1 is-0 truncate text-start text-sm font-normal",
506
- "data-tooltip": true
507
- }, toLocalizedString(label, t))));
508
- } finally {
509
- _effect.f();
510
- }
406
+ }
407
+ }, [
408
+ onSelect
409
+ ]);
410
+ return /* @__PURE__ */ React5.createElement(TextTooltip, {
411
+ text: toLocalizedString(label, t),
412
+ side: "bottom",
413
+ truncateQuery: "span[data-tooltip]",
414
+ onlyWhenTruncating: true,
415
+ asChild: true,
416
+ ref: forwardedRef
417
+ }, /* @__PURE__ */ React5.createElement(Button, {
418
+ "data-testid": "treeItem.heading",
419
+ variant: "ghost",
420
+ density: "fine",
421
+ classNames: [
422
+ "grow gap-2 ps-0.5 hover:bg-transparent dark:hover:bg-transparent",
423
+ "disabled:cursor-default disabled:opacity-100",
424
+ className
425
+ ],
426
+ disabled,
427
+ onClick: handleSelect,
428
+ onKeyDown: handleButtonKeydown,
429
+ ...current && {
430
+ "aria-current": "location"
431
+ }
432
+ }, icon && /* @__PURE__ */ React5.createElement(Icon2, {
433
+ icon: icon ?? "ph--placeholder--regular",
434
+ size: 5,
435
+ classNames: [
436
+ "my-1",
437
+ styles?.surfaceText
438
+ ]
439
+ }), /* @__PURE__ */ React5.createElement("span", {
440
+ className: "flex-1 w-0 truncate text-start font-normal",
441
+ "data-tooltip": true
442
+ }, toLocalizedString(label, t))));
511
443
  }));
512
444
 
513
445
  // src/components/Tree/TreeItemToggle.tsx
514
- import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
515
- import React6, { forwardRef as forwardRef3, memo as memo2 } from "react";
516
- import { Button as Button2, Icon as Icon4 } from "@dxos/react-ui";
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: [
527
- "is-6 pli-0 dx-focus-ring-inset",
528
- hidden ? "hidden" : !isBranch && "invisible"
529
- ],
530
- onClick: onToggle
531
- }, /* @__PURE__ */ React6.createElement(Icon4, {
532
- icon: "ph--caret-right--bold",
533
- size: 3,
534
- classNames: [
535
- "transition duration-200",
536
- open && "rotate-90"
537
- ]
538
- }));
539
- } finally {
540
- _effect.f();
541
- }
446
+ import React6, { forwardRef as forwardRef2, memo as memo2 } from "react";
447
+ import { IconButton as IconButton2 } from "@dxos/react-ui";
448
+ var TreeItemToggle = /* @__PURE__ */ memo2(/* @__PURE__ */ forwardRef2(({ open, isBranch, hidden, classNames, ...props }, forwardedRef) => {
449
+ return /* @__PURE__ */ React6.createElement(IconButton2, {
450
+ ref: forwardedRef,
451
+ "data-testid": "treeItem.toggle",
452
+ "aria-expanded": open,
453
+ variant: "ghost",
454
+ density: "fine",
455
+ classNames: [
456
+ "h-full w-6 px-0",
457
+ "[&_svg]:transition-[transform] [&_svg]:duration-200",
458
+ open && "[&_svg]:rotate-90",
459
+ hidden ? "hidden" : !isBranch && "invisible",
460
+ classNames
461
+ ],
462
+ size: 3,
463
+ icon: "ph--caret-right--bold",
464
+ iconOnly: true,
465
+ noTooltip: true,
466
+ label: open ? "Click to close" : "Click to open",
467
+ tabIndex: -1,
468
+ ...props
469
+ });
542
470
  }));
543
471
 
544
- // src/components/Tree/helpers.ts
545
- var DEFAULT_INDENTATION = 8;
546
- var paddingIndentation = (level, indentation = DEFAULT_INDENTATION) => ({
547
- paddingInlineStart: `${(level - 1) * indentation}px`
548
- });
549
-
550
472
  // src/components/Tree/TreeItem.tsx
551
473
  var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx";
552
474
  var hoverableDescriptionIcons = "[--icons-color:inherit] hover-hover:[--icons-color:var(--description-text)] hover-hover:hover:[--icons-color:inherit] focus-within:[--icons-color:inherit]";
@@ -556,312 +478,333 @@ var TreeDataSchema = Schema.Struct({
556
478
  item: Schema.Any
557
479
  });
558
480
  var isTreeData = (data) => Schema.is(TreeDataSchema)(data);
559
- var RawTreeItem = ({ item, path: _path, last, draggable: _draggable, renderColumns: Columns, canDrop, onOpenChange, onSelect, levelOffset = 2 }) => {
560
- var _effect = _useSignals7();
561
- try {
562
- const rowRef = useRef2(null);
563
- const buttonRef = useRef2(null);
564
- const openRef = useRef2(false);
565
- const cancelExpandRef = useRef2(null);
566
- const [_state, setState] = useState3("idle");
567
- const [instruction, setInstruction] = useState3(null);
568
- const [menuOpen, setMenuOpen] = useState3(false);
569
- const { useItems, getProps, isOpen, isCurrent } = useTree();
570
- const items = useItems(item);
571
- const { id, label, parentOf, icon, disabled, className, headingClassName, testId } = getProps(item, _path);
572
- const path = useMemo(() => [
573
- ..._path,
574
- id
575
- ], [
576
- _path,
577
- id
578
- ]);
579
- const open = isOpen(path, item);
580
- const current = isCurrent(path, item);
581
- const level = path.length - levelOffset;
582
- const isBranch = !!parentOf;
583
- const mode = last ? "last-in-group" : open ? "expanded" : "standard";
584
- const cancelExpand = useCallback3(() => {
585
- if (cancelExpandRef.current) {
586
- clearTimeout(cancelExpandRef.current);
587
- cancelExpandRef.current = null;
588
- }
589
- }, []);
590
- useEffect3(() => {
591
- if (!_draggable) {
592
- return;
593
- }
594
- invariant2(buttonRef.current, void 0, {
595
- F: __dxlog_file2,
596
- L: 105,
597
- S: void 0,
598
- A: [
599
- "buttonRef.current",
600
- ""
601
- ]
602
- });
603
- const data = {
604
- id,
605
- path,
606
- item
607
- };
608
- return combine2(
609
- draggable2({
610
- element: buttonRef.current,
611
- getInitialData: () => data,
612
- onDragStart: () => {
613
- setState("dragging");
614
- if (open) {
615
- openRef.current = true;
616
- onOpenChange?.({
617
- item,
618
- path,
619
- open: false
620
- });
621
- }
622
- },
623
- onDrop: () => {
624
- setState("idle");
625
- if (openRef.current) {
626
- onOpenChange?.({
627
- item,
628
- path,
629
- open: true
630
- });
631
- }
632
- }
633
- }),
634
- // https://github.com/atlassian/pragmatic-drag-and-drop/blob/main/packages/hitbox/constellation/index/about.mdx
635
- dropTargetForElements2({
636
- element: buttonRef.current,
637
- getData: ({ input, element }) => {
638
- return attachInstruction(data, {
639
- input,
640
- element,
641
- indentPerLevel: DEFAULT_INDENTATION,
642
- currentLevel: level,
643
- mode,
644
- block: isBranch ? [] : [
645
- "make-child"
646
- ]
481
+ var RawTreeItem = ({ item, path: pathProp, levelOffset = 2, last, draggable: draggableProp, renderColumns: Columns, blockInstruction, canDrop, canSelect, onOpenChange, onSelect, onItemHover }) => {
482
+ const rowRef = useRef2(null);
483
+ const buttonRef = useRef2(null);
484
+ const openRef = useRef2(false);
485
+ const cancelExpandRef = useRef2(null);
486
+ const [_state, setState] = useState3("idle");
487
+ const [instruction, setInstruction] = useState3(null);
488
+ const [menuOpen, setMenuOpen] = useState3(false);
489
+ const { itemProps: itemPropsAtom, childIds: childIdsAtom, itemOpen: itemOpenAtom, itemCurrent: itemCurrentAtom } = useTree();
490
+ const path = useMemo(() => [
491
+ ...pathProp,
492
+ item.id
493
+ ], [
494
+ pathProp,
495
+ item.id
496
+ ]);
497
+ const { id, parentOf, label, className, headingClassName, icon, iconHue, disabled, testId } = useAtomValue(itemPropsAtom(path));
498
+ const childIds = useAtomValue(childIdsAtom(item.id));
499
+ const open = useAtomValue(itemOpenAtom(path));
500
+ const current = useAtomValue(itemCurrentAtom(path));
501
+ const level = path.length - levelOffset;
502
+ const isBranch = !!parentOf;
503
+ const mode = last ? "last-in-group" : open ? "expanded" : "standard";
504
+ const canSelectItem = canSelect?.({
505
+ item,
506
+ path
507
+ }) ?? true;
508
+ const data = {
509
+ id,
510
+ path,
511
+ item
512
+ };
513
+ const cancelExpand = useCallback3(() => {
514
+ if (cancelExpandRef.current) {
515
+ clearTimeout(cancelExpandRef.current);
516
+ cancelExpandRef.current = null;
517
+ }
518
+ }, []);
519
+ useEffect3(() => {
520
+ if (!draggableProp) {
521
+ return;
522
+ }
523
+ invariant2(buttonRef.current, void 0, {
524
+ F: __dxlog_file2,
525
+ L: 135,
526
+ S: void 0,
527
+ A: [
528
+ "buttonRef.current",
529
+ ""
530
+ ]
531
+ });
532
+ return combine2(
533
+ draggable2({
534
+ element: buttonRef.current,
535
+ getInitialData: () => data,
536
+ onDragStart: () => {
537
+ setState("dragging");
538
+ if (open) {
539
+ openRef.current = true;
540
+ onOpenChange?.({
541
+ item,
542
+ path,
543
+ open: false
647
544
  });
648
- },
649
- canDrop: ({ source }) => {
650
- const _canDrop = canDrop ?? (() => true);
651
- return source.element !== buttonRef.current && _canDrop({
652
- source: source.data,
653
- target: data
545
+ }
546
+ },
547
+ onDrop: () => {
548
+ setState("idle");
549
+ if (openRef.current) {
550
+ onOpenChange?.({
551
+ item,
552
+ path,
553
+ open: true
654
554
  });
655
- },
656
- getIsSticky: () => true,
657
- onDrag: ({ self, source }) => {
658
- const instruction2 = extractInstruction(self.data);
659
- if (source.data.id !== id) {
660
- if (instruction2?.type === "make-child" && isBranch && !open && !cancelExpandRef.current) {
661
- cancelExpandRef.current = setTimeout(() => {
662
- onOpenChange?.({
663
- item,
664
- path,
665
- open: true
666
- });
667
- }, 500);
668
- }
669
- if (instruction2?.type !== "make-child") {
670
- cancelExpand();
671
- }
672
- setInstruction(instruction2);
673
- } else if (instruction2?.type === "reparent") {
674
- setInstruction(instruction2);
675
- } else {
676
- setInstruction(null);
555
+ }
556
+ }
557
+ }),
558
+ // https://github.com/atlassian/pragmatic-drag-and-drop/blob/main/packages/hitbox/constellation/index/about.mdx
559
+ dropTargetForElements2({
560
+ element: buttonRef.current,
561
+ getData: ({ input, element }) => {
562
+ return attachInstruction(data, {
563
+ input,
564
+ element,
565
+ indentPerLevel: DEFAULT_INDENTATION,
566
+ currentLevel: level,
567
+ mode,
568
+ block: isBranch ? [] : [
569
+ "make-child"
570
+ ]
571
+ });
572
+ },
573
+ canDrop: ({ source }) => {
574
+ const _canDrop = canDrop ?? (() => true);
575
+ return source.element !== buttonRef.current && _canDrop({
576
+ source: source.data,
577
+ target: data
578
+ });
579
+ },
580
+ getIsSticky: () => true,
581
+ onDrag: ({ self, source }) => {
582
+ const desired = extractInstruction(self.data);
583
+ const block = desired && blockInstruction?.({
584
+ instruction: desired,
585
+ source: source.data,
586
+ target: data
587
+ });
588
+ const instruction2 = block && desired.type !== "instruction-blocked" ? {
589
+ type: "instruction-blocked",
590
+ desired
591
+ } : desired;
592
+ if (source.data.id !== id) {
593
+ if (instruction2?.type === "make-child" && isBranch && !open && !cancelExpandRef.current) {
594
+ cancelExpandRef.current = setTimeout(() => {
595
+ onOpenChange?.({
596
+ item,
597
+ path,
598
+ open: true
599
+ });
600
+ }, 500);
677
601
  }
678
- },
679
- onDragLeave: () => {
680
- cancelExpand();
681
- setInstruction(null);
682
- },
683
- onDrop: () => {
684
- cancelExpand();
602
+ if (instruction2?.type !== "make-child") {
603
+ cancelExpand();
604
+ }
605
+ setInstruction(instruction2);
606
+ } else if (instruction2?.type === "reparent") {
607
+ setInstruction(instruction2);
608
+ } else {
685
609
  setInstruction(null);
686
610
  }
687
- })
688
- );
689
- }, [
690
- _draggable,
691
- item,
692
- id,
693
- mode,
694
- path,
695
- open,
696
- canDrop
697
- ]);
698
- useEffect3(() => () => cancelExpand(), [
699
- cancelExpand
700
- ]);
701
- const handleOpenChange = useCallback3(() => onOpenChange?.({
702
- item,
703
- path,
704
- open: !open
705
- }), [
706
- onOpenChange,
707
- item,
708
- path,
709
- open
710
- ]);
711
- const handleSelect = useCallback3((option = false) => {
712
- if (isBranch) {
713
- handleOpenChange();
714
- } else {
715
- rowRef.current?.focus();
716
- onSelect?.({
717
- item,
718
- path,
719
- current: !current,
720
- option
721
- });
722
- }
723
- }, [
724
- item,
725
- path,
726
- current,
727
- isBranch,
728
- handleOpenChange,
729
- onSelect
730
- ]);
731
- const handleKeyDown = useCallback3((event) => {
732
- switch (event.key) {
733
- case "ArrowRight":
734
- isBranch && !open && handleOpenChange();
735
- break;
736
- case "ArrowLeft":
737
- isBranch && open && handleOpenChange();
738
- break;
739
- case " ":
740
- handleSelect(event.altKey);
741
- break;
742
- }
743
- }, [
744
- isBranch,
745
- open,
746
- handleOpenChange,
747
- handleSelect
748
- ]);
749
- return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(Treegrid.Row, {
750
- ref: rowRef,
751
- key: id,
752
- id,
753
- "aria-labelledby": `${id}__label`,
754
- parentOf: parentOf?.join(Treegrid.PARENT_OF_SEPARATOR),
755
- classNames: [
756
- "grid grid-cols-subgrid col-[tree-row] mbs-0.5 aria-[current]:bg-activeSurface",
757
- hoverableControls,
758
- hoverableFocusedKeyboardControls,
759
- hoverableFocusedWithinControls,
760
- hoverableDescriptionIcons,
761
- ghostHover,
762
- className
763
- ],
764
- "data-itemid": id,
765
- "data-testid": testId,
766
- // NOTE(thure): This is intentionally an empty string to for descendents to select by in the CSS
767
- // without alerting the user (except for in the correct link element). See also:
768
- // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current#description
769
- "aria-current": current ? "" : void 0,
770
- onKeyDown: handleKeyDown,
771
- onContextMenu: (event) => {
772
- event.preventDefault();
773
- setMenuOpen(true);
774
- }
775
- }, /* @__PURE__ */ React7.createElement(Treegrid.Cell, {
776
- indent: true,
777
- classNames: "relative grid grid-cols-subgrid col-[tree-row]",
778
- style: paddingIndentation(level)
779
- }, /* @__PURE__ */ React7.createElement("div", {
780
- role: "none",
781
- className: "flex items-center"
782
- }, /* @__PURE__ */ React7.createElement(TreeItemToggle, {
783
- isBranch,
784
- open,
785
- onToggle: handleOpenChange
786
- }), /* @__PURE__ */ React7.createElement(TreeItemHeading, {
787
- ref: buttonRef,
788
- label,
789
- icon,
790
- className: headingClassName,
791
- disabled,
792
- current,
793
- onSelect: handleSelect
794
- })), Columns && /* @__PURE__ */ React7.createElement(Columns, {
795
- item,
796
- path,
797
- open,
798
- menuOpen,
799
- setMenuOpen
800
- }), instruction && /* @__PURE__ */ React7.createElement(NaturalTreeItem.DropIndicator, {
801
- instruction,
802
- gap: 2
803
- }))), open && items.map((item2, index) => /* @__PURE__ */ React7.createElement(TreeItem, {
804
- key: item2.id,
805
- item: item2,
806
- path,
807
- last: index === items.length - 1,
808
- draggable: _draggable,
809
- renderColumns: Columns,
810
- canDrop,
811
- onOpenChange,
812
- onSelect
813
- })));
814
- } finally {
815
- _effect.f();
816
- }
611
+ },
612
+ onDragLeave: () => {
613
+ cancelExpand();
614
+ setInstruction(null);
615
+ },
616
+ onDrop: () => {
617
+ cancelExpand();
618
+ setInstruction(null);
619
+ }
620
+ })
621
+ );
622
+ }, [
623
+ draggableProp,
624
+ item,
625
+ id,
626
+ mode,
627
+ path,
628
+ open,
629
+ blockInstruction,
630
+ canDrop
631
+ ]);
632
+ useEffect3(() => () => cancelExpand(), [
633
+ cancelExpand
634
+ ]);
635
+ const handleOpenToggle = useCallback3(() => onOpenChange?.({
636
+ item,
637
+ path,
638
+ open: !open
639
+ }), [
640
+ onOpenChange,
641
+ item,
642
+ path,
643
+ open
644
+ ]);
645
+ const handleSelect = useCallback3((option = false) => {
646
+ if (isBranch && (option || current)) {
647
+ handleOpenToggle();
648
+ } else if (canSelectItem) {
649
+ canSelect?.({
650
+ item,
651
+ path
652
+ });
653
+ rowRef.current?.focus();
654
+ onSelect?.({
655
+ item,
656
+ path,
657
+ current: !current,
658
+ option
659
+ });
660
+ }
661
+ }, [
662
+ item,
663
+ path,
664
+ current,
665
+ isBranch,
666
+ canSelectItem,
667
+ handleOpenToggle,
668
+ onSelect
669
+ ]);
670
+ const handleKeyDown = useCallback3((event) => {
671
+ switch (event.key) {
672
+ case "ArrowRight":
673
+ case "ArrowLeft":
674
+ isBranch && handleOpenToggle();
675
+ break;
676
+ }
677
+ }, [
678
+ isBranch,
679
+ open,
680
+ handleOpenToggle,
681
+ handleSelect
682
+ ]);
683
+ const handleItemHover = useCallback3(() => {
684
+ onItemHover?.({
685
+ item
686
+ });
687
+ }, [
688
+ onItemHover,
689
+ item
690
+ ]);
691
+ const handleContextMenu = useCallback3((event) => {
692
+ event.preventDefault();
693
+ setMenuOpen(true);
694
+ }, [
695
+ setMenuOpen
696
+ ]);
697
+ const childProps = {
698
+ draggable: draggableProp,
699
+ renderColumns: Columns,
700
+ blockInstruction,
701
+ canDrop,
702
+ canSelect,
703
+ onItemHover,
704
+ onOpenChange,
705
+ onSelect
706
+ };
707
+ return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(Treegrid.Row, {
708
+ ref: rowRef,
709
+ key: id,
710
+ id,
711
+ "aria-labelledby": `${id}__label`,
712
+ parentOf: parentOf?.join(Treegrid.PARENT_OF_SEPARATOR),
713
+ "data-object-id": id,
714
+ "data-testid": testId,
715
+ // NOTE(thure): This is intentionally an empty string to for descendents to select by in the CSS
716
+ // without alerting the user (except for in the correct link element). See also:
717
+ // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current#description
718
+ "aria-current": current ? "" : void 0,
719
+ classNames: mx4("grid grid-cols-subgrid col-[tree-row] mt-0.5 is-current:bg-active-surface", hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, hoverableDescriptionIcons, ghostFocusWithin, ghostHover, className),
720
+ onKeyDown: handleKeyDown,
721
+ onMouseEnter: handleItemHover,
722
+ onContextMenu: handleContextMenu
723
+ }, /* @__PURE__ */ React7.createElement("div", {
724
+ role: "none",
725
+ className: "indent relative grid grid-cols-subgrid col-[tree-row]",
726
+ style: paddingIndentation(level)
727
+ }, /* @__PURE__ */ React7.createElement(Treegrid.Cell, {
728
+ classNames: "flex items-center"
729
+ }, /* @__PURE__ */ React7.createElement(TreeItemToggle, {
730
+ isBranch,
731
+ open,
732
+ onClick: handleOpenToggle
733
+ }), /* @__PURE__ */ React7.createElement(TreeItemHeading, {
734
+ disabled,
735
+ current,
736
+ label,
737
+ className: headingClassName,
738
+ icon,
739
+ iconHue,
740
+ onSelect: handleSelect,
741
+ ref: buttonRef
742
+ })), Columns && /* @__PURE__ */ React7.createElement(Columns, {
743
+ item,
744
+ path,
745
+ open,
746
+ menuOpen,
747
+ setMenuOpen
748
+ }), instruction && /* @__PURE__ */ React7.createElement(NaturalTreeItem.DropIndicator, {
749
+ instruction,
750
+ gap: 2
751
+ }))), open && childIds.map((childId, index) => /* @__PURE__ */ React7.createElement(TreeItemById, {
752
+ key: childId,
753
+ id: childId,
754
+ path,
755
+ last: index === childIds.length - 1,
756
+ ...childProps
757
+ })));
817
758
  };
818
759
  var TreeItem = /* @__PURE__ */ memo3(RawTreeItem);
760
+ var RawTreeItemById = ({ id, ...props }) => {
761
+ const { item: itemAtom } = useTree();
762
+ const item = useAtomValue(itemAtom(id));
763
+ if (!item) {
764
+ return null;
765
+ }
766
+ return /* @__PURE__ */ React7.createElement(TreeItem, {
767
+ item,
768
+ ...props
769
+ });
770
+ };
771
+ var TreeItemById = /* @__PURE__ */ memo3(RawTreeItemById);
819
772
 
820
773
  // src/components/Tree/Tree.tsx
821
- 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 }) => {
822
- var _effect = _useSignals8();
823
- try {
824
- const context = useMemo2(() => ({
825
- useItems,
826
- getProps,
827
- isOpen,
828
- isCurrent
829
- }), [
830
- useItems,
831
- getProps,
832
- isOpen,
833
- isCurrent
834
- ]);
835
- const items = useItems(root);
836
- const treePath = useMemo2(() => path ? [
837
- ...path,
838
- id
839
- ] : [
840
- id
841
- ], [
842
- id,
843
- path
844
- ]);
845
- return /* @__PURE__ */ React8.createElement(Treegrid2.Root, {
846
- gridTemplateColumns,
847
- classNames
848
- }, /* @__PURE__ */ React8.createElement(TreeProvider, {
849
- value: context
850
- }, items.map((item, index) => /* @__PURE__ */ React8.createElement(TreeItem, {
851
- key: item.id,
852
- item,
853
- last: index === items.length - 1,
854
- path: treePath,
855
- levelOffset,
856
- draggable: draggable3,
857
- renderColumns,
858
- canDrop,
859
- onOpenChange,
860
- onSelect
861
- }))));
862
- } finally {
863
- _effect.f();
864
- }
774
+ 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 }) => {
775
+ const childIds = useAtomValue2(model.childIds(rootId));
776
+ const treePath = useMemo2(() => path ? [
777
+ ...path,
778
+ id
779
+ ] : [
780
+ id
781
+ ], [
782
+ id,
783
+ path
784
+ ]);
785
+ const childProps = {
786
+ path: treePath,
787
+ levelOffset,
788
+ draggable: draggable3,
789
+ renderColumns,
790
+ blockInstruction,
791
+ canDrop,
792
+ canSelect,
793
+ onOpenChange,
794
+ onSelect,
795
+ onItemHover
796
+ };
797
+ return /* @__PURE__ */ React8.createElement(Treegrid2.Root, {
798
+ gridTemplateColumns,
799
+ classNames
800
+ }, /* @__PURE__ */ React8.createElement(TreeProvider, {
801
+ value: model
802
+ }, childIds.map((childId, index) => /* @__PURE__ */ React8.createElement(TreeItemById, {
803
+ key: childId,
804
+ id: childId,
805
+ last: index === childIds.length - 1,
806
+ ...childProps
807
+ }))));
865
808
  };
866
809
 
867
810
  // src/util/path.ts
@@ -881,13 +824,17 @@ var Path = {
881
824
  };
882
825
  export {
883
826
  Accordion,
827
+ DEFAULT_INDENTATION,
884
828
  List,
885
829
  Path,
886
830
  Tree,
887
831
  TreeDataSchema,
888
832
  TreeItem,
833
+ TreeItemById,
834
+ TreeItemToggle,
889
835
  TreeProvider,
890
836
  isTreeData,
837
+ paddingIndentation,
891
838
  useTree
892
839
  };
893
840
  //# sourceMappingURL=index.mjs.map