@dxos/react-ui-mosaic 0.3.3-main.006ca4d → 0.3.3-main.082f8b3

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 (55) hide show
  1. package/dist/lib/browser/index.mjs +513 -41
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/index.d.ts +1 -0
  5. package/dist/types/src/index.d.ts.map +1 -1
  6. package/dist/types/src/mosaic/Container.d.ts +9 -1
  7. package/dist/types/src/mosaic/Container.d.ts.map +1 -1
  8. package/dist/types/src/mosaic/Mosaic.d.ts +3 -2
  9. package/dist/types/src/mosaic/Mosaic.d.ts.map +1 -1
  10. package/dist/types/src/mosaic/Root.d.ts.map +1 -1
  11. package/dist/types/src/mosaic/Tile.d.ts +6 -0
  12. package/dist/types/src/mosaic/Tile.d.ts.map +1 -1
  13. package/dist/types/src/mosaic/hooks/index.d.ts +0 -1
  14. package/dist/types/src/mosaic/hooks/index.d.ts.map +1 -1
  15. package/dist/types/src/mosaic/hooks/useItemsWithPreview.d.ts +2 -1
  16. package/dist/types/src/mosaic/hooks/useItemsWithPreview.d.ts.map +1 -1
  17. package/dist/types/src/stories/Home.stories.d.ts +11 -0
  18. package/dist/types/src/stories/Home.stories.d.ts.map +1 -0
  19. package/dist/types/src/testing/decorators.d.ts.map +1 -1
  20. package/dist/types/src/testing/generator.d.ts +4 -4
  21. package/dist/types/src/testing/generator.d.ts.map +1 -1
  22. package/dist/types/src/testing/index.d.ts +0 -1
  23. package/dist/types/src/testing/index.d.ts.map +1 -1
  24. package/dist/types/src/views/Grid/Grid.d.ts +3 -3
  25. package/dist/types/src/views/Grid/Grid.d.ts.map +1 -1
  26. package/dist/types/src/views/Grid/Grid.stories.d.ts +1 -1
  27. package/dist/types/src/views/Stack/Columns.stories.d.ts +1 -1
  28. package/dist/types/src/views/Stack/Columns.stories.d.ts.map +1 -1
  29. package/dist/types/src/views/Tree/testing.d.ts +1 -1
  30. package/dist/types/src/views/Tree/testing.d.ts.map +1 -1
  31. package/package.json +13 -14
  32. package/src/index.ts +3 -0
  33. package/src/mosaic/Container.tsx +10 -2
  34. package/src/mosaic/Mosaic.ts +6 -2
  35. package/src/mosaic/Root.tsx +1 -2
  36. package/src/mosaic/Tile.tsx +4 -0
  37. package/src/mosaic/hooks/index.ts +0 -1
  38. package/src/mosaic/hooks/useItemsWithPreview.ts +56 -20
  39. package/src/stories/Home.stories.tsx +87 -0
  40. package/src/testing/decorators.tsx +1 -0
  41. package/src/testing/generator.ts +9 -9
  42. package/src/testing/index.ts +0 -1
  43. package/src/views/Grid/Grid.tsx +27 -14
  44. package/src/views/Grid/testing.tsx +2 -2
  45. package/src/views/Kanban/Kanban.tsx +1 -1
  46. package/src/views/Stack/Columns.stories.tsx +1 -1
  47. package/src/views/Stack/testing.tsx +1 -1
  48. package/src/views/Tree/Tree.tsx +17 -11
  49. package/src/views/Tree/testing.tsx +13 -12
  50. package/dist/types/src/mosaic/hooks/useSortedItems.d.ts +0 -6
  51. package/dist/types/src/mosaic/hooks/useSortedItems.d.ts.map +0 -1
  52. package/dist/types/src/testing/next-fractional-index.d.ts +0 -5
  53. package/dist/types/src/testing/next-fractional-index.d.ts.map +0 -1
  54. package/src/mosaic/hooks/useSortedItems.ts +0 -14
  55. package/src/testing/next-fractional-index.ts +0 -36
@@ -181,7 +181,7 @@ var MosaicRoot = ({ Component: Component2 = DefaultComponent, debug, children })
181
181
  over
182
182
  });
