@dxos/react-ui-mosaic 0.3.3-main.006ca4d → 0.3.3-main.052ad73

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 (49) hide show
  1. package/dist/lib/browser/index.mjs +512 -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/next-fractional-index.d.ts +1 -1
  21. package/dist/types/src/testing/next-fractional-index.d.ts.map +1 -1
  22. package/dist/types/src/views/Grid/Grid.d.ts +3 -3
  23. package/dist/types/src/views/Grid/Grid.d.ts.map +1 -1
  24. package/dist/types/src/views/Grid/Grid.stories.d.ts +1 -1
  25. package/dist/types/src/views/Stack/Columns.stories.d.ts +1 -1
  26. package/dist/types/src/views/Stack/Columns.stories.d.ts.map +1 -1
  27. package/dist/types/src/views/Tree/testing.d.ts +1 -1
  28. package/dist/types/src/views/Tree/testing.d.ts.map +1 -1
  29. package/package.json +12 -12
  30. package/src/index.ts +3 -0
  31. package/src/mosaic/Container.tsx +10 -2
  32. package/src/mosaic/Mosaic.ts +6 -2
  33. package/src/mosaic/Root.tsx +1 -2
  34. package/src/mosaic/Tile.tsx +4 -0
  35. package/src/mosaic/hooks/index.ts +0 -1
  36. package/src/mosaic/hooks/useItemsWithPreview.ts +56 -20
  37. package/src/stories/Home.stories.tsx +87 -0
  38. package/src/testing/decorators.tsx +1 -0
  39. package/src/testing/next-fractional-index.ts +1 -1
  40. package/src/views/Grid/Grid.tsx +25 -14
  41. package/src/views/Grid/testing.tsx +2 -2
  42. package/src/views/Kanban/Kanban.tsx +1 -1
  43. package/src/views/Stack/Columns.stories.tsx +1 -1
  44. package/src/views/Stack/testing.tsx +1 -1
  45. package/src/views/Tree/Tree.tsx +17 -11
  46. package/src/views/Tree/testing.tsx +11 -9
  47. package/dist/types/src/mosaic/hooks/useSortedItems.d.ts +0 -6
  48. package/dist/types/src/mosaic/hooks/useSortedItems.d.ts.map +0 -1
  49. package/src/mosaic/hooks/useSortedItems.ts +0 -14
