Added dice style select
This commit is contained in:
parent
c99e5bf5f8
commit
84b198c851
@ -1,12 +1,12 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Divider } from "theme-ui";
|
import { Divider } from "theme-ui";
|
||||||
|
|
||||||
function StyledDivider({ vertical }) {
|
function StyledDivider({ vertical, color }) {
|
||||||
return (
|
return (
|
||||||
<Divider
|
<Divider
|
||||||
my={vertical ? 0 : 2}
|
my={vertical ? 0 : 2}
|
||||||
mx={vertical ? 2 : 0}
|
mx={vertical ? 2 : 0}
|
||||||
bg="text"
|
bg={color}
|
||||||
sx={{
|
sx={{
|
||||||
height: vertical ? "24px" : "2px",
|
height: vertical ? "24px" : "2px",
|
||||||
width: vertical ? "2px" : "24px",
|
width: vertical ? "2px" : "24px",
|
||||||
@ -19,6 +19,7 @@ function StyledDivider({ vertical }) {
|
|||||||
|
|
||||||
StyledDivider.defaultProps = {
|
StyledDivider.defaultProps = {
|
||||||
vertical: false,
|
vertical: false,
|
||||||
|
color: "text",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default StyledDivider;
|
export default StyledDivider;
|
@ -2,7 +2,7 @@ import React, { useState, Fragment } from "react";
|
|||||||
import { IconButton, Flex, Box } from "theme-ui";
|
import { IconButton, Flex, Box } from "theme-ui";
|
||||||
|
|
||||||
import RadioIconButton from "./controls/RadioIconButton";
|
import RadioIconButton from "./controls/RadioIconButton";
|
||||||
import Divider from "./controls/Divider";
|
import Divider from "../Divider";
|
||||||
|
|
||||||
import SelectMapButton from "./SelectMapButton";
|
import SelectMapButton from "./SelectMapButton";
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import BrushFillIcon from "../../../icons/BrushFillIcon";
|
|||||||
import UndoButton from "./UndoButton";
|
import UndoButton from "./UndoButton";
|
||||||
import RedoButton from "./RedoButton";
|
import RedoButton from "./RedoButton";
|
||||||
|
|
||||||
import Divider from "./Divider";
|
import Divider from "../../Divider";
|
||||||
|
|
||||||
function BrushToolSettings({
|
function BrushToolSettings({
|
||||||
settings,
|
settings,
|
||||||
|
@ -6,7 +6,7 @@ import EraseAllIcon from "../../../icons/EraseAllIcon";
|
|||||||
import UndoButton from "./UndoButton";
|
import UndoButton from "./UndoButton";
|
||||||
import RedoButton from "./RedoButton";
|
import RedoButton from "./RedoButton";
|
||||||
|
|
||||||
import Divider from "./Divider";
|
import Divider from "../../Divider";
|
||||||
|
|
||||||
function EraseToolSettings({ onToolAction, disabledActions }) {
|
function EraseToolSettings({ onToolAction, disabledActions }) {
|
||||||
return (
|
return (
|
||||||
|
@ -12,7 +12,7 @@ import FogToggleIcon from "../../../icons/FogToggleIcon";
|
|||||||
import UndoButton from "./UndoButton";
|
import UndoButton from "./UndoButton";
|
||||||
import RedoButton from "./RedoButton";
|
import RedoButton from "./RedoButton";
|
||||||
|
|
||||||
import Divider from "./Divider";
|
import Divider from "../../Divider";
|
||||||
|
|
||||||
function BrushToolSettings({
|
function BrushToolSettings({
|
||||||
settings,
|
settings,
|
||||||
|
@ -12,7 +12,7 @@ import ShapeTriangleIcon from "../../../icons/ShapeTriangleIcon";
|
|||||||
import UndoButton from "./UndoButton";
|
import UndoButton from "./UndoButton";
|
||||||
import RedoButton from "./RedoButton";
|
import RedoButton from "./RedoButton";
|
||||||
|
|
||||||
import Divider from "./Divider";
|
import Divider from "../../Divider";
|
||||||
|
|
||||||
function ShapeToolSettings({
|
function ShapeToolSettings({
|
||||||
settings,
|
settings,
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
import { Flex } from "theme-ui";
|
import { Flex, IconButton } from "theme-ui";
|
||||||
|
|
||||||
import SunsetDice from "../../../dice/galaxy/GalaxyDice";
|
|
||||||
|
|
||||||
import D20Icon from "../../../icons/D20Icon";
|
import D20Icon from "../../../icons/D20Icon";
|
||||||
import D12Icon from "../../../icons/D12Icon";
|
import D12Icon from "../../../icons/D12Icon";
|
||||||
@ -11,9 +9,19 @@ import D6Icon from "../../../icons/D6Icon";
|
|||||||
import D4Icon from "../../../icons/D4Icon";
|
import D4Icon from "../../../icons/D4Icon";
|
||||||
import D100Icon from "../../../icons/D100Icon";
|
import D100Icon from "../../../icons/D100Icon";
|
||||||
|
|
||||||
|
import SelectDiceIcon from "../../../icons/SelectDiceIcon";
|
||||||
|
import SelectDiceModal from "../../../modals/SelectDiceModal";
|
||||||
|
|
||||||
import DiceButton from "./DiceButton";
|
import DiceButton from "./DiceButton";
|
||||||
|
|
||||||
|
import Divider from "../../Divider";
|
||||||
|
|
||||||
|
import { dice } from "../../../dice";
|
||||||
|
|
||||||
function DiceButtons({ diceRolls, onDiceAdd }) {
|
function DiceButtons({ diceRolls, onDiceAdd }) {
|
||||||
|
const [isSelectModalOpen, setIsSelectModalOpen] = useState(false);
|
||||||
|
const [selectedDice, setSelectedDice] = useState(dice[0]);
|
||||||
|
|
||||||
const diceCounts = {};
|
const diceCounts = {};
|
||||||
for (let dice of diceRolls) {
|
for (let dice of diceRolls) {
|
||||||
if (dice.type in diceCounts) {
|
if (dice.type in diceCounts) {
|
||||||
@ -24,57 +32,82 @@ function DiceButtons({ diceRolls, onDiceAdd }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex sx={{ justifyContent: "center", flexWrap: "wrap", width: "100%" }}>
|
<>
|
||||||
<DiceButton
|
<Flex
|
||||||
title="Add D20"
|
sx={{
|
||||||
count={diceCounts.d20}
|
justifyContent: "center",
|
||||||
onClick={() => onDiceAdd(SunsetDice, "d20")}
|
flexWrap: "wrap",
|
||||||
|
width: "100%",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<D20Icon />
|
<IconButton
|
||||||
</DiceButton>
|
color="hsl(210, 50%, 96%)"
|
||||||
<DiceButton
|
onClick={() => setIsSelectModalOpen(true)}
|
||||||
title="Add D12"
|
>
|
||||||
count={diceCounts.d12}
|
<SelectDiceIcon />
|
||||||
onClick={() => onDiceAdd(SunsetDice, "d12")}
|
</IconButton>
|
||||||
>
|
<Divider vertical color="hsl(210, 50%, 96%)" />
|
||||||
<D12Icon />
|
<DiceButton
|
||||||
</DiceButton>
|
title="Add D20"
|
||||||
<DiceButton
|
count={diceCounts.d20}
|
||||||
title="Add D10"
|
onClick={() => onDiceAdd(selectedDice.class, "d20")}
|
||||||
count={diceCounts.d10}
|
>
|
||||||
onClick={() => onDiceAdd(SunsetDice, "d10")}
|
<D20Icon />
|
||||||
>
|
</DiceButton>
|
||||||
<D10Icon />
|
<DiceButton
|
||||||
</DiceButton>
|
title="Add D12"
|
||||||
<DiceButton
|
count={diceCounts.d12}
|
||||||
title="Add D8"
|
onClick={() => onDiceAdd(selectedDice.class, "d12")}
|
||||||
count={diceCounts.d8}
|
>
|
||||||
onClick={() => onDiceAdd(SunsetDice, "d8")}
|
<D12Icon />
|
||||||
>
|
</DiceButton>
|
||||||
<D8Icon />
|
<DiceButton
|
||||||
</DiceButton>
|
title="Add D10"
|
||||||
<DiceButton
|
count={diceCounts.d10}
|
||||||
title="Add D6"
|
onClick={() => onDiceAdd(selectedDice.class, "d10")}
|
||||||
count={diceCounts.d6}
|
>
|
||||||
onClick={() => onDiceAdd(SunsetDice, "d6")}
|
<D10Icon />
|
||||||
>
|
</DiceButton>
|
||||||
<D6Icon />
|
<DiceButton
|
||||||
</DiceButton>
|
title="Add D8"
|
||||||
<DiceButton
|
count={diceCounts.d8}
|
||||||
title="Add D4"
|
onClick={() => onDiceAdd(selectedDice.class, "d8")}
|
||||||
count={diceCounts.d4}
|
>
|
||||||
onClick={() => onDiceAdd(SunsetDice, "d4")}
|
<D8Icon />
|
||||||
>
|
</DiceButton>
|
||||||
<D4Icon />
|
<DiceButton
|
||||||
</DiceButton>
|
title="Add D6"
|
||||||
<DiceButton
|
count={diceCounts.d6}
|
||||||
title="Add D100"
|
onClick={() => onDiceAdd(selectedDice.class, "d6")}
|
||||||
count={diceCounts.d100}
|
>
|
||||||
onClick={() => onDiceAdd(SunsetDice, "d100")}
|
<D6Icon />
|
||||||
>
|
</DiceButton>
|
||||||
<D100Icon />
|
<DiceButton
|
||||||
</DiceButton>
|
title="Add D4"
|
||||||
</Flex>
|
count={diceCounts.d4}
|
||||||
|
onClick={() => onDiceAdd(selectedDice.class, "d4")}
|
||||||
|
>
|
||||||
|
<D4Icon />
|
||||||
|
</DiceButton>
|
||||||
|
<DiceButton
|
||||||
|
title="Add D100"
|
||||||
|
count={diceCounts.d100}
|
||||||
|
onClick={() => onDiceAdd(selectedDice.class, "d100")}
|
||||||
|
>
|
||||||
|
<D100Icon />
|
||||||
|
</DiceButton>
|
||||||
|
</Flex>
|
||||||
|
<SelectDiceModal
|
||||||
|
isOpen={isSelectModalOpen}
|
||||||
|
onRequestClose={() => setIsSelectModalOpen(false)}
|
||||||
|
defaultDice={selectedDice}
|
||||||
|
onDone={(dice) => {
|
||||||
|
setSelectedDice(dice);
|
||||||
|
setIsSelectModalOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
55
src/components/map/dice/DiceTile.js
Normal file
55
src/components/map/dice/DiceTile.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex, Image, Text } from "theme-ui";
|
||||||
|
|
||||||
|
function DiceTile({ dice, isSelected, onDiceSelect, onDone }) {
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
onClick={() => onDiceSelect(dice)}
|
||||||
|
sx={{
|
||||||
|
borderColor: "primary",
|
||||||
|
borderStyle: isSelected ? "solid" : "none",
|
||||||
|
borderWidth: "4px",
|
||||||
|
position: "relative",
|
||||||
|
width: "150px",
|
||||||
|
height: "150px",
|
||||||
|
borderRadius: "4px",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
m={2}
|
||||||
|
bg="muted"
|
||||||
|
onDoubleClick={() => onDone(dice)}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
sx={{ width: "100%", height: "100%", objectFit: "contain" }}
|
||||||
|
src={dice.preview}
|
||||||
|
/>
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
background:
|
||||||
|
"linear-gradient(to bottom, rgba(0,0,0,0) 70%, rgba(0,0,0,0.65) 100%);",
|
||||||
|
alignItems: "flex-end",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
p={2}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
as="p"
|
||||||
|
variant="heading"
|
||||||
|
color="hsl(210, 50%, 96%)"
|
||||||
|
sx={{ textAlign: "center" }}
|
||||||
|
>
|
||||||
|
{dice.name}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DiceTile;
|
33
src/components/map/dice/DiceTiles.js
Normal file
33
src/components/map/dice/DiceTiles.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex } from "theme-ui";
|
||||||
|
import SimpleBar from "simplebar-react";
|
||||||
|
|
||||||
|
import DiceTile from "./DiceTile";
|
||||||
|
|
||||||
|
function DiceTiles({ dice, onDiceSelect, selectedDice, onDone }) {
|
||||||
|
return (
|
||||||
|
<SimpleBar style={{ maxHeight: "300px", width: "500px" }}>
|
||||||
|
<Flex
|
||||||
|
py={2}
|
||||||
|
bg="muted"
|
||||||
|
sx={{
|
||||||
|
flexWrap: "wrap",
|
||||||
|
width: "500px",
|
||||||
|
borderRadius: "4px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{dice.map((dice) => (
|
||||||
|
<DiceTile
|
||||||
|
key={dice.key}
|
||||||
|
dice={dice}
|
||||||
|
isSelected={selectedDice && dice.key === selectedDice.key}
|
||||||
|
onDiceSelect={onDiceSelect}
|
||||||
|
onDone={onDone}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
</SimpleBar>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DiceTiles;
|
BIN
src/dice/galaxy/preview.png
Normal file
BIN
src/dice/galaxy/preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
40
src/dice/index.js
Normal file
40
src/dice/index.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import Case from "case";
|
||||||
|
|
||||||
|
import GalaxyDice from "./galaxy/GalaxyDice";
|
||||||
|
import IronDice from "./iron/IronDice";
|
||||||
|
import NebulaDice from "./nebula/NebulaDice";
|
||||||
|
import SunriseDice from "./sunrise/SunriseDice";
|
||||||
|
import SunsetDice from "./sunset/SunsetDice";
|
||||||
|
import WalnutDice from "./walnut/WalnutDice";
|
||||||
|
|
||||||
|
import GalaxyPreview from "./galaxy/preview.png";
|
||||||
|
import IronPreview from "./iron/preview.png";
|
||||||
|
import NebulaPreview from "./nebula/preview.png";
|
||||||
|
import SunrisePreview from "./sunrise/preview.png";
|
||||||
|
import SunsetPreview from "./sunset/preview.png";
|
||||||
|
import WalnutPreview from "./walnut/preview.png";
|
||||||
|
|
||||||
|
export const diceClasses = {
|
||||||
|
galaxy: GalaxyDice,
|
||||||
|
nebula: NebulaDice,
|
||||||
|
sunrise: SunriseDice,
|
||||||
|
sunset: SunsetDice,
|
||||||
|
iron: IronDice,
|
||||||
|
walnut: WalnutDice,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const dicePreviews = {
|
||||||
|
galaxy: GalaxyPreview,
|
||||||
|
nebula: NebulaPreview,
|
||||||
|
sunrise: SunrisePreview,
|
||||||
|
sunset: SunsetPreview,
|
||||||
|
iron: IronPreview,
|
||||||
|
walnut: WalnutPreview,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const dice = Object.keys(diceClasses).map((key) => ({
|
||||||
|
key,
|
||||||
|
name: Case.capital(key),
|
||||||
|
class: diceClasses[key],
|
||||||
|
preview: dicePreviews[key],
|
||||||
|
}));
|
BIN
src/dice/iron/preview.png
Normal file
BIN
src/dice/iron/preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
src/dice/nebula/preview.png
Normal file
BIN
src/dice/nebula/preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
src/dice/sunrise/preview.png
Normal file
BIN
src/dice/sunrise/preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
src/dice/sunset/preview.png
Normal file
BIN
src/dice/sunset/preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
src/dice/walnut/preview.png
Normal file
BIN
src/dice/walnut/preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
18
src/icons/SelectDiceIcon.js
Normal file
18
src/icons/SelectDiceIcon.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
function SelectMapIcon() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
fill="currentcolor"
|
||||||
|
>
|
||||||
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SelectMapIcon;
|
35
src/modals/SelectDiceModal.js
Normal file
35
src/modals/SelectDiceModal.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { Flex, Label, Button } from "theme-ui";
|
||||||
|
|
||||||
|
import Modal from "../components/Modal";
|
||||||
|
import DiceTiles from "../components/map/dice/DiceTiles";
|
||||||
|
|
||||||
|
import { dice } from "../dice";
|
||||||
|
|
||||||
|
function SelectDiceModal({ isOpen, onRequestClose, onDone, defaultDice }) {
|
||||||
|
const [selectedDice, setSelectedDice] = useState(defaultDice);
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onRequestClose={onRequestClose}>
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
flexDirection: "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Label pt={2} pb={1}>
|
||||||
|
Select a dice style
|
||||||
|
</Label>
|
||||||
|
<DiceTiles
|
||||||
|
dice={dice}
|
||||||
|
onDiceSelect={setSelectedDice}
|
||||||
|
selectedDice={selectedDice}
|
||||||
|
onDone={onDone}
|
||||||
|
/>
|
||||||
|
<Button my={2} variant="primary" onClick={() => onDone(selectedDice)}>
|
||||||
|
Done
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SelectDiceModal;
|
Loading…
Reference in New Issue
Block a user