Add type to controls and change colour types
This commit is contained in:
parent
72b6994a2e
commit
49b8caa2d7
@ -1,10 +1,17 @@
|
|||||||
import React from "react";
|
|
||||||
import { IconButton } from "theme-ui";
|
import { IconButton } from "theme-ui";
|
||||||
|
|
||||||
import BlendOnIcon from "../../../icons/BlendOnIcon";
|
import BlendOnIcon from "../../../icons/BlendOnIcon";
|
||||||
import BlendOffIcon from "../../../icons/BlendOffIcon";
|
import BlendOffIcon from "../../../icons/BlendOffIcon";
|
||||||
|
|
||||||
function AlphaBlendToggle({ useBlending, onBlendingChange }) {
|
type AlphaBlendToggleProps = {
|
||||||
|
useBlending: boolean;
|
||||||
|
onBlendingChange: (useBlending: boolean) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
function AlphaBlendToggle({
|
||||||
|
useBlending,
|
||||||
|
onBlendingChange,
|
||||||
|
}: AlphaBlendToggleProps) {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label={useBlending ? "Disable Blending (O)" : "Enable Blending (O)"}
|
aria-label={useBlending ? "Disable Blending (O)" : "Enable Blending (O)"}
|
@ -1,10 +1,16 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Box } from "theme-ui";
|
import { Box, SxProp } from "theme-ui";
|
||||||
|
|
||||||
import colors, { colorOptions } from "../../../helpers/colors";
|
import colors, { colorOptions, Color } from "../../../helpers/colors";
|
||||||
import MapMenu from "../MapMenu";
|
import MapMenu from "../MapMenu";
|
||||||
|
|
||||||
function ColorCircle({ color, selected, onClick, sx }) {
|
type ColorCircleProps = {
|
||||||
|
color: Color;
|
||||||
|
selected: boolean;
|
||||||
|
onClick?: React.MouseEventHandler<HTMLDivElement>;
|
||||||
|
} & SxProp;
|
||||||
|
|
||||||
|
function ColorCircle({ color, selected, onClick, sx }: ColorCircleProps) {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
key={color}
|
key={color}
|
||||||
@ -34,24 +40,30 @@ function ColorCircle({ color, selected, onClick, sx }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ColorControl({ color, onColorChange, exclude }) {
|
type ColorControlProps = {
|
||||||
|
color: Color;
|
||||||
|
onColorChange: (newColor: Color) => void;
|
||||||
|
exclude: Color[];
|
||||||
|
};
|
||||||
|
|
||||||
|
function ColorControl({ color, onColorChange, exclude }: ColorControlProps) {
|
||||||
const [showColorMenu, setShowColorMenu] = useState(false);
|
const [showColorMenu, setShowColorMenu] = useState(false);
|
||||||
const [colorMenuOptions, setColorMenuOptions] = useState({});
|
const [colorMenuOptions, setColorMenuOptions] = useState({});
|
||||||
|
|
||||||
function handleControlClick(event) {
|
function handleControlClick(event: React.MouseEvent<HTMLDivElement>) {
|
||||||
if (showColorMenu) {
|
if (showColorMenu) {
|
||||||
setShowColorMenu(false);
|
setShowColorMenu(false);
|
||||||
setColorMenuOptions({});
|
setColorMenuOptions({});
|
||||||
} else {
|
} else {
|
||||||
setShowColorMenu(true);
|
setShowColorMenu(true);
|
||||||
const rect = event.target.getBoundingClientRect();
|
const rect = event.currentTarget.getBoundingClientRect();
|
||||||
setColorMenuOptions({
|
setColorMenuOptions({
|
||||||
// Align the right of the submenu to the left of the tool and center vertically
|
// Align the right of the submenu to the left of the tool and center vertically
|
||||||
left: `${rect.left + rect.width / 2}px`,
|
left: `${rect.left + rect.width / 2}px`,
|
||||||
top: `${rect.bottom + 16}px`,
|
top: `${rect.bottom + 16}px`,
|
||||||
style: { transform: "translateX(-50%)" },
|
style: { transform: "translateX(-50%)" },
|
||||||
// Exclude this node from the sub menus auto close
|
// Exclude this node from the sub menus auto close
|
||||||
excludeNode: event.target,
|
excludeNode: event.currentTarget,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { Flex, IconButton } from "theme-ui";
|
import { Flex, IconButton } from "theme-ui";
|
||||||
import { useMedia } from "react-media";
|
import { useMedia } from "react-media";
|
||||||
|
|
||||||
@ -26,14 +26,23 @@ import { useKeyboard } from "../../../contexts/KeyboardContext";
|
|||||||
|
|
||||||
import shortcuts from "../../../shortcuts";
|
import shortcuts from "../../../shortcuts";
|
||||||
|
|
||||||
|
import { DrawingToolSettings, DrawingToolType } from "../../../types/Drawing";
|
||||||
|
|
||||||
|
type DrawingToolSettingsProps = {
|
||||||
|
settings: DrawingToolSettings;
|
||||||
|
onSettingChange: (change: Partial<DrawingToolSettings>) => void;
|
||||||
|
onToolAction: (action: string) => void;
|
||||||
|
disabledActions: string[];
|
||||||
|
};
|
||||||
|
|
||||||
function DrawingToolSettings({
|
function DrawingToolSettings({
|
||||||
settings,
|
settings,
|
||||||
onSettingChange,
|
onSettingChange,
|
||||||
onToolAction,
|
onToolAction,
|
||||||
disabledActions,
|
disabledActions,
|
||||||
}) {
|
}: DrawingToolSettingsProps) {
|
||||||
// Keyboard shotcuts
|
// Keyboard shotcuts
|
||||||
function handleKeyDown(event) {
|
function handleKeyDown(event: KeyboardEvent) {
|
||||||
if (shortcuts.drawBrush(event)) {
|
if (shortcuts.drawBrush(event)) {
|
||||||
onSettingChange({ type: "brush" });
|
onSettingChange({ type: "brush" });
|
||||||
} else if (shortcuts.drawPaint(event)) {
|
} else if (shortcuts.drawPaint(event)) {
|
||||||
@ -115,7 +124,9 @@ function DrawingToolSettings({
|
|||||||
<Divider vertical />
|
<Divider vertical />
|
||||||
<ToolSection
|
<ToolSection
|
||||||
tools={tools}
|
tools={tools}
|
||||||
onToolClick={(tool) => onSettingChange({ type: tool.id })}
|
onToolClick={(tool) =>
|
||||||
|
onSettingChange({ type: tool.id as DrawingToolType })
|
||||||
|
}
|
||||||
collapse={isSmallScreen}
|
collapse={isSmallScreen}
|
||||||
/>
|
/>
|
||||||
<Divider vertical />
|
<Divider vertical />
|
@ -1,10 +1,19 @@
|
|||||||
import React from "react";
|
|
||||||
import { IconButton } from "theme-ui";
|
import { IconButton } from "theme-ui";
|
||||||
|
|
||||||
import CutOnIcon from "../../../icons/FogCutOnIcon";
|
import CutOnIcon from "../../../icons/FogCutOnIcon";
|
||||||
import CutOffIcon from "../../../icons/FogCutOffIcon";
|
import CutOffIcon from "../../../icons/FogCutOffIcon";
|
||||||
|
|
||||||
function FogCutToggle({ useFogCut, onFogCutChange, disabled }) {
|
type FogCutToggleProps = {
|
||||||
|
useFogCut: boolean;
|
||||||
|
onFogCutChange: (useFogCut: boolean) => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
function FogCutToggle({
|
||||||
|
useFogCut,
|
||||||
|
onFogCutChange,
|
||||||
|
disabled,
|
||||||
|
}: FogCutToggleProps) {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label={
|
aria-label={
|
@ -1,10 +1,17 @@
|
|||||||
import React from "react";
|
|
||||||
import { IconButton } from "theme-ui";
|
import { IconButton } from "theme-ui";
|
||||||
|
|
||||||
import PreviewOnIcon from "../../../icons/FogPreviewOnIcon";
|
import PreviewOnIcon from "../../../icons/FogPreviewOnIcon";
|
||||||
import PreviewOffIcon from "../../../icons/FogPreviewOffIcon";
|
import PreviewOffIcon from "../../../icons/FogPreviewOffIcon";
|
||||||
|
|
||||||
function FogPreviewToggle({ useFogPreview, onFogPreviewChange }) {
|
type FogPreviewToggleProps = {
|
||||||
|
useFogPreview: boolean;
|
||||||
|
onFogPreviewChange: (useFogCut: boolean) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
function FogPreviewToggle({
|
||||||
|
useFogPreview,
|
||||||
|
onFogPreviewChange,
|
||||||
|
}: FogPreviewToggleProps) {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label={
|
aria-label={
|
@ -1,4 +1,3 @@
|
|||||||
import React from "react";
|
|
||||||
import { Flex } from "theme-ui";
|
import { Flex } from "theme-ui";
|
||||||
import { useMedia } from "react-media";
|
import { useMedia } from "react-media";
|
||||||
|
|
||||||
@ -24,14 +23,23 @@ import { useKeyboard } from "../../../contexts/KeyboardContext";
|
|||||||
|
|
||||||
import shortcuts from "../../../shortcuts";
|
import shortcuts from "../../../shortcuts";
|
||||||
|
|
||||||
function BrushToolSettings({
|
import { FogToolSettings, FogToolType } from "../../../types/Fog";
|
||||||
|
|
||||||
|
type FogToolSettingsProps = {
|
||||||
|
settings: FogToolSettings;
|
||||||
|
onSettingChange: (change: Partial<FogToolSettings>) => void;
|
||||||
|
onToolAction: (action: string) => void;
|
||||||
|
disabledActions: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
function FogToolSettings({
|
||||||
settings,
|
settings,
|
||||||
onSettingChange,
|
onSettingChange,
|
||||||
onToolAction,
|
onToolAction,
|
||||||
disabledActions,
|
disabledActions,
|
||||||
}) {
|
}: FogToolSettingsProps) {
|
||||||
// Keyboard shortcuts
|
// Keyboard shortcuts
|
||||||
function handleKeyDown(event) {
|
function handleKeyDown(event: KeyboardEvent) {
|
||||||
if (shortcuts.fogPolygon(event)) {
|
if (shortcuts.fogPolygon(event)) {
|
||||||
onSettingChange({ type: "polygon" });
|
onSettingChange({ type: "polygon" });
|
||||||
} else if (shortcuts.fogBrush(event)) {
|
} else if (shortcuts.fogBrush(event)) {
|
||||||
@ -86,7 +94,9 @@ function BrushToolSettings({
|
|||||||
<Flex sx={{ alignItems: "center" }}>
|
<Flex sx={{ alignItems: "center" }}>
|
||||||
<ToolSection
|
<ToolSection
|
||||||
tools={drawTools}
|
tools={drawTools}
|
||||||
onToolClick={(tool) => onSettingChange({ type: tool.id })}
|
onToolClick={(tool) =>
|
||||||
|
onSettingChange({ type: tool.id as FogToolType })
|
||||||
|
}
|
||||||
collapse={isSmallScreen}
|
collapse={isSmallScreen}
|
||||||
/>
|
/>
|
||||||
<Divider vertical />
|
<Divider vertical />
|
||||||
@ -134,4 +144,4 @@ function BrushToolSettings({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BrushToolSettings;
|
export default FogToolSettings;
|
@ -1,10 +1,19 @@
|
|||||||
import React from "react";
|
|
||||||
import { IconButton } from "theme-ui";
|
import { IconButton } from "theme-ui";
|
||||||
|
|
||||||
import MultilayerOnIcon from "../../../icons/FogMultilayerOnIcon";
|
import MultilayerOnIcon from "../../../icons/FogMultilayerOnIcon";
|
||||||
import MultilayerOffIcon from "../../../icons/FogMultilayerOffIcon";
|
import MultilayerOffIcon from "../../../icons/FogMultilayerOffIcon";
|
||||||
|
|
||||||
function MultilayerToggle({ multilayer, onMultilayerChange, disabled }) {
|
type MultilayerToggleProps = {
|
||||||
|
multilayer: boolean;
|
||||||
|
onMultilayerChange: (multilayer: boolean) => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
function MultilayerToggle({
|
||||||
|
multilayer,
|
||||||
|
onMultilayerChange,
|
||||||
|
disabled,
|
||||||
|
}: MultilayerToggleProps) {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label={
|
aria-label={
|
@ -1,9 +1,18 @@
|
|||||||
import React from "react";
|
|
||||||
import { Flex } from "theme-ui";
|
import { Flex } from "theme-ui";
|
||||||
|
|
||||||
import ColorControl from "./ColorControl";
|
import ColorControl from "./ColorControl";
|
||||||
|
|
||||||
function PointerToolSettings({ settings, onSettingChange }) {
|
import { PointerToolSettings } from "../../../types/Pointer";
|
||||||
|
|
||||||
|
type PointerToolSettingsProps = {
|
||||||
|
settings: PointerToolSettings;
|
||||||
|
onSettingChange: (change: Partial<PointerToolSettings>) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
function PointerToolSettings({
|
||||||
|
settings,
|
||||||
|
onSettingChange,
|
||||||
|
}: PointerToolSettingsProps) {
|
||||||
return (
|
return (
|
||||||
<Flex sx={{ alignItems: "center" }}>
|
<Flex sx={{ alignItems: "center" }}>
|
||||||
<ColorControl
|
<ColorControl
|
@ -5,7 +5,12 @@ import RedoIcon from "../../../icons/RedoIcon";
|
|||||||
|
|
||||||
import { isMacLike } from "../../../helpers/shared";
|
import { isMacLike } from "../../../helpers/shared";
|
||||||
|
|
||||||
function RedoButton({ onClick, disabled }) {
|
type RedoButtonProps = {
|
||||||
|
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
|
disabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
function RedoButton({ onClick, disabled }: RedoButtonProps) {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
title={`Redo (${isMacLike ? "Cmd" : "Ctrl"} + Shift + Z)`}
|
title={`Redo (${isMacLike ? "Cmd" : "Ctrl"} + Shift + Z)`}
|
@ -3,10 +3,24 @@ import { Box, Flex } from "theme-ui";
|
|||||||
|
|
||||||
import RadioIconButton from "../../RadioIconButton";
|
import RadioIconButton from "../../RadioIconButton";
|
||||||
|
|
||||||
|
export type Tool = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
isSelected: boolean;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
disabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ToolSectionProps = {
|
||||||
|
collapse: boolean;
|
||||||
|
tools: Tool[];
|
||||||
|
onToolClick: (tool: Tool) => void;
|
||||||
|
};
|
||||||
|
|
||||||
// Section of map tools with the option to collapse into a vertical list
|
// Section of map tools with the option to collapse into a vertical list
|
||||||
function ToolSection({ collapse, tools, onToolClick }) {
|
function ToolSection({ collapse, tools, onToolClick }: ToolSectionProps) {
|
||||||
const [showMore, setShowMore] = useState(false);
|
const [showMore, setShowMore] = useState(false);
|
||||||
const [collapsedTool, setCollapsedTool] = useState();
|
const [collapsedTool, setCollapsedTool] = useState<Tool>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const selectedTool = tools.find((tool) => tool.isSelected);
|
const selectedTool = tools.find((tool) => tool.isSelected);
|
||||||
@ -20,7 +34,7 @@ function ToolSection({ collapse, tools, onToolClick }) {
|
|||||||
}
|
}
|
||||||
}, [tools]);
|
}, [tools]);
|
||||||
|
|
||||||
function handleToolClick(tool) {
|
function handleToolClick(tool: Tool) {
|
||||||
if (collapse && tool.isSelected) {
|
if (collapse && tool.isSelected) {
|
||||||
setShowMore(!showMore);
|
setShowMore(!showMore);
|
||||||
} else if (collapse && !tool.isSelected) {
|
} else if (collapse && !tool.isSelected) {
|
||||||
@ -29,7 +43,7 @@ function ToolSection({ collapse, tools, onToolClick }) {
|
|||||||
onToolClick(tool);
|
onToolClick(tool);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderTool(tool) {
|
function renderTool(tool: Tool) {
|
||||||
return (
|
return (
|
||||||
<RadioIconButton
|
<RadioIconButton
|
||||||
title={tool.title}
|
title={tool.title}
|
||||||
@ -85,7 +99,9 @@ function ToolSection({ collapse, tools, onToolClick }) {
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return tools.map((tool) => (
|
return (
|
||||||
|
<>
|
||||||
|
{tools.map((tool) => (
|
||||||
<RadioIconButton
|
<RadioIconButton
|
||||||
title={tool.title}
|
title={tool.title}
|
||||||
onClick={() => handleToolClick(tool)}
|
onClick={() => handleToolClick(tool)}
|
||||||
@ -95,7 +111,9 @@ function ToolSection({ collapse, tools, onToolClick }) {
|
|||||||
>
|
>
|
||||||
{tool.icon}
|
{tool.icon}
|
||||||
</RadioIconButton>
|
</RadioIconButton>
|
||||||
));
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,12 @@ import UndoIcon from "../../../icons/UndoIcon";
|
|||||||
|
|
||||||
import { isMacLike } from "../../../helpers/shared";
|
import { isMacLike } from "../../../helpers/shared";
|
||||||
|
|
||||||
function UndoButton({ onClick, disabled }) {
|
type UndoButtonProps = {
|
||||||
|
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
|
disabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
function UndoButton({ onClick, disabled }: UndoButtonProps) {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
title={`Undo (${isMacLike ? "Cmd" : "Ctrl"} + Z)`}
|
title={`Undo (${isMacLike ? "Cmd" : "Ctrl"} + Z)`}
|
@ -206,7 +206,7 @@ export function GroupProvider({
|
|||||||
/**
|
/**
|
||||||
* Shortcuts
|
* Shortcuts
|
||||||
*/
|
*/
|
||||||
function handleKeyDown(event: React.KeyboardEvent) {
|
function handleKeyDown(event: KeyboardEvent) {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -218,7 +218,7 @@ export function GroupProvider({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKeyUp(event: React.KeyboardEvent) {
|
function handleKeyUp(event: KeyboardEvent) {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import { EventEmitter } from "events";
|
|||||||
|
|
||||||
const KeyboardContext = React.createContext({ keyEmitter: new EventEmitter() });
|
const KeyboardContext = React.createContext({ keyEmitter: new EventEmitter() });
|
||||||
|
|
||||||
export function KeyboardProvider({ children }: { children: any}) {
|
export function KeyboardProvider({ children }: { children: React.ReactNode }) {
|
||||||
const [keyEmitter] = useState(new EventEmitter());
|
const [keyEmitter] = useState(new EventEmitter());
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function handleKeyDown(event: Event) {
|
function handleKeyDown(event: Event) {
|
||||||
@ -45,11 +45,10 @@ export function KeyboardProvider({ children }: { children: any}) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export function useKeyboard(
|
||||||
* @param {KeyboardEvent} onKeyDown
|
onKeyDown?: (event: KeyboardEvent) => void,
|
||||||
* @param {KeyboardEvent} onKeyUp
|
onKeyUp?: (event: KeyboardEvent) => void
|
||||||
*/
|
) {
|
||||||
export function useKeyboard(onKeyDown: (...args: any[]) => void, onKeyUp: (...args: any[]) => void) {
|
|
||||||
const context = useContext(KeyboardContext);
|
const context = useContext(KeyboardContext);
|
||||||
if (context === undefined) {
|
if (context === undefined) {
|
||||||
throw new Error("useKeyboard must be used within a KeyboardProvider");
|
throw new Error("useKeyboard must be used within a KeyboardProvider");
|
||||||
|
@ -1,20 +1,5 @@
|
|||||||
export type Colors = {
|
|
||||||
blue: string;
|
|
||||||
orange: string;
|
|
||||||
red: string;
|
|
||||||
yellow: string;
|
|
||||||
purple: string;
|
|
||||||
green: string;
|
|
||||||
pink: string;
|
|
||||||
teal: string;
|
|
||||||
black: string;
|
|
||||||
darkGray: string;
|
|
||||||
lightGray: string;
|
|
||||||
white: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Colors used for the game for theme general UI colors look at theme.js
|
// Colors used for the game for theme general UI colors look at theme.js
|
||||||
const colors: Colors = {
|
const colors = {
|
||||||
blue: "rgb(26, 106, 255)",
|
blue: "rgb(26, 106, 255)",
|
||||||
orange: "rgb(255, 116, 51)",
|
orange: "rgb(255, 116, 51)",
|
||||||
red: "rgb(255, 77, 77)",
|
red: "rgb(255, 77, 77)",
|
||||||
@ -29,6 +14,10 @@ const colors: Colors = {
|
|||||||
white: "rgb(255, 255, 255)",
|
white: "rgb(255, 255, 255)",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const colorOptions = Object.keys(colors);
|
export type Colors = typeof colors;
|
||||||
|
|
||||||
|
export type Color = keyof Colors;
|
||||||
|
|
||||||
|
export const colorOptions = Object.keys(colors) as Color[];
|
||||||
|
|
||||||
export default colors;
|
export default colors;
|
||||||
|
@ -30,12 +30,15 @@ import { useAssets } from "../contexts/AssetsContext";
|
|||||||
import { GroupProvider } from "../contexts/GroupContext";
|
import { GroupProvider } from "../contexts/GroupContext";
|
||||||
import { TileDragProvider } from "../contexts/TileDragContext";
|
import { TileDragProvider } from "../contexts/TileDragContext";
|
||||||
|
|
||||||
|
import { Map } from "../types/Map";
|
||||||
|
import { MapState } from "../types/MapState";
|
||||||
|
|
||||||
type SelectMapProps = {
|
type SelectMapProps = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onDone: any;
|
onDone: () => void;
|
||||||
onMapChange: any;
|
onMapChange: (map?: Map, mapState?: MapState) => void;
|
||||||
onMapReset: any;
|
onMapReset: (newState: MapState) => void;
|
||||||
currentMap: any;
|
currentMap?: Map;
|
||||||
};
|
};
|
||||||
|
|
||||||
function SelectMapModal({
|
function SelectMapModal({
|
||||||
@ -79,9 +82,9 @@ function SelectMapModal({
|
|||||||
|
|
||||||
const [isLargeImageWarningModalOpen, setShowLargeImageWarning] =
|
const [isLargeImageWarningModalOpen, setShowLargeImageWarning] =
|
||||||
useState(false);
|
useState(false);
|
||||||
const largeImageWarningFiles = useRef<any>();
|
const largeImageWarningFiles = useRef<File[]>();
|
||||||
|
|
||||||
async function handleImagesUpload(files: any) {
|
async function handleImagesUpload(files: File[]) {
|
||||||
if (navigator.storage) {
|
if (navigator.storage) {
|
||||||
// Attempt to enable persistant storage
|
// Attempt to enable persistant storage
|
||||||
await navigator.storage.persist();
|
await navigator.storage.persist();
|
||||||
@ -132,9 +135,11 @@ function SelectMapModal({
|
|||||||
async function handleLargeImageWarningConfirm() {
|
async function handleLargeImageWarningConfirm() {
|
||||||
setShowLargeImageWarning(false);
|
setShowLargeImageWarning(false);
|
||||||
const files = largeImageWarningFiles.current;
|
const files = largeImageWarningFiles.current;
|
||||||
|
if (files) {
|
||||||
for (let file of files) {
|
for (let file of files) {
|
||||||
await handleImageUpload(file);
|
await handleImageUpload(file);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
largeImageWarningFiles.current = undefined;
|
largeImageWarningFiles.current = undefined;
|
||||||
clearFileInput();
|
clearFileInput();
|
||||||
}
|
}
|
||||||
@ -171,7 +176,7 @@ function SelectMapModal({
|
|||||||
onMapChange(map, mapState);
|
onMapChange(map, mapState);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
} else {
|
} else {
|
||||||
onMapChange(null, null);
|
onMapChange(undefined, undefined);
|
||||||
}
|
}
|
||||||
onDone();
|
onDone();
|
||||||
}
|
}
|
||||||
@ -220,9 +225,15 @@ function SelectMapModal({
|
|||||||
}}
|
}}
|
||||||
shouldCloseOnEsc={!isDraggingMap}
|
shouldCloseOnEsc={!isDraggingMap}
|
||||||
>
|
>
|
||||||
<ImageDrop onDrop={handleImagesUpload} dropText="Drop map to import">
|
<ImageDrop
|
||||||
|
onDrop={({ files }) => handleImagesUpload(files)}
|
||||||
|
dropText="Drop map to import"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
onChange={(event) => handleImagesUpload(event.target.files)}
|
onChange={(event) =>
|
||||||
|
event.target.files &&
|
||||||
|
handleImagesUpload(Array.from(event.target.files))
|
||||||
|
}
|
||||||
type="file"
|
type="file"
|
||||||
accept="image/jpeg, image/gif, image/png, image/webp"
|
accept="image/jpeg, image/gif, image/png, image/webp"
|
||||||
style={{ display: "none" }}
|
style={{ display: "none" }}
|
||||||
|
@ -79,7 +79,7 @@ function SelectTokensModal({
|
|||||||
useState(false);
|
useState(false);
|
||||||
const largeImageWarningFiles = useRef<File[]>();
|
const largeImageWarningFiles = useRef<File[]>();
|
||||||
|
|
||||||
async function handleImagesUpload(files: FileList) {
|
async function handleImagesUpload(files: File[]) {
|
||||||
if (navigator.storage) {
|
if (navigator.storage) {
|
||||||
// Attempt to enable persistant storage
|
// Attempt to enable persistant storage
|
||||||
await navigator.storage.persist();
|
await navigator.storage.persist();
|
||||||
@ -231,10 +231,14 @@ function SelectTokensModal({
|
|||||||
}}
|
}}
|
||||||
shouldCloseOnEsc={!isDraggingToken}
|
shouldCloseOnEsc={!isDraggingToken}
|
||||||
>
|
>
|
||||||
<ImageDrop onDrop={handleImagesUpload} dropText="Drop token to import">
|
<ImageDrop
|
||||||
|
onDrop={({ files }) => handleImagesUpload(files)}
|
||||||
|
dropText="Drop token to import"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
onChange={(event) =>
|
||||||
event.target.files && handleImagesUpload(event.target.files)
|
event.target.files &&
|
||||||
|
handleImagesUpload(Array.from(event.target.files))
|
||||||
}
|
}
|
||||||
type="file"
|
type="file"
|
||||||
accept="image/jpeg, image/gif, image/png, image/webp"
|
accept="image/jpeg, image/gif, image/png, image/webp"
|
||||||
|
@ -19,96 +19,76 @@ function singleKey(event: KeyboardEvent, key: string): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function undo(event: KeyboardEvent): boolean {
|
||||||
* @param {Keyboard} event
|
|
||||||
* @returns {string | boolean}
|
|
||||||
*/
|
|
||||||
function undo(event: KeyboardEvent): string | boolean {
|
|
||||||
const { key, ctrlKey, metaKey, shiftKey } = event;
|
const { key, ctrlKey, metaKey, shiftKey } = event;
|
||||||
return (key === "z" || key === "Z") && (ctrlKey || metaKey) && !shiftKey;
|
return (key === "z" || key === "Z") && (ctrlKey || metaKey) && !shiftKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function redo(event: KeyboardEvent): boolean {
|
||||||
* @param {Keyboard} event
|
|
||||||
* @returns {string | boolean}
|
|
||||||
*/
|
|
||||||
function redo(event: KeyboardEvent): string | boolean {
|
|
||||||
const { key, ctrlKey, metaKey, shiftKey } = event;
|
const { key, ctrlKey, metaKey, shiftKey } = event;
|
||||||
return (key === "z" || key === "Z") && (ctrlKey || metaKey) && shiftKey;
|
return (key === "z" || key === "Z") && (ctrlKey || metaKey) && shiftKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function zoomIn(event: KeyboardEvent): boolean {
|
||||||
* @param {Keyboard} event
|
|
||||||
* @returns {string | boolean}
|
|
||||||
*/
|
|
||||||
function zoomIn(event: KeyboardEvent): string | boolean {
|
|
||||||
const { key, ctrlKey, metaKey } = event;
|
const { key, ctrlKey, metaKey } = event;
|
||||||
return (key === "=" || key === "+") && !ctrlKey && !metaKey;
|
return (key === "=" || key === "+") && !ctrlKey && !metaKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function zoomOut(event: KeyboardEvent): boolean {
|
||||||
* @param {Keyboard} event
|
|
||||||
* @returns {string | boolean}
|
|
||||||
*/
|
|
||||||
function zoomOut(event: KeyboardEvent): string | boolean {
|
|
||||||
const { key, ctrlKey, metaKey } = event;
|
const { key, ctrlKey, metaKey } = event;
|
||||||
return (key === "-" || key === "_") && !ctrlKey && !metaKey;
|
return (key === "-" || key === "_") && !ctrlKey && !metaKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
type Shortcut = (event: KeyboardEvent) => boolean;
|
||||||
* @callback shortcut
|
|
||||||
* @param {KeyboardEvent} event
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {Object.<string, shortcut>}
|
* @type {Object.<string, shortcut>}
|
||||||
*/
|
*/
|
||||||
const shortcuts = {
|
const shortcuts: Record<string, Shortcut> = {
|
||||||
// Tools
|
// Tools
|
||||||
move: (event: KeyboardEvent) => singleKey(event, " "),
|
move: (event) => singleKey(event, " "),
|
||||||
moveTool: (event: KeyboardEvent) => singleKey(event, "w"),
|
moveTool: (event) => singleKey(event, "w"),
|
||||||
drawingTool: (event: KeyboardEvent) => singleKey(event, "d"),
|
drawingTool: (event) => singleKey(event, "d"),
|
||||||
fogTool: (event: KeyboardEvent) => singleKey(event, "f"),
|
fogTool: (event) => singleKey(event, "f"),
|
||||||
measureTool: (event: KeyboardEvent) => singleKey(event, "m"),
|
measureTool: (event) => singleKey(event, "m"),
|
||||||
pointerTool: (event: KeyboardEvent) => singleKey(event, "q"),
|
pointerTool: (event) => singleKey(event, "q"),
|
||||||
noteTool: (event: KeyboardEvent) => singleKey(event, "n"),
|
noteTool: (event) => singleKey(event, "n"),
|
||||||
// Map editor
|
// Map editor
|
||||||
gridNudgeUp: ({ key }: { key: string}) => key === "ArrowUp",
|
gridNudgeUp: ({ key }) => key === "ArrowUp",
|
||||||
gridNudgeLeft: ({ key }: { key: string }) => key === "ArrowLeft",
|
gridNudgeLeft: ({ key }) => key === "ArrowLeft",
|
||||||
gridNudgeRight: ({ key }: { key: string }) => key === "ArrowRight",
|
gridNudgeRight: ({ key }) => key === "ArrowRight",
|
||||||
gridNudgeDown: ({ key }: { key: string }) => key === "ArrowDown",
|
gridNudgeDown: ({ key }) => key === "ArrowDown",
|
||||||
// Drawing tool
|
// Drawing tool
|
||||||
drawBrush: (event: KeyboardEvent) => singleKey(event, "b"),
|
drawBrush: (event) => singleKey(event, "b"),
|
||||||
drawPaint: (event: KeyboardEvent) => singleKey(event, "p"),
|
drawPaint: (event) => singleKey(event, "p"),
|
||||||
drawLine: (event: KeyboardEvent) => singleKey(event, "l"),
|
drawLine: (event) => singleKey(event, "l"),
|
||||||
drawRect: (event: KeyboardEvent) => singleKey(event, "r"),
|
drawRect: (event) => singleKey(event, "r"),
|
||||||
drawCircle: (event: KeyboardEvent) => singleKey(event, "c"),
|
drawCircle: (event) => singleKey(event, "c"),
|
||||||
drawTriangle: (event: KeyboardEvent) => singleKey(event, "t"),
|
drawTriangle: (event) => singleKey(event, "t"),
|
||||||
drawErase: (event: KeyboardEvent) => singleKey(event, "e"),
|
drawErase: (event) => singleKey(event, "e"),
|
||||||
drawBlend: (event: KeyboardEvent) => singleKey(event, "o"),
|
drawBlend: (event) => singleKey(event, "o"),
|
||||||
// Fog tool
|
// Fog tool
|
||||||
fogPolygon: (event: KeyboardEvent) => singleKey(event, "p"),
|
fogPolygon: (event) => singleKey(event, "p"),
|
||||||
fogRectangle: (event: KeyboardEvent) => singleKey(event, "r"),
|
fogRectangle: (event) => singleKey(event, "r"),
|
||||||
fogBrush: (event: KeyboardEvent) => singleKey(event, "b"),
|
fogBrush: (event) => singleKey(event, "b"),
|
||||||
fogToggle: (event: KeyboardEvent) => singleKey(event, "t"),
|
fogToggle: (event) => singleKey(event, "t"),
|
||||||
fogErase: (event: KeyboardEvent) => singleKey(event, "e"),
|
fogErase: (event) => singleKey(event, "e"),
|
||||||
fogLayer: (event: KeyboardEvent) => singleKey(event, "l"),
|
fogLayer: (event) => singleKey(event, "l"),
|
||||||
fogPreview: (event: KeyboardEvent) => singleKey(event, "f"),
|
fogPreview: (event) => singleKey(event, "f"),
|
||||||
fogCut: (event: KeyboardEvent) => singleKey(event, "c"),
|
fogCut: (event) => singleKey(event, "c"),
|
||||||
fogFinishPolygon: ({ key }: { key: string }) => key === "Enter",
|
fogFinishPolygon: ({ key }) => key === "Enter",
|
||||||
fogCancelPolygon: ({ key }: { key: string }) => key === "Escape",
|
fogCancelPolygon: ({ key }) => key === "Escape",
|
||||||
// Stage interaction
|
// Stage interaction
|
||||||
stageZoomIn: zoomIn,
|
stageZoomIn: zoomIn,
|
||||||
stageZoomOut: zoomOut,
|
stageZoomOut: zoomOut,
|
||||||
stagePrecisionZoom: ({ key }: { key: string }) => key === "Shift",
|
stagePrecisionZoom: ({ key }) => key === "Shift",
|
||||||
// Select
|
// Select
|
||||||
selectRange: ({ key }: { key: string }) => key === "Shift",
|
selectRange: ({ key }) => key === "Shift",
|
||||||
selectMultiple: ({ key }: { key: string }) => key === "Control" || key === "Meta",
|
selectMultiple: ({ key }) => key === "Control" || key === "Meta",
|
||||||
// Common
|
// Common
|
||||||
undo,
|
undo,
|
||||||
redo,
|
redo,
|
||||||
delete: ({ key }: { key: string }) => key === "Backspace" || key === "Delete",
|
delete: ({ key }) => key === "Backspace" || key === "Delete",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default shortcuts;
|
export default shortcuts;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import Vector2 from "../helpers/Vector2";
|
import Vector2 from "../helpers/Vector2";
|
||||||
|
import { Color } from "../helpers/colors";
|
||||||
|
|
||||||
export type DrawingToolType =
|
export type DrawingToolType =
|
||||||
| "brush"
|
| "brush"
|
||||||
@ -11,7 +12,7 @@ export type DrawingToolType =
|
|||||||
|
|
||||||
export type DrawingToolSettings = {
|
export type DrawingToolSettings = {
|
||||||
type: DrawingToolType;
|
type: DrawingToolType;
|
||||||
color: string;
|
color: Color;
|
||||||
useBlending: boolean;
|
useBlending: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import Vector2 from "../helpers/Vector2";
|
import Vector2 from "../helpers/Vector2";
|
||||||
|
import { Color } from "../helpers/colors";
|
||||||
|
|
||||||
export type FogToolType =
|
export type FogToolType =
|
||||||
| "polygon"
|
| "polygon"
|
||||||
@ -20,7 +21,7 @@ export type FogData = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Fog = {
|
export type Fog = {
|
||||||
color: string;
|
color: Color;
|
||||||
data: FogData;
|
data: FogData;
|
||||||
id: string;
|
id: string;
|
||||||
strokeWidth: number;
|
strokeWidth: number;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
import { Color } from "../helpers/colors";
|
||||||
|
|
||||||
export type Note = {
|
export type Note = {
|
||||||
id: string;
|
id: string;
|
||||||
color: string;
|
color: Color;
|
||||||
lastModified: number;
|
lastModified: number;
|
||||||
lastModifiedBy: string;
|
lastModifiedBy: string;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import Vector2 from "../helpers/Vector2";
|
import Vector2 from "../helpers/Vector2";
|
||||||
|
import { Color } from "../helpers/colors";
|
||||||
|
|
||||||
export type PointerToolSettings = {
|
export type PointerToolSettings = {
|
||||||
color: string;
|
color: Color;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PointerState = {
|
export type PointerState = {
|
||||||
position: Vector2;
|
position: Vector2;
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
id: string;
|
id: string;
|
||||||
color: string;
|
color: Color;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user