@dxos/react-ui-list 0.7.1 → 0.7.2-staging.6d26b2a

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 +137 -82
  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 +169 -112
  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 +137 -82
  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 +25 -24
  20. package/dist/types/src/components/Tree/TreeItem.d.ts.map +1 -1
  21. package/dist/types/src/components/Tree/helpers.d.ts +0 -3
  22. package/dist/types/src/components/Tree/helpers.d.ts.map +1 -1
  23. package/dist/types/src/components/Tree/index.d.ts +1 -1
  24. package/dist/types/src/components/Tree/index.d.ts.map +1 -1
  25. package/dist/types/src/components/Tree/testing.d.ts +3 -6
  26. package/dist/types/src/components/Tree/testing.d.ts.map +1 -1
  27. package/package.json +16 -18
  28. package/src/components/List/DropIndicator.tsx +7 -2
  29. package/src/components/Tree/DropIndicator.tsx +7 -8
  30. package/src/components/Tree/Tree.stories.tsx +71 -70
  31. package/src/components/Tree/Tree.tsx +29 -24
  32. package/src/components/Tree/TreeContext.tsx +32 -0
  33. package/src/components/Tree/TreeItem.tsx +116 -80
  34. package/src/components/Tree/helpers.ts +0 -16
  35. package/src/components/Tree/index.ts +1 -1
  36. package/src/components/Tree/testing.ts +4 -73
  37. package/dist/types/src/components/Tree/types.d.ts +0 -18
  38. package/dist/types/src/components/Tree/types.d.ts.map +0 -1
  39. package/src/components/Tree/types.ts +0 -34
