Ensure order of selected tiles is kept when moving them
This commit is contained in:
parent
dd130a008e
commit
69eafb868c
@ -66,7 +66,6 @@ function MapTiles({ maps, onMapEdit, onMapSelect, subgroup, columns }) {
|
|||||||
onTileSelect={onGroupSelect}
|
onTileSelect={onGroupSelect}
|
||||||
disableGrouping={subgroup}
|
disableGrouping={subgroup}
|
||||||
openGroupId={openGroupId}
|
openGroupId={openGroupId}
|
||||||
columns={columns}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,11 @@ import {
|
|||||||
useSensors,
|
useSensors,
|
||||||
closestCenter,
|
closestCenter,
|
||||||
} from "@dnd-kit/core";
|
} from "@dnd-kit/core";
|
||||||
import { SortableContext, arrayMove } from "@dnd-kit/sortable";
|
import { SortableContext } from "@dnd-kit/sortable";
|
||||||
import { animated, useSpring, config } from "react-spring";
|
import { animated, useSpring, config } from "react-spring";
|
||||||
import { Badge } from "theme-ui";
|
import { Badge } from "theme-ui";
|
||||||
|
|
||||||
import { moveGroups } from "../../helpers/group";
|
import { moveGroupsInto, moveGroups } from "../../helpers/group";
|
||||||
import { keyBy } from "../../helpers/shared";
|
import { keyBy } from "../../helpers/shared";
|
||||||
import Vector2 from "../../helpers/Vector2";
|
import Vector2 from "../../helpers/Vector2";
|
||||||
|
|
||||||
@ -27,7 +27,6 @@ function SortableTiles({
|
|||||||
onTileSelect,
|
onTileSelect,
|
||||||
disableGrouping,
|
disableGrouping,
|
||||||
openGroupId,
|
openGroupId,
|
||||||
columns,
|
|
||||||
}) {
|
}) {
|
||||||
const mouseSensor = useSensor(MouseSensor, {
|
const mouseSensor = useSensor(MouseSensor, {
|
||||||
activationConstraint: { delay: 250, tolerance: 5 },
|
activationConstraint: { delay: 250, tolerance: 5 },
|
||||||
@ -60,29 +59,28 @@ function SortableTiles({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let selectedIndices = selectedGroupIds.map((groupId) =>
|
||||||
|
groups.findIndex((group) => group.id === groupId)
|
||||||
|
);
|
||||||
|
// Maintain current group sorting
|
||||||
|
selectedIndices = selectedIndices.sort((a, b) => a - b);
|
||||||
|
|
||||||
if (over.id.startsWith("__group__")) {
|
if (over.id.startsWith("__group__")) {
|
||||||
const overId = over.id.slice(9);
|
const overId = over.id.slice(9);
|
||||||
if (overId === active.id) {
|
if (overId === active.id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let newGroups = groups;
|
|
||||||
const overGroupIndex = groups.findIndex((group) => group.id === overId);
|
const overGroupIndex = groups.findIndex((group) => group.id === overId);
|
||||||
const selectedGroupIndices = selectedGroupIds.map((groupId) =>
|
onGroupChange(moveGroupsInto(groups, overGroupIndex, selectedIndices));
|
||||||
groups.findIndex((group) => group.id === groupId)
|
|
||||||
);
|
|
||||||
onGroupChange(
|
|
||||||
moveGroups(newGroups, overGroupIndex, selectedGroupIndices)
|
|
||||||
);
|
|
||||||
onTileSelect();
|
onTileSelect();
|
||||||
} else if (active.id !== over.id) {
|
} else {
|
||||||
let newGroups = groups;
|
if (active.id === over.id) {
|
||||||
for (let groupId of selectedGroupIds) {
|
return;
|
||||||
const oldIndex = newGroups.findIndex((group) => group.id === groupId);
|
|
||||||
const newIndex = newGroups.findIndex((group) => group.id === over.id);
|
|
||||||
newGroups = arrayMove(newGroups, oldIndex, newIndex);
|
|
||||||
}
|
}
|
||||||
onGroupChange(newGroups);
|
|
||||||
|
const overGroupIndex = groups.findIndex((group) => group.id === over.id);
|
||||||
|
onGroupChange(moveGroups(groups, overGroupIndex, selectedIndices));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +96,7 @@ function SortableTiles({
|
|||||||
function renderSortableGroup(group, selectedGroups) {
|
function renderSortableGroup(group, selectedGroups) {
|
||||||
if (overGroupId === group.id && dragId && group.id !== dragId) {
|
if (overGroupId === group.id && dragId && group.id !== dragId) {
|
||||||
// If dragging over a group render a preview of that group
|
// If dragging over a group render a preview of that group
|
||||||
const previewGroup = moveGroups(
|
const previewGroup = moveGroupsInto(
|
||||||
[group, ...selectedGroups],
|
[group, ...selectedGroups],
|
||||||
0,
|
0,
|
||||||
selectedGroups.map((_, i) => i + 1)
|
selectedGroups.map((_, i) => i + 1)
|
||||||
|
@ -6,7 +6,7 @@ import { useGroup } from "../../contexts/GroupContext";
|
|||||||
|
|
||||||
import useResponsiveLayout from "../../hooks/useResponsiveLayout";
|
import useResponsiveLayout from "../../hooks/useResponsiveLayout";
|
||||||
|
|
||||||
function TilesContainer({ columns, children }) {
|
function TilesContainer({ children }) {
|
||||||
const { onGroupSelect } = useGroup();
|
const { onGroupSelect } = useGroup();
|
||||||
|
|
||||||
const layout = useResponsiveLayout();
|
const layout = useResponsiveLayout();
|
||||||
@ -31,7 +31,7 @@ function TilesContainer({ columns, children }) {
|
|||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
}}
|
}}
|
||||||
gap={2}
|
gap={2}
|
||||||
columns={`repeat(${columns}, 1fr)`}
|
columns={`repeat(${layout.tileGridColumns}, 1fr)`}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -6,9 +6,13 @@ import SimpleBar from "simplebar-react";
|
|||||||
|
|
||||||
import { useGroup } from "../../contexts/GroupContext";
|
import { useGroup } from "../../contexts/GroupContext";
|
||||||
|
|
||||||
function TilesOverlay({ columns, children }) {
|
import useResponsiveLayout from "../../hooks/useResponsiveLayout";
|
||||||
|
|
||||||
|
function TilesOverlay({ children }) {
|
||||||
const { openGroupId, onGroupClose, onGroupSelect } = useGroup();
|
const { openGroupId, onGroupClose, onGroupSelect } = useGroup();
|
||||||
|
|
||||||
|
const layout = useResponsiveLayout();
|
||||||
|
|
||||||
const openAnimation = useSpring({
|
const openAnimation = useSpring({
|
||||||
opacity: openGroupId ? 1 : 0,
|
opacity: openGroupId ? 1 : 0,
|
||||||
transform: openGroupId ? "scale(1)" : "scale(0.99)",
|
transform: openGroupId ? "scale(1)" : "scale(0.99)",
|
||||||
@ -88,7 +92,7 @@ function TilesOverlay({ columns, children }) {
|
|||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
}}
|
}}
|
||||||
gap={2}
|
gap={2}
|
||||||
columns={`repeat(${columns}, 1fr)`}
|
columns={`repeat(${layout.groupGridColumns}, 1fr)`}
|
||||||
px={3}
|
px={3}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
@ -9,7 +9,7 @@ import { getGroupItems } from "../../helpers/group";
|
|||||||
|
|
||||||
import { useGroup } from "../../contexts/GroupContext";
|
import { useGroup } from "../../contexts/GroupContext";
|
||||||
|
|
||||||
function TokenTiles({ tokens, onTokenEdit, subgroup, columns }) {
|
function TokenTiles({ tokens, onTokenEdit, subgroup }) {
|
||||||
const {
|
const {
|
||||||
groups,
|
groups,
|
||||||
selectedGroupIds,
|
selectedGroupIds,
|
||||||
@ -71,7 +71,6 @@ function TokenTiles({ tokens, onTokenEdit, subgroup, columns }) {
|
|||||||
onTileSelect={onGroupSelect}
|
onTileSelect={onGroupSelect}
|
||||||
disableGrouping={subgroup}
|
disableGrouping={subgroup}
|
||||||
openGroupId={openGroupId}
|
openGroupId={openGroupId}
|
||||||
columns={columns}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -99,28 +99,28 @@ export function combineGroups(a, b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutably move group at indices `from` into index `to`
|
* Immutably move group at indices `indices` into group at index `into`
|
||||||
* @param {Group[]} groups
|
* @param {Group[]} groups
|
||||||
* @param {number} to
|
* @param {number} into
|
||||||
* @param {number[]} from
|
* @param {number[]} indices
|
||||||
* @returns {Group[]}
|
* @returns {Group[]}
|
||||||
*/
|
*/
|
||||||
export function moveGroups(groups, to, from) {
|
export function moveGroupsInto(groups, into, indices) {
|
||||||
const newGroups = cloneDeep(groups);
|
const newGroups = cloneDeep(groups);
|
||||||
|
|
||||||
const toGroup = newGroups[to];
|
const intoGroup = newGroups[into];
|
||||||
let fromGroups = [];
|
let fromGroups = [];
|
||||||
for (let i of from) {
|
for (let i of indices) {
|
||||||
fromGroups.push(newGroups[i]);
|
fromGroups.push(newGroups[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let combined = toGroup;
|
let combined = intoGroup;
|
||||||
for (let fromGroup of fromGroups) {
|
for (let fromGroup of fromGroups) {
|
||||||
combined = combineGroups(combined, fromGroup);
|
combined = combineGroups(combined, fromGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace and remove old groups
|
// Replace and remove old groups
|
||||||
newGroups[to] = combined;
|
newGroups[into] = combined;
|
||||||
for (let fromGroup of fromGroups) {
|
for (let fromGroup of fromGroups) {
|
||||||
const i = newGroups.findIndex((group) => group.id === fromGroup.id);
|
const i = newGroups.findIndex((group) => group.id === fromGroup.id);
|
||||||
newGroups.splice(i, 1);
|
newGroups.splice(i, 1);
|
||||||
@ -129,6 +129,33 @@ export function moveGroups(groups, to, from) {
|
|||||||
return newGroups;
|
return newGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immutably move group at indices `indices` to index `to`
|
||||||
|
* @param {Group[]} groups
|
||||||
|
* @param {number} into
|
||||||
|
* @param {number[]} indices
|
||||||
|
* @returns {Group[]}
|
||||||
|
*/
|
||||||
|
export function moveGroups(groups, to, indices) {
|
||||||
|
const newGroups = cloneDeep(groups);
|
||||||
|
|
||||||
|
let fromGroups = [];
|
||||||
|
for (let i of indices) {
|
||||||
|
fromGroups.push(newGroups[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove old groups
|
||||||
|
for (let fromGroup of fromGroups) {
|
||||||
|
const i = newGroups.findIndex((group) => group.id === fromGroup.id);
|
||||||
|
newGroups.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add back at new index
|
||||||
|
newGroups.splice(to, 0, ...fromGroups);
|
||||||
|
|
||||||
|
return newGroups;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively find a group within a group array
|
* Recursively find a group within a group array
|
||||||
* @param {Group[]} groups
|
* @param {Group[]} groups
|
||||||
|
@ -259,21 +259,19 @@ function SelectMapModal({
|
|||||||
onGroupsSelect={setSelectedGroupIds}
|
onGroupsSelect={setSelectedGroupIds}
|
||||||
disabled={!isOpen}
|
disabled={!isOpen}
|
||||||
>
|
>
|
||||||
<TilesContainer columns={layout.tileGridColumns}>
|
<TilesContainer>
|
||||||
<MapTiles
|
<MapTiles
|
||||||
maps={maps}
|
maps={maps}
|
||||||
onMapEdit={() => setIsEditModalOpen(true)}
|
onMapEdit={() => setIsEditModalOpen(true)}
|
||||||
onMapSelect={handleMapSelect}
|
onMapSelect={handleMapSelect}
|
||||||
columns={layout.tileGridColumns}
|
|
||||||
/>
|
/>
|
||||||
</TilesContainer>
|
</TilesContainer>
|
||||||
<TilesOverlay columns={layout.groupGridColumns}>
|
<TilesOverlay>
|
||||||
<MapTiles
|
<MapTiles
|
||||||
maps={maps}
|
maps={maps}
|
||||||
onMapEdit={() => setIsEditModalOpen(true)}
|
onMapEdit={() => setIsEditModalOpen(true)}
|
||||||
onMapSelect={handleMapSelect}
|
onMapSelect={handleMapSelect}
|
||||||
subgroup
|
subgroup
|
||||||
columns={layout.groupGridColumns}
|
|
||||||
/>
|
/>
|
||||||
</TilesOverlay>
|
</TilesOverlay>
|
||||||
</GroupProvider>
|
</GroupProvider>
|
||||||
|
@ -200,19 +200,17 @@ function SelectTokensModal({ isOpen, onRequestClose }) {
|
|||||||
onGroupsSelect={setSelectedGroupIds}
|
onGroupsSelect={setSelectedGroupIds}
|
||||||
disabled={!isOpen}
|
disabled={!isOpen}
|
||||||
>
|
>
|
||||||
<TilesContainer columns={layout.tileGridColumns}>
|
<TilesContainer>
|
||||||
<TokenTiles
|
<TokenTiles
|
||||||
tokens={tokens}
|
tokens={tokens}
|
||||||
onTokenEdit={() => setIsEditModalOpen(true)}
|
onTokenEdit={() => setIsEditModalOpen(true)}
|
||||||
columns={layout.tileGridColumns}
|
|
||||||
/>
|
/>
|
||||||
</TilesContainer>
|
</TilesContainer>
|
||||||
<TilesOverlay columns={layout.groupGridColumns}>
|
<TilesOverlay>
|
||||||
<TokenTiles
|
<TokenTiles
|
||||||
tokens={tokens}
|
tokens={tokens}
|
||||||
onTokenEdit={() => setIsEditModalOpen(true)}
|
onTokenEdit={() => setIsEditModalOpen(true)}
|
||||||
subgroup
|
subgroup
|
||||||
columns={layout.groupGridColumns}
|
|
||||||
/>
|
/>
|
||||||
</TilesOverlay>
|
</TilesOverlay>
|
||||||
</GroupProvider>
|
</GroupProvider>
|
||||||
|
Loading…
Reference in New Issue
Block a user