@dxos/react-ui-list 0.8.4-main.937b3ca → 0.8.4-main.9be5663bfe

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 (41) hide show
  1. package/dist/lib/browser/index.mjs +233 -194
  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 +233 -194
  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/AccordionItem.d.ts.map +1 -1
  8. package/dist/types/src/components/List/List.d.ts +6 -4
  9. package/dist/types/src/components/List/List.d.ts.map +1 -1
  10. package/dist/types/src/components/List/ListItem.d.ts +8 -6
  11. package/dist/types/src/components/List/ListItem.d.ts.map +1 -1
  12. package/dist/types/src/components/List/ListRoot.d.ts +2 -2
  13. package/dist/types/src/components/List/ListRoot.d.ts.map +1 -1
  14. package/dist/types/src/components/Tree/Tree.d.ts +6 -5
  15. package/dist/types/src/components/Tree/Tree.d.ts.map +1 -1
  16. package/dist/types/src/components/Tree/Tree.stories.d.ts +1 -1
  17. package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/Tree/TreeContext.d.ts +21 -10
  19. package/dist/types/src/components/Tree/TreeContext.d.ts.map +1 -1
  20. package/dist/types/src/components/Tree/TreeItem.d.ts +8 -0
  21. package/dist/types/src/components/Tree/TreeItem.d.ts.map +1 -1
  22. package/dist/types/src/components/Tree/TreeItemHeading.d.ts.map +1 -1
  23. package/dist/types/src/components/Tree/index.d.ts +2 -0
  24. package/dist/types/src/components/Tree/index.d.ts.map +1 -1
  25. package/dist/types/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +19 -18
  27. package/src/components/Accordion/Accordion.stories.tsx +6 -6
  28. package/src/components/Accordion/AccordionItem.tsx +1 -2
  29. package/src/components/List/List.stories.tsx +10 -10
  30. package/src/components/List/List.tsx +4 -9
  31. package/src/components/List/ListItem.tsx +58 -38
  32. package/src/components/List/ListRoot.tsx +3 -3
  33. package/src/components/List/testing.ts +4 -4
  34. package/src/components/Tree/Tree.stories.tsx +106 -31
  35. package/src/components/Tree/Tree.tsx +30 -40
  36. package/src/components/Tree/TreeContext.tsx +18 -9
  37. package/src/components/Tree/TreeItem.tsx +178 -103
  38. package/src/components/Tree/TreeItemHeading.tsx +3 -4
  39. package/src/components/Tree/TreeItemToggle.tsx +4 -4
  40. package/src/components/Tree/index.ts +2 -0
  41. package/src/components/Tree/testing.ts +5 -5
