@dxos/react-ui-list 0.7.1 → 0.7.2-main.f1adc9f

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 (42) hide show
  1. package/dist/lib/browser/index.mjs +149 -87
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +180 -116
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +149 -87
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/List/DropIndicator.d.ts +5 -4
  11. package/dist/types/src/components/List/DropIndicator.d.ts.map +1 -1
  12. package/dist/types/src/components/Tree/DropIndicator.d.ts +2 -1
  13. package/dist/types/src/components/Tree/DropIndicator.d.ts.map +1 -1
  14. package/dist/types/src/components/Tree/Tree.d.ts +4 -19
  15. package/dist/types/src/components/Tree/Tree.d.ts.map +1 -1
  16. package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
  17. package/dist/types/src/components/Tree/TreeContext.d.ts +20 -0
  18. package/dist/types/src/components/Tree/TreeContext.d.ts.map +1 -0
  19. package/dist/types/src/components/Tree/TreeItem.d.ts +26 -24
  20. package/dist/types/src/components/Tree/TreeItem.d.ts.map +1 -1
  21. package/dist/types/src/components/Tree/TreeItemHeading.d.ts +1 -1
  22. package/dist/types/src/components/Tree/TreeItemHeading.d.ts.map +1 -1
  23. package/dist/types/src/components/Tree/helpers.d.ts +0 -3
  24. package/dist/types/src/components/Tree/helpers.d.ts.map +1 -1
  25. package/dist/types/src/components/Tree/index.d.ts +1 -1
  26. package/dist/types/src/components/Tree/index.d.ts.map +1 -1
  27. package/dist/types/src/components/Tree/testing.d.ts +3 -6
  28. package/dist/types/src/components/Tree/testing.d.ts.map +1 -1
  29. package/package.json +16 -18
  30. package/src/components/List/DropIndicator.tsx +7 -2
  31. package/src/components/Tree/DropIndicator.tsx +7 -8
  32. package/src/components/Tree/Tree.stories.tsx +71 -70
  33. package/src/components/Tree/Tree.tsx +29 -24
  34. package/src/components/Tree/TreeContext.tsx +32 -0
  35. package/src/components/Tree/TreeItem.tsx +122 -83
  36. package/src/components/Tree/TreeItemHeading.tsx +14 -5
  37. package/src/components/Tree/helpers.ts +0 -16
  38. package/src/components/Tree/index.ts +1 -1
  39. package/src/components/Tree/testing.ts +4 -73
  40. package/dist/types/src/components/Tree/types.d.ts +0 -18
  41. package/dist/types/src/components/Tree/types.d.ts.map +0 -1
  42. package/src/components/Tree/types.ts +0 -34
@@ -28,12 +28,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var node_exports = {};
30
30
  __export(node_exports, {
31
- ItemSchema: () => ItemSchema,
32
31
  List: () => List,
33
32
  RawTreeItem: () => RawTreeItem,
34
33
  Tree: () => Tree,
34
+ TreeDataSchema: () => TreeDataSchema,
35
35
  TreeItem: () => TreeItem,
36
- isItem: () => isItem
36
+ TreeProvider: () => TreeProvider,
37
+ isTreeData: () => isTreeData,
38
+ useTree: () => useTree
37
39
  });
38
40
  module.exports = __toCommonJS(node_exports);
39
41
  var import_combine = require("@atlaskit/pragmatic-drag-and-drop/combine");
@@ -55,24 +57,25 @@ var import_react_context2 = require("@radix-ui/react-context");
55
57
  var import_react3 = __toESM(require("react"));
56
58
  var import_react4 = __toESM(require("react"));
57
59
  var import_react_ui2 = require("@dxos/react-ui");
58
- var import_react_ui_mosaic = require("@dxos/react-ui-mosaic");
60
+ var import_react5 = require("react");
61
+ var import_debug = require("@dxos/debug");
59
62
  var import_combine2 = require("@atlaskit/pragmatic-drag-and-drop/combine");
60
63
  var import_adapter3 = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
61
64
  var import_tree_item = require("@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item");
