Fix tile drag cancel with modal open
This commit is contained in:
parent
63f77059f1
commit
a8c355f251
@ -6,6 +6,7 @@ import {
|
||||
DragOverlay,
|
||||
DndContext,
|
||||
PointerSensor,
|
||||
KeyboardSensor,
|
||||
useSensor,
|
||||
useSensors,
|
||||
} from "@dnd-kit/core";
|
||||
@ -45,7 +46,8 @@ function TokenBar({ onMapTokensStateCreate }) {
|
||||
const pointerSensor = useSensor(PointerSensor, {
|
||||
activationConstraint: { distance: 5 },
|
||||
});
|
||||
const sensors = useSensors(pointerSensor);
|
||||
const keyboardSensor = useSensor(KeyboardSensor);
|
||||
const sensors = useSensors(pointerSensor, keyboardSensor);
|
||||
|
||||
function handleDragStart({ active }) {
|
||||
setDragId(active.id);
|
||||
@ -93,6 +95,10 @@ function TokenBar({ onMapTokensStateCreate }) {
|
||||
}
|
||||
}
|
||||
|
||||
function handleDragCancel() {
|
||||
setDragId(null);
|
||||
}
|
||||
|
||||
function renderToken(group, draggable = true) {
|
||||
if (group.type === "item") {
|
||||
const token = tokensById[group.id];
|
||||
@ -132,6 +138,7 @@ function TokenBar({ onMapTokensStateCreate }) {
|
||||
<DndContext
|
||||
onDragStart={handleDragStart}
|
||||
onDragEnd={handleDragEnd}
|
||||
onDragCancel={handleDragCancel}
|
||||
autoScroll={false}
|
||||
sensors={sensors}
|
||||
>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useState, useContext } from "react";
|
||||
import {
|
||||
DndContext,
|
||||
MouseSensor,
|
||||
TouchSensor,
|
||||
PointerSensor,
|
||||
KeyboardSensor,
|
||||
useSensor,
|
||||
useSensors,
|
||||
closestCenter,
|
||||
@ -38,7 +38,13 @@ function rectIntersection(rects, point) {
|
||||
return null;
|
||||
}
|
||||
|
||||
export function TileDragProvider({ onDragAdd, children }) {
|
||||
export function TileDragProvider({
|
||||
onDragAdd,
|
||||
onDragStart,
|
||||
onDragEnd,
|
||||
onDragCancel,
|
||||
children,
|
||||
}) {
|
||||
const {
|
||||
groups,
|
||||
activeGroups,
|
||||
@ -50,29 +56,32 @@ export function TileDragProvider({ onDragAdd, children }) {
|
||||
filter,
|
||||
} = useGroup();
|
||||
|
||||
const mouseSensor = useSensor(MouseSensor, {
|
||||
activationConstraint: { delay: 250, tolerance: 5 },
|
||||
});
|
||||
const touchSensor = useSensor(TouchSensor, {
|
||||
const pointerSensor = useSensor(PointerSensor, {
|
||||
activationConstraint: { delay: 250, tolerance: 5 },
|
||||
});
|
||||
const keyboardSensor = useSensor(KeyboardSensor);
|
||||
|
||||
const sensors = useSensors(mouseSensor, touchSensor);
|
||||
const sensors = useSensors(pointerSensor, keyboardSensor);
|
||||
|
||||
const [dragId, setDragId] = useState();
|
||||
const [overId, setOverId] = useState();
|
||||
const [dragCursor, setDragCursor] = useState("pointer");
|
||||
|
||||
function handleDragStart({ active, over }) {
|
||||
function handleDragStart(event) {
|
||||
const { active, over } = event;
|
||||
setDragId(active.id);
|
||||
setOverId(over?.id);
|
||||
if (!selectedGroupIds.includes(active.id)) {
|
||||
onGroupSelect(active.id);
|
||||
}
|
||||
setDragCursor("grabbing");
|
||||
|
||||
onDragStart && onDragStart(event);
|
||||
}
|
||||
|
||||
function handleDragOver({ over }) {
|
||||
function handleDragOver(event) {
|
||||
const { over } = event;
|
||||
|
||||
setOverId(over?.id);
|
||||
if (over) {
|
||||
if (
|
||||
@ -88,56 +97,64 @@ export function TileDragProvider({ onDragAdd, children }) {
|
||||
}
|
||||
}
|
||||
|
||||
function handleDragEnd({ active, over }) {
|
||||
function handleDragEnd(event) {
|
||||
const { active, over } = event;
|
||||
|
||||
setDragId();
|
||||
setOverId();
|
||||
setDragCursor("pointer");
|
||||
if (!active || !over || active.id === over.id) {
|
||||
return;
|
||||
if (active && over && active.id !== over.id) {
|
||||
let selectedIndices = selectedGroupIds.map((groupId) =>
|
||||
activeGroups.findIndex((group) => group.id === groupId)
|
||||
);
|
||||
// Maintain current group sorting
|
||||
selectedIndices = selectedIndices.sort((a, b) => a - b);
|
||||
|
||||
if (over.id.startsWith(GROUP_ID_PREFIX)) {
|
||||
onGroupSelect();
|
||||
// Handle tile group
|
||||
const overId = over.id.slice(9);
|
||||
if (overId !== active.id) {
|
||||
const overGroupIndex = activeGroups.findIndex(
|
||||
(group) => group.id === overId
|
||||
);
|
||||
onGroupsChange(
|
||||
moveGroupsInto(activeGroups, overGroupIndex, selectedIndices),
|
||||
openGroupId
|
||||
);
|
||||
}
|
||||
} else if (over.id === UNGROUP_ID) {
|
||||
onGroupSelect();
|
||||
// Handle tile ungroup
|
||||
const newGroups = ungroup(groups, openGroupId, selectedIndices);
|
||||
// Close group if it was removed
|
||||
if (!newGroups.find((group) => group.id === openGroupId)) {
|
||||
onGroupClose();
|
||||
}
|
||||
onGroupsChange(newGroups);
|
||||
} 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
|
||||
const overGroupIndex = activeGroups.findIndex(
|
||||
(group) => group.id === over.id
|
||||
);
|
||||
onGroupsChange(
|
||||
moveGroups(activeGroups, overGroupIndex, selectedIndices),
|
||||
openGroupId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let selectedIndices = selectedGroupIds.map((groupId) =>
|
||||
activeGroups.findIndex((group) => group.id === groupId)
|
||||
);
|
||||
// Maintain current group sorting
|
||||
selectedIndices = selectedIndices.sort((a, b) => a - b);
|
||||
onDragEnd && onDragEnd(event);
|
||||
}
|
||||
|
||||
if (over.id.startsWith(GROUP_ID_PREFIX)) {
|
||||
onGroupSelect();
|
||||
// Handle tile group
|
||||
const overId = over.id.slice(9);
|
||||
if (overId === active.id) {
|
||||
return;
|
||||
}
|
||||
function handleDragCancel(event) {
|
||||
setDragId();
|
||||
setOverId();
|
||||
setDragCursor("pointer");
|
||||
|
||||
const overGroupIndex = activeGroups.findIndex(
|
||||
(group) => group.id === overId
|
||||
);
|
||||
onGroupsChange(
|
||||
moveGroupsInto(activeGroups, overGroupIndex, selectedIndices),
|
||||
openGroupId
|
||||
);
|
||||
} else if (over.id === UNGROUP_ID) {
|
||||
onGroupSelect();
|
||||
// Handle tile ungroup
|
||||
const newGroups = ungroup(groups, openGroupId, selectedIndices);
|
||||
// Close group if it was removed
|
||||
if (!newGroups.find((group) => group.id === openGroupId)) {
|
||||
onGroupClose();
|
||||
}
|
||||
onGroupsChange(newGroups);
|
||||
} 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
|
||||
const overGroupIndex = activeGroups.findIndex(
|
||||
(group) => group.id === over.id
|
||||
);
|
||||
onGroupsChange(
|
||||
moveGroups(activeGroups, overGroupIndex, selectedIndices),
|
||||
openGroupId
|
||||
);
|
||||
}
|
||||
onDragCancel && onDragCancel(event);
|
||||
}
|
||||
|
||||
function customCollisionDetection(rects, rect) {
|
||||
@ -183,6 +200,7 @@ export function TileDragProvider({ onDragAdd, children }) {
|
||||
onDragStart={handleDragStart}
|
||||
onDragEnd={handleDragEnd}
|
||||
onDragOver={handleDragOver}
|
||||
onDragCancel={handleDragCancel}
|
||||
sensors={sensors}
|
||||
collisionDetection={customCollisionDetection}
|
||||
>
|
||||
|
@ -168,6 +168,8 @@ function SelectMapModal({
|
||||
|
||||
const [editingMapId, setEditingMapId] = useState();
|
||||
|
||||
const [isDraggingMap, setIsDraggingMap] = useState(false);
|
||||
|
||||
const [canAddDraggedMap, setCanAddDraggedMap] = useState(false);
|
||||
function handleGroupsSelect(groupIds) {
|
||||
if (groupIds.length === 1) {
|
||||
@ -197,6 +199,7 @@ function SelectMapModal({
|
||||
isOpen={isOpen}
|
||||
onRequestClose={handleClose}
|
||||
style={{ maxWidth: layout.modalSize, width: "calc(100% - 16px)" }}
|
||||
shouldCloseOnEsc={!isDraggingMap}
|
||||
>
|
||||
<ImageDrop onDrop={handleImagesUpload} dropText="Drop map to import">
|
||||
<input
|
||||
@ -229,7 +232,12 @@ function SelectMapModal({
|
||||
</Label>
|
||||
<TileActionBar onAdd={openImageDialog} addTitle="Import Map(s)" />
|
||||
<Box sx={{ position: "relative" }}>
|
||||
<TileDragProvider onDragAdd={canAddDraggedMap && handleDragAdd}>
|
||||
<TileDragProvider
|
||||
onDragAdd={canAddDraggedMap && handleDragAdd}
|
||||
onDragStart={() => setIsDraggingMap(true)}
|
||||
onDragEnd={() => setIsDraggingMap(false)}
|
||||
onDragCancel={() => setIsDraggingMap(false)}
|
||||
>
|
||||
<TilesContainer>
|
||||
<MapTiles
|
||||
maps={maps}
|
||||
@ -238,7 +246,12 @@ function SelectMapModal({
|
||||
/>
|
||||
</TilesContainer>
|
||||
</TileDragProvider>
|
||||
<TileDragProvider onDragAdd={canAddDraggedMap && handleDragAdd}>
|
||||
<TileDragProvider
|
||||
onDragAdd={canAddDraggedMap && handleDragAdd}
|
||||
onDragStart={() => setIsDraggingMap(true)}
|
||||
onDragEnd={() => setIsDraggingMap(false)}
|
||||
onDragCancel={() => setIsDraggingMap(false)}
|
||||
>
|
||||
<TilesOverlay modalSize={modalSize}>
|
||||
<MapTiles
|
||||
maps={maps}
|
||||
|
@ -139,6 +139,8 @@ function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
||||
*/
|
||||
const [editingTokenId, setEditingTokenId] = useState();
|
||||
|
||||
const [isDraggingToken, setIsDraggingToken] = useState(false);
|
||||
|
||||
const mapStageRef = useMapStage();
|
||||
function handleTokensAddToMap(groupIds, rect) {
|
||||
let clientPosition = new Vector2(
|
||||
@ -198,6 +200,7 @@ function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
||||
isOpen={isOpen}
|
||||
onRequestClose={onRequestClose}
|
||||
style={{ maxWidth: layout.modalSize, width: "calc(100% - 16px)" }}
|
||||
shouldCloseOnEsc={!isDraggingToken}
|
||||
>
|
||||
<ImageDrop onDrop={handleImagesUpload} dropText="Drop token to import">
|
||||
<input
|
||||
@ -232,7 +235,12 @@ function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
||||
addTitle="Import Token(s)"
|
||||
/>
|
||||
<Box sx={{ position: "relative" }}>
|
||||
<TileDragProvider onDragAdd={handleTokensAddToMap}>
|
||||
<TileDragProvider
|
||||
onDragAdd={handleTokensAddToMap}
|
||||
onDragStart={() => setIsDraggingToken(true)}
|
||||
onDragEnd={() => setIsDraggingToken(false)}
|
||||
onDragCancel={() => setIsDraggingToken(false)}
|
||||
>
|
||||
<TilesContainer>
|
||||
<TokenTiles
|
||||
tokens={tokens}
|
||||
@ -240,7 +248,12 @@ function SelectTokensModal({ isOpen, onRequestClose, onMapTokensStateCreate }) {
|
||||
/>
|
||||
</TilesContainer>
|
||||
</TileDragProvider>
|
||||
<TileDragProvider onDragAdd={handleTokensAddToMap}>
|
||||
<TileDragProvider
|
||||
onDragAdd={handleTokensAddToMap}
|
||||
onDragStart={() => setIsDraggingToken(true)}
|
||||
onDragEnd={() => setIsDraggingToken(false)}
|
||||
onDragCancel={() => setIsDraggingToken(false)}
|
||||
>
|
||||
<TilesOverlay modalSize={modalSize}>
|
||||
<TokenTiles
|
||||
tokens={tokens}
|
||||
|
Loading…
Reference in New Issue
Block a user