@@ -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,465 @@ 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, 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
+ }, /* @__PURE__ */ React8.createElement("div", {
730
+ className: mx2("flex grow overflow-auto", className)
731
+ }, /* @__PURE__ */ React8.createElement("div", {
732
+ ref: containerRef,
733
+ className: mx2("grow overflow-auto snap-x snap-mandatory md:snap-none")
734
+ }, /* @__PURE__ */ React8.createElement("div", {
735
+ className: "group block relative",
736
+ style: {
737
+ ...bounds,
738
+ margin: marginSize
739
+ }
740
+ }, matrix && /* @__PURE__ */ React8.createElement("div", {
741
+ style: {
742
+ padding: options.spacing
743
+ }
744
+ }, /* @__PURE__ */ React8.createElement("div", {
745
+ className: "relative"
746
+ }, matrix.map((row) => row.map(({ x, y }) => /* @__PURE__ */ React8.createElement(GridCell, {
747
+ key: `${x}-${y}`,
748
+ path: id,
749
+ position: {
750
+ x,
751
+ y
752
+ },
753
+ bounds: getBounds({
754
+ x,
755
+ y
756
+ }, cellBounds),
757
+ padding: options.spacing,
758
+ onCreate
759
+ }))))), /* @__PURE__ */ React8.createElement("div", null, items.map((item) => {
760
+ const position = layout[item.id] ?? {
761
+ x: 0,
762
+ y: 0
763
+ };
764
+ return /* @__PURE__ */ React8.createElement(Mosaic.DraggableTile, {
765
+ key: item.id,
766
+ item,
767
+ path: id,
768
+ position,
769
+ Component: Component2,
770
+ draggableStyle: {
771
+ position: "absolute",
772
+ ...getBounds(position, cellBounds, options.spacing)
773
+ },
774
+ onSelect: () => handleSelect(item.id),
775
+ onAction
776
+ });
777
+ }))), debug && /* @__PURE__ */ React8.createElement(Mosaic.Debug, {
778
+ data: {
779
+ items: items?.length
780
+ },
781
+ position: "bottom-right"
782
+ }))));
783
+ };
784
+ var GridCell = ({ path, position, bounds, padding, onCreate }) => {
785
+ const { overItem } = useMosaic();
786
+ const isOverContainer = path === overItem?.path;
787
+ const { setNodeRef, isOver } = useDroppable2({
788
+ id: Path.create(path, "cell", `${position.x}-${position.y}`),
789
+ data: {
790
+ path,
791
+ position
792
+ }
793
+ });
794
+ return /* @__PURE__ */ React8.createElement("div", {
795
+ ref: setNodeRef,
796
+ style: {
797
+ ...bounds,
798
+ padding
799
+ },
800
+ className: "absolute flex justify-center items-center grow select-none cursor-pointer"
801
+ }, /* @__PURE__ */ React8.createElement("div", {
802
+ 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")
803
+ }, /* @__PURE__ */ React8.createElement("div", {
804
+ className: mx2("opacity-10 transition ease-in-out duration-300 group-hover/cell:opacity-100", isOverContainer && "hidden")
805
+ }, onCreate && // TODO(burdon): Style button.
806
+ /* @__PURE__ */ React8.createElement(Button, {
807
+ variant: "ghost",
808
+ onClick: () => onCreate(position)
809
+ }, /* @__PURE__ */ React8.createElement(PlusCircle, {
810
+ className: getSize(8)
811
+ })))));
812
+ };
813
+
814
+ // packages/ui/react-ui-mosaic/src/views/Kanban/Kanban.tsx
815
+ import React9, { forwardRef as forwardRef2, useMemo as useMemo2 } from "react";
816
+ import { Card as Card2 } from "@dxos/react-ui";
817
+ import { groupSurface, mx as mx3 } from "@dxos/react-ui-theme";
818
+ var Kanban = ({ id, columns, Component: TileComponent = Mosaic.DefaultComponent, debug, onDrop }) => {
819
+ const Component2 = useMemo2(() => OverlayComponent(id, TileComponent), [
820
+ id,
821
+ TileComponent
822
+ ]);
823
+ return /* @__PURE__ */ React9.createElement(Mosaic.Container, {
824
+ id,
825
+ debug,
826
+ Component: Component2,
827
+ // Restrict columns to x-axis.
828
+ modifier: ({ path, item }, { transform }) => path === Path.create(id, item.id) ? {
829
+ ...transform,
830
+ y: 0
831
+ } : transform,
832
+ // Restrict to objects from other columns.
833
+ // TODO(burdon): Consider objects from other containers.
834
+ // TODO(wittjosiah): Allow override.
835
+ onOver: ({ active, over }) => Path.length(active.path) >= Path.length(over.path) ? "transfer" : "reject",
836
+ onDrop
837
+ }, /* @__PURE__ */ React9.createElement("div", {
838
+ className: "grow flex overflow-y-hidden overflow-x-auto"
839
+ }, /* @__PURE__ */ React9.createElement("div", {
840
+ className: "flex"
841
+ }, /* @__PURE__ */ React9.createElement(Mosaic.SortableContext, {
842
+ items: columns,
843
+ direction: "horizontal"
844
+ }, columns.map((column, index) => /* @__PURE__ */ React9.createElement(Mosaic.SortableTile, {
845
+ key: column.id,
846
+ item: column,
847
+ path: id,
848
+ position: index,
849
+ Component: Component2,
850
+ debug
851
+ }))))));
852
+ };
853
+ var OverlayComponent = (id, Component2) => /* @__PURE__ */ forwardRef2((props, ref) => {
854
+ const isColumn = Path.hasRoot(props.path, id) && Path.length(props.path) === 2;
855
+ if (isColumn && props.active === "overlay") {
856
+ return (
857
+ // Needs to not override the main kanban path.
858
+ /* @__PURE__ */ React9.createElement(Mosaic.Container, {
859
+ id: `${id}-active`,
860
+ Component: Component2
861
+ }, /* @__PURE__ */ React9.createElement(KanbanColumnComponent, {
862
+ ...props,
863
+ ref
864
+ }))
865
+ );
866
+ }
867
+ return isColumn ? /* @__PURE__ */ React9.createElement(KanbanColumnComponent, {
868
+ ...props,
869
+ ref
870
+ }) : /* @__PURE__ */ React9.createElement(Component2, {
871
+ ...props,
872
+ ref
873
+ });
874
+ });
875
+ var KanbanColumnComponent = /* @__PURE__ */ forwardRef2(({ path, item, active, draggableStyle, draggableProps, debug }, forwardRef1) => {
876
+ const { id, title, items } = item;
877
+ const { Component: Component2 } = useContainer();
878
+ const itemsWithPreview = useItemsWithPreview({
879
+ path,
880
+ items
881
+ });
882
+ return /* @__PURE__ */ React9.createElement("div", {
883
+ role: "none",
884
+ className: "grow flex flex-col",
885
+ ref: forwardRef1
886
+ }, /* @__PURE__ */ React9.createElement("div", {
887
+ className: mx3(groupSurface, "grow flex flex-col w-[300px] snap-center overflow-hidden m-1", active === "rearrange" && "opacity-0"),
888
+ style: draggableStyle
889
+ }, /* @__PURE__ */ React9.createElement(Card2.Root, {
890
+ classNames: "shrink-0 bg-cyan-200"
891
+ }, /* @__PURE__ */ React9.createElement(Card2.Header, null, /* @__PURE__ */ React9.createElement(Card2.DragHandle, draggableProps), /* @__PURE__ */ React9.createElement(Card2.Title, {
892
+ title
893
+ }), /* @__PURE__ */ React9.createElement(Card2.Menu, null))), /* @__PURE__ */ React9.createElement("div", {
894
+ className: mx3("flex flex-col grow overflow-y-scroll")
895
+ }, /* @__PURE__ */ React9.createElement("div", {
896
+ className: "flex flex-col my-1"
897
+ }, /* @__PURE__ */ React9.createElement(Mosaic.SortableContext, {
898
+ id: path,
899
+ items: itemsWithPreview,
900
+ direction: "vertical"
901
+ }, itemsWithPreview.map((item2, index) => /* @__PURE__ */ React9.createElement(Mosaic.SortableTile, {
902
+ key: item2.id,
903
+ item: item2,
904
+ path,
905
+ position: index,
906
+ Component: Component2,
907
+ className: "m-1"
908
+ }))))), debug && /* @__PURE__ */ React9.createElement(Mosaic.Debug, {
909
+ data: {
910
+ path,
911
+ id,
912
+ items: itemsWithPreview.length
913
+ }
914
+ })));
915
+ });
916
+
917
+ // packages/ui/react-ui-mosaic/src/views/Stack/Stack.tsx
918
+ import React10 from "react";
919
+ import { mx as mx4 } from "@dxos/react-ui-theme";
920
+ var Stack = ({ id, Component: Component2 = Mosaic.DefaultComponent, onOver, onDrop, items = [], direction = "vertical", debug }) => {
921
+ const itemsWithPreview = useItemsWithPreview({
922
+ path: id,
923
+ items
924
+ });
925
+ return /* @__PURE__ */ React10.createElement("div", {
926
+ className: mx4("flex overflow-hidden", direction === "vertical" && "w-[300px]")
927
+ }, /* @__PURE__ */ React10.createElement("div", {
928
+ className: mx4("flex flex-col w-full my-1", direction === "vertical" ? "overflow-y-auto" : "overflow-x-auto")
929
+ }, /* @__PURE__ */ React10.createElement(Mosaic.Container, {
930
+ id,
931
+ Component: Component2,
932
+ onOver,
933
+ onDrop
934
+ }, /* @__PURE__ */ React10.createElement(Mosaic.SortableContext, {
935
+ items: itemsWithPreview,
936
+ direction
937
+ }, itemsWithPreview.map((item, index) => /* @__PURE__ */ React10.createElement(Mosaic.SortableTile, {
938
+ key: item.id,
939
+ item,
940
+ path: id,
941
+ position: index,
942
+ className: "m-1"
943
+ })))), debug && /* @__PURE__ */ React10.createElement("div", {
944
+ className: "grow"
945
+ }, /* @__PURE__ */ React10.createElement(Mosaic.Debug, {
946
+ data: {
947
+ id,
948
+ items: itemsWithPreview.length
949
+ }
950
+ }))));
951
+ };
952
+
953
+ // packages/ui/react-ui-mosaic/src/views/Tree/Tree.tsx
954
+ import React11, { forwardRef as forwardRef3, useMemo as useMemo3 } from "react";
955
+ import { Card as Card3, Tree as TreeComponent, TreeItem as TreeItemComponent } from "@dxos/react-ui";
956
+ import { dropRing, mx as mx5 } from "@dxos/react-ui-theme";
957
+ var Tree = ({ id, Component: Component2 = TreeItem, onOver, onDrop, items = [], debug, compare }) => {
958
+ return /* @__PURE__ */ React11.createElement(Mosaic.Container, {
959
+ id,
960
+ debug,
961
+ Component: Component2,
962
+ onOver,
963
+ onDrop,
964
+ compare
965
+ }, /* @__PURE__ */ React11.createElement(TreeRoot, {
966
+ items
967
+ }));
968
+ };
969
+ var TreeRoot = ({ items }) => {
970
+ const { id, Component: Component2, compare } = useContainer();
971
+ const sortedItems = useMemo3(() => {
972
+ return compare ? [
973
+ ...items
974
+ ].sort(compare) : items;
975
+ }, [
976
+ items,
977
+ compare
978
+ ]);
979
+ const itemsWithPreview = useItemsWithPreview({
980
+ items: sortedItems,
981
+ path: id,
982
+ strategy: "layout-stable"
983
+ });
984
+ return /* @__PURE__ */ React11.createElement(TreeComponent.Root, {
985
+ classNames: "flex flex-col"
986
+ }, /* @__PURE__ */ React11.createElement(Mosaic.SortableContext, {
987
+ id,
988
+ items: itemsWithPreview,
989
+ direction: "vertical"
990
+ }, itemsWithPreview.map((item, index) => /* @__PURE__ */ React11.createElement(TreeItemComponent.Root, {
991
+ key: item.id,
992
+ collapsible: true,
993
+ defaultOpen: true
994
+ }, /* @__PURE__ */ React11.createElement(Mosaic.SortableTile, {
995
+ item,
996
+ path: id,
997
+ position: index,
998
+ Component: Component2
999
+ })))));
1000
+ };
1001
+ var TreeItem = /* @__PURE__ */ forwardRef3(({ path, draggableStyle, draggableProps, item, operation, active, isOver, isDragging, className }, forwardedRef) => {
1002
+ return /* @__PURE__ */ React11.createElement("div", {
1003
+ ref: forwardedRef,
1004
+ style: draggableStyle,
1005
+ className: mx5("flex flex-col rounded", className, (active === "rearrange" || active === "origin") && "opacity-0", active === "destination" && "opacity-20", isOver && dropRing)
1006
+ }, /* @__PURE__ */ React11.createElement(Card3.Header, null, /* @__PURE__ */ React11.createElement(Card3.DragHandle, draggableProps), /* @__PURE__ */ React11.createElement(Card3.Title, {
1007
+ title: item.label ?? path,
1008
+ classNames: "truncate"
1009
+ })), !active && item.children && /* @__PURE__ */ React11.createElement(TreeBranch, {
1010
+ path,
1011
+ items: item.children
1012
+ }));
1013
+ });
1014
+ var TreeBranch = ({ path, items }) => {
1015
+ const { operation, overItem } = useMosaic();
1016
+ const { Component: Component2, compare } = useContainer();
1017
+ const sortedItems = useMemo3(() => {
1018
+ return compare ? [
1019
+ ...items
1020
+ ].sort(compare) : items;
1021
+ }, [
1022
+ items,
1023
+ compare
1024
+ ]);
1025
+ const itemsWithPreview = useItemsWithPreview({
1026
+ items: sortedItems,
1027
+ path,
1028
+ strategy: "layout-stable"
1029
+ });
1030
+ return /* @__PURE__ */ React11.createElement(TreeItemComponent.Body, {
1031
+ className: "pis-4"
1032
+ }, /* @__PURE__ */ React11.createElement(Mosaic.SortableContext, {
1033
+ id: path,
1034
+ items: itemsWithPreview,
1035
+ direction: "vertical"
1036
+ }, itemsWithPreview.map((child, index) => /* @__PURE__ */ React11.createElement(TreeComponent.Branch, {
1037
+ key: child.id
1038
+ }, /* @__PURE__ */ React11.createElement(TreeItemComponent.Root, {
1039
+ collapsible: true,
1040
+ defaultOpen: true
1041
+ }, /* @__PURE__ */ React11.createElement(Mosaic.SortableTile, {
1042
+ item: child,
1043
+ path,
1044
+ position: index,
1045
+ Component: Component2,
1046
+ isOver: overItem?.path === Path.create(path, child.id) && (operation === "transfer" || operation === "copy")
1047
+ }))))));
1048
+ };
586
1049
  export {
1050
+ Grid,
1051
+ Kanban,
587
1052
  Mosaic,
588
1053
  Path,
1054
+ Stack,
1055
+ Tree,
1056
+ calculateCellWidth,
1057
+ createMatrix,
1058
+ getBounds,
1059
+ getDimension,
1060
+ getPanelBounds,
589
1061
  getTransformCSS,
590
1062
  swapItems,
591
1063
  useContainer,
592
1064
  useItemsWithPreview,
593
- useMosaic,
594
- useSortedItems
1065
+ useMosaic
595
1066
  };
596
1067
  //# sourceMappingURL=index.mjs.map