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
|
2021-06-12 21:25:03 +10:00
|
|
|
columns="1fr 1fr"
|
2021-06-03 16:05:57 +10:00
|
|
|
bg="muted"
|
2021-06-12 21:25:03 +10:00
|
|
|
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;
|