Refactored keyboard shortcuts to be global and not dependent on map interaction
This commit is contained in:
parent
670f047049
commit
b7a89a4a4a
61
src/App.js
61
src/App.js
|
@ -15,7 +15,8 @@ import { DatabaseProvider } from "./contexts/DatabaseContext";
|
|||
import { MapDataProvider } from "./contexts/MapDataContext";
|
||||
import { TokenDataProvider } from "./contexts/TokenDataContext";
|
||||
import { MapLoadingProvider } from "./contexts/MapLoadingContext";
|
||||
import { SettingsProvider } from "./contexts/SettingsContext.js";
|
||||
import { SettingsProvider } from "./contexts/SettingsContext";
|
||||
import { KeyboardProvider } from "./contexts/KeyboardContext";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
|
@ -23,34 +24,36 @@ function App() {
|
|||
<DatabaseProvider>
|
||||
<SettingsProvider>
|
||||
<AuthProvider>
|
||||
<Router>
|
||||
<Switch>
|
||||
<Route path="/howTo">
|
||||
<HowTo />
|
||||
</Route>
|
||||
<Route path="/releaseNotes">
|
||||
<ReleaseNotes />
|
||||
</Route>
|
||||
<Route path="/about">
|
||||
<About />
|
||||
</Route>
|
||||
<Route path="/faq">
|
||||
<FAQ />
|
||||
</Route>
|
||||
<Route path="/game/:id">
|
||||
<MapLoadingProvider>
|
||||
<MapDataProvider>
|
||||
<TokenDataProvider>
|
||||
<Game />
|
||||
</TokenDataProvider>
|
||||
</MapDataProvider>
|
||||
</MapLoadingProvider>
|
||||
</Route>
|
||||
<Route path="/">
|
||||
<Home />
|
||||
</Route>
|
||||
</Switch>
|
||||
</Router>
|
||||
<KeyboardProvider>
|
||||
<Router>
|
||||
<Switch>
|
||||
<Route path="/howTo">
|
||||
<HowTo />
|
||||
</Route>
|
||||
<Route path="/releaseNotes">
|
||||
<ReleaseNotes />
|
||||
</Route>
|
||||
<Route path="/about">
|
||||
<About />
|
||||
</Route>
|
||||
<Route path="/faq">
|
||||
<FAQ />
|
||||
</Route>
|
||||
<Route path="/game/:id">
|
||||
<MapLoadingProvider>
|
||||
<MapDataProvider>
|
||||
<TokenDataProvider>
|
||||
<Game />
|
||||
</TokenDataProvider>
|
||||
</MapDataProvider>
|
||||
</MapLoadingProvider>
|
||||
</Route>
|
||||
<Route path="/">
|
||||
<Home />
|
||||
</Route>
|
||||
</Switch>
|
||||
</Router>
|
||||
</KeyboardProvider>
|
||||
</AuthProvider>
|
||||
</SettingsProvider>
|
||||
</DatabaseProvider>
|
||||
|
|
|
@ -20,6 +20,7 @@ import {
|
|||
getRelativePointerPositionNormalized,
|
||||
Tick,
|
||||
} from "../../helpers/konva";
|
||||
import useKeyboard from "../../helpers/useKeyboard";
|
||||
|
||||
function MapFog({
|
||||
map,
|
||||
|
@ -248,44 +249,37 @@ function MapFog({
|
|||
}, [toolSettings, drawingShape, onShapeSubtract, onShapeAdd]);
|
||||
|
||||
// Add keyboard shortcuts
|
||||
useEffect(() => {
|
||||
function handleKeyDown({ key }) {
|
||||
if (key === "Enter" && toolSettings.type === "polygon" && drawingShape) {
|
||||
finishDrawingPolygon();
|
||||
}
|
||||
if (key === "Escape" && drawingShape) {
|
||||
setDrawingShape(null);
|
||||
}
|
||||
if (key === "Alt" && drawingShape) {
|
||||
updateShapeColor();
|
||||
}
|
||||
function handleKeyDown({ key }) {
|
||||
if (key === "Enter" && toolSettings.type === "polygon" && drawingShape) {
|
||||
finishDrawingPolygon();
|
||||
}
|
||||
if (key === "Escape" && drawingShape) {
|
||||
setDrawingShape(null);
|
||||
}
|
||||
if (key === "Alt" && drawingShape) {
|
||||
updateShapeColor();
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyUp({ key }) {
|
||||
if (key === "Alt" && drawingShape) {
|
||||
updateShapeColor();
|
||||
function handleKeyUp({ key }) {
|
||||
if (key === "Alt" && drawingShape) {
|
||||
updateShapeColor();
|
||||
}
|
||||
}
|
||||
|
||||
function updateShapeColor() {
|
||||
setDrawingShape((prevShape) => {
|
||||
if (!prevShape) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return {
|
||||
...prevShape,
|
||||
color: toolSettings.useFogSubtract ? "black" : "red",
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function updateShapeColor() {
|
||||
setDrawingShape((prevShape) => {
|
||||
if (!prevShape) {
|
||||
return;
|
||||
}
|
||||
return {
|
||||
...prevShape,
|
||||
color: toolSettings.useFogSubtract ? "black" : "red",
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
interactionEmitter.on("keyDown", handleKeyDown);
|
||||
interactionEmitter.on("keyUp", handleKeyUp);
|
||||
return () => {
|
||||
interactionEmitter.off("keyDown", handleKeyDown);
|
||||
interactionEmitter.off("keyUp", handleKeyUp);
|
||||
};
|
||||
}, [finishDrawingPolygon, interactionEmitter, drawingShape, toolSettings]);
|
||||
useKeyboard(handleKeyDown, handleKeyUp);
|
||||
|
||||
function handleShapeOver(shape, isDown) {
|
||||
if (shouldHover && isDown) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import normalizeWheel from "normalize-wheel";
|
|||
|
||||
import usePreventOverscroll from "../../helpers/usePreventOverscroll";
|
||||
import useDataSource from "../../helpers/useDataSource";
|
||||
import useKeyboard from "../../helpers/useKeyboard";
|
||||
|
||||
import { mapSources as defaultMapSources } from "../../maps";
|
||||
|
||||
|
@ -18,6 +19,7 @@ import MapStageContext, {
|
|||
} from "../../contexts/MapStageContext";
|
||||
import AuthContext from "../../contexts/AuthContext";
|
||||
import SettingsContext from "../../contexts/SettingsContext";
|
||||
import KeyboardContext from "../../contexts/KeyboardContext";
|
||||
|
||||
const wheelZoomSpeed = -0.001;
|
||||
const touchZoomSpeed = 0.005;
|
||||
|
@ -206,88 +208,49 @@ function MapInteraction({
|
|||
stageHeightRef.current = height;
|
||||
}
|
||||
|
||||
// Added key events to interaction emitter
|
||||
useEffect(() => {
|
||||
function handleKeyDown(event) {
|
||||
// Ignore text input
|
||||
if (event.target instanceof HTMLInputElement) {
|
||||
return;
|
||||
}
|
||||
interactionEmitter.emit("keyDown", event);
|
||||
function handleKeyDown(event) {
|
||||
// Change to pan tool when pressing space
|
||||
if (event.key === " " && selectedToolId === "pan") {
|
||||
// Stop active state on pan icon from being selected
|
||||
event.preventDefault();
|
||||
}
|
||||
if (
|
||||
event.key === " " &&
|
||||
selectedToolId !== "pan" &&
|
||||
!disabledControls.includes("pan")
|
||||
) {
|
||||
event.preventDefault();
|
||||
previousSelectedToolRef.current = selectedToolId;
|
||||
onSelectedToolChange("pan");
|
||||
}
|
||||
|
||||
function handleKeyUp(event) {
|
||||
// Ignore text input
|
||||
if (event.target instanceof HTMLInputElement) {
|
||||
return;
|
||||
}
|
||||
interactionEmitter.emit("keyUp", event);
|
||||
// Basic keyboard shortcuts
|
||||
if (event.key === "w" && !disabledControls.includes("pan")) {
|
||||
onSelectedToolChange("pan");
|
||||
}
|
||||
|
||||
document.body.addEventListener("keydown", handleKeyDown);
|
||||
document.body.addEventListener("keyup", handleKeyUp);
|
||||
document.body.tabIndex = 1;
|
||||
return () => {
|
||||
document.body.removeEventListener("keydown", handleKeyDown);
|
||||
document.body.removeEventListener("keyup", handleKeyUp);
|
||||
document.body.tabIndex = 0;
|
||||
};
|
||||
}, [interactionEmitter]);
|
||||
|
||||
// Create default keyboard shortcuts
|
||||
useEffect(() => {
|
||||
function handleKeyDown(event) {
|
||||
// Change to pan tool when pressing space
|
||||
if (event.key === " " && selectedToolId === "pan") {
|
||||
// Stop active state on pan icon from being selected
|
||||
event.preventDefault();
|
||||
}
|
||||
if (
|
||||
event.key === " " &&
|
||||
selectedToolId !== "pan" &&
|
||||
!disabledControls.includes("pan")
|
||||
) {
|
||||
event.preventDefault();
|
||||
previousSelectedToolRef.current = selectedToolId;
|
||||
onSelectedToolChange("pan");
|
||||
}
|
||||
|
||||
// Basic keyboard shortcuts
|
||||
if (event.key === "w" && !disabledControls.includes("pan")) {
|
||||
onSelectedToolChange("pan");
|
||||
}
|
||||
if (event.key === "d" && !disabledControls.includes("drawing")) {
|
||||
onSelectedToolChange("drawing");
|
||||
}
|
||||
if (event.key === "f" && !disabledControls.includes("fog")) {
|
||||
onSelectedToolChange("fog");
|
||||
}
|
||||
if (event.key === "m" && !disabledControls.includes("measure")) {
|
||||
onSelectedToolChange("measure");
|
||||
}
|
||||
if (event.key === "q" && !disabledControls.includes("pointer")) {
|
||||
onSelectedToolChange("pointer");
|
||||
}
|
||||
if (event.key === "d" && !disabledControls.includes("drawing")) {
|
||||
onSelectedToolChange("drawing");
|
||||
}
|
||||
|
||||
function handleKeyUp(event) {
|
||||
if (event.key === " " && selectedToolId === "pan") {
|
||||
onSelectedToolChange(previousSelectedToolRef.current);
|
||||
}
|
||||
if (event.key === "f" && !disabledControls.includes("fog")) {
|
||||
onSelectedToolChange("fog");
|
||||
}
|
||||
if (event.key === "m" && !disabledControls.includes("measure")) {
|
||||
onSelectedToolChange("measure");
|
||||
}
|
||||
if (event.key === "q" && !disabledControls.includes("pointer")) {
|
||||
onSelectedToolChange("pointer");
|
||||
}
|
||||
}
|
||||
|
||||
interactionEmitter.on("keyDown", handleKeyDown);
|
||||
interactionEmitter.on("keyUp", handleKeyUp);
|
||||
return () => {
|
||||
interactionEmitter.off("keyDown", handleKeyDown);
|
||||
interactionEmitter.off("keyUp", handleKeyUp);
|
||||
};
|
||||
}, [
|
||||
interactionEmitter,
|
||||
onSelectedToolChange,
|
||||
disabledControls,
|
||||
selectedToolId,
|
||||
]);
|
||||
function handleKeyUp(event) {
|
||||
if (event.key === " " && selectedToolId === "pan") {
|
||||
onSelectedToolChange(previousSelectedToolRef.current);
|
||||
}
|
||||
}
|
||||
|
||||
useKeyboard(handleKeyDown, handleKeyUp);
|
||||
// Get keyboard context to pass to Konva
|
||||
const keyboardValue = useContext(KeyboardContext);
|
||||
|
||||
function getCursorForTool(tool) {
|
||||
switch (tool) {
|
||||
|
@ -360,11 +323,13 @@ function MapInteraction({
|
|||
{/* Forward auth context to konva elements */}
|
||||
<AuthContext.Provider value={auth}>
|
||||
<SettingsContext.Provider value={settings}>
|
||||
<MapInteractionProvider value={mapInteraction}>
|
||||
<MapStageProvider value={mapStageRef}>
|
||||
{mapLoaded && children}
|
||||
</MapStageProvider>
|
||||
</MapInteractionProvider>
|
||||
<KeyboardContext.Provider value={keyboardValue}>
|
||||
<MapInteractionProvider value={mapInteraction}>
|
||||
<MapStageProvider value={mapStageRef}>
|
||||
{mapLoaded && children}
|
||||
</MapStageProvider>
|
||||
</MapInteractionProvider>
|
||||
</KeyboardContext.Provider>
|
||||
</SettingsContext.Provider>
|
||||
</AuthContext.Provider>
|
||||
</Layer>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useContext } from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { Flex, IconButton } from "theme-ui";
|
||||
import { useMedia } from "react-media";
|
||||
|
||||
|
@ -21,7 +21,7 @@ import RedoButton from "./RedoButton";
|
|||
|
||||
import Divider from "../../Divider";
|
||||
|
||||
import MapInteractionContext from "../../../contexts/MapInteractionContext";
|
||||
import useKeyboard from "../../../helpers/useKeyboard";
|
||||
|
||||
function DrawingToolSettings({
|
||||
settings,
|
||||
|
@ -29,49 +29,41 @@ function DrawingToolSettings({
|
|||
onToolAction,
|
||||
disabledActions,
|
||||
}) {
|
||||
const { interactionEmitter } = useContext(MapInteractionContext);
|
||||
|
||||
// Keyboard shotcuts
|
||||
useEffect(() => {
|
||||
function handleKeyDown({ key, ctrlKey, metaKey, shiftKey }) {
|
||||
if (key === "b") {
|
||||
onSettingChange({ type: "brush" });
|
||||
} else if (key === "p") {
|
||||
onSettingChange({ type: "paint" });
|
||||
} else if (key === "l") {
|
||||
onSettingChange({ type: "line" });
|
||||
} else if (key === "r") {
|
||||
onSettingChange({ type: "rectangle" });
|
||||
} else if (key === "c") {
|
||||
onSettingChange({ type: "circle" });
|
||||
} else if (key === "t") {
|
||||
onSettingChange({ type: "triangle" });
|
||||
} else if (key === "e") {
|
||||
onSettingChange({ type: "erase" });
|
||||
} else if (key === "o") {
|
||||
onSettingChange({ useBlending: !settings.useBlending });
|
||||
} else if (
|
||||
(key === "z" || key === "Z") &&
|
||||
(ctrlKey || metaKey) &&
|
||||
shiftKey &&
|
||||
!disabledActions.includes("redo")
|
||||
) {
|
||||
onToolAction("mapRedo");
|
||||
} else if (
|
||||
key === "z" &&
|
||||
(ctrlKey || metaKey) &&
|
||||
!shiftKey &&
|
||||
!disabledActions.includes("undo")
|
||||
) {
|
||||
onToolAction("mapUndo");
|
||||
}
|
||||
function handleKeyDown({ key, ctrlKey, metaKey, shiftKey }) {
|
||||
if (key === "b") {
|
||||
onSettingChange({ type: "brush" });
|
||||
} else if (key === "p") {
|
||||
onSettingChange({ type: "paint" });
|
||||
} else if (key === "l") {
|
||||
onSettingChange({ type: "line" });
|
||||
} else if (key === "r") {
|
||||
onSettingChange({ type: "rectangle" });
|
||||
} else if (key === "c") {
|
||||
onSettingChange({ type: "circle" });
|
||||
} else if (key === "t") {
|
||||
onSettingChange({ type: "triangle" });
|
||||
} else if (key === "e") {
|
||||
onSettingChange({ type: "erase" });
|
||||
} else if (key === "o") {
|
||||
onSettingChange({ useBlending: !settings.useBlending });
|
||||
} else if (
|
||||
(key === "z" || key === "Z") &&
|
||||
(ctrlKey || metaKey) &&
|
||||
shiftKey &&
|
||||
!disabledActions.includes("redo")
|
||||
) {
|
||||
onToolAction("mapRedo");
|
||||
} else if (
|
||||
key === "z" &&
|
||||
(ctrlKey || metaKey) &&
|
||||
!shiftKey &&
|
||||
!disabledActions.includes("undo")
|
||||
) {
|
||||
onToolAction("mapUndo");
|
||||
}
|
||||
|
||||
interactionEmitter.on("keyDown", handleKeyDown);
|
||||
return () => {
|
||||
interactionEmitter.off("keyDown", handleKeyDown);
|
||||
};
|
||||
});
|
||||
}
|
||||
useKeyboard(handleKeyDown);
|
||||
|
||||
// Change to brush if on erase and it gets disabled
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useContext, useEffect } from "react";
|
||||
import React from "react";
|
||||
import { Flex } from "theme-ui";
|
||||
import { useMedia } from "react-media";
|
||||
|
||||
|
@ -15,11 +15,11 @@ import FogSubtractIcon from "../../../icons/FogSubtractIcon";
|
|||
|
||||
import UndoButton from "./UndoButton";
|
||||
import RedoButton from "./RedoButton";
|
||||
import ToolSection from "./ToolSection";
|
||||
|
||||
import Divider from "../../Divider";
|
||||
|
||||
import MapInteractionContext from "../../../contexts/MapInteractionContext";
|
||||
import ToolSection from "./ToolSection";
|
||||
import useKeyboard from "../../../helpers/useKeyboard";
|
||||
|
||||
function BrushToolSettings({
|
||||
settings,
|
||||
|
@ -27,55 +27,46 @@ function BrushToolSettings({
|
|||
onToolAction,
|
||||
disabledActions,
|
||||
}) {
|
||||
const { interactionEmitter } = useContext(MapInteractionContext);
|
||||
|
||||
// Keyboard shortcuts
|
||||
useEffect(() => {
|
||||
function handleKeyDown({ key, ctrlKey, metaKey, shiftKey }) {
|
||||
if (key === "Alt") {
|
||||
onSettingChange({ useFogSubtract: !settings.useFogSubtract });
|
||||
} else if (key === "p") {
|
||||
onSettingChange({ type: "polygon" });
|
||||
} else if (key === "b") {
|
||||
onSettingChange({ type: "brush" });
|
||||
} else if (key === "t") {
|
||||
onSettingChange({ type: "toggle" });
|
||||
} else if (key === "r") {
|
||||
onSettingChange({ type: "remove" });
|
||||
} else if (key === "s") {
|
||||
onSettingChange({ useEdgeSnapping: !settings.useEdgeSnapping });
|
||||
} else if (key === "f") {
|
||||
onSettingChange({ preview: !settings.preview });
|
||||
} else if (
|
||||
(key === "z" || key === "Z") &&
|
||||
(ctrlKey || metaKey) &&
|
||||
shiftKey &&
|
||||
!disabledActions.includes("redo")
|
||||
) {
|
||||
onToolAction("fogRedo");
|
||||
} else if (
|
||||
key === "z" &&
|
||||
(ctrlKey || metaKey) &&
|
||||
!shiftKey &&
|
||||
!disabledActions.includes("undo")
|
||||
) {
|
||||
onToolAction("fogUndo");
|
||||
}
|
||||
function handleKeyDown({ key, ctrlKey, metaKey, shiftKey }) {
|
||||
if (key === "Alt") {
|
||||
onSettingChange({ useFogSubtract: !settings.useFogSubtract });
|
||||
} else if (key === "p") {
|
||||
onSettingChange({ type: "polygon" });
|
||||
} else if (key === "b") {
|
||||
onSettingChange({ type: "brush" });
|
||||
} else if (key === "t") {
|
||||
onSettingChange({ type: "toggle" });
|
||||
} else if (key === "r") {
|
||||
onSettingChange({ type: "remove" });
|
||||
} else if (key === "s") {
|
||||
onSettingChange({ useEdgeSnapping: !settings.useEdgeSnapping });
|
||||
} else if (key === "f") {
|
||||
onSettingChange({ preview: !settings.preview });
|
||||
} else if (
|
||||
(key === "z" || key === "Z") &&
|
||||
(ctrlKey || metaKey) &&
|
||||
shiftKey &&
|
||||
!disabledActions.includes("redo")
|
||||
) {
|
||||
onToolAction("fogRedo");
|
||||
} else if (
|
||||
key === "z" &&
|
||||
(ctrlKey || metaKey) &&
|
||||
!shiftKey &&
|
||||
!disabledActions.includes("undo")
|
||||
) {
|
||||
onToolAction("fogUndo");
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyUp({ key }) {
|
||||
if (key === "Alt") {
|
||||
onSettingChange({ useFogSubtract: !settings.useFogSubtract });
|
||||
}
|
||||
function handleKeyUp({ key }) {
|
||||
if (key === "Alt") {
|
||||
onSettingChange({ useFogSubtract: !settings.useFogSubtract });
|
||||
}
|
||||
}
|
||||
|
||||
interactionEmitter.on("keyDown", handleKeyDown);
|
||||
interactionEmitter.on("keyUp", handleKeyUp);
|
||||
return () => {
|
||||
interactionEmitter.off("keyDown", handleKeyDown);
|
||||
interactionEmitter.off("keyUp", handleKeyUp);
|
||||
};
|
||||
});
|
||||
useKeyboard(handleKeyDown, handleKeyUp);
|
||||
|
||||
const isSmallScreen = useMedia({ query: "(max-width: 799px)" });
|
||||
const drawTools = [
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useContext } from "react";
|
||||
import React from "react";
|
||||
import { Flex, Input, Text } from "theme-ui";
|
||||
|
||||
import ToolSection from "./ToolSection";
|
||||
|
@ -8,28 +8,21 @@ import MeasureManhattanIcon from "../../../icons/MeasureManhattanIcon";
|
|||
|
||||
import Divider from "../../Divider";
|
||||
|
||||
import MapInteractionContext from "../../../contexts/MapInteractionContext";
|
||||
import useKeyboard from "../../../helpers/useKeyboard";
|
||||
|
||||
function MeasureToolSettings({ settings, onSettingChange }) {
|
||||
const { interactionEmitter } = useContext(MapInteractionContext);
|
||||
|
||||
// Keyboard shortcuts
|
||||
useEffect(() => {
|
||||
function handleKeyDown({ key }) {
|
||||
if (key === "g") {
|
||||
onSettingChange({ type: "chebyshev" });
|
||||
} else if (key === "l") {
|
||||
onSettingChange({ type: "euclidean" });
|
||||
} else if (key === "c") {
|
||||
onSettingChange({ type: "manhattan" });
|
||||
}
|
||||
function handleKeyDown({ key }) {
|
||||
if (key === "g") {
|
||||
onSettingChange({ type: "chebyshev" });
|
||||
} else if (key === "l") {
|
||||
onSettingChange({ type: "euclidean" });
|
||||
} else if (key === "c") {
|
||||
onSettingChange({ type: "manhattan" });
|
||||
}
|
||||
interactionEmitter.on("keyDown", handleKeyDown);
|
||||
}
|
||||
|
||||
return () => {
|
||||
interactionEmitter.off("keyDown", handleKeyDown);
|
||||
};
|
||||
});
|
||||
useKeyboard(handleKeyDown);
|
||||
|
||||
const tools = [
|
||||
{
|
||||
|
|
42
src/contexts/KeyboardContext.js
Normal file
42
src/contexts/KeyboardContext.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
const KeyboardContext = React.createContext({ keyEmitter: new EventEmitter() });
|
||||
|
||||
export function KeyboardProvider({ children }) {
|
||||
const [keyEmitter] = useState(new EventEmitter());
|
||||
useEffect(() => {
|
||||
function handleKeyDown(event) {
|
||||
// Ignore text input
|
||||
if (event.target instanceof HTMLInputElement) {
|
||||
return;
|
||||
}
|
||||
keyEmitter.emit("keyDown", event);
|
||||
}
|
||||
|
||||
function handleKeyUp(event) {
|
||||
// Ignore text input
|
||||
if (event.target instanceof HTMLInputElement) {
|
||||
return;
|
||||
}
|
||||
keyEmitter.emit("keyUp", event);
|
||||
}
|
||||
|
||||
document.body.addEventListener("keydown", handleKeyDown);
|
||||
document.body.addEventListener("keyup", handleKeyUp);
|
||||
document.body.tabIndex = 1;
|
||||
return () => {
|
||||
document.body.removeEventListener("keydown", handleKeyDown);
|
||||
document.body.removeEventListener("keyup", handleKeyUp);
|
||||
document.body.tabIndex = 0;
|
||||
};
|
||||
}, [keyEmitter]);
|
||||
|
||||
return (
|
||||
<KeyboardContext.Provider value={{ keyEmitter }}>
|
||||
{children}
|
||||
</KeyboardContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export default KeyboardContext;
|
26
src/helpers/useKeyboard.js
Normal file
26
src/helpers/useKeyboard.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { useEffect, useContext } from "react";
|
||||
|
||||
import KeyboardContext from "../contexts/KeyboardContext";
|
||||
|
||||
function useKeyboard(onKeyDown, onKeyUp) {
|
||||
const { keyEmitter } = useContext(KeyboardContext);
|
||||
useEffect(() => {
|
||||
if (onKeyDown) {
|
||||
keyEmitter.on("keyDown", onKeyDown);
|
||||
}
|
||||
if (onKeyUp) {
|
||||
keyEmitter.on("keyUp", onKeyUp);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (onKeyDown) {
|
||||
keyEmitter.off("keyDown", onKeyDown);
|
||||
}
|
||||
if (onKeyUp) {
|
||||
keyEmitter.off("keyUp", onKeyUp);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export default useKeyboard;
|
Loading…
Reference in New Issue
Block a user