@dxos/react-ui-list 0.6.13-main.ed424a1 → 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.
Files changed (52) hide show
  1. package/dist/lib/browser/index.mjs +411 -26
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/List/List.d.ts +1 -1
  5. package/dist/types/src/components/List/List.d.ts.map +1 -1
  6. package/dist/types/src/components/List/List.stories.d.ts +6 -10
  7. package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
  8. package/dist/types/src/components/List/ListItem.d.ts +1 -3
  9. package/dist/types/src/components/List/ListItem.d.ts.map +1 -1
  10. package/dist/types/src/components/List/ListRoot.d.ts +5 -3
  11. package/dist/types/src/components/List/ListRoot.d.ts.map +1 -1
  12. package/dist/types/src/components/List/testing.d.ts.map +1 -0
  13. package/dist/types/src/components/Tree/DropIndicator.d.ts +7 -0
  14. package/dist/types/src/components/Tree/DropIndicator.d.ts.map +1 -0
  15. package/dist/types/src/components/Tree/Tree.d.ts +24 -0
  16. package/dist/types/src/components/Tree/Tree.d.ts.map +1 -0
  17. package/dist/types/src/components/Tree/Tree.stories.d.ts +8 -0
  18. package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -0
  19. package/dist/types/src/components/Tree/TreeItem.d.ts +34 -0
  20. package/dist/types/src/components/Tree/TreeItem.d.ts.map +1 -0
  21. package/dist/types/src/components/Tree/TreeItemHeading.d.ts +12 -0
  22. package/dist/types/src/components/Tree/TreeItemHeading.d.ts.map +1 -0
  23. package/dist/types/src/components/Tree/TreeItemToggle.d.ts +8 -0
  24. package/dist/types/src/components/Tree/TreeItemToggle.d.ts.map +1 -0
  25. package/dist/types/src/components/Tree/helpers.d.ts +8 -0
  26. package/dist/types/src/components/Tree/helpers.d.ts.map +1 -0
  27. package/dist/types/src/components/Tree/index.d.ts +4 -0
  28. package/dist/types/src/components/Tree/index.d.ts.map +1 -0
  29. package/dist/types/src/components/Tree/testing.d.ts +26 -0
  30. package/dist/types/src/components/Tree/testing.d.ts.map +1 -0
  31. package/dist/types/src/components/Tree/types.d.ts +18 -0
  32. package/dist/types/src/components/Tree/types.d.ts.map +1 -0
  33. package/dist/types/src/components/index.d.ts +1 -0
  34. package/dist/types/src/components/index.d.ts.map +1 -1
  35. package/package.json +20 -15
  36. package/src/components/List/List.stories.tsx +25 -19
  37. package/src/components/List/ListItem.tsx +10 -8
  38. package/src/components/List/ListRoot.tsx +48 -21
  39. package/src/components/Tree/DropIndicator.tsx +79 -0
  40. package/src/components/Tree/Tree.stories.tsx +116 -0
  41. package/src/components/Tree/Tree.tsx +56 -0
  42. package/src/components/Tree/TreeItem.tsx +237 -0
  43. package/src/components/Tree/TreeItemHeading.tsx +62 -0
  44. package/src/components/Tree/TreeItemToggle.tsx +35 -0
  45. package/src/components/Tree/helpers.ts +25 -0
  46. package/src/components/Tree/index.ts +7 -0
  47. package/src/components/Tree/testing.ts +170 -0
  48. package/src/components/Tree/types.ts +34 -0
  49. package/src/components/index.ts +1 -0
  50. package/dist/types/src/testing.d.ts.map +0 -1
  51. /package/dist/types/src/{testing.d.ts → components/List/testing.d.ts} +0 -0
  52. /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 * (${gap} + ${strokeSize}px))`;
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,18 +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 { reorderWithEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/util/reorder-with-edge";
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 { useControlledValue } from "@dxos/react-ui";
56
+ import React2, { useCallback, useEffect, useState } from "react";
58
57
  var LIST_NAME = "List";
59
58
  var [ListProvider, useListContext] = createContext(LIST_NAME);
60
- var ListRoot = ({ classNames, children, items: _items = [], isItem, ...props }) => {
61
- const [items, setItems] = useControlledValue(_items);
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
+ ]);
62
72
  const [state, setState] = useState(idle);
63
73
  useEffect(() => {
74
+ if (!items) {
75
+ return;
76
+ }
64
77
  return monitorForElements({
65
- canMonitor: ({ source }) => isItem(source.data),
78
+ canMonitor: ({ source }) => isItem2(source.data),
66
79
  onDrop: ({ location, source }) => {
67
80
  const target = location.current.dropTargets[0];
68
81
  if (!target) {
@@ -70,35 +83,37 @@ var ListRoot = ({ classNames, children, items: _items = [], isItem, ...props })
70
83
  }
71
84
  const sourceData = source.data;
72
85
  const targetData = target.data;
73
- if (!isItem(sourceData) || !isItem(targetData)) {
86
+ if (!isItem2(sourceData) || !isItem2(targetData)) {
74
87
  return;
75
88
  }
76
- const sourceIdx = items.findIndex((item) => item.id === sourceData.id);
77
- const targetIdx = items.findIndex((item) => item.id === targetData.id);
89
+ const sourceIdx = items.findIndex((item) => isEqual(item, sourceData));
90
+ const targetIdx = items.findIndex((item) => isEqual(item, targetData));
78
91
  if (targetIdx < 0 || sourceIdx < 0) {
79
92
  return;
80
93
  }
81
94
  const closestEdgeOfTarget = extractClosestEdge(targetData);
82
- setItems(reorderWithEdge({
83
- list: items,
95
+ const destinationIndex = getReorderDestinationIndex({
96
+ closestEdgeOfTarget,
84
97
  startIndex: sourceIdx,
85
98
  indexOfTarget: targetIdx,
86
- axis: "vertical",
87
- closestEdgeOfTarget
88
- }));
99
+ axis: "vertical"
100
+ });
101
+ onMove?.(sourceIdx, destinationIndex);
89
102
  }
90
103
  });
91
104
  }, [
92
- items
105
+ items,
106
+ isEqual,
107
+ onMove
93
108
  ]);
94
109
  return /* @__PURE__ */ React2.createElement(ListProvider, {
95
- isItem,
110
+ isItem: isItem2,
96
111
  state,
97
112
  setState,
98
113
  ...props
99
114
  }, children?.({
100
115
  state,
101
- items
116
+ items: items ?? []
102
117
  }));
103
118
  };
104
119
 
@@ -114,7 +129,7 @@ var defaultContext = {};
114
129
  var LIST_ITEM_NAME = "ListItem";
115
130
  var [ListItemProvider, useListItemContext] = createContext2(LIST_ITEM_NAME, defaultContext);
116
131
  var ListItem = ({ children, classNames, item }) => {
117
- const { isItem, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
132
+ const { isItem: isItem2, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
118
133
  const ref = useRef(null);
119
134
  const dragHandleRef = useRef(null);
120
135
  const [state, setState] = useState2(idle);
@@ -122,7 +137,7 @@ var ListItem = ({ children, classNames, item }) => {
122
137
  const element = ref.current;
123
138
  invariant(element, void 0, {
124
139
  F: __dxlog_file,
125
- L: 89,
140
+ L: 91,
126
141
  S: void 0,
127
142
  A: [
128
143
  "element",
@@ -182,7 +197,7 @@ var ListItem = ({ children, classNames, item }) => {
182
197
  dropTargetForElements({
183
198
  element,
184
199
  canDrop: ({ source }) => {
185
- return source.element !== element && isItem(source.data);
200
+ return source.element !== element && isItem2(source.data);
186
201
  },
187
202
  getData: ({ input }) => {
188
203
  return attachClosestEdge(item, {
@@ -266,7 +281,7 @@ var ListItemDragHandle = () => {
266
281
  const { dragHandleRef } = useListItemContext("DRAG_HANDLE");
267
282
  return /* @__PURE__ */ React3.createElement(IconButton, {
268
283
  ref: dragHandleRef,
269
- icon: "ph--dots-six--regular"
284
+ icon: "ph--dots-six-vertical--regular"
270
285
  });
271
286
  };
272
287
  var ListItemDragPreview = ({ children }) => {
@@ -276,10 +291,10 @@ var ListItemDragPreview = ({ children }) => {
276
291
  }), state.container) : null;
277
292
  };
278
293
  var ListItemWrapper = ({ classNames, children }) => /* @__PURE__ */ React3.createElement("div", {
279
- className: mx2("flex w-full", classNames)
294
+ className: mx2("flex is-full gap-2", classNames)
280
295
  }, children);
281
296
  var ListItemTitle = ({ classNames, children, ...props }) => /* @__PURE__ */ React3.createElement("div", {
282
- className: mx2("grow items-center truncate", classNames),
297
+ className: mx2("flex grow items-center truncate", classNames),
283
298
  ...props
284
299
  }, children);
285
300
 
@@ -294,7 +309,377 @@ var List = {
294
309
  ItemTitle: ListItemTitle,
295
310
  IconButton
296
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);
297
677
  export {
298
- List
678
+ ItemSchema,
679
+ List,
680
+ RawTreeItem,
681
+ Tree,
682
+ TreeItem,
683
+ isItem
299
684
  };
300
685
  //# sourceMappingURL=index.mjs.map