diff --git a/src/components/Draggable.js b/src/components/drag/Draggable.js
similarity index 100%
rename from src/components/Draggable.js
rename to src/components/drag/Draggable.js
diff --git a/src/components/Droppable.js b/src/components/drag/Droppable.js
similarity index 100%
rename from src/components/Droppable.js
rename to src/components/drag/Droppable.js
diff --git a/src/components/Sortable.js b/src/components/drag/Sortable.js
similarity index 90%
rename from src/components/Sortable.js
rename to src/components/drag/Sortable.js
index 128a0e2..24f6783 100644
--- a/src/components/Sortable.js
+++ b/src/components/drag/Sortable.js
@@ -13,11 +13,10 @@ function Sortable({ id, children }) {
const style = {
cursor: "pointer",
- touchAction: "none",
opacity: isDragging ? 0.25 : undefined,
transform:
transform && `translate3d(${transform.x}px, ${transform.y}px, 0px)`,
- zIndex: isDragging ? 100 : 0,
+ zIndex: isDragging ? 100 : undefined,
transition,
};
diff --git a/src/components/drag/SortableTiles.js b/src/components/drag/SortableTiles.js
new file mode 100644
index 0000000..e8f794e
--- /dev/null
+++ b/src/components/drag/SortableTiles.js
@@ -0,0 +1,67 @@
+import React, { useState } from "react";
+import { createPortal } from "react-dom";
+import {
+ DndContext,
+ DragOverlay,
+ MouseSensor,
+ TouchSensor,
+ useSensor,
+ useSensors,
+} from "@dnd-kit/core";
+import { SortableContext, arrayMove } from "@dnd-kit/sortable";
+import { animated, useSpring, config } from "react-spring";
+
+function SortableTiles({ groups, onGroupChange, renderTile, children }) {
+ const mouseSensor = useSensor(MouseSensor, {
+ activationConstraint: { delay: 250, tolerance: 5 },
+ });
+ const touchSensor = useSensor(TouchSensor, {
+ activationConstraint: { delay: 250, tolerance: 5 },
+ });
+
+ const sensors = useSensors(mouseSensor, touchSensor);
+
+ const [dragId, setDragId] = useState();
+
+ function handleDragStart({ active }) {
+ setDragId(active.id);
+ }
+
+ function handleDragEnd({ active, over }) {
+ setDragId();
+ if (active && over && active.id !== over.id) {
+ const oldIndex = groups.indexOf(active.id);
+ const newIndex = groups.indexOf(over.id);
+ onGroupChange(arrayMove(groups, oldIndex, newIndex));
+ }
+ }
+
+ const dragBounce = useSpring({
+ transform: !!dragId ? "scale(1.05)" : "scale(1)",
+ config: config.wobbly,
+ });
+
+ return (
+
+
+ {children}
+ {createPortal(
+
+ {dragId && (
+
+ {renderTile(dragId)}
+
+ )}
+ ,
+ document.body
+ )}
+
+
+ );
+}
+
+export default SortableTiles;
diff --git a/src/components/map/MapTiles.js b/src/components/map/MapTiles.js
index 811467f..14f08d0 100644
--- a/src/components/map/MapTiles.js
+++ b/src/components/map/MapTiles.js
@@ -1,9 +1,6 @@
-import React, { useState } from "react";
-import { createPortal } from "react-dom";
+import React from "react";
import { Flex, Box, Text, IconButton, Close, Grid } from "theme-ui";
import SimpleBar from "simplebar-react";
-import { DndContext, DragOverlay } from "@dnd-kit/core";
-import { SortableContext, arrayMove } from "@dnd-kit/sortable";
import RemoveMapIcon from "../../icons/RemoveMapIcon";
import ResetMapIcon from "../../icons/ResetMapIcon";
@@ -11,7 +8,9 @@ import ResetMapIcon from "../../icons/ResetMapIcon";
import MapTile from "./MapTile";
import Link from "../Link";
import FilterBar from "../FilterBar";
-import Sortable from "../Sortable";
+
+import Sortable from "../drag/Sortable";
+import SortableTiles from "../drag/SortableTiles";
import { useDatabase } from "../../contexts/DatabaseContext";
@@ -36,7 +35,6 @@ function MapTiles({
}) {
const { databaseStatus } = useDatabase();
const layout = useResponsiveLayout();
- const [dragId, setDragId] = useState();
let hasMapState = false;
for (let state of selectedMapStates) {
@@ -55,7 +53,8 @@ function MapTiles({
(map) => map.type === "default"
);
- function mapToTile(map) {
+ function mapToTile(mapId) {
+ const map = maps.find((map) => map.id === mapId);
const isSelected = selectedMaps.includes(map);
return (
1;
- function handleDragStart({ active }) {
- setDragId(active.id);
- }
-
- function handleDragEnd({ active, over }) {
- setDragId();
- if (active && over && active.id !== over.id) {
- const oldIndex = groups.indexOf(active.id);
- const newIndex = groups.indexOf(over.id);
- onMapsGroup(arrayMove(groups, oldIndex, newIndex));
- }
- }
-
return (
-
-
-
- onMapSelect()}
- search={search}
- onSearchChange={onSearchChange}
- selectMode={selectMode}
- onSelectModeChange={onSelectModeChange}
- onAdd={onMapAdd}
- addTitle="Add Map"
- />
-
+
+ onMapSelect()}
+ search={search}
+ onSearchChange={onSearchChange}
+ selectMode={selectMode}
+ onSelectModeChange={onSelectModeChange}
+ onAdd={onMapAdd}
+ addTitle="Add Map"
+ />
+
+ onMapSelect()}
>
- onMapSelect()}
- >
- {groups.map((mapId) => (
-
- {mapToTile(maps.find((map) => map.id === mapId))}
-
- ))}
-
-
- {databaseStatus === "disabled" && (
-
-
- Map saving is unavailable. See FAQ{" "}
- for more information.
-
-
- )}
- {selectedMaps.length > 0 && (
-
- onMapSelect()}
- />
-
- onMapsReset()}
- disabled={!hasMapState}
- >
-
-
- onMapsRemove()}
- disabled={hasSelectedDefaultMap}
- >
-
-
-
-
- )}
-
- {createPortal(
-
- {dragId && mapToTile(maps.find((maps) => maps.id === dragId))}
- ,
- document.body
+ {groups.map((mapId) => (
+
+ {mapToTile(mapId)}
+
+ ))}
+
+
+ {databaseStatus === "disabled" && (
+
+
+ Map saving is unavailable. See FAQ{" "}
+ for more information.
+
+
)}
-
-
+ {selectedMaps.length > 0 && (
+
+ onMapSelect()}
+ />
+
+ onMapsReset()}
+ disabled={!hasMapState}
+ >
+
+
+ onMapsRemove()}
+ disabled={hasSelectedDefaultMap}
+ >
+
+
+
+
+ )}
+
+
);
}
diff --git a/src/components/token/TokenBar.js b/src/components/token/TokenBar.js
index d103402..25a0fb5 100644
--- a/src/components/token/TokenBar.js
+++ b/src/components/token/TokenBar.js
@@ -6,7 +6,7 @@ import { DragOverlay, DndContext } from "@dnd-kit/core";
import ListToken from "./ListToken";
import SelectTokensButton from "./SelectTokensButton";
-import Draggable from "../Draggable";
+import Draggable from "../drag/Draggable";
import useSetting from "../../hooks/useSetting";
diff --git a/src/components/token/TokenTiles.js b/src/components/token/TokenTiles.js
index a35ee87..16f09b0 100644
--- a/src/components/token/TokenTiles.js
+++ b/src/components/token/TokenTiles.js
@@ -1,9 +1,6 @@
-import React, { useState } from "react";
-import { createPortal } from "react-dom";
+import React from "react";
import { Flex, Box, Text, IconButton, Close, Grid } from "theme-ui";
import SimpleBar from "simplebar-react";
-import { DndContext, DragOverlay } from "@dnd-kit/core";
-import { SortableContext, arrayMove } from "@dnd-kit/sortable";
import RemoveTokenIcon from "../../icons/RemoveTokenIcon";
import TokenHideIcon from "../../icons/TokenHideIcon";
@@ -12,7 +9,9 @@ import TokenShowIcon from "../../icons/TokenShowIcon";
import TokenTile from "./TokenTile";
import Link from "../Link";
import FilterBar from "../FilterBar";
-import Sortable from "../Sortable";
+
+import Sortable from "../drag/Sortable";
+import SortableTiles from "../drag/SortableTiles";
import { useDatabase } from "../../contexts/DatabaseContext";
@@ -35,14 +34,14 @@ function TokenTiles({
}) {
const { databaseStatus } = useDatabase();
const layout = useResponsiveLayout();
- const [dragId, setDragId] = useState();
let hasSelectedDefaultToken = selectedTokens.some(
(token) => token.type === "default"
);
let allTokensVisible = selectedTokens.every((token) => !token.hideInSidebar);
- function tokenToTile(token) {
+ function tokenToTile(tokenId) {
+ const token = tokens.find((token) => token.id === tokenId);
const isSelected = selectedTokens.includes(token);
return (
-
-
- onTokenSelect()}
- search={search}
- onSearchChange={onSearchChange}
- selectMode={selectMode}
- onSelectModeChange={onSelectModeChange}
- onAdd={onTokenAdd}
- addTitle="Add Token"
- />
-
+
+ onTokenSelect()}
+ search={search}
+ onSearchChange={onSearchChange}
+ selectMode={selectMode}
+ onSelectModeChange={onSelectModeChange}
+ onAdd={onTokenAdd}
+ addTitle="Add Token"
+ />
+
+ onTokenSelect()}
>
- onTokenSelect()}
- >
- {groups.map((tokenId) => (
-
- {tokenToTile(tokens.find((token) => token.id === tokenId))}
-
- ))}
-
-
- {databaseStatus === "disabled" && (
-
-
- Token saving is unavailable. See{" "}
- FAQ for more information.
-
-
- )}
- {selectedTokens.length > 0 && (
-
- onTokenSelect()}
- />
-
- onTokensHide(allTokensVisible)}
- >
- {allTokensVisible ? : }
-
- onTokensRemove()}
- disabled={hasSelectedDefaultToken}
- >
-
-
-
-
- )}
-
- {createPortal(
-
- {dragId && tokenToTile(tokens.find((token) => token.id === dragId))}
- ,
- document.body
+ {groups.map((tokenId) => (
+
+ {tokenToTile(tokenId)}
+
+ ))}
+
+
+ {databaseStatus === "disabled" && (
+
+
+ Token saving is unavailable. See FAQ{" "}
+ for more information.
+
+
)}
-
-
+ {selectedTokens.length > 0 && (
+
+ onTokenSelect()}
+ />
+
+ onTokensHide(allTokensVisible)}
+ >
+ {allTokensVisible ? : }
+
+ onTokensRemove()}
+ disabled={hasSelectedDefaultToken}
+ >
+
+
+
+
+ )}
+
+
);
}