diff --git a/src/components/MapToken.js b/src/components/MapToken.js
index 27d49de..0923478 100644
--- a/src/components/MapToken.js
+++ b/src/components/MapToken.js
@@ -2,6 +2,7 @@ import React, { useRef } from "react";
import { Box, Image } from "theme-ui";
import TokenLabel from "./TokenLabel";
+import TokenStatus from "./TokenStatus";
import usePreventTouch from "../helpers/usePreventTouch";
@@ -51,8 +52,10 @@ function MapToken({ token, tokenSizePercent, className }) {
data-id={token.id}
data-size={token.size}
data-label={token.label}
+ data-status={token.status}
ref={imageRef}
/>
+ {token.status && }
{token.label && }
diff --git a/src/components/ProxyToken.js b/src/components/ProxyToken.js
index 1f0787a..e66d0a0 100644
--- a/src/components/ProxyToken.js
+++ b/src/components/ProxyToken.js
@@ -5,12 +5,14 @@ import interact from "interactjs";
import usePortal from "../helpers/usePortal";
import TokenLabel from "./TokenLabel";
+import TokenStatus from "./TokenStatus";
function ProxyToken({ tokenClassName, onProxyDragEnd }) {
const proxyContainer = usePortal("root");
const [imageSource, setImageSource] = useState("");
const [label, setLabel] = useState("");
+ const [status, setStatus] = useState("");
const proxyRef = useRef();
const proxyOnMap = useRef(false);
@@ -24,6 +26,7 @@ function ProxyToken({ tokenClassName, onProxyDragEnd }) {
target.parentElement.style.opacity = "0.25";
setImageSource(target.src);
setLabel(target.dataset.label || "");
+ setStatus(target.dataset.status || "");
let proxy = proxyRef.current;
if (proxy) {
@@ -141,6 +144,7 @@ function ProxyToken({ tokenClassName, onProxyDragEnd }) {
width: "100%",
}}
/>
+ {status && }
{label && }
,
diff --git a/src/components/TokenMenu.js b/src/components/TokenMenu.js
index 49dffcb..817b18f 100644
--- a/src/components/TokenMenu.js
+++ b/src/components/TokenMenu.js
@@ -1,7 +1,9 @@
import React, { useEffect, useState } from "react";
import Modal from "react-modal";
import interact from "interactjs";
-import { useThemeUI, Box, Input } from "theme-ui";
+import { Box, Input } from "theme-ui";
+
+import { statusOptions, statusToColor } from "../helpers/status";
function TokenMenu({ tokenClassName, onTokenChange }) {
const [isOpen, setIsOpen] = useState(false);
@@ -10,7 +12,7 @@ function TokenMenu({ tokenClassName, onTokenChange }) {
setIsOpen(false);
}
- const [currentToken, setCurrentToken] = useState(0);
+ const [currentToken, setCurrentToken] = useState({});
const [menuLeft, setMenuLeft] = useState(0);
const [menuTop, setMenuTop] = useState(0);
@@ -27,6 +29,23 @@ function TokenMenu({ tokenClassName, onTokenChange }) {
}
}
+ function handleStatusChange(status) {
+ const statuses =
+ currentToken.status.split(" ").filter((s) => s !== "") || [];
+ let newStatuses = [];
+ if (statuses.includes(status)) {
+ newStatuses = statuses.filter((s) => s !== status);
+ } else {
+ newStatuses = [...statuses, status];
+ }
+ const newStatus = newStatuses.join(" ");
+ setCurrentToken((prevToken) => ({
+ ...prevToken,
+ status: newStatus,
+ }));
+ onTokenChange({ ...currentToken, status: newStatus });
+ }
+
useEffect(() => {
function handleTokenMenuOpen(event) {
const target = event.target;
@@ -64,17 +83,22 @@ function TokenMenu({ tokenClassName, onTokenChange }) {
};
}, [tokenClassName]);
- const { theme } = useThemeUI();
-
function handleModalContent(node) {
if (node) {
const tokenLabelInput = node.querySelector("#changeTokenLabel");
tokenLabelInput.focus();
- // Highlight label section of input
tokenLabelInput.setSelectionRange(7, 8);
- tokenLabelInput.onblur = () => {
- setIsOpen(false);
- };
+
+ // Close modal if interacting with any other element
+ function handlePointerDown(event) {
+ const path = event.composedPath();
+ if (!path.includes(node)) {
+ setIsOpen(false);
+ document.body.removeEventListener("pointerdown", handlePointerDown);
+ }
+ }
+ document.body.addEventListener("pointerdown", handlePointerDown);
+
// Check for wheel event to close modal as well
document.body.addEventListener(
"wheel",
@@ -93,7 +117,7 @@ function TokenMenu({ tokenClassName, onTokenChange }) {
style={{
overlay: { top: "0", bottom: "initial" },
content: {
- backgroundColor: theme.colors.highlight,
+ backgroundColor: "hsla(230, 25%, 18%, 0.8)",
top: `${menuTop}px`,
left: `${menuLeft}px`,
right: "initial",
@@ -105,21 +129,63 @@ function TokenMenu({ tokenClassName, onTokenChange }) {
}}
contentRef={handleModalContent}
>
- {
- e.preventDefault();
- handleRequestClose();
- }}
- sx={{ width: "72px" }}
- >
-
+
+ {
+ e.preventDefault();
+ handleRequestClose();
+ }}
+ >
+
+
+
+ {statusOptions.map((status) => (
+ handleStatusChange(status)}
+ >
+ {currentToken.status && currentToken.status.includes(status) && (
+
+ )}
+
+ ))}
+
);
diff --git a/src/components/TokenStatus.js b/src/components/TokenStatus.js
new file mode 100644
index 0000000..6da6302
--- /dev/null
+++ b/src/components/TokenStatus.js
@@ -0,0 +1,47 @@
+import React from "react";
+import { Box } from "theme-ui";
+
+import { statusToColor } from "../helpers/status";
+
+function TokenStatus({ statuses }) {
+ return (
+
+ {statuses.map((status, index) => (
+
+
+
+ ))}
+
+ );
+}
+
+export default TokenStatus;
diff --git a/src/components/Tokens.js b/src/components/Tokens.js
index 9882c23..1d9a2ae 100644
--- a/src/components/Tokens.js
+++ b/src/components/Tokens.js
@@ -22,6 +22,7 @@ function Tokens({ onCreateMapToken }) {
id: shortid.generate(),
size: tokenSize,
label: "",
+ status: "",
});
}
}
diff --git a/src/helpers/status.js b/src/helpers/status.js
new file mode 100644
index 0000000..b787bfc
--- /dev/null
+++ b/src/helpers/status.js
@@ -0,0 +1,27 @@
+export function statusToColor(status) {
+ switch (status) {
+ case "blue":
+ return "rgb(26, 106, 255)";
+ case "orange":
+ return "rgb(255, 116, 51)";
+ case "red":
+ return "rgb(255, 77, 77)";
+ case "purple":
+ return "rgb(136, 77, 255)";
+ case "green":
+ return "rgb(133, 255, 102)";
+ case "pink":
+ return "rgb(235, 138, 255)";
+ default:
+ throw Error("Color not implemented");
+ }
+}
+
+export const statusOptions = [
+ "blue",
+ "orange",
+ "red",
+ "purple",
+ "green",
+ "pink",
+];