62
- var import_react5 = __toESM(require("react"));
65
+ var import_react6 = __toESM(require("react"));
66
+ var import_echo_schema = require("@dxos/echo-schema");
63
67
  var import_invariant2 = require("@dxos/invariant");
64
68
  var import_react_ui3 = require("@dxos/react-ui");
65
69
  var import_react_ui_theme3 = require("@dxos/react-ui-theme");
66
- var import_react6 = __toESM(require("react"));
67
- var import_react_ui_theme4 = require("@dxos/react-ui-theme");
68
70
  var import_react7 = __toESM(require("react"));
71
+ var import_react_ui_theme4 = require("@dxos/react-ui-theme");
72
+ var import_react8 = __toESM(require("react"));
69
73
  var import_react_ui4 = require("@dxos/react-ui");
70
74
  var import_react_ui_text_tooltip = require("@dxos/react-ui-text-tooltip");
71
75
  var import_react_ui_theme5 = require("@dxos/react-ui-theme");
72
- var import_react8 = __toESM(require("react"));
76
+ var import_react9 = __toESM(require("react"));
73
77
  var import_react_ui5 = require("@dxos/react-ui");
74
78
  var import_react_ui_theme6 = require("@dxos/react-ui-theme");
75
- var import_echo_schema = require("@dxos/echo-schema");
76
79
  var edgeToOrientationMap = {
77
80
  top: "horizontal",
78
81
  bottom: "horizontal",
@@ -92,8 +95,8 @@ var edgeStyles = {
92
95
  var strokeSize = 2;
93
96
  var terminalSize = 8;
94
97
  var offsetToAlignTerminalWithLine = (strokeSize - terminalSize) / 2;
95
- var DropIndicator = ({ edge, gap: gap2 = "0px" }) => {
96
- const lineOffset = `calc(-0.5 * (${gap2} + ${strokeSize}px))`;
98
+ var DropIndicator = ({ edge, gap = 0 }) => {
99
+ const lineOffset = `calc(-0.5 * (${gap}px + ${strokeSize}px))`;
97
100
  const orientation = edgeToOrientationMap[edge];
98
101
  return /* @__PURE__ */ import_react2.default.createElement("div", {
99
102
  style: {
@@ -110,7 +113,7 @@ var DropIndicator = ({ edge, gap: gap2 = "0px" }) => {
110
113
  var LIST_NAME = "List";
111
114
  var [ListProvider, useListContext] = (0, import_react_context2.createContext)(LIST_NAME);
112
115
  var defaultGetId = (item) => item?.id;
113
- var ListRoot = ({ classNames, children, items, isItem: isItem2, getId = defaultGetId, onMove, ...props }) => {
116
+ var ListRoot = ({ classNames, children, items, isItem, getId = defaultGetId, onMove, ...props }) => {
114
117
  const isEqual = (0, import_react3.useCallback)((a, b) => {
115
118
  const idA = getId?.(a);
116
119
  const idB = getId?.(b);
@@ -128,7 +131,7 @@ var ListRoot = ({ classNames, children, items, isItem: isItem2, getId = defaultG
128
131
  return;
129
132
  }
130
133
  return (0, import_adapter2.monitorForElements)({
131
- canMonitor: ({ source }) => isItem2(source.data),
134
+ canMonitor: ({ source }) => isItem(source.data),
132
135
  onDrop: ({ location, source }) => {
133
136
  const target = location.current.dropTargets[0];
134
137
  if (!target) {
@@ -136,7 +139,7 @@ var ListRoot = ({ classNames, children, items, isItem: isItem2, getId = defaultG
136
139
  }
137
140
  const sourceData = source.data;
138
141
  const targetData = target.data;
139
- if (!isItem2(sourceData) || !isItem2(targetData)) {
142
+ if (!isItem(sourceData) || !isItem(targetData)) {
140
143
  return;
141
144
  }
142
145
  const sourceIdx = items.findIndex((item) => isEqual(item, sourceData));
@@ -160,7 +163,7 @@ var ListRoot = ({ classNames, children, items, isItem: isItem2, getId = defaultG
160
163
  onMove
161
164
  ]);
162
165
  return /* @__PURE__ */ import_react3.default.createElement(ListProvider, {
163
- isItem: isItem2,
166
+ isItem,
164
167
  state,
165
168
  setState,
166
169
  ...props
@@ -180,7 +183,7 @@ var defaultContext = {};
180
183
  var LIST_ITEM_NAME = "ListItem";
181
184
  var [ListItemProvider, useListItemContext] = (0, import_react_context.createContext)(LIST_ITEM_NAME, defaultContext);
182
185
  var ListItem = ({ children, classNames, item }) => {
183
- const { isItem: isItem2, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
186
+ const { isItem, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
184
187
  const ref = (0, import_react.useRef)(null);
185
188
  const dragHandleRef = (0, import_react.useRef)(null);
186
189
  const [state, setState] = (0, import_react.useState)(idle);
@@ -248,7 +251,7 @@ var ListItem = ({ children, classNames, item }) => {
248
251
  (0, import_adapter.dropTargetForElements)({
249
252
  element,
250
253
  canDrop: ({ source }) => {
251
- return source.element !== element && isItem2(source.data);
254
+ return source.element !== element && isItem(source.data);
252
255
  },
253
256
  getData: ({ input }) => {
254
257
  return (0, import_closest_edge.attachClosestEdge)(item, {
@@ -358,6 +361,9 @@ var List = {
358
361
  ItemTitle: ListItemTitle,
359
362
  IconButton
360
363
  };
364
+ var TreeContext = /* @__PURE__ */ (0, import_react5.createContext)(null);
365
+ var useTree = () => (0, import_react5.useContext)(TreeContext) ?? (0, import_debug.raise)(new Error("TreeContext not found"));
366
+ var TreeProvider = TreeContext.Provider;
361
367
  var edgeToOrientationMap2 = {
362
368
  "reorder-above": "sibling",
363
369
  "reorder-below": "sibling",
@@ -379,16 +385,15 @@ var instructionStyles = {
379
385
  var strokeSize2 = 2;
380
386
  var terminalSize2 = 8;
381
387
  var offsetToAlignTerminalWithLine2 = (strokeSize2 - terminalSize2) / 2;
382
- var gap = "0px";
383
- var DropIndicator2 = ({ instruction }) => {
384
- const lineOffset = `calc(-0.5 * (${gap} + ${strokeSize2}px))`;
388
+ var DropIndicator2 = ({ instruction, gap = 0 }) => {
389
+ const lineOffset = `calc(-0.5 * (${gap}px + ${strokeSize2}px))`;
385
390
  const isBlocked = instruction.type === "instruction-blocked";
386
391
  const desiredInstruction = isBlocked ? instruction.desired : instruction;
387
392
  const orientation = edgeToOrientationMap2[desiredInstruction.type];
388
393
  if (isBlocked) {
389
394
  return null;
390
395
  }
391
- return /* @__PURE__ */ import_react6.default.createElement("div", {
396
+ return /* @__PURE__ */ import_react7.default.createElement("div", {
392
397
  style: {
393
398
  "--line-thickness": `${strokeSize2}px`,
394
399
  "--line-offset": `${lineOffset}`,
@@ -401,45 +406,51 @@ var DropIndicator2 = ({ instruction }) => {
401
406
  className: (0, import_react_ui_theme4.mx)("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])
402
407
  });
403
408
  };
404
- var TreeItemHeading = /* @__PURE__ */ (0, import_react7.memo)(/* @__PURE__ */ (0, import_react7.forwardRef)(({ label, icon, className, disabled, current, onSelect }, forwardedRef) => {
409
+ var TreeItemHeading = /* @__PURE__ */ (0, import_react8.memo)(/* @__PURE__ */ (0, import_react8.forwardRef)(({ label, icon, className, disabled, current, onSelect }, forwardedRef) => {
405
410
  const { t } = (0, import_react_ui4.useTranslation)();
406
- const handleButtonKeydown = (0, import_react7.useCallback)((event) => {
411
+ const handleSelect = (0, import_react8.useCallback)((event) => {
412
+ onSelect?.(event.altKey);
413
+ }, [
414
+ onSelect
415
+ ]);
416
+ const handleButtonKeydown = (0, import_react8.useCallback)((event) => {
407
417
  if (event.key === " " || event.key === "Enter") {
408
418
  event.preventDefault();
409
419
  event.stopPropagation();
410
- onSelect?.();
420
+ onSelect?.(event.altKey);
411
421
  }
412
422
  }, [
413
423
  onSelect
414
424
  ]);
415
- return /* @__PURE__ */ import_react7.default.createElement(import_react_ui_text_tooltip.TextTooltip, {
425
+ return /* @__PURE__ */ import_react8.default.createElement(import_react_ui_text_tooltip.TextTooltip, {
416
426
  text: (0, import_react_ui4.toLocalizedString)(label, t),
417
427
  side: "bottom",
418
428
  truncateQuery: "span[data-tooltip]",
419
429
  onlyWhenTruncating: true,
420
430
  asChild: true,
421
431
  ref: forwardedRef
422
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui4.Button, {
432
+ }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui4.Button, {
423
433
  "data-testid": "treeItem.heading",
424
434
  variant: "ghost",
425
435
  density: "fine",
426
436
  classNames: (0, import_react_ui_theme5.mx)("grow gap-2 !pis-0.5 hover:!bg-transparent dark:hover:!bg-transparent", "disabled:!cursor-default disabled:!opacity-100", className),
427
437
  disabled,
428
- onClick: onSelect,
438
+ onClick: handleSelect,
429
439
  onKeyDown: handleButtonKeydown,
430
440
  ...current && {
431
441
  "aria-current": "location"
432
442
  }
433
- }, icon && /* @__PURE__ */ import_react7.default.createElement(import_react_ui4.Icon, {
443
+ }, icon && /* @__PURE__ */ import_react8.default.createElement(import_react_ui4.Icon, {
434
444
  icon: icon ?? "ph--placeholder--regular",
435
445
  size: 4,
436
446
  classNames: "is-[1em] bs-[1em] mlb-1"
437
- }), /* @__PURE__ */ import_react7.default.createElement("span", {
438
- className: "flex-1 is-0 truncate text-start text-sm font-normal"
447
+ }), /* @__PURE__ */ import_react8.default.createElement("span", {
448
+ className: "flex-1 is-0 truncate text-start text-sm font-normal",
449
+ "data-tooltip": true
439
450
  }, (0, import_react_ui4.toLocalizedString)(label, t))));
440
451
  }));
441
- var TreeItemToggle = /* @__PURE__ */ (0, import_react8.memo)(/* @__PURE__ */ (0, import_react8.forwardRef)(({ open, isBranch, onToggle }, forwardedRef) => {
442
- return /* @__PURE__ */ import_react8.default.createElement(import_react_ui5.Button, {
452
+ var TreeItemToggle = /* @__PURE__ */ (0, import_react9.memo)(/* @__PURE__ */ (0, import_react9.forwardRef)(({ open, isBranch, onToggle }, forwardedRef) => {
453
+ return /* @__PURE__ */ import_react9.default.createElement(import_react_ui5.Button, {
443
454
  ref: forwardedRef,
444
455
  "data-testid": "treeItem.toggle",
445
456
  "aria-expanded": open,
@@ -447,7 +458,7 @@ var TreeItemToggle = /* @__PURE__ */ (0, import_react8.memo)(/* @__PURE__ */ (0,
447
458
  density: "fine",
448
459
  classNames: (0, import_react_ui_theme6.mx)("is-6 !pli-1", !isBranch && "invisible"),
449
460
  onClick: onToggle
450
- }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui5.Icon, {
461
+ }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui5.Icon, {
451
462
  icon: "ph--caret-right--regular",
452
463
  size: 3,
453
464
  classNames: (0, import_react_ui_theme6.mx)("transition duration-200", open && "rotate-90")
@@ -457,43 +468,59 @@ var DEFAULT_INDENTATION = 8;
457
468
  var paddingIndendation = (level, indentation = DEFAULT_INDENTATION) => ({
458
469
  paddingInlineStart: `${(level - 1) * indentation}px`
459
470
  });
460
- var getMode = (items, index) => {
461
- const item = items[index];
462
- const next = items[index + 1];
463
- if (!next || item.path.length > next.path.length) {
464
- return "last-in-group";
465
- } else if (item.path.length < next.path.length) {
466
- return "expanded";
467
- } else {
468
- return "standard";
469
- }
470
- };
471
471
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx";
472
472
  var hoverableDescriptionIcons = "[--icons-color:inherit] hover-hover:[--icons-color:var(--description-text)] hover-hover:hover:[--icons-color:inherit] focus-within:[--icons-color:inherit]";
473
- var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderColumns: Columns, canDrop, onOpenChange, onSelect }) => {
474
- const { id, label, icon, className, headingClassName, disabled, path, parentOf } = item;
473
+ var TreeDataSchema = import_echo_schema.S.Struct({
474
+ id: import_echo_schema.S.String,
475
+ path: import_echo_schema.S.Array(import_echo_schema.S.String),
476
+ item: import_echo_schema.S.Any
477
+ });
478
+ var isTreeData = (data) => import_echo_schema.S.is(TreeDataSchema)(data);
479
+ var RawTreeItem = ({ item, path: _path, last, draggable: draggable2, renderColumns: Columns, canDrop, onOpenChange, onSelect }) => {
480
+ const { getItems, getProps, isOpen, isCurrent } = useTree();
481
+ const items = getItems(item);
482
+ const { id, label, parentOf, icon, disabled, className, headingClassName, testId } = getProps(item, _path);
483
+ const path = (0, import_react6.useMemo)(() => [
484
+ ..._path,
485
+ id
486
+ ], [
487
+ _path,
488
+ id
489
+ ]);
490
+ const open = isOpen(path, item);
491
+ const current = isCurrent(path, item);
475
492
  const level = path.length - 2;
476
493
  const isBranch = !!parentOf;
477
- const rowRef = (0, import_react5.useRef)(null);
478
- const buttonRef = (0, import_react5.useRef)(null);
479
- const openRef = (0, import_react5.useRef)(false);
480
- const cancelExpandRef = (0, import_react5.useRef)(null);
481
- const [_state, setState] = (0, import_react5.useState)("idle");
482
- const [instruction, setInstruction] = (0, import_react5.useState)(null);
483
- const [menuOpen, setMenuOpen] = (0, import_react5.useState)(false);
484
- const cancelExpand = (0, import_react5.useCallback)(() => {
494
+ const mode = last ? "last-in-group" : open ? "expanded" : "standard";
495
+ const data = (0, import_react6.useMemo)(() => ({
496
+ id,
497
+ path,
498
+ item
499
+ }), [
500
+ id,
501
+ path,
502
+ item
503
+ ]);
504
+ const rowRef = (0, import_react6.useRef)(null);
505
+ const buttonRef = (0, import_react6.useRef)(null);
506
+ const openRef = (0, import_react6.useRef)(false);
507
+ const cancelExpandRef = (0, import_react6.useRef)(null);
508
+ const [_state, setState] = (0, import_react6.useState)("idle");
509
+ const [instruction, setInstruction] = (0, import_react6.useState)(null);
510
+ const [menuOpen, setMenuOpen] = (0, import_react6.useState)(false);
511
+ const cancelExpand = (0, import_react6.useCallback)(() => {
485
512
  if (cancelExpandRef.current) {
486
513
  clearTimeout(cancelExpandRef.current);
487
514
  cancelExpandRef.current = null;
488
515
  }
489
516
  }, []);
490
- (0, import_react5.useEffect)(() => {
491
- if (!_draggable) {
517
+ (0, import_react6.useEffect)(() => {
518
+ if (!draggable2) {
492
519
  return;
493
520
  }
494
521
  (0, import_invariant2.invariant)(buttonRef.current, void 0, {
495
522
  F: __dxlog_file2,
496
- L: 87,
523
+ L: 104,
497
524
  S: void 0,
498
525
  A: [
499
526
  "buttonRef.current",
@@ -502,24 +529,32 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
502
529
  });
503
530
  return (0, import_combine2.combine)((0, import_adapter3.draggable)({
504
531
  element: buttonRef.current,
505
- getInitialData: () => item,
532
+ getInitialData: () => data,
506
533
  onDragStart: () => {
507
534
  setState("dragging");
508
535
  if (open) {
509
536
  openRef.current = true;
510
- onOpenChange?.(item, false);
537
+ onOpenChange?.({
538
+ item,
539
+ path,
540
+ open: false
541
+ });
511
542
  }
512
543
  },
513
544
  onDrop: () => {
514
545
  setState("idle");
515
546
  if (openRef.current) {
516
- onOpenChange?.(item, true);
547
+ onOpenChange?.({
548
+ item,
549
+ path,
550
+ open: true
551
+ });
517
552
  }
518
553
  }
519
554
  }), (0, import_adapter3.dropTargetForElements)({
520
555
  element: buttonRef.current,
521
556
  getData: ({ input, element }) => {
522
- return (0, import_tree_item.attachInstruction)(item, {
557
+ return (0, import_tree_item.attachInstruction)(data, {
523
558
  input,
524
559
  element,
525
560
  indentPerLevel: DEFAULT_INDENTATION,
@@ -532,15 +567,19 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
532
567
  },
533
568
  canDrop: ({ source }) => {
534
569
  const _canDrop = canDrop ?? (() => true);
535
- return source.element !== buttonRef.current && _canDrop(source.data, item);
570
+ return source.element !== buttonRef.current && _canDrop(source.data, data);
536
571
  },
537
572
  getIsSticky: () => true,
538
573
  onDrag: ({ self, source }) => {
539
574
  const instruction2 = (0, import_tree_item.extractInstruction)(self.data);
540
- if (source.data.id !== item.id) {
575
+ if (source.data.id !== id) {
541
576
  if (instruction2?.type === "make-child" && isBranch && !open && !cancelExpandRef.current) {
542
577
  cancelExpandRef.current = setTimeout(() => {
543
- onOpenChange?.(item, true);
578
+ onOpenChange?.({
579
+ item,
580
+ path,
581
+ open: true
582
+ });
544
583
  }, 500);
545
584
  }
546
585
  if (instruction2?.type !== "make-child") {
@@ -563,29 +602,42 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
563
602
  }
564
603
  }));
565
604
  }, [
566
- import_adapter3.draggable,
605
+ draggable2,
567
606
  item,
607
+ id,
568
608
  mode,
609
+ path,
569
610
  open,
570
611
  canDrop
571
612
  ]);
572
- (0, import_react5.useEffect)(() => () => cancelExpand(), [
613
+ (0, import_react6.useEffect)(() => () => cancelExpand(), [
573
614
  cancelExpand
574
615
  ]);
575
- const handleOpenChange = (0, import_react5.useCallback)(() => onOpenChange?.(item, !open), [
616
+ const handleOpenChange = (0, import_react6.useCallback)(() => onOpenChange?.({
617
+ item,
618
+ path,
619
+ open: !open
620
+ }), [
576
621
  onOpenChange,
577
622
  item,
623
+ path,
578
624
  open
579
625
  ]);
580
- const handleSelect = (0, import_react5.useCallback)(() => {
626
+ const handleSelect = (0, import_react6.useCallback)((option = false) => {
581
627
  rowRef.current?.focus();
582
- onSelect?.(item, !current);
628
+ onSelect?.({
629
+ item,
630
+ path,
631
+ current: !current,
632
+ option
633
+ });
583
634
  }, [
584
635
  onSelect,
585
636
  item,
637
+ path,
586
638
  current
587
639
  ]);
588
- const handleKeyDown = (0, import_react5.useCallback)((event) => {
640
+ const handleKeyDown = (0, import_react6.useCallback)((event) => {
589
641
  switch (event.key) {
590
642
  case "ArrowRight":
591
643
  isBranch && !open && handleOpenChange();
@@ -594,7 +646,7 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
594
646
  isBranch && open && handleOpenChange();
595
647
  break;
596
648
  case " ":
597
- handleSelect();
649
+ handleSelect(event.altKey);
598
650
  break;
599
651
  }
600
652
  }, [
@@ -603,15 +655,15 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
603
655
  handleOpenChange,
604
656
  handleSelect
605
657
  ]);
606
- return /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Treegrid.Row, {
658
+ return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Treegrid.Row, {
607
659
  ref: rowRef,
608
660
  key: id,
609
661
  id,
610
662
  "aria-labelledby": `${id}__label`,
611
663
  parentOf: parentOf?.join(import_react_ui3.Treegrid.PARENT_OF_SEPARATOR),
612
664
  classNames: (0, import_react_ui_theme3.mx)("grid grid-cols-subgrid col-[tree-row] mt-[2px] aria-[current]:bg-input", import_react_ui_theme3.hoverableControls, import_react_ui_theme3.hoverableFocusedKeyboardControls, import_react_ui_theme3.hoverableFocusedWithinControls, hoverableDescriptionIcons, import_react_ui_theme3.ghostHover, import_react_ui_theme3.focusRing, className),
613
- "data-itemid": item.id,
614
- "data-testid": item.testId,
665
+ "data-itemid": id,
666
+ "data-testid": testId,
615
667
  // NOTE(thure): This is intentionally an empty string to for descendents to select by in the CSS
616
668
  // without alerting the user (except for in the correct link element). See also:
617
669
  // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current#description
@@ -621,18 +673,18 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
621
673
  event.preventDefault();
622
674
  setMenuOpen(true);
623
675
  }
624
- }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui3.Treegrid.Cell, {
676
+ }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui3.Treegrid.Cell, {
625
677
  indent: true,
626
678
  classNames: "relative grid grid-cols-subgrid col-[tree-row]",
627
679
  style: paddingIndendation(level)
628
- }, /* @__PURE__ */ import_react5.default.createElement("div", {
680
+ }, /* @__PURE__ */ import_react6.default.createElement("div", {
629
681
  role: "none",
630
682
  className: "flex items-center"
631
- }, /* @__PURE__ */ import_react5.default.createElement(TreeItemToggle, {
683
+ }, /* @__PURE__ */ import_react6.default.createElement(TreeItemToggle, {
632
684
  open,
633
685
  isBranch,
634
686
  onToggle: handleOpenChange
635
- }), /* @__PURE__ */ import_react5.default.createElement(TreeItemHeading, {
687
+ }), /* @__PURE__ */ import_react6.default.createElement(TreeItemHeading, {
636
688
  ref: buttonRef,
637
689
  label,
638
690
  icon,
@@ -640,59 +692,71 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
640
692
  disabled,
641
693
  current,
642
694
  onSelect: handleSelect
643
- })), Columns && /* @__PURE__ */ import_react5.default.createElement(Columns, {
695
+ })), Columns && /* @__PURE__ */ import_react6.default.createElement(Columns, {
644
696
  item,
697
+ path,
645
698
  menuOpen,
646
699
  setMenuOpen
647
- }), instruction && /* @__PURE__ */ import_react5.default.createElement(DropIndicator2, {
648
- instruction
700
+ }), instruction && /* @__PURE__ */ import_react6.default.createElement(DropIndicator2, {
701
+ instruction,
702
+ gap: 2
703
+ }))), open && items.map((item2, index) => /* @__PURE__ */ import_react6.default.createElement(TreeItem, {
704
+ key: item2.id,
705
+ item: item2,
706
+ path,
707
+ last: index === items.length - 1,
708
+ draggable: draggable2,
709
+ renderColumns: Columns,
710
+ canDrop,
711
+ onOpenChange,
712
+ onSelect
649
713
  })));
650
714
  };
651
- var TreeItem = /* @__PURE__ */ (0, import_react5.memo)(RawTreeItem);
652
- var Tree = ({ items, open, current, draggable: draggable3 = false, gridTemplateColumns = "[tree-row-start] 1fr min-content [tree-row-end]", classNames, renderColumns, canDrop, onOpenChange, onSelect }) => {
715
+ var TreeItem = /* @__PURE__ */ (0, import_react6.memo)(RawTreeItem);
716
+ var Tree = ({ id, getItems, getProps, isOpen, isCurrent, draggable: draggable2 = false, gridTemplateColumns = "[tree-row-start] 1fr min-content [tree-row-end]", classNames, renderColumns, canDrop, onOpenChange, onSelect }) => {
717
+ const context = (0, import_react4.useMemo)(() => ({
718
+ getItems,
719
+ getProps,
720
+ isOpen,
721
+ isCurrent
722
+ }), [
723
+ getItems,
724
+ getProps,
725
+ isOpen,
726
+ isCurrent
727
+ ]);
728
+ const items = getItems();
729
+ const path = (0, import_react4.useMemo)(() => [
730
+ id
731
+ ], [
732
+ id
733
+ ]);
653
734
  return /* @__PURE__ */ import_react4.default.createElement(import_react_ui2.Treegrid.Root, {
654
735
  gridTemplateColumns,
655
736
  classNames
656
- }, items.map((item, i) => {
657
- const path = import_react_ui_mosaic.Path.create(...item.path);
658
- return /* @__PURE__ */ import_react4.default.createElement(TreeItem, {
659
- key: item.id,
660
- item,
661
- mode: getMode(items, i),
662
- open: open.includes(path),
663
- // TODO(wittjosiah): This should also be path-based.
664
- current: current.includes(item.id),
665
- draggable: draggable3,
666
- renderColumns,
667
- canDrop,
668
- onOpenChange,
669
- onSelect
670
- });
671
- }));
737
+ }, /* @__PURE__ */ import_react4.default.createElement(TreeProvider, {
738
+ value: context
739
+ }, items.map((item, index) => /* @__PURE__ */ import_react4.default.createElement(TreeItem, {
740
+ key: item.id,
741
+ item,
742
+ last: index === items.length - 1,
743
+ path,
744
+ draggable: draggable2,
745
+ renderColumns,
746
+ canDrop,
747
+ onOpenChange,
748
+ onSelect
749
+ }))));
672
750
  };
673
- var LabelSchema = import_echo_schema.S.Union(import_echo_schema.S.String, import_echo_schema.S.Tuple(import_echo_schema.S.String, import_echo_schema.S.Struct({
674
- ns: import_echo_schema.S.String,
675
- count: import_echo_schema.S.optional(import_echo_schema.S.Number)
676
- })));
677
- var ItemSchema = import_echo_schema.S.mutable(import_echo_schema.S.Struct({
678
- id: import_echo_schema.S.String,
679
- label: import_echo_schema.S.mutable(LabelSchema),
680
- icon: import_echo_schema.S.optional(import_echo_schema.S.String),
681
- disabled: import_echo_schema.S.optional(import_echo_schema.S.Boolean),
682
- className: import_echo_schema.S.optional(import_echo_schema.S.String),
683
- headingClassName: import_echo_schema.S.optional(import_echo_schema.S.String),
684
- testId: import_echo_schema.S.optional(import_echo_schema.S.String),
685
- path: import_echo_schema.S.Array(import_echo_schema.S.String),
686
- parentOf: import_echo_schema.S.optional(import_echo_schema.S.Array(import_echo_schema.S.String))
687
- }));
688
- var isItem = import_echo_schema.S.is(ItemSchema);
689
751
  // Annotate the CommonJS export names for ESM import in node:
690
752
  0 && (module.exports = {
691
- ItemSchema,
692
753
  List,
693
754
  RawTreeItem,
694
755
  Tree,
756
+ TreeDataSchema,
695
757
  TreeItem,
696
- isItem
758
+ TreeProvider,
759
+ isTreeData,
760
+ useTree
697
761
  });
698
762
  //# sourceMappingURL=index.cjs.map