@dxos/react-ui-list 0.6.13-main.548ca8d → 0.6.14-main.1366248
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.
- package/dist/lib/browser/index.mjs +413 -31
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/List/List.d.ts +1 -1
- package/dist/types/src/components/List/List.d.ts.map +1 -1
- package/dist/types/src/components/List/List.stories.d.ts +6 -10
- package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
- package/dist/types/src/components/List/ListItem.d.ts +1 -3
- package/dist/types/src/components/List/ListItem.d.ts.map +1 -1
- package/dist/types/src/components/List/ListRoot.d.ts +5 -3
- package/dist/types/src/components/List/ListRoot.d.ts.map +1 -1
- package/dist/types/src/components/List/testing.d.ts.map +1 -0
- package/dist/types/src/components/Tree/DropIndicator.d.ts +7 -0
- package/dist/types/src/components/Tree/DropIndicator.d.ts.map +1 -0
- package/dist/types/src/components/Tree/Tree.d.ts +24 -0
- package/dist/types/src/components/Tree/Tree.d.ts.map +1 -0
- package/dist/types/src/components/Tree/Tree.stories.d.ts +8 -0
- package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -0
- package/dist/types/src/components/Tree/TreeItem.d.ts +34 -0
- package/dist/types/src/components/Tree/TreeItem.d.ts.map +1 -0
- package/dist/types/src/components/Tree/TreeItemHeading.d.ts +12 -0
- package/dist/types/src/components/Tree/TreeItemHeading.d.ts.map +1 -0
- package/dist/types/src/components/Tree/TreeItemToggle.d.ts +8 -0
- package/dist/types/src/components/Tree/TreeItemToggle.d.ts.map +1 -0
- package/dist/types/src/components/Tree/helpers.d.ts +8 -0
- package/dist/types/src/components/Tree/helpers.d.ts.map +1 -0
- package/dist/types/src/components/Tree/index.d.ts +4 -0
- package/dist/types/src/components/Tree/index.d.ts.map +1 -0
- package/dist/types/src/components/Tree/testing.d.ts +26 -0
- package/dist/types/src/components/Tree/testing.d.ts.map +1 -0
- package/dist/types/src/components/Tree/types.d.ts +18 -0
- package/dist/types/src/components/Tree/types.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/package.json +20 -15
- package/src/components/List/List.stories.tsx +25 -19
- package/src/components/List/ListItem.tsx +11 -9
- package/src/components/List/ListRoot.tsx +47 -23
- package/src/components/Tree/DropIndicator.tsx +79 -0
- package/src/components/Tree/Tree.stories.tsx +116 -0
- package/src/components/Tree/Tree.tsx +56 -0
- package/src/components/Tree/TreeItem.tsx +237 -0
- package/src/components/Tree/TreeItemHeading.tsx +62 -0
- package/src/components/Tree/TreeItemToggle.tsx +35 -0
- package/src/components/Tree/helpers.ts +25 -0
- package/src/components/Tree/index.ts +7 -0
- package/src/components/Tree/testing.ts +170 -0
- package/src/components/Tree/types.ts +34 -0
- package/src/components/index.ts +1 -0
- package/dist/types/src/testing.d.ts.map +0 -1
- /package/dist/types/src/{testing.d.ts → components/List/testing.d.ts} +0 -0
- /package/src/{testing.ts → components/List/testing.ts} +0 -0
|
@@ -32,8 +32,8 @@ var edgeStyles = {
|
|
|
32
32
|
var strokeSize = 2;
|
|
33
33
|
var terminalSize = 8;
|
|
34
34
|
var offsetToAlignTerminalWithLine = (strokeSize - terminalSize) / 2;
|
|
35
|
-
var DropIndicator = ({ edge, gap = "0px" }) => {
|
|
36
|
-
const lineOffset = `calc(-0.5 * (${
|
|
35
|
+
var DropIndicator = ({ edge, gap: gap2 = "0px" }) => {
|
|
36
|
+
const lineOffset = `calc(-0.5 * (${gap2} + ${strokeSize}px))`;
|
|
37
37
|
const orientation = edgeToOrientationMap[edge];
|
|
38
38
|
return /* @__PURE__ */ React.createElement("div", {
|
|
39
39
|
style: {
|
|
@@ -51,19 +51,31 @@ var DropIndicator = ({ edge, gap = "0px" }) => {
|
|
|
51
51
|
// packages/ui/react-ui-list/src/components/List/ListRoot.tsx
|
|
52
52
|
import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
|
53
53
|
import { extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
|
|
54
|
-
import {
|
|
54
|
+
import { getReorderDestinationIndex } from "@atlaskit/pragmatic-drag-and-drop-hitbox/util/get-reorder-destination-index";
|
|
55
55
|
import { createContext } from "@radix-ui/react-context";
|
|
56
|
-
import React2, { useEffect, useState } from "react";
|
|
57
|
-
import { flushSync } from "react-dom";
|
|
58
|
-
import { useControlledValue } from "@dxos/react-ui";
|
|
56
|
+
import React2, { useCallback, useEffect, useState } from "react";
|
|
59
57
|
var LIST_NAME = "List";
|
|
60
58
|
var [ListProvider, useListContext] = createContext(LIST_NAME);
|
|
61
|
-
var
|
|
62
|
-
|
|
59
|
+
var defaultGetId = (item) => item?.id;
|
|
60
|
+
var ListRoot = ({ classNames, children, items, isItem: isItem2, getId = defaultGetId, onMove, ...props }) => {
|
|
61
|
+
const isEqual = useCallback((a, b) => {
|
|
62
|
+
const idA = getId?.(a);
|
|
63
|
+
const idB = getId?.(b);
|
|
64
|
+
if (idA !== void 0 && idB !== void 0) {
|
|
65
|
+
return idA === idB;
|
|
66
|
+
} else {
|
|
67
|
+
return a === b;
|
|
68
|
+
}
|
|
69
|
+
}, [
|
|
70
|
+
getId
|
|
71
|
+
]);
|
|
63
72
|
const [state, setState] = useState(idle);
|
|
64
73
|
useEffect(() => {
|
|
74
|
+
if (!items) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
65
77
|
return monitorForElements({
|
|
66
|
-
canMonitor: ({ source }) =>
|
|
78
|
+
canMonitor: ({ source }) => isItem2(source.data),
|
|
67
79
|
onDrop: ({ location, source }) => {
|
|
68
80
|
const target = location.current.dropTargets[0];
|
|
69
81
|
if (!target) {
|
|
@@ -71,37 +83,37 @@ var ListRoot = ({ classNames, children, items: _items = [], isItem, ...props })
|
|
|
71
83
|
}
|
|
72
84
|
const sourceData = source.data;
|
|
73
85
|
const targetData = target.data;
|
|
74
|
-
if (!
|
|
86
|
+
if (!isItem2(sourceData) || !isItem2(targetData)) {
|
|
75
87
|
return;
|
|
76
88
|
}
|
|
77
|
-
const sourceIdx = items.findIndex((item) => item
|
|
78
|
-
const targetIdx = items.findIndex((item) => item
|
|
89
|
+
const sourceIdx = items.findIndex((item) => isEqual(item, sourceData));
|
|
90
|
+
const targetIdx = items.findIndex((item) => isEqual(item, targetData));
|
|
79
91
|
if (targetIdx < 0 || sourceIdx < 0) {
|
|
80
92
|
return;
|
|
81
93
|
}
|
|
82
94
|
const closestEdgeOfTarget = extractClosestEdge(targetData);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
axis: "vertical",
|
|
89
|
-
closestEdgeOfTarget
|
|
90
|
-
}));
|
|
95
|
+
const destinationIndex = getReorderDestinationIndex({
|
|
96
|
+
closestEdgeOfTarget,
|
|
97
|
+
startIndex: sourceIdx,
|
|
98
|
+
indexOfTarget: targetIdx,
|
|
99
|
+
axis: "vertical"
|
|
91
100
|
});
|
|
101
|
+
onMove?.(sourceIdx, destinationIndex);
|
|
92
102
|
}
|
|
93
103
|
});
|
|
94
104
|
}, [
|
|
95
|
-
items
|
|
105
|
+
items,
|
|
106
|
+
isEqual,
|
|
107
|
+
onMove
|
|
96
108
|
]);
|
|
97
109
|
return /* @__PURE__ */ React2.createElement(ListProvider, {
|
|
98
|
-
isItem,
|
|
110
|
+
isItem: isItem2,
|
|
99
111
|
state,
|
|
100
112
|
setState,
|
|
101
113
|
...props
|
|
102
114
|
}, children?.({
|
|
103
115
|
state,
|
|
104
|
-
items
|
|
116
|
+
items: items ?? []
|
|
105
117
|
}));
|
|
106
118
|
};
|
|
107
119
|
|
|
@@ -117,7 +129,7 @@ var defaultContext = {};
|
|
|
117
129
|
var LIST_ITEM_NAME = "ListItem";
|
|
118
130
|
var [ListItemProvider, useListItemContext] = createContext2(LIST_ITEM_NAME, defaultContext);
|
|
119
131
|
var ListItem = ({ children, classNames, item }) => {
|
|
120
|
-
const { isItem, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
|
|
132
|
+
const { isItem: isItem2, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
|
|
121
133
|
const ref = useRef(null);
|
|
122
134
|
const dragHandleRef = useRef(null);
|
|
123
135
|
const [state, setState] = useState2(idle);
|
|
@@ -125,7 +137,7 @@ var ListItem = ({ children, classNames, item }) => {
|
|
|
125
137
|
const element = ref.current;
|
|
126
138
|
invariant(element, void 0, {
|
|
127
139
|
F: __dxlog_file,
|
|
128
|
-
L:
|
|
140
|
+
L: 91,
|
|
129
141
|
S: void 0,
|
|
130
142
|
A: [
|
|
131
143
|
"element",
|
|
@@ -185,7 +197,7 @@ var ListItem = ({ children, classNames, item }) => {
|
|
|
185
197
|
dropTargetForElements({
|
|
186
198
|
element,
|
|
187
199
|
canDrop: ({ source }) => {
|
|
188
|
-
return source.element !== element &&
|
|
200
|
+
return source.element !== element && isItem2(source.data);
|
|
189
201
|
},
|
|
190
202
|
getData: ({ input }) => {
|
|
191
203
|
return attachClosestEdge(item, {
|
|
@@ -236,7 +248,7 @@ var ListItem = ({ children, classNames, item }) => {
|
|
|
236
248
|
}, /* @__PURE__ */ React3.createElement("div", {
|
|
237
249
|
ref,
|
|
238
250
|
role: "listitem",
|
|
239
|
-
className: mx2("flex", classNames, stateStyles[state.type])
|
|
251
|
+
className: mx2("flex overflow-hidden", classNames, stateStyles[state.type])
|
|
240
252
|
}, children), state.type === "is-dragging-over" && state.closestEdge && /* @__PURE__ */ React3.createElement(DropIndicator, {
|
|
241
253
|
edge: state.closestEdge
|
|
242
254
|
})));
|
|
@@ -269,7 +281,7 @@ var ListItemDragHandle = () => {
|
|
|
269
281
|
const { dragHandleRef } = useListItemContext("DRAG_HANDLE");
|
|
270
282
|
return /* @__PURE__ */ React3.createElement(IconButton, {
|
|
271
283
|
ref: dragHandleRef,
|
|
272
|
-
icon: "ph--dots-six--regular"
|
|
284
|
+
icon: "ph--dots-six-vertical--regular"
|
|
273
285
|
});
|
|
274
286
|
};
|
|
275
287
|
var ListItemDragPreview = ({ children }) => {
|
|
@@ -279,10 +291,10 @@ var ListItemDragPreview = ({ children }) => {
|
|
|
279
291
|
}), state.container) : null;
|
|
280
292
|
};
|
|
281
293
|
var ListItemWrapper = ({ classNames, children }) => /* @__PURE__ */ React3.createElement("div", {
|
|
282
|
-
className: mx2("flex
|
|
294
|
+
className: mx2("flex is-full gap-2", classNames)
|
|
283
295
|
}, children);
|
|
284
296
|
var ListItemTitle = ({ classNames, children, ...props }) => /* @__PURE__ */ React3.createElement("div", {
|
|
285
|
-
className: mx2("flex
|
|
297
|
+
className: mx2("flex grow items-center truncate", classNames),
|
|
286
298
|
...props
|
|
287
299
|
}, children);
|
|
288
300
|
|
|
@@ -297,7 +309,377 @@ var List = {
|
|
|
297
309
|
ItemTitle: ListItemTitle,
|
|
298
310
|
IconButton
|
|
299
311
|
};
|
|
312
|
+
|
|
313
|
+
// packages/ui/react-ui-list/src/components/Tree/Tree.tsx
|
|
314
|
+
import React8 from "react";
|
|
315
|
+
import { Treegrid as Treegrid2 } from "@dxos/react-ui";
|
|
316
|
+
import { Path } from "@dxos/react-ui-mosaic";
|
|
317
|
+
|
|
318
|
+
// packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx
|
|
319
|
+
import { combine as combine2 } from "@atlaskit/pragmatic-drag-and-drop/combine";
|
|
320
|
+
import { draggable as draggable2, dropTargetForElements as dropTargetForElements2 } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
|
321
|
+
import { attachInstruction, extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item";
|
|
322
|
+
import React7, { memo as memo3, useCallback as useCallback3, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
323
|
+
import { invariant as invariant2 } from "@dxos/invariant";
|
|
324
|
+
import { Treegrid } from "@dxos/react-ui";
|
|
325
|
+
import { focusRing, hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, mx as mx6 } from "@dxos/react-ui-theme";
|
|
326
|
+
|
|
327
|
+
// packages/ui/react-ui-list/src/components/Tree/DropIndicator.tsx
|
|
328
|
+
import React4 from "react";
|
|
329
|
+
import { mx as mx3 } from "@dxos/react-ui-theme";
|
|
330
|
+
var edgeToOrientationMap2 = {
|
|
331
|
+
"reorder-above": "sibling",
|
|
332
|
+
"reorder-below": "sibling",
|
|
333
|
+
"make-child": "child",
|
|
334
|
+
reparent: "child"
|
|
335
|
+
};
|
|
336
|
+
var orientationStyles2 = {
|
|
337
|
+
// TODO(wittjosiah): Stop using left/right here.
|
|
338
|
+
sibling: "bs-[--line-thickness] left-[--horizontal-indent] right-0 bg-accentSurface before:left-[--negative-terminal-size]",
|
|
339
|
+
child: "is-full block-start-0 block-end-0 border-[length:--line-thickness] before:invisible"
|
|
340
|
+
};
|
|
341
|
+
var instructionStyles = {
|
|
342
|
+
"reorder-above": "block-start-[--line-offset] before:block-start-[--offset-terminal]",
|
|
343
|
+
"reorder-below": "block-end-[--line-offset] before:block-end-[--offset-terminal]",
|
|
344
|
+
"make-child": "border-accentSurface",
|
|
345
|
+
// TODO(wittjosiah): This is not occurring in the current implementation.
|
|
346
|
+
reparent: ""
|
|
347
|
+
};
|
|
348
|
+
var strokeSize2 = 2;
|
|
349
|
+
var terminalSize2 = 8;
|
|
350
|
+
var offsetToAlignTerminalWithLine2 = (strokeSize2 - terminalSize2) / 2;
|
|
351
|
+
var gap = "0px";
|
|
352
|
+
var DropIndicator2 = ({ instruction }) => {
|
|
353
|
+
const lineOffset = `calc(-0.5 * (${gap} + ${strokeSize2}px))`;
|
|
354
|
+
const isBlocked = instruction.type === "instruction-blocked";
|
|
355
|
+
const desiredInstruction = isBlocked ? instruction.desired : instruction;
|
|
356
|
+
const orientation = edgeToOrientationMap2[desiredInstruction.type];
|
|
357
|
+
if (isBlocked) {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
361
|
+
style: {
|
|
362
|
+
"--line-thickness": `${strokeSize2}px`,
|
|
363
|
+
"--line-offset": `${lineOffset}`,
|
|
364
|
+
"--terminal-size": `${terminalSize2}px`,
|
|
365
|
+
"--terminal-radius": `${terminalSize2 / 2}px`,
|
|
366
|
+
"--negative-terminal-size": `-${terminalSize2}px`,
|
|
367
|
+
"--offset-terminal": `${offsetToAlignTerminalWithLine2}px`,
|
|
368
|
+
"--horizontal-indent": `${desiredInstruction.currentLevel * desiredInstruction.indentPerLevel + 4}px`
|
|
369
|
+
},
|
|
370
|
+
className: mx3("absolute z-10 pointer-events-none", "before:is-[--terminal-size] before:bs-[--terminal-size] box-border before:absolute", "before:border-[length:--line-thickness] before:border-solid before:border-accentSurface before:rounded-full", orientationStyles2[orientation], instructionStyles[desiredInstruction.type])
|
|
371
|
+
});
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
// packages/ui/react-ui-list/src/components/Tree/TreeItemHeading.tsx
|
|
375
|
+
import React5, { forwardRef as forwardRef2, memo, useCallback as useCallback2 } from "react";
|
|
376
|
+
import { Button, Icon as Icon2, toLocalizedString, useTranslation } from "@dxos/react-ui";
|
|
377
|
+
import { TextTooltip } from "@dxos/react-ui-text-tooltip";
|
|
378
|
+
import { mx as mx4 } from "@dxos/react-ui-theme";
|
|
379
|
+
var TreeItemHeading = /* @__PURE__ */ memo(/* @__PURE__ */ forwardRef2(({ label, icon, className, disabled, current, onSelect }, forwardedRef) => {
|
|
380
|
+
const { t } = useTranslation();
|
|
381
|
+
const handleButtonKeydown = useCallback2((event) => {
|
|
382
|
+
if (event.key === " " || event.key === "Enter") {
|
|
383
|
+
event.preventDefault();
|
|
384
|
+
event.stopPropagation();
|
|
385
|
+
onSelect?.();
|
|
386
|
+
}
|
|
387
|
+
}, [
|
|
388
|
+
onSelect
|
|
389
|
+
]);
|
|
390
|
+
return /* @__PURE__ */ React5.createElement(TextTooltip, {
|
|
391
|
+
text: toLocalizedString(label, t),
|
|
392
|
+
side: "bottom",
|
|
393
|
+
truncateQuery: "span[data-tooltip]",
|
|
394
|
+
onlyWhenTruncating: true,
|
|
395
|
+
asChild: true,
|
|
396
|
+
ref: forwardedRef
|
|
397
|
+
}, /* @__PURE__ */ React5.createElement(Button, {
|
|
398
|
+
"data-testid": "treeItem.heading",
|
|
399
|
+
variant: "ghost",
|
|
400
|
+
density: "fine",
|
|
401
|
+
classNames: mx4("grow gap-1 !pis-0.5 hover:!bg-transparent dark:hover:!bg-transparent", className),
|
|
402
|
+
disabled,
|
|
403
|
+
onClick: onSelect,
|
|
404
|
+
onKeyDown: handleButtonKeydown,
|
|
405
|
+
...current && {
|
|
406
|
+
"aria-current": "location"
|
|
407
|
+
}
|
|
408
|
+
}, icon && /* @__PURE__ */ React5.createElement(Icon2, {
|
|
409
|
+
icon: icon ?? "ph--placeholder--regular",
|
|
410
|
+
size: 4,
|
|
411
|
+
classNames: "is-[1em] bs-[1em] mlb-1"
|
|
412
|
+
}), /* @__PURE__ */ React5.createElement("span", {
|
|
413
|
+
className: "flex-1 is-0 truncate text-start text-sm font-normal"
|
|
414
|
+
}, toLocalizedString(label, t))));
|
|
415
|
+
}));
|
|
416
|
+
|
|
417
|
+
// packages/ui/react-ui-list/src/components/Tree/TreeItemToggle.tsx
|
|
418
|
+
import React6, { forwardRef as forwardRef3, memo as memo2 } from "react";
|
|
419
|
+
import { Button as Button2, Icon as Icon3 } from "@dxos/react-ui";
|
|
420
|
+
import { mx as mx5 } from "@dxos/react-ui-theme";
|
|
421
|
+
var TreeItemToggle = /* @__PURE__ */ memo2(/* @__PURE__ */ forwardRef3(({ open, isBranch, onToggle }, forwardedRef) => {
|
|
422
|
+
return /* @__PURE__ */ React6.createElement(Button2, {
|
|
423
|
+
ref: forwardedRef,
|
|
424
|
+
"data-testid": "treeItem.toggle",
|
|
425
|
+
variant: "ghost",
|
|
426
|
+
density: "fine",
|
|
427
|
+
classNames: mx5("!pli-1", !isBranch && "invisible"),
|
|
428
|
+
onClick: onToggle
|
|
429
|
+
}, /* @__PURE__ */ React6.createElement(Icon3, {
|
|
430
|
+
icon: "ph--caret-right--regular",
|
|
431
|
+
size: 3,
|
|
432
|
+
classNames: mx5("transition duration-200", open && "rotate-90")
|
|
433
|
+
}));
|
|
434
|
+
}));
|
|
435
|
+
|
|
436
|
+
// packages/ui/react-ui-list/src/components/Tree/helpers.ts
|
|
437
|
+
var DEFAULT_INDENTATION = 8;
|
|
438
|
+
var paddingIndendation = (level, indentation = DEFAULT_INDENTATION) => ({
|
|
439
|
+
paddingInlineStart: `${(level - 1) * indentation}px`
|
|
440
|
+
});
|
|
441
|
+
var getMode = (items, index) => {
|
|
442
|
+
const item = items[index];
|
|
443
|
+
const next = items[index + 1];
|
|
444
|
+
if (!next || item.path.length > next.path.length) {
|
|
445
|
+
return "last-in-group";
|
|
446
|
+
} else if (item.path.length < next.path.length) {
|
|
447
|
+
return "expanded";
|
|
448
|
+
} else {
|
|
449
|
+
return "standard";
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
// packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx
|
|
454
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx";
|
|
455
|
+
var hoverableDescriptionIcons = "[--icons-color:inherit] hover-hover:[--icons-color:var(--description-text)] hover-hover:hover:[--icons-color:inherit] focus-within:[--icons-color:inherit]";
|
|
456
|
+
var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderColumns: Columns, canDrop, onOpenChange, onSelect }) => {
|
|
457
|
+
const { id, label, icon, className, headingClassName, disabled, path, parentOf } = item;
|
|
458
|
+
const level = path.length - 2;
|
|
459
|
+
const isBranch = !!parentOf;
|
|
460
|
+
const rowRef = useRef2(null);
|
|
461
|
+
const buttonRef = useRef2(null);
|
|
462
|
+
const openRef = useRef2(false);
|
|
463
|
+
const cancelExpandRef = useRef2(null);
|
|
464
|
+
const [_state, setState] = useState3("idle");
|
|
465
|
+
const [instruction, setInstruction] = useState3(null);
|
|
466
|
+
const [menuOpen, setMenuOpen] = useState3(false);
|
|
467
|
+
const cancelExpand = useCallback3(() => {
|
|
468
|
+
if (cancelExpandRef.current) {
|
|
469
|
+
clearTimeout(cancelExpandRef.current);
|
|
470
|
+
cancelExpandRef.current = null;
|
|
471
|
+
}
|
|
472
|
+
}, []);
|
|
473
|
+
useEffect3(() => {
|
|
474
|
+
if (!_draggable) {
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
invariant2(buttonRef.current, void 0, {
|
|
478
|
+
F: __dxlog_file2,
|
|
479
|
+
L: 86,
|
|
480
|
+
S: void 0,
|
|
481
|
+
A: [
|
|
482
|
+
"buttonRef.current",
|
|
483
|
+
""
|
|
484
|
+
]
|
|
485
|
+
});
|
|
486
|
+
return combine2(draggable2({
|
|
487
|
+
element: buttonRef.current,
|
|
488
|
+
getInitialData: () => item,
|
|
489
|
+
onDragStart: () => {
|
|
490
|
+
setState("dragging");
|
|
491
|
+
if (open) {
|
|
492
|
+
openRef.current = true;
|
|
493
|
+
onOpenChange?.(item, false);
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
onDrop: () => {
|
|
497
|
+
setState("idle");
|
|
498
|
+
if (openRef.current) {
|
|
499
|
+
onOpenChange?.(item, true);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}), dropTargetForElements2({
|
|
503
|
+
element: buttonRef.current,
|
|
504
|
+
getData: ({ input, element }) => {
|
|
505
|
+
return attachInstruction(item, {
|
|
506
|
+
input,
|
|
507
|
+
element,
|
|
508
|
+
indentPerLevel: DEFAULT_INDENTATION,
|
|
509
|
+
currentLevel: level,
|
|
510
|
+
mode,
|
|
511
|
+
block: isBranch ? [] : [
|
|
512
|
+
"make-child"
|
|
513
|
+
]
|
|
514
|
+
});
|
|
515
|
+
},
|
|
516
|
+
canDrop: ({ source }) => {
|
|
517
|
+
const _canDrop = canDrop ?? (() => true);
|
|
518
|
+
return source.element !== buttonRef.current && _canDrop(source.data, item);
|
|
519
|
+
},
|
|
520
|
+
getIsSticky: () => true,
|
|
521
|
+
onDrag: ({ self, source }) => {
|
|
522
|
+
const instruction2 = extractInstruction(self.data);
|
|
523
|
+
if (source.data.id !== item.id) {
|
|
524
|
+
if (instruction2?.type === "make-child" && isBranch && !open && !cancelExpandRef.current) {
|
|
525
|
+
cancelExpandRef.current = setTimeout(() => {
|
|
526
|
+
onOpenChange?.(item, true);
|
|
527
|
+
}, 500);
|
|
528
|
+
}
|
|
529
|
+
if (instruction2?.type !== "make-child") {
|
|
530
|
+
cancelExpand();
|
|
531
|
+
}
|
|
532
|
+
setInstruction(instruction2);
|
|
533
|
+
} else if (instruction2?.type === "reparent") {
|
|
534
|
+
setInstruction(instruction2);
|
|
535
|
+
} else {
|
|
536
|
+
setInstruction(null);
|
|
537
|
+
}
|
|
538
|
+
},
|
|
539
|
+
onDragLeave: () => {
|
|
540
|
+
cancelExpand();
|
|
541
|
+
setInstruction(null);
|
|
542
|
+
},
|
|
543
|
+
onDrop: () => {
|
|
544
|
+
cancelExpand();
|
|
545
|
+
setInstruction(null);
|
|
546
|
+
}
|
|
547
|
+
}));
|
|
548
|
+
}, [
|
|
549
|
+
draggable2,
|
|
550
|
+
item,
|
|
551
|
+
mode,
|
|
552
|
+
open,
|
|
553
|
+
canDrop
|
|
554
|
+
]);
|
|
555
|
+
useEffect3(() => () => cancelExpand(), [
|
|
556
|
+
cancelExpand
|
|
557
|
+
]);
|
|
558
|
+
const handleOpenChange = useCallback3(() => onOpenChange?.(item, !open), [
|
|
559
|
+
onOpenChange,
|
|
560
|
+
item,
|
|
561
|
+
open
|
|
562
|
+
]);
|
|
563
|
+
const handleSelect = useCallback3(() => {
|
|
564
|
+
rowRef.current?.focus();
|
|
565
|
+
onSelect?.(item, !current);
|
|
566
|
+
}, [
|
|
567
|
+
onSelect,
|
|
568
|
+
item,
|
|
569
|
+
current
|
|
570
|
+
]);
|
|
571
|
+
const handleKeyDown = useCallback3((event) => {
|
|
572
|
+
switch (event.key) {
|
|
573
|
+
case "ArrowRight":
|
|
574
|
+
isBranch && !open && handleOpenChange();
|
|
575
|
+
break;
|
|
576
|
+
case "ArrowLeft":
|
|
577
|
+
isBranch && open && handleOpenChange();
|
|
578
|
+
break;
|
|
579
|
+
case " ":
|
|
580
|
+
handleSelect();
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
}, [
|
|
584
|
+
isBranch,
|
|
585
|
+
open,
|
|
586
|
+
handleOpenChange,
|
|
587
|
+
handleSelect
|
|
588
|
+
]);
|
|
589
|
+
return /* @__PURE__ */ React7.createElement(Treegrid.Row, {
|
|
590
|
+
ref: rowRef,
|
|
591
|
+
key: id,
|
|
592
|
+
id,
|
|
593
|
+
"aria-labelledby": `${id}__label`,
|
|
594
|
+
parentOf: parentOf?.join(Treegrid.PARENT_OF_SEPARATOR),
|
|
595
|
+
classNames: mx6("grid grid-cols-subgrid col-[tree-row] aria-[current]:bg-input", hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, hoverableDescriptionIcons, focusRing, className),
|
|
596
|
+
"data-itemid": item.id,
|
|
597
|
+
"data-testid": item.testId,
|
|
598
|
+
// NOTE(thure): This is intentionally an empty string to for descendents to select by in the CSS
|
|
599
|
+
// without alerting the user (except for in the correct link element). See also:
|
|
600
|
+
// https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current#description
|
|
601
|
+
"aria-current": current ? "" : void 0,
|
|
602
|
+
onKeyDown: handleKeyDown,
|
|
603
|
+
onContextMenu: (event) => {
|
|
604
|
+
event.preventDefault();
|
|
605
|
+
setMenuOpen(true);
|
|
606
|
+
}
|
|
607
|
+
}, /* @__PURE__ */ React7.createElement(Treegrid.Cell, {
|
|
608
|
+
indent: true,
|
|
609
|
+
classNames: "relative grid grid-cols-subgrid col-[tree-row]",
|
|
610
|
+
style: paddingIndendation(level)
|
|
611
|
+
}, /* @__PURE__ */ React7.createElement("div", {
|
|
612
|
+
role: "none",
|
|
613
|
+
className: "flex items-center"
|
|
614
|
+
}, /* @__PURE__ */ React7.createElement(TreeItemToggle, {
|
|
615
|
+
open,
|
|
616
|
+
isBranch,
|
|
617
|
+
onToggle: handleOpenChange
|
|
618
|
+
}), /* @__PURE__ */ React7.createElement(TreeItemHeading, {
|
|
619
|
+
ref: buttonRef,
|
|
620
|
+
label,
|
|
621
|
+
icon,
|
|
622
|
+
className: headingClassName,
|
|
623
|
+
disabled,
|
|
624
|
+
current,
|
|
625
|
+
onSelect: handleSelect
|
|
626
|
+
})), Columns && /* @__PURE__ */ React7.createElement(Columns, {
|
|
627
|
+
item,
|
|
628
|
+
menuOpen,
|
|
629
|
+
setMenuOpen
|
|
630
|
+
}), instruction && /* @__PURE__ */ React7.createElement(DropIndicator2, {
|
|
631
|
+
instruction
|
|
632
|
+
})));
|
|
633
|
+
};
|
|
634
|
+
var TreeItem = /* @__PURE__ */ memo3(RawTreeItem);
|
|
635
|
+
|
|
636
|
+
// packages/ui/react-ui-list/src/components/Tree/Tree.tsx
|
|
637
|
+
var Tree = ({ items, open, current, draggable: draggable3 = false, gridTemplateColumns = "[tree-row-start] 1fr min-content [tree-row-end]", classNames, renderColumns, canDrop, onOpenChange, onSelect }) => {
|
|
638
|
+
return /* @__PURE__ */ React8.createElement(Treegrid2.Root, {
|
|
639
|
+
gridTemplateColumns,
|
|
640
|
+
classNames
|
|
641
|
+
}, items.map((item, i) => {
|
|
642
|
+
const path = Path.create(...item.path);
|
|
643
|
+
return /* @__PURE__ */ React8.createElement(TreeItem, {
|
|
644
|
+
key: item.id,
|
|
645
|
+
item,
|
|
646
|
+
mode: getMode(items, i),
|
|
647
|
+
open: open.includes(path),
|
|
648
|
+
// TODO(wittjosiah): This should also be path-based.
|
|
649
|
+
current: current.includes(item.id),
|
|
650
|
+
draggable: draggable3,
|
|
651
|
+
renderColumns,
|
|
652
|
+
canDrop,
|
|
653
|
+
onOpenChange,
|
|
654
|
+
onSelect
|
|
655
|
+
});
|
|
656
|
+
}));
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
// packages/ui/react-ui-list/src/components/Tree/types.ts
|
|
660
|
+
import { S } from "@dxos/echo-schema";
|
|
661
|
+
var LabelSchema = S.Union(S.String, S.Tuple(S.String, S.Struct({
|
|
662
|
+
ns: S.String,
|
|
663
|
+
count: S.optional(S.Number)
|
|
664
|
+
})));
|
|
665
|
+
var ItemSchema = S.mutable(S.Struct({
|
|
666
|
+
id: S.String,
|
|
667
|
+
label: S.mutable(LabelSchema),
|
|
668
|
+
icon: S.optional(S.String),
|
|
669
|
+
disabled: S.optional(S.Boolean),
|
|
670
|
+
className: S.optional(S.String),
|
|
671
|
+
headingClassName: S.optional(S.String),
|
|
672
|
+
testId: S.optional(S.String),
|
|
673
|
+
path: S.Array(S.String),
|
|
674
|
+
parentOf: S.optional(S.Array(S.String))
|
|
675
|
+
}));
|
|
676
|
+
var isItem = S.is(ItemSchema);
|
|
300
677
|
export {
|
|
301
|
-
|
|
678
|
+
ItemSchema,
|
|
679
|
+
List,
|
|
680
|
+
RawTreeItem,
|
|
681
|
+
Tree,
|
|
682
|
+
TreeItem,
|
|
683
|
+
isItem
|
|
302
684
|
};
|
|
303
685
|
//# sourceMappingURL=index.mjs.map
|