├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── src
└── use-wasd.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS config files
2 | .DS_Store
3 |
4 | # Visual Studio Code
5 | .vscode/*
6 | !.vscode/settings.json
7 | !.vscode/tasks.json
8 | !.vscode/launch.json
9 | !.vscode/extensions.json
10 | !.vscode/*.code-snippets
11 |
12 | # Local History for Visual Studio Code
13 | .history/
14 |
15 | # Built Visual Studio Code Extensions
16 | *.vsix
17 |
18 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
19 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
20 | .idea
21 |
22 | # dependencies
23 | /node_modules
24 |
25 | # debug
26 | npm-debug.log*
27 |
28 | # bundling
29 | .parcel-cache
30 | dist
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #
2 |
3 | [](https://www.npmjs.com/package/use-wasd)
4 | [](<[https://bundlephobia.com/result?p=use-wasd](https://bundlephobia.com/package/use-wasd@2.0.1)>)
5 | [](https://www.npmjs.com/package/use-wasd)
6 |
7 | Easy and agnostic react hook to handle keys and key-combinations on your keyboard.
8 |
9 | ```bash
10 | npm install use-wasd
11 | ```
12 |
13 | This hook returns an object with the keys and combos and their pressed state.
14 |
15 | ```js
16 | import useWASD from "use-wasd";
17 |
18 | export default function App() {
19 | const keyboard = useWASD();
20 |
21 | return (
22 |
23 | {JSON.stringify(keyboard)}
24 |
25 | );
26 | }
27 | ```
28 |
29 | 
30 |
31 | ---
32 |
33 | ### Table of Content
34 |
35 | - [Options](#options)
36 | - [allow/block](#allowblock)
37 | - [combos](#combos)
38 | - [initialValue](#initialvalue)
39 | - [preventDefault](#preventdefault)
40 | - [ref](#ref)
41 | - [Performance](#performance)
42 | - [Destructuring](#destructuring)
43 | - [Memoization](#memoization)
44 | - [Examples](#examples)
45 | - [Learn](#learn)
46 |
47 | ---
48 |
49 | ## Options
50 |
51 | You can pass an optional `options` object.
52 |
53 | ```js
54 | const options = { allow: ["w", "a", "s", "d"] };
55 |
56 | export default function App() {
57 | const { w, a ,s ,d } = useWASD(options);
58 | ...
59 | }
60 | ```
61 |
62 | Available options are:
63 |
64 | - allow
65 | - block
66 | - combos
67 | - initialValue
68 | - preventDefault
69 | - ref
70 |
71 | ---
72 |
73 | ### allow/block
74 |
75 | You can and should explicitly allow or block keys.
76 |
77 | ```js
78 | const options = {
79 | // either
80 | allow: ["w", "shift", "c"],
81 | // or
82 | block: ["c"],
83 | };
84 | ```
85 |
86 | > Do not use both.
87 |
88 | ---
89 |
90 | ### combos
91 |
92 | You can define custom combos.
93 |
94 | ```js
95 | const options = {
96 | allow: ["w", "shift", "space"],
97 | combos: { sprint: ["w", "shift"], sprintJump: ["w", "shift", "space"] }
98 | };
99 |
100 | export default function App() {
101 | const { sprint, sprintJump } = useWASD(options);
102 | ...
103 | }
104 | ```
105 |
106 | > You don´t need to also allow combos, it´s enough if the keys for the combo are allowed and not blocked.
107 |
108 | 
109 |
110 | ---
111 |
112 | ### initialValue
113 |
114 | You can initially fill the object.
115 |
116 | ```js
117 | const options = {
118 | initialValue: { w: true, shift: false, sprint: false },
119 | };
120 | ```
121 |
122 | > Note that the `"keydown"` event will always set keys `true`, while the `"keyup"` event will always set to `false`. Initially setting a key to `true` will not reverse the mechanism.
123 |
124 | 
125 |
126 | ---
127 |
128 | ### preventDefault
129 |
130 | You can call `event.preventDefault()` to prevent default actions for keys.
131 |
132 | ```js
133 | const options = { preventDefault: ["arrowup", "arrowdown"] };
134 | ```
135 |
136 | You can also set it to `true` to prevent the default function for every key.
137 |
138 | ```js
139 | const options = { preventDefault: true };
140 | ```
141 |
142 | > Be aware that by doing so you can jeopardize the a11y
143 |
144 | 
145 |
146 | ---
147 |
148 | ### ref
149 |
150 | By default the EventListener will be added to the `document`, if you want it to be added to another element, you can pass it as `ref`.
151 |
152 | ```js
153 | export default function App() {
154 | const ref = useRef();
155 | const keyboard = useWASD({...options, ref});
156 | ...
157 | }
158 | ```
159 |
160 | 
161 |
162 | ---
163 |
164 | ## Performance
165 |
166 | ### Destructuring
167 |
168 | > We recommend destructuring the object returned by useWASD.
169 |
170 | ```diff
171 |
172 | export default function App() {
173 | - const keyboard = useWASD();
174 | + const { w, a ,s ,d } = useWASD();
175 | ...
176 | }
177 | ```
178 |
179 | ### Memoization
180 |
181 | > We recommend memoizing the options object.
182 |
183 | Here are 3 common examples of passing the options object:
184 |
185 | 1. Declare it outside the Component.
186 |
187 | ```js
188 | const options = {...};
189 |
190 | export default function App() {
191 | const keyboard = useWASD(options);
192 | ...
193 | }
194 | ```
195 |
196 | 2. Using useMemo hook.
197 |
198 | ```js
199 |
200 | export default function App() {
201 | const options = useMemo(() => ({...}), []);
202 | const keyboard = useWASD(options);
203 | ...
204 | }
205 | ```
206 |
207 | 3. Using useRef hook.
208 |
209 | ```js
210 |
211 | export default function App() {
212 | const options = useRef({...});
213 | const keyboard = useWASD(options.current);
214 | ...
215 | }
216 | ```
217 |
218 | Do not pass the object directly into the hook, this would cause unnecessary rerenders.
219 |
220 | ```js
221 |
222 | export default function App() {
223 | const keyboard = useWASD({...});
224 | ...
225 | }
226 | ```
227 |
228 | ---
229 |
230 | ## Examples
231 |
232 | [Basic Example](https://codesandbox.io/s/github/doemser/dead-simple-react/tree/main/examples/use-wasd/use-wasd-basic)
233 |
234 | [combos Example](https://codesandbox.io/s/github/doemser/dead-simple-react/tree/main/examples/use-wasd/use-wasd-combos)
235 |
236 | [initialValue Example](https://codesandbox.io/s/github/doemser/dead-simple-react/tree/main/examples/use-wasd/use-wasd-initial-value)
237 |
238 | [preventDefault Example](https://codesandbox.io/s/github/doemser/dead-simple-react/tree/main/examples/use-wasd/use-wasd-prevent-default)
239 |
240 | [ref Example](https://codesandbox.io/s/github/doemser/dead-simple-react/tree/main/examples/use-wasd/use-wasd-ref)
241 |
242 | ---
243 |
244 | ## Learn
245 |
246 | [useWASD vanilla source](https://codesandbox.io/s/github/doemser/dead-simple-react/tree/main/examples/use-wasd/use-wasd-vanilla)
247 |
248 | > if you are familiar with typescript, you can also find the source code on [github](https://github.com/doemser/use-wasd/blob/main/src/use-wasd.ts).
249 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "use-wasd",
3 | "version": "2.0.6",
4 | "license": "MIT",
5 | "description": "Easy and agnostic react hook to handle keys and key-combinations on your keyboard.",
6 | "keywords": [
7 | "react",
8 | "hook",
9 | "keyboard",
10 | "track",
11 | "keys",
12 | "shortcuts",
13 | "wasd",
14 | "combos",
15 | "combination",
16 | "gaming"
17 | ],
18 | "files": [
19 | "dist"
20 | ],
21 | "author": "doemser",
22 | "main": "dist/use-wasd.js",
23 | "source": "src/use-wasd.ts",
24 | "types": "dist/types.d.ts",
25 | "module": "dist/esm/use-wasd.js",
26 | "peerDependencies": {
27 | "react": ">=18",
28 | "react-dom": ">=18"
29 | },
30 | "devDependencies": {
31 | "@parcel/packager-ts": "^2.7.0",
32 | "@parcel/transformer-typescript-types": "^2.7.0",
33 | "@types/react": "^18.0.21",
34 | "@types/react-dom": "^18.0.6",
35 | "parcel": "^2.7.0",
36 | "react": "^18.2.0",
37 | "react-dom": "^18.2.0",
38 | "react-scripts": "^5.0.1",
39 | "typescript": "4.7"
40 | },
41 | "repository": {
42 | "type": "git",
43 | "url": "git+https://github.com:doemser/use-wasd.git"
44 | },
45 | "homepage": "http://doemser.de",
46 | "scripts": {
47 | "test": "react-scripts test --env=jsdom",
48 | "build": "parcel build",
49 | "dev": "parcel watch",
50 | "release": "parcel build && npm publish"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/use-wasd.ts:
--------------------------------------------------------------------------------
1 | import { MutableRefObject, useEffect, useRef, useState } from "react";
2 |
3 | export interface UseWASDOptions {
4 | allowed?: string[];
5 | blocked?: string[];
6 | combos?: Record