diff --git a/src/components/map/MapTile.js b/src/components/map/MapTile.js
new file mode 100644
index 0000000..b06fc4c
--- /dev/null
+++ b/src/components/map/MapTile.js
@@ -0,0 +1,143 @@
+import React, { useState, useEffect } from "react";
+import { Flex, Image as UIImage, IconButton, Box } from "theme-ui";
+
+import db from "../../database";
+
+import RemoveMapIcon from "../../icons/RemoveMapIcon";
+import ResetMapIcon from "../../icons/ResetMapIcon";
+import ExpandMoreDotIcon from "../../icons/ExpandMoreDotIcon";
+
+function MapTile({ map, isSelected, onMapSelect, onMapRemove, onMapReset }) {
+ const [isMapTileMenuOpen, setIsTileMenuOpen] = useState(false);
+ const [hasMapState, setHasMapState] = useState(false);
+
+ useEffect(() => {
+ async function checkForMapState() {
+ const state = await db.table("states").get(map.id);
+ if (
+ state &&
+ (Object.values(state.tokens).length > 0 || state.drawActions.length > 0)
+ ) {
+ setHasMapState(true);
+ }
+ }
+
+ checkForMapState();
+ }, [map]);
+
+ const expandButton = (
+ {
+ e.preventDefault();
+ e.stopPropagation();
+ setIsTileMenuOpen(true);
+ }}
+ bg="overlay"
+ sx={{ borderRadius: "50%" }}
+ m={1}
+ >
+
+
+ );
+
+ function removeButton(map) {
+ return (
+ {
+ e.preventDefault();
+ e.stopPropagation();
+ setIsTileMenuOpen(false);
+ onMapRemove(map.id);
+ }}
+ bg="overlay"
+ sx={{ borderRadius: "50%" }}
+ m={1}
+ >
+
+
+ );
+ }
+
+ function resetButton(map) {
+ return (
+ {
+ e.preventDefault();
+ e.stopPropagation();
+ setHasMapState(false);
+ setIsTileMenuOpen(false);
+ onMapReset(map.id);
+ }}
+ bg="overlay"
+ sx={{ borderRadius: "50%" }}
+ m={1}
+ >
+
+
+ );
+ }
+
+ return (
+ {
+ setIsTileMenuOpen(false);
+ onMapSelect(map);
+ }}
+ >
+
+ {/* Show expand button only if both reset and remove is available */}
+ {isSelected && (
+
+ {map.default && hasMapState && resetButton(map)}
+ {!map.default && hasMapState && !isMapTileMenuOpen && expandButton}
+ {!map.default && !hasMapState && removeButton(map)}
+
+ )}
+ {/* Tile menu for two actions */}
+ {!map.default && isMapTileMenuOpen && isSelected && (
+ setIsTileMenuOpen(false)}
+ >
+ {!map.default && removeButton(map)}
+ {hasMapState && resetButton(map)}
+
+ )}
+
+ );
+}
+
+export default MapTile;
diff --git a/src/components/map/MapTiles.js b/src/components/map/MapTiles.js
index a2bc073..796ae8e 100644
--- a/src/components/map/MapTiles.js
+++ b/src/components/map/MapTiles.js
@@ -1,60 +1,18 @@
import React from "react";
-import { Flex, Image as UIImage, IconButton } from "theme-ui";
+import { Flex } from "theme-ui";
import AddIcon from "../../icons/AddIcon";
-import RemoveIcon from "../../icons/RemoveIcon";
-function MapTiles({ maps, selectedMap, onMapSelect, onMapAdd, onMapRemove }) {
- const tileProps = {
- m: 2,
- bg: "muted",
- };
-
- const tileStyle = {
- width: "150px",
- height: "150px",
- borderRadius: "4px",
- justifyContent: "center",
- alignItems: "center",
- cursor: "pointer",
- };
-
- function tile(map) {
- return (
- onMapSelect(map)}
- >
-
- {!map.default && map.id === selectedMap && (
- {
- e.preventDefault();
- e.stopPropagation();
- onMapRemove(map.id);
- }}
- sx={{ position: "absolute", top: 0, right: 0 }}
- >
-
-
- )}
-
- );
- }
+import MapTile from "./MapTile";
+function MapTiles({
+ maps,
+ selectedMap,
+ onMapSelect,
+ onMapAdd,
+ onMapRemove,
+ onMapReset,
+}) {
return (
- {maps.map(tile)}
+ {maps.map((map) => (
+
+ ))}
);
}
diff --git a/src/icons/ExpandMoreDotIcon.js b/src/icons/ExpandMoreDotIcon.js
new file mode 100644
index 0000000..6259f07
--- /dev/null
+++ b/src/icons/ExpandMoreDotIcon.js
@@ -0,0 +1,18 @@
+import React from "react";
+
+function ExpandMoreDotIcon() {
+ return (
+
+ );
+}
+
+export default ExpandMoreDotIcon;
diff --git a/src/icons/RemoveIcon.js b/src/icons/RemoveIcon.js
deleted file mode 100644
index d09fbc8..0000000
--- a/src/icons/RemoveIcon.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from "react";
-
-function RemoveIcon() {
- return (
-
- );
-}
-
-export default RemoveIcon;
diff --git a/src/icons/RemoveMapIcon.js b/src/icons/RemoveMapIcon.js
new file mode 100644
index 0000000..a7dd3f3
--- /dev/null
+++ b/src/icons/RemoveMapIcon.js
@@ -0,0 +1,18 @@
+import React from "react";
+
+function RemoveMapIcon() {
+ return (
+
+ );
+}
+
+export default RemoveMapIcon;
diff --git a/src/icons/ResetMapIcon.js b/src/icons/ResetMapIcon.js
new file mode 100644
index 0000000..02ac13b
--- /dev/null
+++ b/src/icons/ResetMapIcon.js
@@ -0,0 +1,18 @@
+import React from "react";
+
+function ResetMapIcon() {
+ return (
+
+ );
+}
+
+export default ResetMapIcon;
diff --git a/src/maps/index.js b/src/maps/index.js
index 4a9524d..1c0eb07 100644
--- a/src/maps/index.js
+++ b/src/maps/index.js
@@ -16,35 +16,35 @@ const defaultProps = {
export const blank = {
...defaultProps,
source: blankImage,
- id: "Blank Grid 22x22",
+ id: "__default_blank",
};
export const grass = {
...defaultProps,
source: grassImage,
- id: "Grass Grid 22x22",
+ id: "__default_grass",
};
export const sand = {
...defaultProps,
source: sandImage,
- id: "Sand Grid 22x22",
+ id: "__default_sand",
};
export const stone = {
...defaultProps,
source: stoneImage,
- id: "Stone Grid 22x22",
+ id: "__default_stone",
};
export const water = {
...defaultProps,
source: waterImage,
- id: "Water Grid 22x22",
+ id: "__default_water",
};
export const wood = {
...defaultProps,
source: woodImage,
- id: "Wood Grid 22x22",
+ id: "__default_wood",
};
diff --git a/src/modals/SelectMapModal.js b/src/modals/SelectMapModal.js
index 970e7df..c1dbc71 100644
--- a/src/modals/SelectMapModal.js
+++ b/src/modals/SelectMapModal.js
@@ -23,7 +23,7 @@ function SelectMapModal({ isOpen, onRequestClose, onDone }) {
const [currentMap, setCurrentMap] = useState(null);
const [maps, setMaps] = useState(Object.values(defaultMaps));
- // Load maps from the database
+ // Load maps from the database and ensure state is properly setup
useEffect(() => {
async function loadMaps() {
let storedMaps = await db.table("maps").toArray();
@@ -35,7 +35,20 @@ function SelectMapModal({ isOpen, onRequestClose, onDone }) {
}
setMaps((prevMaps) => [...storedMaps, ...prevMaps]);
}
+
+ async function setupDefaultMapStatesIfNeeded() {
+ for (let defaultMap of Object.values(defaultMaps)) {
+ let state = await db.table("states").get(defaultMap.id);
+ if (!state) {
+ await db
+ .table("states")
+ .add({ ...defaultMapState, mapId: defaultMap.id });
+ }
+ }
+ }
+
loadMaps();
+ setupDefaultMapStatesIfNeeded();
}, []);
const [gridX, setGridX] = useState(defaultMapSize);
@@ -111,6 +124,10 @@ function SelectMapModal({ isOpen, onRequestClose, onDone }) {
setGridY(map.gridY);
}
+ async function handleMapReset(id) {
+ await db.table("states").put({ ...defaultMapState, mapId: id });
+ }
+
async function handleSubmit(e) {
e.preventDefault();
if (currentMap) {
@@ -199,6 +216,7 @@ function SelectMapModal({ isOpen, onRequestClose, onDone }) {
onMapRemove={handleMapRemove}
selectedMap={currentMap && currentMap.id}
onMapSelect={handleMapSelect}
+ onMapReset={handleMapReset}
/>