@@ -46,7 +46,7 @@ var AccordionItemHeader = ({ classNames, children, ...props }) => {
46
46
  ...props,
47
47
  className: mx2(classNames)
48
48
  }, /* @__PURE__ */ React2.createElement(AccordionPrimitive2.Trigger, {
49
- className: "group flex items-center p-2 dx-focus-ring-inset is-full text-start"
49
+ className: "group flex items-center p-2 dx-focus-ring-inset w-full text-start"
50
50
  }, children, /* @__PURE__ */ React2.createElement(Icon, {
51
51
  icon: "ph--caret-right--regular",
52
52
  size: 4,
@@ -71,11 +71,12 @@ var Accordion = {
71
71
  };
72
72
 
73
73
  // src/components/List/ListItem.tsx
74
+ import { attachClosestEdge, extractClosestEdge as extractClosestEdge2 } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
74
75
  import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
75
76
  import { draggable, dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
76
77
  import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview";
77
- import { attachClosestEdge, extractClosestEdge as extractClosestEdge2 } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
78
78
  import { createContext as createContext4 } from "@radix-ui/react-context";
79
+ import { Slot } from "@radix-ui/react-slot";
79
80
  import React4, { useEffect as useEffect2, useRef, useState as useState2 } from "react";
80
81
  import { createPortal } from "react-dom";
81
82
  import { invariant } from "@dxos/invariant";
@@ -83,9 +84,9 @@ import { IconButton, ListItem as NaturalListItem, useTranslation } from "@dxos/r
83
84
  import { mx as mx3, osTranslations } from "@dxos/ui-theme";
84
85
 
85
86
  // src/components/List/ListRoot.tsx
86
- import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
87
87
  import { extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
88
88
  import { getReorderDestinationIndex } from "@atlaskit/pragmatic-drag-and-drop-hitbox/util/get-reorder-destination-index";
89
+ import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
89
90
  import { createContext as createContext3 } from "@radix-ui/react-context";
90
91
  import React3, { useCallback, useEffect, useState } from "react";
91
92
  var LIST_NAME = "List";
@@ -162,16 +163,17 @@ var stateStyles = {
162
163
  var defaultContext = {};
163
164
  var LIST_ITEM_NAME = "ListItem";
164
165
  var [ListItemProvider, useListItemContext] = createContext4(LIST_ITEM_NAME, defaultContext);
165
- var ListItem = ({ children, classNames, item, ...props }) => {
166
+ var ListItem = ({ children, classNames, item, asChild, selected, ...props }) => {
167
+ const Comp = asChild ? Slot : "div";
166
168
  const { isItem, readonly, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
167
- const ref = useRef(null);
169
+ const rootRef = useRef(null);
168
170
  const dragHandleRef = useRef(null);
169
171
  const [state, setState] = useState2(idle);
170
172
  useEffect2(() => {
171
- const element = ref.current;
173
+ const element = rootRef.current;
172
174
  invariant(element, void 0, {
173
175
  F: __dxlog_file,
174
- L: 98,
176
+ L: 109,
175
177
  S: void 0,
176
178
  A: [
177
179
  "element",
@@ -280,40 +282,41 @@ var ListItem = ({ children, classNames, item, ...props }) => {
280
282
  return /* @__PURE__ */ React4.createElement(ListItemProvider, {
281
283
  item,
282
284
  dragHandleRef
283
- }, /* @__PURE__ */ React4.createElement("div", {
284
- ref,
285
+ }, /* @__PURE__ */ React4.createElement(Comp, {
286
+ ...props,
285
287
  role: "listitem",
286
- className: mx3("flex relative", classNames, stateStyles[state.type]),
287
- ...props
288
- }, children, state.type === "is-dragging-over" && state.closestEdge && /* @__PURE__ */ React4.createElement(NaturalListItem.DropIndicator, {
288
+ "aria-selected": selected,
289
+ className: mx3("relative p-1 dx-selected dx-hover", classNames, stateStyles[state.type]),
290
+ ref: rootRef
291
+ }, children), state.type === "is-dragging-over" && state.closestEdge && /* @__PURE__ */ React4.createElement(NaturalListItem.DropIndicator, {
289
292
  edge: state.closestEdge
290
- })));
293
+ }));
291
294
  };
292
- var ListItemDeleteButton = ({ autoHide = true, classNames, disabled, icon = "ph--x--regular", label, ...props }) => {
293
- const { state } = useListContext("DELETE_BUTTON");
295
+ var ListItemIconButton = ({ autoHide = true, iconOnly = true, variant = "ghost", classNames, disabled, ...props }) => {
296
+ const { state } = useListContext("ITEM_BUTTON");
294
297
  const isDisabled = state.type !== "idle" || disabled;
295
- const { t } = useTranslation(osTranslations);
296
298
  return /* @__PURE__ */ React4.createElement(IconButton, {
297
- iconOnly: true,
298
- variant: "ghost",
299
299
  ...props,
300
- icon,
301
300
  disabled: isDisabled,
302
- label: label ?? t("delete label"),
301
+ iconOnly,
302
+ variant,
303
303
  classNames: [
304
304
  classNames,
305
305
  autoHide && disabled && "hidden"
306
306
  ]
307
307
  });
308
308
  };
309
- var ListItemButton = ({ autoHide = true, iconOnly = true, variant = "ghost", classNames, disabled, ...props }) => {
310
- const { state } = useListContext("ITEM_BUTTON");
309
+ var ListItemDeleteButton = ({ autoHide = true, classNames, disabled, icon = "ph--x--regular", label, ...props }) => {
310
+ const { state } = useListContext("DELETE_BUTTON");
311
311
  const isDisabled = state.type !== "idle" || disabled;
312
+ const { t } = useTranslation(osTranslations);
312
313
  return /* @__PURE__ */ React4.createElement(IconButton, {
313
314
  ...props,
315
+ variant: "ghost",
314
316
  disabled: isDisabled,
315
- iconOnly,
316
- variant,
317
+ icon,
318
+ iconOnly: true,
319
+ label: label ?? t("delete.label"),
317
320
  classNames: [
318
321
  classNames,
319
322
  autoHide && disabled && "hidden"
@@ -324,12 +327,12 @@ var ListItemDragHandle = ({ disabled }) => {
324
327
  const { dragHandleRef } = useListItemContext("DRAG_HANDLE");
325
328
  const { t } = useTranslation(osTranslations);
326
329
  return /* @__PURE__ */ React4.createElement(IconButton, {
327
- iconOnly: true,
328
330
  variant: "ghost",
329
- label: t("drag handle label"),
330
- ref: dragHandleRef,
331
+ disabled,
331
332
  icon: "ph--dots-six-vertical--regular",
332
- disabled
333
+ iconOnly: true,
334
+ label: t("drag-handle.label"),
335
+ ref: dragHandleRef
333
336
  });
334
337
  };
335
338
  var ListItemDragPreview = ({ children }) => {
@@ -339,9 +342,11 @@ var ListItemDragPreview = ({ children }) => {
339
342
  }), state.container) : null;
340
343
  };
341
344
  var ListItemWrapper = ({ classNames, children }) => /* @__PURE__ */ React4.createElement("div", {
342
- className: mx3("flex is-full gap-2", classNames)
345
+ role: "none",
346
+ className: mx3("flex w-full gap-2", classNames)
343
347
  }, children);
344
348
  var ListItemTitle = ({ classNames, children, ...props }) => /* @__PURE__ */ React4.createElement("div", {
349
+ role: "none",
345
350
  className: mx3("flex grow items-center truncate", classNames),
346
351
  ...props
347
352
  }, children);
@@ -353,12 +358,13 @@ var List = {
353
358
  ItemDragPreview: ListItemDragPreview,
354
359
  ItemWrapper: ListItemWrapper,
355
360
  ItemDragHandle: ListItemDragHandle,
361
+ ItemIconButton: ListItemIconButton,
356
362
  ItemDeleteButton: ListItemDeleteButton,
357
- ItemButton: ListItemButton,
358
363
  ItemTitle: ListItemTitle
359
364
  };
360
365
 
361
366
  // src/components/Tree/Tree.tsx
367
+ import { useAtomValue as useAtomValue2 } from "@effect-atom/atom-react";
362
368
  import React8, { useMemo as useMemo2 } from "react";
363
369
  import { Treegrid as Treegrid2 } from "@dxos/react-ui";
364
370
 
@@ -370,14 +376,15 @@ var TreeProvider = TreeContext.Provider;
370
376
  var useTree = () => useContext(TreeContext) ?? raise(new Error("TreeContext not found"));
371
377
 
372
378
  // src/components/Tree/TreeItem.tsx
379
+ import { attachInstruction, extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item";
373
380
  import { combine as combine2 } from "@atlaskit/pragmatic-drag-and-drop/combine";
374
381
  import { draggable as draggable2, dropTargetForElements as dropTargetForElements2 } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
375
- import { attachInstruction, extractInstruction } from "@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item";
382
+ import { useAtomValue } from "@effect-atom/atom-react";
376
383
  import * as Schema from "effect/Schema";
377
384
  import React7, { memo as memo3, useCallback as useCallback3, useEffect as useEffect3, useMemo, useRef as useRef2, useState as useState3 } from "react";
378
385
  import { invariant as invariant2 } from "@dxos/invariant";
379
- import { TreeItem as NaturalTreeItem, Treegrid } from "@dxos/react-ui";
380
- import { ghostFocusWithin, ghostHover, hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls } from "@dxos/ui-theme";
386
+ import { TreeItem as NaturalTreeItem, Treegrid, TREEGRID_PARENT_OF_SEPARATOR } from "@dxos/react-ui";
387
+ import { ghostFocusWithin, ghostHover, hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, mx as mx4 } from "@dxos/ui-theme";
381
388
 
382
389
  // src/components/Tree/helpers.ts
383
390
  var DEFAULT_INDENTATION = 8;
@@ -417,9 +424,8 @@ var TreeItemHeading = /* @__PURE__ */ memo(/* @__PURE__ */ forwardRef(({ label,
417
424
  }, /* @__PURE__ */ React5.createElement(Button, {
418
425
  "data-testid": "treeItem.heading",
419
426
  variant: "ghost",
420
- density: "fine",
421
427
  classNames: [
422
- "grow gap-2 pis-0.5 hover:bg-transparent dark:hover:bg-transparent",
428
+ "grow gap-2 ps-0.5 hover:bg-transparent dark:hover:bg-transparent",
423
429
  "disabled:cursor-default disabled:opacity-100",
424
430
  className
425
431
  ],
@@ -431,13 +437,12 @@ var TreeItemHeading = /* @__PURE__ */ memo(/* @__PURE__ */ forwardRef(({ label,
431
437
  }
432
438
  }, icon && /* @__PURE__ */ React5.createElement(Icon2, {
433
439
  icon: icon ?? "ph--placeholder--regular",
434
- size: 5,
435
440
  classNames: [
436
- "mlb-1",
437
- styles?.icon
441
+ "my-1",
442
+ styles?.surfaceText
438
443
  ]
439
444
  }), /* @__PURE__ */ React5.createElement("span", {
440
- className: "flex-1 is-0 truncate text-start text-sm font-normal",
445
+ className: "flex-1 w-0 truncate text-start font-normal",
441
446
  "data-tooltip": true
442
447
  }, toLocalizedString(label, t))));
443
448
  }));
@@ -445,7 +450,7 @@ var TreeItemHeading = /* @__PURE__ */ memo(/* @__PURE__ */ forwardRef(({ label,
445
450
  // src/components/Tree/TreeItemToggle.tsx
446
451
  import React6, { forwardRef as forwardRef2, memo as memo2 } from "react";
447
452
  import { IconButton as IconButton2 } from "@dxos/react-ui";
448
- var TreeItemToggle = /* @__PURE__ */ memo2(/* @__PURE__ */ forwardRef2(({ open, isBranch, hidden, classNames, ...props }, forwardedRef) => {
453
+ var TreeItemToggle = /* @__PURE__ */ memo2(/* @__PURE__ */ forwardRef2(({ classNames, open, isBranch, hidden, ...props }, forwardedRef) => {
449
454
  return /* @__PURE__ */ React6.createElement(IconButton2, {
450
455
  ref: forwardedRef,
451
456
  "data-testid": "treeItem.toggle",
@@ -453,9 +458,9 @@ var TreeItemToggle = /* @__PURE__ */ memo2(/* @__PURE__ */ forwardRef2(({ open,
453
458
  variant: "ghost",
454
459
  density: "fine",
455
460
  classNames: [
456
- "bs-full is-6 pli-0",
457
- "[&_svg]:transition-[transform] [&_svg]:duration-200",
458
- open && "[&_svg]:rotate-90",
461
+ "h-full w-6 px-0",
462
+ "[&_svg]:transition-transform [&_svg]:duration-200",
463
+ open ? "[&_svg]:rotate-90" : "[&_svg]:rotate-0",
459
464
  hidden ? "hidden" : !isBranch && "invisible",
460
465
  classNames
461
466
  ],
@@ -478,7 +483,7 @@ var TreeDataSchema = Schema.Struct({
478
483
  item: Schema.Any
479
484
  });
480
485
  var isTreeData = (data) => Schema.is(TreeDataSchema)(data);
481
- var RawTreeItem = ({ item, path: _path, levelOffset = 2, last, draggable: _draggable, renderColumns: Columns, blockInstruction, canDrop, canSelect, onOpenChange, onSelect }) => {
486
+ var RawTreeItem = ({ item, path: pathProp, levelOffset = 2, last, draggable: draggableProp, renderColumns: Columns, blockInstruction, canDrop, canSelect, onOpenChange, onSelect, onItemHover }) => {
482
487
  const rowRef = useRef2(null);
483
488
  const buttonRef = useRef2(null);
484
489
  const openRef = useRef2(false);
@@ -486,18 +491,18 @@ var RawTreeItem = ({ item, path: _path, levelOffset = 2, last, draggable: _dragg
486
491
  const [_state, setState] = useState3("idle");
487
492
  const [instruction, setInstruction] = useState3(null);
488
493
  const [menuOpen, setMenuOpen] = useState3(false);
489
- const { useItems, getProps, useIsOpen, useIsCurrent } = useTree();
490
- const items = useItems(item);
491
- const { id, parentOf, label, className, headingClassName, icon, iconHue, disabled, testId } = getProps(item, _path);
494
+ const { itemProps: itemPropsAtom, childIds: childIdsAtom, itemOpen: itemOpenAtom, itemCurrent: itemCurrentAtom } = useTree();
492
495
  const path = useMemo(() => [
493
- ..._path,
494
- id
496
+ ...pathProp,
497
+ item.id
495
498
  ], [
496
- _path,
497
- id
499
+ pathProp,
500
+ item.id
498
501
  ]);
499
- const open = useIsOpen(path, item);
500
- const current = useIsCurrent(path, item);
502
+ const { id, parentOf, draggable: itemDraggable, droppable: itemDroppable, label, className, headingClassName, icon, iconHue, disabled, testId } = useAtomValue(itemPropsAtom(path));
503
+ const childIds = useAtomValue(childIdsAtom(item.id));
504
+ const open = useAtomValue(itemOpenAtom(path));
505
+ const current = useAtomValue(itemCurrentAtom(path));
501
506
  const level = path.length - levelOffset;
502
507
  const isBranch = !!parentOf;
503
508
  const mode = last ? "last-in-group" : open ? "expanded" : "standard";
@@ -505,122 +510,140 @@ var RawTreeItem = ({ item, path: _path, levelOffset = 2, last, draggable: _dragg
505
510
  item,
506
511
  path
507
512
  }) ?? true;
513
+ const data = {
514
+ id,
515
+ path,
516
+ item
517
+ };
518
+ const shouldSeedNativeDragData = typeof document !== "undefined" && document.body.hasAttribute("data-platform");
508
519
  const cancelExpand = useCallback3(() => {
509
520
  if (cancelExpandRef.current) {
510
521
  clearTimeout(cancelExpandRef.current);
511
522
  cancelExpandRef.current = null;
512
523
  }
513
524
  }, []);
525
+ const isItemDraggable = draggableProp && itemDraggable !== false;
526
+ const isItemDroppable = itemDroppable !== false;
527
+ const nativeDragText = id;
514
528
  useEffect3(() => {
515
- if (!_draggable) {
529
+ if (!draggableProp) {
516
530
  return;
517
531
  }
518
532
  invariant2(buttonRef.current, void 0, {
519
533
  F: __dxlog_file2,
520
- L: 111,
534
+ L: 150,
521
535
  S: void 0,
522
536
  A: [
523
537
  "buttonRef.current",
524
538
  ""
525
539
  ]
526
540
  });
527
- const data = {
528
- id,
529
- path,
530
- item
531
- };
532
- return combine2(
533
- draggable2({
534
- element: buttonRef.current,
535
- getInitialData: () => data,
536
- onDragStart: () => {
537
- setState("dragging");
538
- if (open) {
539
- openRef.current = true;
540
- onOpenChange?.({
541
- item,
542
- path,
543
- open: false
544
- });
545
- }
546
- },
547
- onDrop: () => {
548
- setState("idle");
549
- if (openRef.current) {
550
- onOpenChange?.({
551
- item,
552
- path,
553
- open: true
554
- });
555
- }
541
+ const makeDraggable = () => draggable2({
542
+ element: buttonRef.current,
543
+ getInitialData: () => data,
544
+ getInitialDataForExternal: () => {
545
+ if (!shouldSeedNativeDragData) {
546
+ return {};
556
547
  }
557
- }),
558
- // https://github.com/atlassian/pragmatic-drag-and-drop/blob/main/packages/hitbox/constellation/index/about.mdx
559
- dropTargetForElements2({
560
- element: buttonRef.current,
561
- getData: ({ input, element }) => {
562
- return attachInstruction(data, {
563
- input,
564
- element,
565
- indentPerLevel: DEFAULT_INDENTATION,
566
- currentLevel: level,
567
- mode,
568
- block: isBranch ? [] : [
569
- "make-child"
570
- ]
548
+ return {
549
+ "text/plain": nativeDragText
550
+ };
551
+ },
552
+ onDragStart: () => {
553
+ setState("dragging");
554
+ if (open) {
555
+ openRef.current = true;
556
+ onOpenChange?.({
557
+ item,
558
+ path,
559
+ open: false
571
560
  });
572
- },
573
- canDrop: ({ source }) => {
574
- const _canDrop = canDrop ?? (() => true);
575
- return source.element !== buttonRef.current && _canDrop({
576
- source: source.data,
577
- target: data
578
- });
579
- },
580
- getIsSticky: () => true,
581
- onDrag: ({ self, source }) => {
582
- const desired = extractInstruction(self.data);
583
- const block = desired && blockInstruction?.({
584
- instruction: desired,
585
- source: source.data,
586
- target: data
561
+ }
562
+ },
563
+ onDrop: () => {
564
+ setState("idle");
565
+ if (openRef.current) {
566
+ onOpenChange?.({
567
+ item,
568
+ path,
569
+ open: true
587
570
  });
588
- const instruction2 = block && desired.type !== "instruction-blocked" ? {
589
- type: "instruction-blocked",
590
- desired
591
- } : desired;
592
- if (source.data.id !== id) {
593
- if (instruction2?.type === "make-child" && isBranch && !open && !cancelExpandRef.current) {
594
- cancelExpandRef.current = setTimeout(() => {
595
- onOpenChange?.({
596
- item,
597
- path,
598
- open: true
599
- });
600
- }, 500);
601
- }
602
- if (instruction2?.type !== "make-child") {
603
- cancelExpand();
604
- }
605
- setInstruction(instruction2);
606
- } else if (instruction2?.type === "reparent") {
607
- setInstruction(instruction2);
608
- } else {
609
- setInstruction(null);
571
+ }
572
+ }
573
+ });
574
+ if (!isItemDroppable) {
575
+ return isItemDraggable ? makeDraggable() : void 0;
576
+ }
577
+ const dropTarget = dropTargetForElements2({
578
+ element: buttonRef.current,
579
+ getData: ({ input, element }) => {
580
+ return attachInstruction(data, {
581
+ input,
582
+ element,
583
+ indentPerLevel: DEFAULT_INDENTATION,
584
+ currentLevel: level,
585
+ mode,
586
+ block: isBranch ? [] : [
587
+ "make-child"
588
+ ]
589
+ });
590
+ },
591
+ canDrop: ({ source }) => {
592
+ const _canDrop = canDrop ?? (() => true);
593
+ return source.element !== buttonRef.current && _canDrop({
594
+ source: source.data,
595
+ target: data
596
+ });
597
+ },
598
+ getIsSticky: () => true,
599
+ onDrag: ({ self, source }) => {
600
+ const desired = extractInstruction(self.data);
601
+ const block = desired && blockInstruction?.({
602
+ instruction: desired,
603
+ source: source.data,
604
+ target: data
605
+ });
606
+ const instruction2 = block && desired.type !== "instruction-blocked" ? {
607
+ type: "instruction-blocked",
608
+ desired
609
+ } : desired;
610
+ if (source.data.id !== id) {
611
+ if (instruction2?.type === "make-child" && isBranch && !open && !cancelExpandRef.current) {
612
+ cancelExpandRef.current = setTimeout(() => {
613
+ onOpenChange?.({
614
+ item,
615
+ path,
616
+ open: true
617
+ });
618
+ }, 500);
610
619
  }
611
- },
612
- onDragLeave: () => {
613
- cancelExpand();
614
- setInstruction(null);
615
- },
616
- onDrop: () => {
617
- cancelExpand();
620
+ if (instruction2?.type !== "make-child") {
621
+ cancelExpand();
622
+ }
623
+ setInstruction(instruction2);
624
+ } else if (instruction2?.type === "reparent") {
625
+ setInstruction(instruction2);
626
+ } else {
618
627
  setInstruction(null);
619
628
  }
620
- })
621
- );
629
+ },
630
+ onDragLeave: () => {
631
+ cancelExpand();
632
+ setInstruction(null);
633
+ },
634
+ onDrop: () => {
635
+ cancelExpand();
636
+ setInstruction(null);
637
+ }
638
+ });
639
+ if (!isItemDraggable) {
640
+ return dropTarget;
641
+ }
642
+ return combine2(makeDraggable(), dropTarget);
622
643
  }, [
623
- _draggable,
644
+ draggableProp,
645
+ isItemDraggable,
646
+ isItemDroppable,
624
647
  item,
625
648
  id,
626
649
  mode,
@@ -680,33 +703,46 @@ var RawTreeItem = ({ item, path: _path, levelOffset = 2, last, draggable: _dragg
680
703
  handleOpenToggle,
681
704
  handleSelect
682
705
  ]);
706
+ const handleItemHover = useCallback3(() => {
707
+ onItemHover?.({
708
+ item
709
+ });
710
+ }, [
711
+ onItemHover,
712
+ item
713
+ ]);
714
+ const handleContextMenu = useCallback3((event) => {
715
+ event.preventDefault();
716
+ setMenuOpen(true);
717
+ }, [
718
+ setMenuOpen
719
+ ]);
720
+ const childProps = {
721
+ draggable: draggableProp,
722
+ renderColumns: Columns,
723
+ blockInstruction,
724
+ canDrop,
725
+ canSelect,
726
+ onItemHover,
727
+ onOpenChange,
728
+ onSelect
729
+ };
683
730
  return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(Treegrid.Row, {
684
731
  ref: rowRef,
685
732
  key: id,
686
733
  id,
687
734
  "aria-labelledby": `${id}__label`,
688
- parentOf: parentOf?.join(Treegrid.PARENT_OF_SEPARATOR),
689
- classNames: [
690
- "grid grid-cols-subgrid col-[tree-row] mbs-0.5 aria-[current]:bg-activeSurface",
691
- hoverableControls,
692
- hoverableFocusedKeyboardControls,
693
- hoverableFocusedWithinControls,
694
- hoverableDescriptionIcons,
695
- ghostHover,
696
- ghostFocusWithin,
697
- className
698
- ],
735
+ parentOf: parentOf?.join(TREEGRID_PARENT_OF_SEPARATOR),
699
736
  "data-object-id": id,
700
737
  "data-testid": testId,
701
738
  // NOTE(thure): This is intentionally an empty string to for descendents to select by in the CSS
702
739
  // without alerting the user (except for in the correct link element). See also:
703
740
  // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current#description
704
741
  "aria-current": current ? "" : void 0,
742
+ classNames: mx4("grid grid-cols-subgrid col-[tree-row] mt-0.5 is-current:bg-active-surface", hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, hoverableDescriptionIcons, ghostFocusWithin, ghostHover, className),
705
743
  onKeyDown: handleKeyDown,
706
- onContextMenu: (event) => {
707
- event.preventDefault();
708
- setMenuOpen(true);
709
- }
744
+ onMouseEnter: handleItemHover,
745
+ onContextMenu: handleContextMenu
710
746
  }, /* @__PURE__ */ React7.createElement("div", {
711
747
  role: "none",
712
748
  className: "indent relative grid grid-cols-subgrid col-[tree-row]",
@@ -735,36 +771,31 @@ var RawTreeItem = ({ item, path: _path, levelOffset = 2, last, draggable: _dragg
735
771
  }), instruction && /* @__PURE__ */ React7.createElement(NaturalTreeItem.DropIndicator, {
736
772
  instruction,
737
773
  gap: 2
738
- }))), open && items.map((item2, index) => /* @__PURE__ */ React7.createElement(TreeItem, {
739
- key: item2.id,
740
- item: item2,
774
+ }))), open && childIds.map((childId, index) => /* @__PURE__ */ React7.createElement(TreeItemById, {
775
+ key: childId,
776
+ id: childId,
741
777
  path,
742
- last: index === items.length - 1,
743
- draggable: _draggable,
744
- renderColumns: Columns,
745
- blockInstruction,
746
- canDrop,
747
- canSelect,
748
- onOpenChange,
749
- onSelect
778
+ last: index === childIds.length - 1,
779
+ ...childProps
750
780
  })));
751
781
  };
752
782
  var TreeItem = /* @__PURE__ */ memo3(RawTreeItem);
783
+ var RawTreeItemById = ({ id, ...props }) => {
784
+ const { item: itemAtom } = useTree();
785
+ const item = useAtomValue(itemAtom(id));
786
+ if (!item) {
787
+ return null;
788
+ }
789
+ return /* @__PURE__ */ React7.createElement(TreeItem, {
790
+ item,
791
+ ...props
792
+ });
793
+ };
794
+ var TreeItemById = /* @__PURE__ */ memo3(RawTreeItemById);
753
795
 
754
796
  // src/components/Tree/Tree.tsx
755
- var Tree = ({ root, path, id, useItems, getProps, useIsOpen, useIsCurrent, draggable: draggable3 = false, gridTemplateColumns = "[tree-row-start] 1fr min-content [tree-row-end]", classNames, levelOffset, renderColumns, blockInstruction, canDrop, canSelect, onOpenChange, onSelect }) => {
756
- const context = useMemo2(() => ({
757
- useItems,
758
- getProps,
759
- useIsOpen,
760
- useIsCurrent
761
- }), [
762
- useItems,
763
- getProps,
764
- useIsOpen,
765
- useIsCurrent
766
- ]);
767
- const items = useItems(root);
797
+ 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 }) => {
798
+ const childIds = useAtomValue2(model.childIds(rootId));
768
799
  const treePath = useMemo2(() => path ? [
769
800
  ...path,
770
801
  id
@@ -774,15 +805,7 @@ var Tree = ({ root, path, id, useItems, getProps, useIsOpen, useIsCurrent, dragg
774
805
  id,
775
806
  path
776
807
  ]);
777
- return /* @__PURE__ */ React8.createElement(Treegrid2.Root, {
778
- gridTemplateColumns,
779
- classNames
780
- }, /* @__PURE__ */ React8.createElement(TreeProvider, {
781
- value: context
782
- }, items.map((item, index) => /* @__PURE__ */ React8.createElement(TreeItem, {
783
- key: item.id,
784
- item,
785
- last: index === items.length - 1,
808
+ const childProps = {
786
809
  path: treePath,
787
810
  levelOffset,
788
811
  draggable: draggable3,
@@ -791,7 +814,19 @@ var Tree = ({ root, path, id, useItems, getProps, useIsOpen, useIsCurrent, dragg
791
814
  canDrop,
792
815
  canSelect,
793
816
  onOpenChange,
794
- onSelect
817
+ onSelect,
818
+ onItemHover
819
+ };
820
+ return /* @__PURE__ */ React8.createElement(Treegrid2.Root, {
821
+ gridTemplateColumns,
822
+ classNames
823
+ }, /* @__PURE__ */ React8.createElement(TreeProvider, {
824
+ value: model
825
+ }, childIds.map((childId, index) => /* @__PURE__ */ React8.createElement(TreeItemById, {
826
+ key: childId,
827
+ id: childId,
828
+ last: index === childIds.length - 1,
829
+ ...childProps
795
830
  }))));
796
831
  };
797
832
 
@@ -812,13 +847,17 @@ var Path = {
812
847
  };
813
848
  export {
814
849
  Accordion,
850
+ DEFAULT_INDENTATION,
815
851
  List,
816
852
  Path,
817
853
  Tree,
818
854
  TreeDataSchema,
819
855
  TreeItem,
856
+ TreeItemById,
857
+ TreeItemToggle,
820
858
  TreeProvider,
821
859
  isTreeData,
860
+ paddingIndentation,
822
861
  useTree
823
862
  };
824
863
  //# sourceMappingURL=index.mjs.map