@dxos/react-ui-list 0.8.4-main.72ec0f3 → 0.8.4-main.74a063c4e0

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