Move drag and drop to dnd-kit

This commit is contained in:
Mitchell McCaffrey
2021-05-06 15:04:53 +10:00
parent bd522017a7
commit 8aa3bda90d
16 changed files with 322 additions and 359 deletions
+89
View File
@@ -0,0 +1,89 @@
import React, { useEffect, useRef, useState } from "react";
import { Box, IconButton } from "theme-ui";
import RemoveTokenIcon from "../../icons/RemoveTokenIcon";
function DragOverlay({ dragging, node, onRemove }) {
const [isRemoveHovered, setIsRemoveHovered] = useState(false);
const removeTokenRef = useRef();
// Detect token hover on remove icon manually to support touch devices
useEffect(() => {
const map = document.querySelector(".map");
const mapRect = map.getBoundingClientRect();
function detectRemoveHover() {
if (!node || !dragging || !removeTokenRef.current) {
return;
}
const stage = node.getStage();
if (!stage) {
return;
}
const pointerPosition = stage.getPointerPosition();
const screenSpacePointerPosition = {
x: pointerPosition.x + mapRect.left,
y: pointerPosition.y + mapRect.top,
};
const removeIconPosition = removeTokenRef.current.getBoundingClientRect();
if (
screenSpacePointerPosition.x > removeIconPosition.left &&
screenSpacePointerPosition.y > removeIconPosition.top &&
screenSpacePointerPosition.x < removeIconPosition.right &&
screenSpacePointerPosition.y < removeIconPosition.bottom
) {
if (!isRemoveHovered) {
setIsRemoveHovered(true);
}
} else if (isRemoveHovered) {
setIsRemoveHovered(false);
}
}
let handler;
if (node && dragging) {
handler = setInterval(detectRemoveHover, 100);
}
return () => {
if (handler) {
clearInterval(handler);
}
};
}, [isRemoveHovered, dragging, node]);
// Detect drag end of token image and remove it if it is over the remove icon
useEffect(() => {
if (!dragging && node && isRemoveHovered) {
onRemove();
}
});
return (
dragging && (
<Box
sx={{
position: "absolute",
bottom: "32px",
left: "50%",
borderRadius: "50%",
transform: isRemoveHovered
? "translateX(-50%) scale(2.0)"
: "translateX(-50%) scale(1.5)",
transition: "transform 250ms ease",
color: isRemoveHovered ? "primary" : "text",
pointerEvents: "none",
}}
bg="overlay"
ref={removeTokenRef}
>
<IconButton>
<RemoveTokenIcon />
</IconButton>
</Box>
)
);
}
export default DragOverlay;
+31 -24
View File
@@ -1,4 +1,5 @@
import React, { useState } from "react";
import { Box } from "theme-ui";
import MapControls from "./MapControls";
import MapInteraction from "./MapInteraction";
@@ -18,6 +19,8 @@ import TokenDragOverlay from "../token/TokenDragOverlay";
import NoteMenu from "../note/NoteMenu";
import NoteDragOverlay from "../note/NoteDragOverlay";
import Droppable from "../Droppable";
import {
AddShapeAction,
CutShapeAction,
@@ -336,30 +339,34 @@ function Map({
);
return (
<MapInteraction
map={map}
mapState={mapState}
controls={
<>
{mapControls}
{tokenMenu}
{noteMenu}
{tokenDragOverlay}
{noteDragOverlay}
</>
}
selectedToolId={selectedToolId}
onSelectedToolChange={setSelectedToolId}
disabledControls={disabledControls}
>
{mapGrid}
{mapDrawing}
{mapNotes}
{mapTokens}
{mapFog}
{mapPointer}
{mapMeasure}
</MapInteraction>
<Box sx={{ flexGrow: 1 }}>
<Droppable id="map" disabled={!map}>
<MapInteraction
map={map}
mapState={mapState}
controls={
<>
{mapControls}
{tokenMenu}
{noteMenu}
{tokenDragOverlay}
{noteDragOverlay}
</>
}
selectedToolId={selectedToolId}
onSelectedToolChange={setSelectedToolId}
disabledControls={disabledControls}
>
{mapGrid}
{mapDrawing}
{mapNotes}
{mapTokens}
{mapFog}
{mapPointer}
{mapMeasure}
</MapInteraction>
</Droppable>
</Box>
);
}
+2 -1
View File
@@ -181,11 +181,12 @@ function MapInteraction({
<GridProvider grid={map?.grid} width={mapWidth} height={mapHeight}>
<Box
sx={{
flexGrow: 1,
position: "relative",
cursor: getCursorForTool(selectedToolId),
touchAction: "none",
outline: "none",
width: "100%",
height: "100%",
}}
ref={containerRef}
className="map"