Files
grungnet/src/components/token/TokenBarTokenGroup.js
T

135 lines
3.4 KiB
JavaScript
Raw Normal View History

2021-06-03 16:05:57 +10:00
import React, { useState, useRef } from "react";
import { Grid, Flex, Box } from "theme-ui";
2021-05-25 18:07:10 +10:00
import { useSpring, animated } from "react-spring";
2021-06-03 16:05:57 +10:00
import { useDraggable } from "@dnd-kit/core";
2021-05-25 18:07:10 +10:00
import TokenImage from "./TokenImage";
import TokenBarToken from "./TokenBarToken";
import Draggable from "../drag/Draggable";
2021-06-03 16:05:57 +10:00
import Vector2 from "../../helpers/Vector2";
2021-05-25 18:07:10 +10:00
import GroupIcon from "../../icons/GroupIcon";
2021-06-03 16:05:57 +10:00
function TokenBarTokenGroup({ group, tokens, draggable }) {
const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
id: draggable && group.id,
disabled: !draggable,
});
2021-05-25 18:07:10 +10:00
const [isOpen, setIsOpen] = useState(false);
const { height } = useSpring({
height: isOpen ? (tokens.length + 1) * 56 : 56,
});
2021-06-03 16:05:57 +10:00
function renderToken(token) {
if (draggable) {
return (
<Draggable id={token.id} key={token.id}>
<TokenBarToken token={token} />
</Draggable>
);
} else {
return <TokenBarToken token={token} key={token.id} />;
}
}
2021-05-25 18:07:10 +10:00
function renderTokens() {
if (isOpen) {
return (
2021-06-03 16:05:57 +10:00
<Grid
columns="1fr"
bg="muted"
sx={{ borderRadius: "8px", gridGap: 0 }}
p={0}
>
2021-05-25 18:07:10 +10:00
<Flex
sx={{
width: "48px",
height: "48px",
alignItems: "center",
justifyContent: "center",
2021-06-03 16:05:57 +10:00
cursor: isDragging ? "grabbing" : "pointer",
2021-05-25 18:07:10 +10:00
color: "primary",
}}
2021-06-03 16:05:57 +10:00
onClick={(e) => handleOpenClick(e, false)}
2021-05-25 18:07:10 +10:00
key="group"
title={group.name}
2021-06-03 16:05:57 +10:00
{...listeners}
{...attributes}
2021-05-25 18:07:10 +10:00
>
<GroupIcon />
</Flex>
2021-06-03 16:05:57 +10:00
{tokens.map(renderToken)}
</Grid>
2021-05-25 18:07:10 +10:00
);
} else {
2021-06-03 16:05:57 +10:00
return (
<Grid
columns="1fr 1fr"
2021-06-03 16:05:57 +10:00
bg="muted"
sx={{
borderRadius: "8px",
gridGap: "4px",
height: "48px",
gridTemplateRows: "1fr 1fr",
}}
2021-06-03 16:05:57 +10:00
p="2px"
2021-06-14 15:50:48 +10:00
alt={group.name}
title={group.name}
2021-06-03 16:05:57 +10:00
{...listeners}
{...attributes}
>
{tokens.slice(0, 4).map((token) => (
<TokenImage
token={token}
key={token.id}
sx={{
userSelect: "none",
touchAction: "none",
pointerEvents: "none",
}}
/>
))}
</Grid>
);
}
}
// Reject the opening of a group if the pointer has moved
const clickDownPositionRef = useRef(new Vector2(0, 0));
function handleOpenDown(event) {
clickDownPositionRef.current = new Vector2(event.clientX, event.clientY);
}
function handleOpenClick(event, newOpen) {
const clickPosition = new Vector2(event.clientX, event.clientY);
const distance = Vector2.distance(
clickPosition,
clickDownPositionRef.current
);
if (distance < 5) {
setIsOpen(newOpen);
2021-05-25 18:07:10 +10:00
}
}
return (
2021-06-03 16:05:57 +10:00
<Box ref={setNodeRef}>
<animated.div
style={{
padding: "4px 0",
width: "48px",
height,
cursor: isOpen ? "default" : isDragging ? "grabbing" : "pointer",
}}
onPointerDown={handleOpenDown}
onClick={(e) => !isOpen && handleOpenClick(e, true)}
2021-05-25 18:07:10 +10:00
>
{renderTokens()}
2021-06-03 16:05:57 +10:00
</animated.div>
</Box>
2021-05-25 18:07:10 +10:00
);
}
export default TokenBarTokenGroup;