183
183
  } else {
184
- return "adopt";
184
+ return "reject";
185
185
  }
186
186
  };
187
187
  setOperation(onOver({
@@ -272,7 +272,7 @@ var MosaicDebug = ({ containers, operation, activeItem, overItem }) => {
272
272
  var useMosaic = () => useContext2(MosaicContext) ?? raise2(new Error("Missing MosaicContext"));
273
273
 
274
274
  // packages/ui/react-ui-mosaic/src/mosaic/hooks/useItemsWithPreview.ts
275
- var useItemsWithPreview = ({ path, items }) => {
275
+ var useItemsWithPreview = ({ path, items, strategy = "default" }) => {
276
276
  const { operation, activeItem, overItem } = useMosaic();
277
277
  const [itemsWithPreview, setItemsWithPreview] = useState2(items);
278
278
  const overParent = (
@@ -282,7 +282,7 @@ var useItemsWithPreview = ({ path, items }) => {
282
282
  );
283
283
  const [lastOverParent, setLastOverParent] = useState2(overParent);
284
284
  useEffect2(() => {
285
- if (operation === "reject" || operation === "rearrange" || !activeItem || !overItem) {
285
+ if (!activeItem || !overItem) {
286
286
  setLastOverParent(void 0);
287
287
  setItemsWithPreview(items);
288
288
  return;
@@ -290,28 +290,56 @@ var useItemsWithPreview = ({ path, items }) => {
290
290
  if (lastOverParent === overParent) {
291
291
  return;
292
292
  }
293
- setLastOverParent(overParent);
294
293
  const activeIsChild = Path.hasChild(path, activeItem.path);
295
294
  const overIsChild = Path.hasChild(path, overItem.path);
296
295
  const overSelf = overItem.path === path;
297
- if (!activeIsChild && overIsChild) {
298
- setItemsWithPreview((items2) => {
299
- const position = overItem.position;
300
- return [
301
- ...items2.slice(0, position),
302
- activeItem.item,
303
- ...items2.slice(position)
304
- ];
305
- });
306
- } else if (!activeIsChild && overSelf) {
307
- setItemsWithPreview((items2) => [
308
- ...items2,
309
- activeItem.item
310
- ]);
311
- } else if (activeIsChild && !overIsChild) {
312
- setItemsWithPreview((items2) => items2.filter((item) => item.id !== activeItem.item.id));
313
- } else {
314
- setItemsWithPreview(items);
296
+ switch (strategy) {
297
+ case "layout-stable":
298
+ setLastOverParent(overParent);
299
+ if (activeIsChild && !overIsChild && operation !== "rearrange") {
300
+ setItemsWithPreview((sortedItems) => sortedItems.map((item) => {
301
+ if (item.id === activeItem.item.id) {
302
+ return {
303
+ ...item,
304
+ id: `${item.id}--origin`
305
+ };
306
+ } else {
307
+ return item;
308
+ }
309
+ }));
310
+ } else {
311
+ setItemsWithPreview(items);
312
+ }
313
+ break;
314
+ case "default":
315
+ default:
316
+ if (operation === "reject" || operation === "rearrange") {
317
+ setLastOverParent(void 0);
318
+ setItemsWithPreview(items);
319
+ return;
320
+ } else {
321
+ setLastOverParent(overParent);
322
+ }
323
+ if (!activeIsChild && overIsChild) {
324
+ setItemsWithPreview((items2) => {
325
+ const position = overItem.position;
326
+ return [
327
+ ...items2.slice(0, position),
328
+ activeItem.item,
329
+ ...items2.slice(position)
330
+ ];
331
+ });
332
+ } else if (!activeIsChild && overSelf) {
333
+ setItemsWithPreview((items2) => [
334
+ ...items2,
335
+ activeItem.item
336
+ ]);
337
+ } else if (activeIsChild && !overIsChild) {
338
+ setItemsWithPreview((items2) => items2.filter((item) => item.id !== activeItem.item.id));
339
+ } else {
340
+ setItemsWithPreview(items);
341
+ }
342
+ break;
315
343
  }
316
344
  }, [
317
345
  operation,
@@ -322,15 +350,7 @@ var useItemsWithPreview = ({ path, items }) => {
322
350
  path,
323
351
  items
324
352
  ]);
325
- return items.length === itemsWithPreview.length ? items : itemsWithPreview;
326
- };
327
-
328
- // packages/ui/react-ui-mosaic/src/mosaic/hooks/useSortedItems.ts
329
- var useSortedItems = (items) => {
330
- const { compare } = useContainer();
331
- return compare ? [
332
- ...items
333
- ].sort(compare) : items;
353
+ return strategy !== "layout-stable" && items.length === itemsWithPreview.length ? items : itemsWithPreview;
334
354
  };
335
355
 
336
356
  // packages/ui/react-ui-mosaic/src/mosaic/DragOverlay.tsx
@@ -344,19 +364,19 @@ var MosaicDragOverlay = ({ delay = 200, debug = false, ...overlayProps }) => {
344
364
  useEffect3(() => {
345
365
  if (activeItem) {
346
366
  let container2;
347
- let OverlayComponent2;
367
+ let OverlayComponent3;
348
368
  if (overItem?.path) {
349
369
  container2 = containers[Path.first(overItem.path)];
350
- OverlayComponent2 = container2?.Component;
370
+ OverlayComponent3 = container2?.Component;
351
371
  }
352
- if (!OverlayComponent2) {
372
+ if (!OverlayComponent3) {
353
373
  container2 = containers[Path.first(activeItem.path)];
354
- OverlayComponent2 = container2?.Component ?? DefaultComponent;
374
+ OverlayComponent3 = container2?.Component ?? DefaultComponent;
355
375
  }
356
376
  clearTimeout(timer.current);
357
377
  timer.current = setTimeout(() => setState({
358
378
  container: container2,
359
- OverlayComponent: OverlayComponent2
379
+ OverlayComponent: OverlayComponent3
360
380
  }), timer.current ? delay : 0);
361
381
  } else {
362
382
  setState({});
@@ -366,7 +386,7 @@ var MosaicDragOverlay = ({ delay = 200, debug = false, ...overlayProps }) => {
366
386
  overItem
367
387
  ]);
368
388
  const container = state.container ?? (activeItem && containers[Path.first(activeItem.path)]);
369
- const OverlayComponent = state.OverlayComponent ?? container?.Component;
389
+ const OverlayComponent2 = state.OverlayComponent ?? container?.Component;
370
390
  const FallbackComponent = (activeItem && containers[Path.first(activeItem.path)])?.Component ?? DefaultComponent;
371
391
  return (
372
392
  // TODO(burdon): Set custom animations (e.g., in/out/around).
@@ -376,7 +396,7 @@ var MosaicDragOverlay = ({ delay = 200, debug = false, ...overlayProps }) => {
376
396
  style: {
377
397
  ...container?.getOverlayStyle?.()
378
398
  }
379
- }, activeItem?.path && container && OverlayComponent && /* @__PURE__ */ React5.createElement(DensityProvider, {
399
+ }, activeItem?.path && container && OverlayComponent2 && /* @__PURE__ */ React5.createElement(DensityProvider, {
380
400
  density: "fine"
381
401
  }, /* @__PURE__ */ React5.createElement(OverlayErrorBoundary, {
382
402
  fallback: /* @__PURE__ */ React5.createElement(FallbackComponent, {
@@ -386,7 +406,7 @@ var MosaicDragOverlay = ({ delay = 200, debug = false, ...overlayProps }) => {
386
406
  operation,
387
407
  active: "overlay"
388
408
  })
389
- }, /* @__PURE__ */ React5.createElement(OverlayComponent, {
409
+ }, /* @__PURE__ */ React5.createElement(OverlayComponent2, {
390
410
  ...container.getOverlayProps?.(),
391
411
  item: activeItem.item,
392
412
  path: activeItem.path,
@@ -583,14 +603,466 @@ var Mosaic = {
583
603
  // TODO(burdon): Don't export; move to util.
584
604
  Debug
585
605
  };
606
+
607
+ // packages/ui/react-ui-mosaic/src/views/Grid/layout.ts
608
+ var createMatrix = (size, value) => {
609
+ const matrix = [];
610
+ for (let x = 0; x < size.x; x++) {
611
+ matrix.push(Array.from({
612
+ length: size.y
613
+ }, (_, y) => value({
614
+ x,
615
+ y
616
+ })));
617
+ }
618
+ return matrix;
619
+ };
620
+ var getDimension = ({ width, height }, spacing = 0) => ({
621
+ width: width - spacing * 2,
622
+ height: height - spacing * 2
623
+ });
624
+ var getBounds = ({ x, y }, { width, height }, spacing = 0) => ({
625
+ left: x * width + spacing * 2,
626
+ top: y * height + spacing * 2,
627
+ width: width - spacing * 2,
628
+ height: height - spacing * 2
629
+ });
630
+ var getPanelBounds = ({ x, y }, { width, height }, spacing = 0) => ({
631
+ width: x * width + spacing * 2,
632
+ height: y * height + spacing * 2
633
+ });
634
+ var calculateCellWidth = (defaultWidth, screenWidth, options = {
635
+ min: 260,
636
+ max: 400
637
+ }) => {
638
+ return screenWidth > options.min && screenWidth < options.max ? screenWidth : defaultWidth;
639
+ };
640
+
641
+ // packages/ui/react-ui-mosaic/src/views/Grid/Grid.tsx
642
+ import { useDroppable as useDroppable2 } from "@dnd-kit/core";
643
+ import { PlusCircle } from "@phosphor-icons/react";
644
+ import defaultsDeep from "lodash.defaultsdeep";
645
+ import React8, { useState as useState4, useMemo, useEffect as useEffect4 } from "react";
646
+ import { useResizeDetector } from "react-resize-detector";
647
+ import { Button, useMediaQuery } from "@dxos/react-ui";
648
+ import { getSize, mx as mx2 } from "@dxos/react-ui-theme";
649
+ var defaultGridOptions = {
650
+ size: {
651
+ x: 8,
652
+ y: 8
653
+ },
654
+ cellBounds: {
655
+ width: 272,
656
+ height: 272
657
+ },
658
+ spacing: 6
659
+ };
660
+ var Grid = ({ id, items = [], layout = {}, options: opts, margin, square = true, debug, selected: controlledSelected, Component: Component2 = Mosaic.DefaultComponent, className, onDrop, onOver, onSelect, onCreate, onAction }) => {
661
+ const { ref: containerRef, width, height } = useResizeDetector({
662
+ refreshRate: 200
663
+ });
664
+ const options = defaultsDeep({}, opts, defaultGridOptions);
665
+ const { matrix, bounds, cellBounds } = useMemo(() => {
666
+ const cellWidth = calculateCellWidth(options.cellBounds.width, width ?? 0);
667
+ const cellBounds2 = {
668
+ width: cellWidth,
669
+ height: square ? cellWidth : options.cellBounds.height
670
+ };
671
+ return {
672
+ matrix: createMatrix(options.size, ({ x, y }) => ({
673
+ x,
674
+ y
675
+ })),
676
+ bounds: getPanelBounds(options.size, cellBounds2, options.spacing),
677
+ cellBounds: cellBounds2
678
+ };
679
+ }, [
680
+ options,
681
+ width
682
+ ]);
683
+ const [isNotMobile] = useMediaQuery("md");
684
+ const marginSize = margin && !isNotMobile ? Math.max(cellBounds.width, cellBounds.height) : 0;
685
+ const [selected, setSelected] = useState4(controlledSelected);
686
+ useEffect4(() => {
687
+ setSelected(controlledSelected);
688
+ if (controlledSelected) {
689
+ scrollToCenter(controlledSelected);
690
+ }
691
+ }, [
692
+ controlledSelected
693
+ ]);
694
+ const scrollToCenter = (id2) => {
695
+ const item = items.find((item2) => item2.id === id2);
696
+ if (item && width && height) {
697
+ const pos = getBounds(layout[item.id], cellBounds);
698
+ const top = pos.top + marginSize - (height - cellBounds.height) / 2;
699
+ const left = pos.left + marginSize - (width - cellBounds.width) / 2;
700
+ containerRef.current.scrollTo({
701
+ top,
702
+ left,
703
+ behavior: "smooth"
704
+ });
705
+ }
706
+ };
707
+ const handleSelect = (id2) => {
708
+ setSelected(id2);
709
+ scrollToCenter(id2);
710
+ onSelect?.(id2);
711
+ };
712
+ useEffect4(() => {
713
+ if (selected) {
714
+ scrollToCenter(selected);
715
+ }
716
+ }, [
717
+ selected,
718
+ width,
719
+ height
720
+ ]);
721
+ return /* @__PURE__ */ React8.createElement(Mosaic.Container, {
722
+ id,
723
+ Component: Component2,
724
+ getOverlayProps: () => ({
725
+ grow: true
726
+ }),
727
+ getOverlayStyle: () => getDimension(cellBounds, options.spacing),
728
+ onDrop,
729
+ onOver
730
+ }, /* @__PURE__ */ React8.createElement("div", {
731
+ className: mx2("flex grow overflow-auto", className)
732
+ }, /* @__PURE__ */ React8.createElement("div", {
733
+ ref: containerRef,
734
+ className: mx2("grow overflow-auto snap-x snap-mandatory md:snap-none")
735
+ }, /* @__PURE__ */ React8.createElement("div", {
736
+ className: "group block relative",
737
+ style: {
738
+ ...bounds,
739
+ margin: marginSize
740
+ }
741
+ }, matrix && /* @__PURE__ */ React8.createElement("div", {
742
+ style: {
743
+ padding: options.spacing
744
+ }
745
+ }, /* @__PURE__ */ React8.createElement("div", {
746
+ className: "relative"
747
+ }, matrix.map((row) => row.map(({ x, y }) => /* @__PURE__ */ React8.createElement(GridCell, {
748
+ key: `${x}-${y}`,
749
+ path: id,
750
+ position: {
751
+ x,
752
+ y
753
+ },
754
+ bounds: getBounds({
755
+ x,
756
+ y
757
+ }, cellBounds),
758
+ padding: options.spacing,
759
+ onCreate
760
+ }))))), /* @__PURE__ */ React8.createElement("div", null, items.map((item) => {
761
+ const position = layout[item.id] ?? {
762
+ x: 0,
763
+ y: 0
764
+ };
765
+ return /* @__PURE__ */ React8.createElement(Mosaic.DraggableTile, {
766
+ key: item.id,
767
+ item,
768
+ path: id,
769
+ position,
770
+ Component: Component2,
771
+ draggableStyle: {
772
+ position: "absolute",
773
+ ...getBounds(position, cellBounds, options.spacing)
774
+ },
775
+ onSelect: () => handleSelect(item.id),
776
+ onAction
777
+ });
778
+ }))), debug && /* @__PURE__ */ React8.createElement(Mosaic.Debug, {
779
+ data: {
780
+ items: items?.length
781
+ },
782
+ position: "bottom-right"
783
+ }))));
784
+ };
785
+ var GridCell = ({ path, position, bounds, padding, onCreate }) => {
786
+ const { overItem } = useMosaic();
787
+ const isOverContainer = path === overItem?.path;
788
+ const { setNodeRef, isOver } = useDroppable2({
789
+ id: Path.create(path, "cell", `${position.x}-${position.y}`),
790
+ data: {
791
+ path,
792
+ position
793
+ }
794
+ });
795
+ return /* @__PURE__ */ React8.createElement("div", {
796
+ ref: setNodeRef,
797
+ style: {
798
+ ...bounds,
799
+ padding
800
+ },
801
+ className: "absolute flex justify-center items-center grow select-none cursor-pointer"
802
+ }, /* @__PURE__ */ React8.createElement("div", {
803
+ className: mx2("group/cell flex group-hover:flex w-full h-full items-center justify-center", "box-border border-dashed border-4 border-neutral-100 rounded-lg", "transition ease-in-out duration-300", isOver && "flex bg-neutral-200 border-neutral-400")
804
+ }, /* @__PURE__ */ React8.createElement("div", {
805
+ className: mx2("opacity-10 transition ease-in-out duration-300 group-hover/cell:opacity-100", isOverContainer && "hidden")
806
+ }, onCreate && // TODO(burdon): Style button.
807
+ /* @__PURE__ */ React8.createElement(Button, {
808
+ variant: "ghost",
809
+ onClick: () => onCreate(position)
810
+ }, /* @__PURE__ */ React8.createElement(PlusCircle, {
811
+ className: getSize(8)
812
+ })))));
813
+ };
814
+
815
+ // packages/ui/react-ui-mosaic/src/views/Kanban/Kanban.tsx
816
+ import React9, { forwardRef as forwardRef2, useMemo as useMemo2 } from "react";
817
+ import { Card as Card2 } from "@dxos/react-ui";
818
+ import { groupSurface, mx as mx3 } from "@dxos/react-ui-theme";
819
+ var Kanban = ({ id, columns, Component: TileComponent = Mosaic.DefaultComponent, debug, onDrop }) => {
820
+ const Component2 = useMemo2(() => OverlayComponent(id, TileComponent), [
821
+ id,
822
+ TileComponent
823
+ ]);
824
+ return /* @__PURE__ */ React9.createElement(Mosaic.Container, {
825
+ id,
826
+ debug,
827
+ Component: Component2,
828
+ // Restrict columns to x-axis.
829
+ modifier: ({ path, item }, { transform }) => path === Path.create(id, item.id) ? {
830
+ ...transform,
831
+ y: 0
832
+ } : transform,
833
+ // Restrict to objects from other columns.
834
+ // TODO(burdon): Consider objects from other containers.
835
+ // TODO(wittjosiah): Allow override.
836
+ onOver: ({ active, over }) => Path.length(active.path) >= Path.length(over.path) ? "transfer" : "reject",
837
+ onDrop
838
+ }, /* @__PURE__ */ React9.createElement("div", {
839
+ className: "grow flex overflow-y-hidden overflow-x-auto"
840
+ }, /* @__PURE__ */ React9.createElement("div", {
841
+ className: "flex"
842
+ }, /* @__PURE__ */ React9.createElement(Mosaic.SortableContext, {
843
+ items: columns,
844
+ direction: "horizontal"
845
+ }, columns.map((column, index) => /* @__PURE__ */ React9.createElement(Mosaic.SortableTile, {
846
+ key: column.id,
847
+ item: column,
848
+ path: id,
849
+ position: index,
850
+ Component: Component2,
851
+ debug
852
+ }))))));
853
+ };
854
+ var OverlayComponent = (id, Component2) => /* @__PURE__ */ forwardRef2((props, ref) => {
855
+ const isColumn = Path.hasRoot(props.path, id) && Path.length(props.path) === 2;
856
+ if (isColumn && props.active === "overlay") {
857
+ return (
858
+ // Needs to not override the main kanban path.
859
+ /* @__PURE__ */ React9.createElement(Mosaic.Container, {
860
+ id: `${id}-active`,
861
+ Component: Component2
862
+ }, /* @__PURE__ */ React9.createElement(KanbanColumnComponent, {
863
+ ...props,
864
+ ref
865
+ }))
866
+ );
867
+ }
868
+ return isColumn ? /* @__PURE__ */ React9.createElement(KanbanColumnComponent, {
869
+ ...props,
870
+ ref
871
+ }) : /* @__PURE__ */ React9.createElement(Component2, {
872
+ ...props,
873
+ ref
874
+ });
875
+ });
876
+ var KanbanColumnComponent = /* @__PURE__ */ forwardRef2(({ path, item, active, draggableStyle, draggableProps, debug }, forwardRef1) => {
877
+ const { id, title, items } = item;
878
+ const { Component: Component2 } = useContainer();
879
+ const itemsWithPreview = useItemsWithPreview({
880
+ path,
881
+ items
882
+ });
883
+ return /* @__PURE__ */ React9.createElement("div", {
884
+ role: "none",
885
+ className: "grow flex flex-col",
886
+ ref: forwardRef1
887
+ }, /* @__PURE__ */ React9.createElement("div", {
888
+ className: mx3(groupSurface, "grow flex flex-col w-[300px] snap-center overflow-hidden m-1", active === "rearrange" && "opacity-0"),
889
+ style: draggableStyle
890
+ }, /* @__PURE__ */ React9.createElement(Card2.Root, {
891
+ classNames: "shrink-0 bg-cyan-200"
892
+ }, /* @__PURE__ */ React9.createElement(Card2.Header, null, /* @__PURE__ */ React9.createElement(Card2.DragHandle, draggableProps), /* @__PURE__ */ React9.createElement(Card2.Title, {
893
+ title
894
+ }), /* @__PURE__ */ React9.createElement(Card2.Menu, null))), /* @__PURE__ */ React9.createElement("div", {
895
+ className: mx3("flex flex-col grow overflow-y-scroll")
896
+ }, /* @__PURE__ */ React9.createElement("div", {
897
+ className: "flex flex-col my-1"
898
+ }, /* @__PURE__ */ React9.createElement(Mosaic.SortableContext, {
899
+ id: path,
900
+ items: itemsWithPreview,
901
+ direction: "vertical"
902
+ }, itemsWithPreview.map((item2, index) => /* @__PURE__ */ React9.createElement(Mosaic.SortableTile, {
903
+ key: item2.id,
904
+ item: item2,
905
+ path,
906
+ position: index,
907
+ Component: Component2,
908
+ className: "m-1"
909
+ }))))), debug && /* @__PURE__ */ React9.createElement(Mosaic.Debug, {
910
+ data: {
911
+ path,
912
+ id,
913
+ items: itemsWithPreview.length
914
+ }
915
+ })));
916
+ });
917
+
918
+ // packages/ui/react-ui-mosaic/src/views/Stack/Stack.tsx
919
+ import React10 from "react";
920
+ import { mx as mx4 } from "@dxos/react-ui-theme";
921
+ var Stack = ({ id, Component: Component2 = Mosaic.DefaultComponent, onOver, onDrop, items = [], direction = "vertical", debug }) => {
922
+ const itemsWithPreview = useItemsWithPreview({
923
+ path: id,
924
+ items
925
+ });
926
+ return /* @__PURE__ */ React10.createElement("div", {
927
+ className: mx4("flex overflow-hidden", direction === "vertical" && "w-[300px]")
928
+ }, /* @__PURE__ */ React10.createElement("div", {
929
+ className: mx4("flex flex-col w-full my-1", direction === "vertical" ? "overflow-y-auto" : "overflow-x-auto")
930
+ }, /* @__PURE__ */ React10.createElement(Mosaic.Container, {
931
+ id,
932
+ Component: Component2,
933
+ onOver,
934
+ onDrop
935
+ }, /* @__PURE__ */ React10.createElement(Mosaic.SortableContext, {
936
+ items: itemsWithPreview,
937
+ direction
938
+ }, itemsWithPreview.map((item, index) => /* @__PURE__ */ React10.createElement(Mosaic.SortableTile, {
939
+ key: item.id,
940
+ item,
941
+ path: id,
942
+ position: index,
943
+ className: "m-1"
944
+ })))), debug && /* @__PURE__ */ React10.createElement("div", {
945
+ className: "grow"
946
+ }, /* @__PURE__ */ React10.createElement(Mosaic.Debug, {
947
+ data: {
948
+ id,
949
+ items: itemsWithPreview.length
950
+ }
951
+ }))));
952
+ };
953
+
954
+ // packages/ui/react-ui-mosaic/src/views/Tree/Tree.tsx
955
+ import React11, { forwardRef as forwardRef3, useMemo as useMemo3 } from "react";
956
+ import { Card as Card3, Tree as TreeComponent, TreeItem as TreeItemComponent } from "@dxos/react-ui";
957
+ import { dropRing, mx as mx5 } from "@dxos/react-ui-theme";
958
+ var Tree = ({ id, Component: Component2 = TreeItem, onOver, onDrop, items = [], debug, compare }) => {
959
+ return /* @__PURE__ */ React11.createElement(Mosaic.Container, {
960
+ id,
961
+ debug,
962
+ Component: Component2,
963
+ onOver,
964
+ onDrop,
965
+ compare
966
+ }, /* @__PURE__ */ React11.createElement(TreeRoot, {
967
+ items
968
+ }));
969
+ };
970
+ var TreeRoot = ({ items }) => {
971
+ const { id, Component: Component2, compare } = useContainer();
972
+ const sortedItems = useMemo3(() => {
973
+ return compare ? [
974
+ ...items
975
+ ].sort(compare) : items;
976
+ }, [
977
+ items,
978
+ compare
979
+ ]);
980
+ const itemsWithPreview = useItemsWithPreview({
981
+ items: sortedItems,
982
+ path: id,
983
+ strategy: "layout-stable"
984
+ });
985
+ return /* @__PURE__ */ React11.createElement(TreeComponent.Root, {
986
+ classNames: "flex flex-col"
987
+ }, /* @__PURE__ */ React11.createElement(Mosaic.SortableContext, {
988
+ id,
989
+ items: itemsWithPreview,
990
+ direction: "vertical"
991
+ }, itemsWithPreview.map((item, index) => /* @__PURE__ */ React11.createElement(TreeItemComponent.Root, {
992
+ key: item.id,
993
+ collapsible: true,
994
+ defaultOpen: true
995
+ }, /* @__PURE__ */ React11.createElement(Mosaic.SortableTile, {
996
+ item,
997
+ path: id,
998
+ position: index,
999
+ Component: Component2
1000
+ })))));
1001
+ };
1002
+ var TreeItem = /* @__PURE__ */ forwardRef3(({ path, draggableStyle, draggableProps, item, operation, active, isOver, isDragging, className }, forwardedRef) => {
1003
+ return /* @__PURE__ */ React11.createElement("div", {
1004
+ ref: forwardedRef,
1005
+ style: draggableStyle,
1006
+ className: mx5("flex flex-col rounded", className, (active === "rearrange" || active === "origin") && "opacity-0", active === "destination" && "opacity-20", isOver && dropRing)
1007
+ }, /* @__PURE__ */ React11.createElement(Card3.Header, null, /* @__PURE__ */ React11.createElement(Card3.DragHandle, draggableProps), /* @__PURE__ */ React11.createElement(Card3.Title, {
1008
+ title: item.label ?? path,
1009
+ classNames: "truncate"
1010
+ })), !active && item.children && /* @__PURE__ */ React11.createElement(TreeBranch, {
1011
+ path,
1012
+ items: item.children
1013
+ }));
1014
+ });
1015
+ var TreeBranch = ({ path, items }) => {
1016
+ const { operation, overItem } = useMosaic();
1017
+ const { Component: Component2, compare } = useContainer();
1018
+ const sortedItems = useMemo3(() => {
1019
+ return compare ? [
1020
+ ...items
1021
+ ].sort(compare) : items;
1022
+ }, [
1023
+ items,
1024
+ compare
1025
+ ]);
1026
+ const itemsWithPreview = useItemsWithPreview({
1027
+ items: sortedItems,
1028
+ path,
1029
+ strategy: "layout-stable"
1030
+ });
1031
+ return /* @__PURE__ */ React11.createElement(TreeItemComponent.Body, {
1032
+ className: "pis-4"
1033
+ }, /* @__PURE__ */ React11.createElement(Mosaic.SortableContext, {
1034
+ id: path,
1035
+ items: itemsWithPreview,
1036
+ direction: "vertical"
1037
+ }, itemsWithPreview.map((child, index) => /* @__PURE__ */ React11.createElement(TreeComponent.Branch, {
1038
+ key: child.id
1039
+ }, /* @__PURE__ */ React11.createElement(TreeItemComponent.Root, {
1040
+ collapsible: true,
1041
+ defaultOpen: true
1042
+ }, /* @__PURE__ */ React11.createElement(Mosaic.SortableTile, {
1043
+ item: child,
1044
+ path,
1045
+ position: index,
1046
+ Component: Component2,
1047
+ isOver: overItem?.path === Path.create(path, child.id) && (operation === "transfer" || operation === "copy")
1048
+ }))))));
1049
+ };
586
1050
  export {
1051
+ Grid,
1052
+ Kanban,
587
1053
  Mosaic,
588
1054
  Path,
1055
+ Stack,
1056
+ Tree,
1057
+ calculateCellWidth,
1058
+ createMatrix,
1059
+ getBounds,
1060
+ getDimension,
1061
+ getPanelBounds,
589
1062
  getTransformCSS,
590
1063
  swapItems,
591
1064
  useContainer,
592
1065
  useItemsWithPreview,
593
- useMosaic,
594
- useSortedItems
1066
+ useMosaic
595
1067
  };
596
1068
  //# sourceMappingURL=index.mjs.map