Files
grungnet/src/components/tile/SortableTiles.js

130 lines
3.4 KiB
JavaScript
Raw Normal View History

2021-05-13 16:26:59 +10:00
import React, { useState } from "react";
import { createPortal } from "react-dom";
import {
DndContext,
DragOverlay,
MouseSensor,
TouchSensor,
useSensor,
useSensors,
closestCenter,
2021-05-13 16:26:59 +10:00
} from "@dnd-kit/core";
import { SortableContext, arrayMove } from "@dnd-kit/sortable";
import { animated, useSpring, config } from "react-spring";
2021-05-24 15:17:23 +10:00
import { combineGroups, moveGroups } from "../../helpers/group";
import SortableTile from "./SortableTile";
2021-05-21 16:12:09 +10:00
function SortableTiles({
groups,
onGroupChange,
renderTile,
onTileSelect,
disableGrouping,
2021-05-24 17:11:46 +10:00
openGroupId,
2021-05-21 16:12:09 +10:00
}) {
2021-05-13 16:26:59 +10:00
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();
const [overId, setOverId] = useState();
2021-05-13 16:26:59 +10:00
function handleDragStart({ active, over }) {
2021-05-13 16:26:59 +10:00
setDragId(active.id);
setOverId(over?.id);
onTileSelect(active.id);
}
function handleDragMove({ over }) {
setOverId(over?.id);
2021-05-13 16:26:59 +10:00
}
function handleDragEnd({ active, over }) {
setDragId();
setOverId();
if (!active || !over) {
return;
}
if (over.id.startsWith("__group__")) {
2021-05-21 16:12:09 +10:00
const overId = over.id.slice(9);
if (overId === active.id) {
return;
}
const activeGroupIndex = groups.findIndex(
(group) => group.id === active.id
);
const overGroupIndex = groups.findIndex((group) => group.id === overId);
onGroupChange(moveGroups(groups, overGroupIndex, activeGroupIndex));
onTileSelect();
} else if (active.id !== over.id) {
2021-05-14 18:02:50 +10:00
const oldIndex = groups.findIndex((group) => group.id === active.id);
const newIndex = groups.findIndex((group) => group.id === over.id);
2021-05-13 16:26:59 +10:00
onGroupChange(arrayMove(groups, oldIndex, newIndex));
}
}
const dragBounce = useSpring({
transform: !!dragId ? "scale(0.9)" : "scale(1)",
2021-05-13 16:26:59 +10:00
config: config.wobbly,
});
const overGroupId =
overId && overId.startsWith("__group__") && overId.slice(9);
function renderSortableGroup(group) {
if (overGroupId === group.id && dragId && group.id !== dragId) {
// If dragging over a group render a preview of that group
return renderTile(
combineGroups(
group,
groups.find((group) => group.id === dragId)
)
);
}
return renderTile(group);
}
2021-05-13 16:26:59 +10:00
return (
<DndContext
onDragStart={handleDragStart}
onDragMove={handleDragMove}
2021-05-13 16:26:59 +10:00
onDragEnd={handleDragEnd}
sensors={sensors}
collisionDetection={closestCenter}
2021-05-13 16:26:59 +10:00
>
<SortableContext items={groups}>
2021-05-24 17:11:46 +10:00
{groups.map((group) => (
<SortableTile
id={group.id}
key={group.id}
disableGrouping={disableGrouping}
hidden={group.id === openGroupId}
>
{renderSortableGroup(group)}
</SortableTile>
))}
2021-05-13 16:26:59 +10:00
{createPortal(
<DragOverlay dropAnimation={null}>
{dragId && (
<animated.div style={dragBounce}>
2021-05-14 18:02:50 +10:00
{renderTile(groups.find((group) => group.id === dragId))}
2021-05-13 16:26:59 +10:00
</animated.div>
)}
</DragOverlay>,
document.body
)}
</SortableContext>
</DndContext>
);
}
export default SortableTiles;