@dxos/react-ui-mosaic 0.3.9-main.58adff6 → 0.3.9-main.5d43cb5

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.
@@ -5,6 +5,12 @@ import { useContext } from "react";
5
5
  import React, { createContext, useEffect } from "react";
6
6
  var DEFAULT_TRANSITION = 200;
7
7
  var DEFAULT_TYPE = "unknown";
8
+ var MosaicOperations = [
9
+ "transfer",
10
+ "copy",
11
+ "rearrange",
12
+ "reject"
13
+ ];
8
14
  var MosaicContainerContext = /* @__PURE__ */ createContext({
9
15
  id: "never",
10
16
  type: DEFAULT_TYPE
@@ -85,6 +91,10 @@ var Path = {
85
91
  onPath: (path, id) => Path.parts(path).includes(id)
86
92
  };
87
93
 
94
+ // packages/ui/react-ui-mosaic/src/mosaic/util/props.ts
95
+ var isTileProps = (props) => typeof props.path === "string" && typeof props.item === "object" && props.item ? "id" in props.item && typeof props.item.id === "string" : false;
96
+ var isTileComponentProps = (props) => isTileProps(props) && typeof props.operation === "string" && MosaicOperations.includes(props.operation);
97
+
88
98
  // packages/ui/react-ui-mosaic/src/mosaic/util/styles.ts
89
99
  import { CSS } from "@dnd-kit/utilities";
90
100
  var getTransformCSS = (transform) => transform ? CSS.Transform.toString(Object.assign(transform, {
@@ -370,19 +380,19 @@ var MosaicDragOverlay = ({ delay = 200, debug = false, ...overlayProps }) => {
370
380
  useEffect3(() => {
371
381
  if (activeItem) {
372
382
  let container2;
373
- let OverlayComponent3;
383
+ let OverlayComponent2;
374
384
  if (overItem?.path) {
375
385
  container2 = containers[Path.first(overItem.path)];
376
- OverlayComponent3 = container2?.Component;
386
+ OverlayComponent2 = container2?.Component;
377
387
  }
378
- if (!OverlayComponent3) {
388
+ if (!OverlayComponent2) {
379
389
  container2 = containers[Path.first(activeItem.path)];
380
- OverlayComponent3 = container2?.Component ?? DefaultComponent;
390
+ OverlayComponent2 = container2?.Component ?? DefaultComponent;
381
391
  }
382
392
  clearTimeout(timer.current);
383
393
  timer.current = setTimeout(() => setState({
384
394
  container: container2,
385
- OverlayComponent: OverlayComponent3
395
+ OverlayComponent: OverlayComponent2
386
396
  }), timer.current ? delay : 0);
387
397
  } else {
388
398
  setState({});
@@ -392,7 +402,7 @@ var MosaicDragOverlay = ({ delay = 200, debug = false, ...overlayProps }) => {
392
402
  overItem
393
403
  ]);
394
404
  const container = state.container ?? (activeItem && containers[Path.first(activeItem.path)]);
395
- const OverlayComponent2 = state.OverlayComponent ?? container?.Component;
405
+ const OverlayComponent = state.OverlayComponent ?? container?.Component;
396
406
  const FallbackComponent = (activeItem && containers[Path.first(activeItem.path)])?.Component ?? DefaultComponent;
397
407
  return (
398
408
  // TODO(burdon): Set custom animations (e.g., in/out/around).
@@ -402,7 +412,7 @@ var MosaicDragOverlay = ({ delay = 200, debug = false, ...overlayProps }) => {
402
412
  style: {
403
413
  ...container?.getOverlayStyle?.()
404
414
  }
405
- }, activeItem?.path && container && OverlayComponent2 && /* @__PURE__ */ React5.createElement(OverlayErrorBoundary, {
415
+ }, activeItem?.path && container && OverlayComponent && /* @__PURE__ */ React5.createElement(OverlayErrorBoundary, {
406
416
  fallback: /* @__PURE__ */ React5.createElement(FallbackComponent, {
407
417
  ...container.getOverlayProps?.(),
408
418
  item: activeItem.item,
@@ -410,10 +420,11 @@ var MosaicDragOverlay = ({ delay = 200, debug = false, ...overlayProps }) => {
410
420
  operation,
411
421
  active: "overlay"
412
422
  })
413
- }, /* @__PURE__ */ React5.createElement(OverlayComponent2, {
423
+ }, /* @__PURE__ */ React5.createElement(OverlayComponent, {
414
424
  ...container.getOverlayProps?.(),
415
425
  item: activeItem.item,
416
426
  path: activeItem.path,
427
+ type: activeItem.type,
417
428
  operation,
418
429
  active: "overlay"
419
430
  }), debug && /* @__PURE__ */ React5.createElement("div", {
@@ -613,441 +624,12 @@ var Mosaic = {
613
624
  // TODO(burdon): Don't export; move to util.
614
625
  Debug
615
626
  };
616
-
617
- // packages/ui/react-ui-mosaic/src/views/Grid/layout.ts
618
- var createMatrix = (size, value) => {
619
- const matrix = [];
620
- for (let x = 0; x < size.x; x++) {
621
- matrix.push(Array.from({
622
- length: size.y
623
- }, (_, y) => value({
624
- x,
625
- y
626
- })));
627
- }
628
- return matrix;
629
- };
630
- var getDimension = ({ width, height }, spacing = 0) => ({
631
- width: width - spacing * 2,
632
- height: height - spacing * 2
633
- });
634
- var getBounds = ({ x, y }, { width, height }, spacing = 0) => ({
635
- left: x * width + spacing * 2,
636
- top: y * height + spacing * 2,
637
- width: width - spacing * 2,
638
- height: height - spacing * 2
639
- });
640
- var getPanelBounds = ({ x, y }, { width, height }, spacing = 0) => ({
641
- width: x * width + spacing * 2,
642
- height: y * height + spacing * 2
643
- });
644
- var calculateCellWidth = (defaultWidth, screenWidth, options = {
645
- min: 260,
646
- max: 400
647
- }) => {
648
- return screenWidth > options.min && screenWidth < options.max ? screenWidth : defaultWidth;
649
- };
650
-
651
- // packages/ui/react-ui-mosaic/src/views/Grid/Grid.tsx
652
- import { useDroppable as useDroppable2 } from "@dnd-kit/core";
653
- import { PlusCircle } from "@phosphor-icons/react";
654
- import defaultsDeep from "lodash.defaultsdeep";
655
- import React8, { useState as useState4, useMemo, useEffect as useEffect4 } from "react";
656
- import { useResizeDetector } from "react-resize-detector";
657
- import { Button, useMediaQuery } from "@dxos/react-ui";
658
- import { getSize, mx as mx2 } from "@dxos/react-ui-theme";
659
- var defaultGridOptions = {
660
- size: {
661
- x: 8,
662
- y: 8
663
- },
664
- cellBounds: {
665
- width: 272,
666
- height: 272
667
- },
668
- spacing: 6
669
- };
670
- var Grid = ({ id, items = [], layout = {}, options: opts, margin, square = true, debug, selected: controlledSelected, Component: Component2 = Mosaic.DefaultComponent, className, onDrop, onOver, onSelect, onCreate, onAction }) => {
671
- const { ref: containerRef, width, height } = useResizeDetector({
672
- refreshRate: 200
673
- });
674
- const options = defaultsDeep({}, opts, defaultGridOptions);
675
- const { matrix, bounds, cellBounds } = useMemo(() => {
676
- const cellWidth = calculateCellWidth(options.cellBounds.width, width ?? 0);
677
- const cellBounds2 = {
678
- width: cellWidth,
679
- height: square ? cellWidth : options.cellBounds.height
680
- };
681
- return {
682
- matrix: createMatrix(options.size, ({ x, y }) => ({
683
- x,
684
- y
685
- })),
686
- bounds: getPanelBounds(options.size, cellBounds2, options.spacing),
687
- cellBounds: cellBounds2
688
- };
689
- }, [
690
- options,
691
- width
692
- ]);
693
- const [isNotMobile] = useMediaQuery("md");
694
- const marginSize = margin && !isNotMobile ? Math.max(cellBounds.width, cellBounds.height) : 0;
695
- const [selected, setSelected] = useState4(controlledSelected);
696
- useEffect4(() => {
697
- setSelected(controlledSelected);
698
- if (controlledSelected) {
699
- scrollToCenter(controlledSelected);
700
- }
701
- }, [
702
- controlledSelected
703
- ]);
704
- const scrollToCenter = (id2) => {
705
- const item = items.find((item2) => item2.id === id2);
706
- if (item && width && height) {
707
- const pos = getBounds(layout[item.id], cellBounds);
708
- const top = pos.top + marginSize - (height - cellBounds.height) / 2;
709
- const left = pos.left + marginSize - (width - cellBounds.width) / 2;
710
- containerRef.current.scrollTo({
711
- top,
712
- left,
713
- behavior: "smooth"
714
- });
715
- }
716
- };
717
- const handleSelect = (id2) => {
718
- setSelected(id2);
719
- scrollToCenter(id2);
720
- onSelect?.(id2);
721
- };
722
- useEffect4(() => {
723
- if (selected) {
724
- scrollToCenter(selected);
725
- }
726
- }, [
727
- selected,
728
- width,
729
- height
730
- ]);
731
- return /* @__PURE__ */ React8.createElement(Mosaic.Container, {
732
- id,
733
- Component: Component2,
734
- getOverlayProps: () => ({
735
- grow: true
736
- }),
737
- getOverlayStyle: () => ({
738
- display: "flex",
739
- ...getDimension(cellBounds, options.spacing)
740
- }),
741
- onDrop,
742
- onOver
743
- }, /* @__PURE__ */ React8.createElement("div", {
744
- className: mx2("flex grow overflow-auto", className)
745
- }, /* @__PURE__ */ React8.createElement("div", {
746
- ref: containerRef,
747
- className: mx2("grow overflow-auto snap-x md:snap-none snap-mandatory")
748
- }, /* @__PURE__ */ React8.createElement("div", {
749
- className: "group block relative",
750
- style: {
751
- ...bounds,
752
- margin: marginSize
753
- }
754
- }, matrix && /* @__PURE__ */ React8.createElement("div", {
755
- style: {
756
- padding: options.spacing
757
- }
758
- }, /* @__PURE__ */ React8.createElement("div", {
759
- className: "relative"
760
- }, matrix.map((row) => row.map(({ x, y }) => /* @__PURE__ */ React8.createElement(GridCell, {
761
- key: `${x}-${y}`,
762
- path: id,
763
- position: {
764
- x,
765
- y
766
- },
767
- bounds: getBounds({
768
- x,
769
- y
770
- }, cellBounds),
771
- padding: options.spacing,
772
- onCreate
773
- }))))), /* @__PURE__ */ React8.createElement("div", null, items.map((item) => {
774
- const position = layout[item.id] ?? {
775
- x: 0,
776
- y: 0
777
- };
778
- return /* @__PURE__ */ React8.createElement(Mosaic.DraggableTile, {
779
- key: item.id,
780
- item,
781
- path: id,
782
- position,
783
- Component: Component2,
784
- draggableStyle: {
785
- position: "absolute",
786
- ...getBounds(position, cellBounds, options.spacing)
787
- },
788
- onSelect: () => handleSelect(item.id),
789
- onAction
790
- });
791
- }))), debug && /* @__PURE__ */ React8.createElement(Mosaic.Debug, {
792
- data: {
793
- items: items?.length
794
- },
795
- position: "bottom-right"
796
- }))));
797
- };
798
- var GridCell = ({ path, position, bounds, padding, onCreate }) => {
799
- const { overItem } = useMosaic();
800
- const isOverContainer = path === overItem?.path;
801
- const { setNodeRef, isOver } = useDroppable2({
802
- id: Path.create(path, "cell", `${position.x}-${position.y}`),
803
- data: {
804
- path,
805
- position
806
- }
807
- });
808
- return /* @__PURE__ */ React8.createElement("div", {
809
- ref: setNodeRef,
810
- style: {
811
- ...bounds,
812
- padding
813
- },
814
- className: "absolute flex justify-center items-center grow select-none cursor-pointer"
815
- }, /* @__PURE__ */ React8.createElement("div", {
816
- className: mx2("group/cell flex group-hover:flex w-full h-full items-center justify-center", "box-border border-dashed border-4 border-neutral-75 dark:border-neutral-850 rounded-lg", "transition ease-in-out duration-300", isOver && "flex bg-neutral-75 dark:bg-neutral-850 border-neutral-200 dark:border-neutral-800")
817
- }, /* @__PURE__ */ React8.createElement("div", {
818
- className: mx2("opacity-10 transition ease-in-out duration-300 group-hover/cell:opacity-100", isOverContainer && "hidden")
819
- }, onCreate && // TODO(burdon): Style button.
820
- /* @__PURE__ */ React8.createElement(Button, {
821
- variant: "ghost",
822
- onClick: () => onCreate(position)
823
- }, /* @__PURE__ */ React8.createElement(PlusCircle, {
824
- className: getSize(8)
825
- })))));
826
- };
827
-
828
- // packages/ui/react-ui-mosaic/src/views/Kanban/Kanban.tsx
829
- import React9, { forwardRef as forwardRef2, useMemo as useMemo2 } from "react";
830
- import { Card as Card2 } from "@dxos/react-ui";
831
- import { groupSurface, mx as mx3 } from "@dxos/react-ui-theme";
832
- var Kanban = ({ id, columns, Component: TileComponent = Mosaic.DefaultComponent, debug, onDrop }) => {
833
- const Component2 = useMemo2(() => OverlayComponent(id, TileComponent), [
834
- id,
835
- TileComponent
836
- ]);
837
- return /* @__PURE__ */ React9.createElement(Mosaic.Container, {
838
- id,
839
- debug,
840
- Component: Component2,
841
- // Restrict columns to x-axis.
842
- modifier: ({ path, item }, { transform }) => path === Path.create(id, item.id) ? {
843
- ...transform,
844
- y: 0
845
- } : transform,
846
- // Restrict to objects from other columns.
847
- // TODO(burdon): Consider objects from other containers.
848
- // TODO(wittjosiah): Allow override.
849
- onOver: ({ active, over }) => Path.length(active.path) >= Path.length(over.path) ? "transfer" : "reject",
850
- onDrop
851
- }, /* @__PURE__ */ React9.createElement("div", {
852
- className: "grow flex overflow-y-hidden overflow-x-auto"
853
- }, /* @__PURE__ */ React9.createElement("div", {
854
- className: "flex"
855
- }, /* @__PURE__ */ React9.createElement(Mosaic.SortableContext, {
856
- items: columns,
857
- direction: "horizontal"
858
- }, columns.map((column, index) => /* @__PURE__ */ React9.createElement(Mosaic.SortableTile, {
859
- key: column.id,
860
- item: column,
861
- path: id,
862
- position: index,
863
- Component: Component2,
864
- debug
865
- }))))));
866
- };
867
- var OverlayComponent = (id, Component2) => /* @__PURE__ */ forwardRef2((props, ref) => {
868
- const isColumn = Path.hasRoot(props.path, id) && Path.length(props.path) === 2;
869
- if (isColumn && props.active === "overlay") {
870
- return (
871
- // Needs to not override the main kanban path.
872
- /* @__PURE__ */ React9.createElement(Mosaic.Container, {
873
- id: `${id}-active`,
874
- Component: Component2
875
- }, /* @__PURE__ */ React9.createElement(KanbanColumnComponent, {
876
- ...props,
877
- ref
878
- }))
879
- );
880
- }
881
- return isColumn ? /* @__PURE__ */ React9.createElement(KanbanColumnComponent, {
882
- ...props,
883
- ref
884
- }) : /* @__PURE__ */ React9.createElement(Component2, {
885
- ...props,
886
- ref
887
- });
888
- });
889
- var KanbanColumnComponent = /* @__PURE__ */ forwardRef2(({ path, item, active, draggableStyle, draggableProps, debug }, forwardRef1) => {
890
- const { id, title, items } = item;
891
- const { Component: Component2 } = useContainer();
892
- const itemsWithPreview = useItemsWithPreview({
893
- path,
894
- items
895
- });
896
- return /* @__PURE__ */ React9.createElement("div", {
897
- role: "none",
898
- className: "grow flex flex-col",
899
- ref: forwardRef1
900
- }, /* @__PURE__ */ React9.createElement("div", {
901
- className: mx3(groupSurface, "grow flex flex-col w-[300px] snap-center overflow-hidden m-1", active === "rearrange" && "opacity-0"),
902
- style: draggableStyle
903
- }, /* @__PURE__ */ React9.createElement(Card2.Root, {
904
- classNames: "shrink-0 bg-cyan-200"
905
- }, /* @__PURE__ */ React9.createElement(Card2.Header, null, /* @__PURE__ */ React9.createElement(Card2.DragHandle, draggableProps), /* @__PURE__ */ React9.createElement(Card2.Title, {
906
- title
907
- }), /* @__PURE__ */ React9.createElement(Card2.Menu, null))), /* @__PURE__ */ React9.createElement("div", {
908
- className: mx3("flex flex-col grow overflow-y-scroll")
909
- }, /* @__PURE__ */ React9.createElement("div", {
910
- className: "flex flex-col my-1"
911
- }, /* @__PURE__ */ React9.createElement(Mosaic.SortableContext, {
912
- id: path,
913
- items: itemsWithPreview,
914
- direction: "vertical"
915
- }, itemsWithPreview.map((item2, index) => /* @__PURE__ */ React9.createElement(Mosaic.SortableTile, {
916
- key: item2.id,
917
- item: item2,
918
- path,
919
- position: index,
920
- Component: Component2,
921
- className: "m-1"
922
- }))))), debug && /* @__PURE__ */ React9.createElement(Mosaic.Debug, {
923
- data: {
924
- path,
925
- id,
926
- items: itemsWithPreview.length
927
- }
928
- })));
929
- });
930
-
931
- // packages/ui/react-ui-mosaic/src/views/Stack/Stack.tsx
932
- import React10 from "react";
933
- import { mx as mx4 } from "@dxos/react-ui-theme";
934
- var Stack = ({ id, Component: Component2 = Mosaic.DefaultComponent, onOver, onDrop, items = [], direction = "vertical", debug }) => {
935
- const itemsWithPreview = useItemsWithPreview({
936
- path: id,
937
- items
938
- });
939
- return /* @__PURE__ */ React10.createElement("div", {
940
- className: mx4("flex overflow-hidden", direction === "vertical" && "w-[300px]")
941
- }, /* @__PURE__ */ React10.createElement("div", {
942
- className: mx4("flex flex-col w-full my-1", direction === "vertical" ? "overflow-y-auto" : "overflow-x-auto")
943
- }, /* @__PURE__ */ React10.createElement(Mosaic.Container, {
944
- id,
945
- Component: Component2,
946
- onOver,
947
- onDrop
948
- }, /* @__PURE__ */ React10.createElement(Mosaic.SortableContext, {
949
- items: itemsWithPreview,
950
- direction
951
- }, itemsWithPreview.map((item, index) => /* @__PURE__ */ React10.createElement(Mosaic.SortableTile, {
952
- key: item.id,
953
- item,
954
- path: id,
955
- position: index,
956
- className: "m-1"
957
- })))), debug && /* @__PURE__ */ React10.createElement("div", {
958
- className: "grow"
959
- }, /* @__PURE__ */ React10.createElement(Mosaic.Debug, {
960
- data: {
961
- id,
962
- items: itemsWithPreview.length
963
- }
964
- }))));
965
- };
966
-
967
- // packages/ui/react-ui-mosaic/src/views/Tree/Tree.tsx
968
- import React11, { forwardRef as forwardRef3 } from "react";
969
- import { Card as Card3, Tree as TreeComponent, TreeItem as TreeItemComponent } from "@dxos/react-ui";
970
- import { dropRing, mx as mx5 } from "@dxos/react-ui-theme";
971
- var Tree = ({ id, Component: Component2 = TreeItem, onOver, onDrop, items = [], debug }) => {
972
- return /* @__PURE__ */ React11.createElement(Mosaic.Container, {
973
- id,
974
- debug,
975
- Component: Component2,
976
- onOver,
977
- onDrop
978
- }, /* @__PURE__ */ React11.createElement(TreeRoot, {
979
- items
980
- }));
981
- };
982
- var TreeRoot = ({ items }) => {
983
- const { id, Component: Component2 } = useContainer();
984
- const itemsWithOrigin = useItemsWithOrigin(id, items);
985
- return /* @__PURE__ */ React11.createElement(TreeComponent.Root, {
986
- classNames: "flex flex-col"
987
- }, /* @__PURE__ */ React11.createElement(Mosaic.SortableContext, {
988
- id,
989
- items: itemsWithOrigin,
990
- direction: "vertical"
991
- }, itemsWithOrigin.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 } = useContainer();
1018
- const itemsWithOrigin = useItemsWithOrigin(path, items);
1019
- return /* @__PURE__ */ React11.createElement(TreeItemComponent.Body, {
1020
- className: "pis-4"
1021
- }, /* @__PURE__ */ React11.createElement(Mosaic.SortableContext, {
1022
- id: path,
1023
- items: itemsWithOrigin,
1024
- direction: "vertical"
1025
- }, itemsWithOrigin.map((child, index) => /* @__PURE__ */ React11.createElement(TreeComponent.Branch, {
1026
- key: child.id
1027
- }, /* @__PURE__ */ React11.createElement(TreeItemComponent.Root, {
1028
- collapsible: true,
1029
- defaultOpen: true
1030
- }, /* @__PURE__ */ React11.createElement(Mosaic.SortableTile, {
1031
- item: child,
1032
- path,
1033
- position: index,
1034
- Component: Component2,
1035
- isOver: overItem?.path === Path.create(path, child.id) && (operation === "transfer" || operation === "copy")
1036
- }))))));
1037
- };
1038
627
  export {
1039
- Grid,
1040
- Kanban,
1041
628
  Mosaic,
1042
629
  Path,
1043
- Stack,
1044
- Tree,
1045
- calculateCellWidth,
1046
- createMatrix,
1047
- getBounds,
1048
- getDimension,
1049
- getPanelBounds,
1050
630
  getTransformCSS,
631
+ isTileComponentProps,
632
+ isTileProps,
1051
633
  swapItems,
1052
634
  useContainer,
1053
635
  useItemsWithOrigin,