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

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