diff --git a/package.json b/package.json
index 602eebd..91aa658 100644
--- a/package.json
+++ b/package.json
@@ -5,8 +5,8 @@
"dependencies": {
"@babylonjs/core": "^4.2.0",
"@babylonjs/loaders": "^4.2.0",
- "@dnd-kit/core": "3.0.2",
- "@dnd-kit/sortable": "^3.0.1",
+ "@dnd-kit/core": "^3.0.4",
+ "@dnd-kit/sortable": "^3.1.0",
"@mitchemmc/dexie-export-import": "^1.0.1",
"@msgpack/msgpack": "^2.4.1",
"@sentry/react": "^6.2.2",
diff --git a/src/components/tile/TilesAddDroppable.js b/src/components/tile/TilesAddDroppable.js
deleted file mode 100644
index 7bd6cde..0000000
--- a/src/components/tile/TilesAddDroppable.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import React from "react";
-import { createPortal } from "react-dom";
-
-import Droppable from "../drag/Droppable";
-
-import { ADD_TO_MAP_ID_PREFIX } from "../../contexts/TileDragContext";
-
-function TilesAddDroppable({ containerSize }) {
- return createPortal(
-
-
-
-
-
-
,
- document.body
- );
-}
-
-export default TilesAddDroppable;
diff --git a/src/components/tile/TilesContainer.js b/src/components/tile/TilesContainer.js
index 8703ee5..005c48d 100644
--- a/src/components/tile/TilesContainer.js
+++ b/src/components/tile/TilesContainer.js
@@ -3,9 +3,12 @@ import { Grid, useThemeUI } from "theme-ui";
import SimpleBar from "simplebar-react";
import { useGroup } from "../../contexts/GroupContext";
+import { ADD_TO_MAP_ID } from "../../contexts/TileDragContext";
import useResponsiveLayout from "../../hooks/useResponsiveLayout";
+import Droppable from "../drag/Droppable";
+
function TilesContainer({ children }) {
const { onGroupSelect } = useGroup();
@@ -28,10 +31,19 @@ function TilesContainer({ children }) {
sx={{
borderRadius: "4px",
overflow: "hidden",
+ position: "relative",
}}
gap={2}
columns={`repeat(${layout.tileGridColumns}, 1fr)`}
>
+
{children}
diff --git a/src/components/tile/TilesOverlay.js b/src/components/tile/TilesOverlay.js
index 40215bf..0c7a81c 100644
--- a/src/components/tile/TilesOverlay.js
+++ b/src/components/tile/TilesOverlay.js
@@ -5,8 +5,7 @@ import ReactResizeDetector from "react-resize-detector";
import SimpleBar from "simplebar-react";
import { useGroup } from "../../contexts/GroupContext";
-
-import TilesUngroupDroppable from "./TilesUngroupDroppable";
+import { UNGROUP_ID, ADD_TO_MAP_ID } from "../../contexts/TileDragContext";
import useResponsiveLayout from "../../hooks/useResponsiveLayout";
@@ -16,7 +15,9 @@ import GroupNameModal from "../../modals/GroupNameModal";
import { renameGroup } from "../../helpers/group";
-function TilesOverlay({ children }) {
+import Droppable from "../drag/Droppable";
+
+function TilesOverlay({ modalSize, children }) {
const {
groups,
openGroupId,
@@ -41,11 +42,6 @@ function TilesOverlay({ children }) {
setContinerSize({ width: size, height: size });
}
- const [overlaySize, setOverlaySize] = useState({ width: 0, height: 0 });
- function handleOverlayResize(width, height) {
- setOverlaySize({ width, height });
- }
-
const [isGroupNameModalOpen, setIsGroupNameModalOpen] = useState(false);
function handleGroupNameChange(name) {
onGroupsChange(renameGroup(groups, openGroupId, name));
@@ -57,28 +53,16 @@ function TilesOverlay({ children }) {
return (
<>
{openGroupId && (
-
)}
- {openGroupId && (
-
-
-
- )}
+
+
{children}
diff --git a/src/components/tile/TilesUngroupDroppable.js b/src/components/tile/TilesUngroupDroppable.js
deleted file mode 100644
index 3363991..0000000
--- a/src/components/tile/TilesUngroupDroppable.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import React from "react";
-import { createPortal } from "react-dom";
-
-import Droppable from "../drag/Droppable";
-
-import { UNGROUP_ID_PREFIX } from "../../contexts/TileDragContext";
-
-function TilesUngroupDroppable({ outerContainerSize, innerContainerSize }) {
- const width = (outerContainerSize.width - innerContainerSize.width) / 2;
- const height = (outerContainerSize.height - innerContainerSize.height) / 2;
-
- return createPortal(
-
-
-
-
-
-
,
- document.body
- );
-}
-
-export default TilesUngroupDroppable;
diff --git a/src/contexts/TileDragContext.js b/src/contexts/TileDragContext.js
index 95aa1a8..767a213 100644
--- a/src/contexts/TileDragContext.js
+++ b/src/contexts/TileDragContext.js
@@ -6,7 +6,6 @@ import {
useSensor,
useSensors,
closestCenter,
- rectIntersection,
} from "@dnd-kit/core";
import { useGroup } from "./GroupContext";
@@ -18,8 +17,26 @@ const TileDragContext = React.createContext();
export const BASE_SORTABLE_ID = "__base__";
export const GROUP_SORTABLE_ID = "__group__";
export const GROUP_ID_PREFIX = "__group__";
-export const UNGROUP_ID_PREFIX = "__ungroup__";
-export const ADD_TO_MAP_ID_PREFIX = "__add__";
+export const UNGROUP_ID = "__ungroup__";
+export const ADD_TO_MAP_ID = "__add__";
+
+// Custom rectIntersect that takes a point
+function rectIntersection(rects, point) {
+ for (let rect of rects) {
+ const [id, bounds] = rect;
+ if (
+ id &&
+ bounds &&
+ point.x > bounds.offsetLeft &&
+ point.x < bounds.offsetLeft + bounds.width &&
+ point.y > bounds.offsetTop &&
+ point.y < bounds.offsetTop + bounds.height
+ ) {
+ return id;
+ }
+ }
+ return null;
+}
export function TileDragProvider({ onDragAdd, children }) {
const {
@@ -59,11 +76,11 @@ export function TileDragProvider({ onDragAdd, children }) {
setOverId(over?.id);
if (over) {
if (
- over.id.startsWith(UNGROUP_ID_PREFIX) ||
+ over.id.startsWith(UNGROUP_ID) ||
over.id.startsWith(GROUP_ID_PREFIX)
) {
setDragCursor("alias");
- } else if (over.id.startsWith(ADD_TO_MAP_ID_PREFIX)) {
+ } else if (over.id.startsWith(ADD_TO_MAP_ID)) {
setDragCursor(onDragAdd ? "copy" : "no-drop");
} else {
setDragCursor("grabbing");
@@ -100,7 +117,7 @@ export function TileDragProvider({ onDragAdd, children }) {
moveGroupsInto(activeGroups, overGroupIndex, selectedIndices),
openGroupId
);
- } else if (over.id.startsWith(UNGROUP_ID_PREFIX)) {
+ } else if (over.id === UNGROUP_ID) {
onGroupSelect();
// Handle tile ungroup
const newGroups = ungroup(groups, openGroupId, selectedIndices);
@@ -109,7 +126,7 @@ export function TileDragProvider({ onDragAdd, children }) {
onGroupClose();
}
onGroupsChange(newGroups);
- } else if (over.id.startsWith(ADD_TO_MAP_ID_PREFIX)) {
+ } else if (over.id === ADD_TO_MAP_ID) {
onDragAdd && onDragAdd(selectedGroupIds, over.rect);
} else if (!filter) {
// Hanlde tile move only if we have no filter
@@ -124,27 +141,39 @@ export function TileDragProvider({ onDragAdd, children }) {
}
function customCollisionDetection(rects, rect) {
- // Handle group rects
- if (openGroupId) {
- const ungroupRects = rects.filter(([id]) =>
- id.startsWith(UNGROUP_ID_PREFIX)
- );
- const intersectingGroupRect = rectIntersection(ungroupRects, rect);
- if (intersectingGroupRect) {
- return intersectingGroupRect;
+ // Calculate rect bottom taking into account any scroll offset
+ const rectBottom = rect.top + rect.bottom - rect.offsetTop;
+ const rectCenter = {
+ x: rect.left + rect.width / 2,
+ y: rectBottom - rect.height / 2,
+ };
+
+ // Find whether out rect center is outside our add to map rect
+ const addRect = rects.find(([id]) => id === ADD_TO_MAP_ID);
+ if (addRect) {
+ const intersectingAddRect = rectIntersection([addRect], rectCenter);
+ if (!intersectingAddRect) {
+ return ADD_TO_MAP_ID;
}
}
- // Handle add to map rects
- const addRects = rects.filter(([id]) =>
- id.startsWith(ADD_TO_MAP_ID_PREFIX)
- );
- const intersectingAddRect = rectIntersection(addRects, rect);
- if (intersectingAddRect) {
- return intersectingAddRect;
+ // Find whether out rect center is outside our ungroup rect
+ if (openGroupId) {
+ const ungroupRect = rects.find(([id]) => id === UNGROUP_ID);
+ if (ungroupRect) {
+ const intersectingGroupRect = rectIntersection(
+ [ungroupRect],
+ rectCenter
+ );
+ if (!intersectingGroupRect) {
+ return UNGROUP_ID;
+ }
+ }
}
- const otherRects = rects.filter(([id]) => id !== UNGROUP_ID_PREFIX);
+ const otherRects = rects.filter(
+ ([id]) => id !== ADD_TO_MAP_ID && id !== UNGROUP_ID
+ );
return closestCenter(otherRects, rect);
}
diff --git a/src/modals/SelectMapModal.js b/src/modals/SelectMapModal.js
index dab60d0..c67e14d 100644
--- a/src/modals/SelectMapModal.js
+++ b/src/modals/SelectMapModal.js
@@ -17,7 +17,6 @@ import SelectMapSelectButton from "../components/map/SelectMapSelectButton";
import TilesOverlay from "../components/tile/TilesOverlay";
import TilesContainer from "../components/tile/TilesContainer";
-import TilesAddDroppable from "../components/tile/TilesAddDroppable";
import TileActionBar from "../components/tile/TileActionBar";
import { findGroup, getItemNames } from "../helpers/group";
@@ -231,7 +230,6 @@ function SelectMapModal({
-
-
-
+
-
-
-
+