Added dice style select

This commit is contained in:
Mitchell McCaffrey 2020-05-26 14:47:37 +10:00
parent c99e5bf5f8
commit 84b198c851
18 changed files with 276 additions and 61 deletions

View File

@ -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;

View File

@ -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";

View File

@ -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,

View File

@ -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 (

View File

@ -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,

View File

@ -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,

View File

@ -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);
}}
/>
</>
); );
} }

View 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;

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

40
src/dice/index.js Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
src/dice/nebula/preview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View 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;

View 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;