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