@@ -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: gap2 = "0px" }) => {
36
- const lineOffset = `calc(-0.5 * (${gap2} + ${strokeSize}px))`;
35
+ var DropIndicator = ({ edge, gap = 0 }) => {
36
+ const lineOffset = `calc(-0.5 * (${gap}px + ${strokeSize}px))`;
37
37
  const orientation = edgeToOrientationMap[edge];
38
38
  return /* @__PURE__ */ React.createElement("div", {
39
39
  style: {
@@ -57,7 +57,7 @@ import React2, { useCallback, useEffect, useState } from "react";
57
57
  var LIST_NAME = "List";
58
58
  var [ListProvider, useListContext] = createContext(LIST_NAME);
59
59
  var defaultGetId = (item) => item?.id;
60
- var ListRoot = ({ classNames, children, items, isItem: isItem2, getId = defaultGetId, onMove, ...props }) => {
60
+ var ListRoot = ({ classNames, children, items, isItem, getId = defaultGetId, onMove, ...props }) => {
61
61
  const isEqual = useCallback((a, b) => {
62
62
  const idA = getId?.(a);
63
63
  const idB = getId?.(b);
@@ -75,7 +75,7 @@ var ListRoot = ({ classNames, children, items, isItem: isItem2, getId = defaultG
75
75
  return;
76
76
  }
77
77
  return monitorForElements({
78
- canMonitor: ({ source }) => isItem2(source.data),
78
+ canMonitor: ({ source }) => isItem(source.data),
79
79
  onDrop: ({ location, source }) => {
80
80
  const target = location.current.dropTargets[0];
81
81
  if (!target) {
@@ -83,7 +83,7 @@ var ListRoot = ({ classNames, children, items, isItem: isItem2, getId = defaultG
83
83
  }
84
84
  const sourceData = source.data;
85
85
  const targetData = target.data;
86
- if (!isItem2(sourceData) || !isItem2(targetData)) {
86
+ if (!isItem(sourceData) || !isItem(targetData)) {
87
87
  return;
88
88
  }
89
89
  const sourceIdx = items.findIndex((item) => isEqual(item, sourceData));
@@ -107,7 +107,7 @@ var ListRoot = ({ classNames, children, items, isItem: isItem2, getId = defaultG
107
107
  onMove
108
108
  ]);
109
109
  return /* @__PURE__ */ React2.createElement(ListProvider, {
110
- isItem: isItem2,
110
+ isItem,
111
111
  state,
112
112
  setState,
113
113
  ...props
@@ -129,7 +129,7 @@ var defaultContext = {};
129
129
  var LIST_ITEM_NAME = "ListItem";
130
130
  var [ListItemProvider, useListItemContext] = createContext2(LIST_ITEM_NAME, defaultContext);
131
131
  var ListItem = ({ children, classNames, item }) => {
132
- const { isItem: isItem2, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
132
+ const { isItem, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
133
133
  const ref = useRef(null);
134
134
  const dragHandleRef = useRef(null);
135
135
  const [state, setState] = useState2(idle);
@@ -197,7 +197,7 @@ var ListItem = ({ children, classNames, item }) => {
197
197
  dropTargetForElements({
198
198
  element,
199
199
  canDrop: ({ source }) => {
200
- return source.element !== element && isItem2(source.data);
200
+ return source.element !== element && isItem(source.data);
201
201
  },
202
202
  getData: ({ input }) => {
203
203
  return attachClosestEdge(item, {
@@ -311,15 +311,22 @@ var List = {
311
311
  };
312
312
 
313
313
  // packages/ui/react-ui-list/src/components/Tree/Tree.tsx
314
- import React8 from "react";
314
+ import React8, { useMemo as useMemo2 } from "react";
315
315
  import { Treegrid as Treegrid2 } from "@dxos/react-ui";
316
- import { Path } from "@dxos/react-ui-mosaic";
316
+
317
+ // packages/ui/react-ui-list/src/components/Tree/TreeContext.tsx
318
+ import { createContext as createContext3, useContext } from "react";
319
+ import { raise } from "@dxos/debug";
320
+ var TreeContext = /* @__PURE__ */ createContext3(null);
321
+ var useTree = () => useContext(TreeContext) ?? raise(new Error("TreeContext not found"));
322
+ var TreeProvider = TreeContext.Provider;
317
323
 
318
324
  // packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx
319
325
  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";
326
+ import { draggable as pragmaticDraggable, dropTargetForElements as dropTargetForElements2 } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
321
327
  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";
328
+ import React7, { memo as memo3, useCallback as useCallback3, useEffect as useEffect3, useMemo, useRef as useRef2, useState as useState3 } from "react";
329
+ import { S } from "@dxos/echo-schema";
323
330
  import { invariant as invariant2 } from "@dxos/invariant";
324
331
  import { Treegrid } from "@dxos/react-ui";
325
332
  import { focusRing, ghostHover, hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, mx as mx6 } from "@dxos/react-ui-theme";
@@ -348,9 +355,8 @@ var instructionStyles = {
348
355
  var strokeSize2 = 2;
349
356
  var terminalSize2 = 8;
350
357
  var offsetToAlignTerminalWithLine2 = (strokeSize2 - terminalSize2) / 2;
351
- var gap = "0px";
352
- var DropIndicator2 = ({ instruction }) => {
353
- const lineOffset = `calc(-0.5 * (${gap} + ${strokeSize2}px))`;
358
+ var DropIndicator2 = ({ instruction, gap = 0 }) => {
359
+ const lineOffset = `calc(-0.5 * (${gap}px + ${strokeSize2}px))`;
354
360
  const isBlocked = instruction.type === "instruction-blocked";
355
361
  const desiredInstruction = isBlocked ? instruction.desired : instruction;
356
362
  const orientation = edgeToOrientationMap2[desiredInstruction.type];
@@ -439,25 +445,41 @@ var DEFAULT_INDENTATION = 8;
439
445
  var paddingIndendation = (level, indentation = DEFAULT_INDENTATION) => ({
440
446
  paddingInlineStart: `${(level - 1) * indentation}px`
441
447
  });
442
- var getMode = (items, index) => {
443
- const item = items[index];
444
- const next = items[index + 1];
445
- if (!next || item.path.length > next.path.length) {
446
- return "last-in-group";
447
- } else if (item.path.length < next.path.length) {
448
- return "expanded";
449
- } else {
450
- return "standard";
451
- }
452
- };
453
448
 
454
449
  // packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx
455
450
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-list/src/components/Tree/TreeItem.tsx";
456
451
  var hoverableDescriptionIcons = "[--icons-color:inherit] hover-hover:[--icons-color:var(--description-text)] hover-hover:hover:[--icons-color:inherit] focus-within:[--icons-color:inherit]";
457
- var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderColumns: Columns, canDrop, onOpenChange, onSelect }) => {
458
- const { id, label, icon, className, headingClassName, disabled, path, parentOf } = item;
452
+ var TreeDataSchema = S.Struct({
453
+ id: S.String,
454
+ path: S.Array(S.String),
455
+ item: S.Any
456
+ });
457
+ var isTreeData = (data) => S.is(TreeDataSchema)(data);
458
+ var RawTreeItem = ({ item, path: _path, last, draggable: draggable2, renderColumns: Columns, canDrop, onOpenChange, onSelect }) => {
459
+ const { getItems, getProps, isOpen, isCurrent } = useTree();
460
+ const items = getItems(item);
461
+ const { id, label, parentOf, icon, disabled, className, headingClassName, testId } = getProps(item, _path);
462
+ const path = useMemo(() => [
463
+ ..._path,
464
+ id
465
+ ], [
466
+ _path,
467
+ id
468
+ ]);
469
+ const open = isOpen(path, item);
470
+ const current = isCurrent(path, item);
459
471
  const level = path.length - 2;
460
472
  const isBranch = !!parentOf;
473
+ const mode = last ? "last-in-group" : open ? "expanded" : "standard";
474
+ const data = useMemo(() => ({
475
+ id,
476
+ path,
477
+ item
478
+ }), [
479
+ id,
480
+ path,
481
+ item
482
+ ]);
461
483
  const rowRef = useRef2(null);
462
484
  const buttonRef = useRef2(null);
463
485
  const openRef = useRef2(false);
@@ -472,38 +494,46 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
472
494
  }
473
495
  }, []);
474
496
  useEffect3(() => {
475
- if (!_draggable) {
497
+ if (!draggable2) {
476
498
  return;
477
499
  }
478
500
  invariant2(buttonRef.current, void 0, {
479
501
  F: __dxlog_file2,
480
- L: 87,
502
+ L: 104,
481
503
  S: void 0,
482
504
  A: [
483
505
  "buttonRef.current",
484
506
  ""
485
507
  ]
486
508
  });
487
- return combine2(draggable2({
509
+ return combine2(pragmaticDraggable({
488
510
  element: buttonRef.current,
489
- getInitialData: () => item,
511
+ getInitialData: () => data,
490
512
  onDragStart: () => {
491
513
  setState("dragging");
492
514
  if (open) {
493
515
  openRef.current = true;
494
- onOpenChange?.(item, false);
516
+ onOpenChange?.({
517
+ item,
518
+ path,
519
+ open: false
520
+ });
495
521
  }
496
522
  },
497
523
  onDrop: () => {
498
524
  setState("idle");
499
525
  if (openRef.current) {
500
- onOpenChange?.(item, true);
526
+ onOpenChange?.({
527
+ item,
528
+ path,
529
+ open: true
530
+ });
501
531
  }
502
532
  }
503
533
  }), dropTargetForElements2({
504
534
  element: buttonRef.current,
505
535
  getData: ({ input, element }) => {
506
- return attachInstruction(item, {
536
+ return attachInstruction(data, {
507
537
  input,
508
538
  element,
509
539
  indentPerLevel: DEFAULT_INDENTATION,
@@ -516,15 +546,19 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
516
546
  },
517
547
  canDrop: ({ source }) => {
518
548
  const _canDrop = canDrop ?? (() => true);
519
- return source.element !== buttonRef.current && _canDrop(source.data, item);
549
+ return source.element !== buttonRef.current && _canDrop(source.data, data);
520
550
  },
521
551
  getIsSticky: () => true,
522
552
  onDrag: ({ self, source }) => {
523
553
  const instruction2 = extractInstruction(self.data);
524
- if (source.data.id !== item.id) {
554
+ if (source.data.id !== id) {
525
555
  if (instruction2?.type === "make-child" && isBranch && !open && !cancelExpandRef.current) {
526
556
  cancelExpandRef.current = setTimeout(() => {
527
- onOpenChange?.(item, true);
557
+ onOpenChange?.({
558
+ item,
559
+ path,
560
+ open: true
561
+ });
528
562
  }, 500);
529
563
  }
530
564
  if (instruction2?.type !== "make-child") {
@@ -549,24 +583,36 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
549
583
  }, [
550
584
  draggable2,
551
585
  item,
586
+ id,
552
587
  mode,
588
+ path,
553
589
  open,
554
590
  canDrop
555
591
  ]);
556
592
  useEffect3(() => () => cancelExpand(), [
557
593
  cancelExpand
558
594
  ]);
559
- const handleOpenChange = useCallback3(() => onOpenChange?.(item, !open), [
595
+ const handleOpenChange = useCallback3(() => onOpenChange?.({
596
+ item,
597
+ path,
598
+ open: !open
599
+ }), [
560
600
  onOpenChange,
561
601
  item,
602
+ path,
562
603
  open
563
604
  ]);
564
605
  const handleSelect = useCallback3(() => {
565
606
  rowRef.current?.focus();
566
- onSelect?.(item, !current);
607
+ onSelect?.({
608
+ item,
609
+ path,
610
+ current: !current
611
+ });
567
612
  }, [
568
613
  onSelect,
569
614
  item,
615
+ path,
570
616
  current
571
617
  ]);
572
618
  const handleKeyDown = useCallback3((event) => {
@@ -587,15 +633,15 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
587
633
  handleOpenChange,
588
634
  handleSelect
589
635
  ]);
590
- return /* @__PURE__ */ React7.createElement(Treegrid.Row, {
636
+ return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(Treegrid.Row, {
591
637
  ref: rowRef,
592
638
  key: id,
593
639
  id,
594
640
  "aria-labelledby": `${id}__label`,
595
641
  parentOf: parentOf?.join(Treegrid.PARENT_OF_SEPARATOR),
596
642
  classNames: mx6("grid grid-cols-subgrid col-[tree-row] mt-[2px] aria-[current]:bg-input", hoverableControls, hoverableFocusedKeyboardControls, hoverableFocusedWithinControls, hoverableDescriptionIcons, ghostHover, focusRing, className),
597
- "data-itemid": item.id,
598
- "data-testid": item.testId,
643
+ "data-itemid": id,
644
+ "data-testid": testId,
599
645
  // NOTE(thure): This is intentionally an empty string to for descendents to select by in the CSS
600
646
  // without alerting the user (except for in the correct link element). See also:
601
647
  // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current#description
@@ -626,61 +672,70 @@ var RawTreeItem = ({ item, mode, open, current, draggable: _draggable, renderCol
626
672
  onSelect: handleSelect
627
673
  })), Columns && /* @__PURE__ */ React7.createElement(Columns, {
628
674
  item,
675
+ path,
629
676
  menuOpen,
630
677
  setMenuOpen
631
678
  }), instruction && /* @__PURE__ */ React7.createElement(DropIndicator2, {
632
- instruction
679
+ instruction,
680
+ gap: 2
681
+ }))), open && items.map((item2, index) => /* @__PURE__ */ React7.createElement(TreeItem, {
682
+ key: item2.id,
683
+ item: item2,
684
+ path,
685
+ last: index === items.length - 1,
686
+ draggable: draggable2,
687
+ renderColumns: Columns,
688
+ canDrop,
689
+ onOpenChange,
690
+ onSelect
633
691
  })));
634
692
  };
635
693
  var TreeItem = /* @__PURE__ */ memo3(RawTreeItem);
636
694
 
637
695
  // packages/ui/react-ui-list/src/components/Tree/Tree.tsx
638
- var Tree = ({ items, open, current, draggable: draggable3 = false, gridTemplateColumns = "[tree-row-start] 1fr min-content [tree-row-end]", classNames, renderColumns, canDrop, onOpenChange, onSelect }) => {
696
+ 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 }) => {
697
+ const context = useMemo2(() => ({
698
+ getItems,
699
+ getProps,
700
+ isOpen,
701
+ isCurrent
702
+ }), [
703
+ getItems,
704
+ getProps,
705
+ isOpen,
706
+ isCurrent
707
+ ]);
708
+ const items = getItems();
709
+ const path = useMemo2(() => [
710
+ id
711
+ ], [
712
+ id
713
+ ]);
639
714
  return /* @__PURE__ */ React8.createElement(Treegrid2.Root, {
640
715
  gridTemplateColumns,
641
716
  classNames
642
- }, items.map((item, i) => {
643
- const path = Path.create(...item.path);
644
- return /* @__PURE__ */ React8.createElement(TreeItem, {
645
- key: item.id,
646
- item,
647
- mode: getMode(items, i),
648
- open: open.includes(path),
649
- // TODO(wittjosiah): This should also be path-based.
650
- current: current.includes(item.id),
651
- draggable: draggable3,
652
- renderColumns,
653
- canDrop,
654
- onOpenChange,
655
- onSelect
656
- });
657
- }));
717
+ }, /* @__PURE__ */ React8.createElement(TreeProvider, {
718
+ value: context
719
+ }, items.map((item, index) => /* @__PURE__ */ React8.createElement(TreeItem, {
720
+ key: item.id,
721
+ item,
722
+ last: index === items.length - 1,
723
+ path,
724
+ draggable: draggable2,
725
+ renderColumns,
726
+ canDrop,
727
+ onOpenChange,
728
+ onSelect
729
+ }))));
658
730
  };
659
-
660
- // packages/ui/react-ui-list/src/components/Tree/types.ts
661
- import { S } from "@dxos/echo-schema";
662
- var LabelSchema = S.Union(S.String, S.Tuple(S.String, S.Struct({
663
- ns: S.String,
664
- count: S.optional(S.Number)
665
- })));
666
- var ItemSchema = S.mutable(S.Struct({
667
- id: S.String,
668
- label: S.mutable(LabelSchema),
669
- icon: S.optional(S.String),
670
- disabled: S.optional(S.Boolean),
671
- className: S.optional(S.String),
672
- headingClassName: S.optional(S.String),
673
- testId: S.optional(S.String),
674
- path: S.Array(S.String),
675
- parentOf: S.optional(S.Array(S.String))
676
- }));
677
- var isItem = S.is(ItemSchema);
678
731
  export {
679
- ItemSchema,
680
732
  List,
681
733
  RawTreeItem,
682
734
  Tree,
735
+ TreeDataSchema,
683
736
  TreeItem,
684
- isItem
737
+ TreeProvider,
738
+ isTreeData,
739
+ useTree
685
740
  };
686
741
  //# sourceMappingURL=index.mjs.map