@dxos/react-ui-list 0.8.4-main.c4373fc → 0.8.4-main.d05673bc65

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