├── docs └── show.gif ├── package.json ├── README.md ├── Keybinds.svelte └── maps.js /docs/show.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThaUnknown/svelte-keybinds/HEAD/docs/show.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-keybinds", 3 | "version": "1.0.9", 4 | "description": "Minimalistic keybinds interface, with rebinding and saving. Made for Svelte.", 5 | "main": "Keybinds.svelte", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/ThaUnknown/svelte-keybinds.git" 12 | }, 13 | "keywords": [ 14 | "keybinds", 15 | "keyboard", 16 | "svelte", 17 | "binds", 18 | "rebinding", 19 | "dragdrop" 20 | ], 21 | "author": "ThaUnknown", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/ThaUnknown/svelte-keybinds/issues" 25 | }, 26 | "homepage": "https://github.com/ThaUnknown/svelte-keybinds#readme" 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Svelte Keybinds 3 |

4 |

5 | chat
6 |

7 | 8 | ## Functions: 9 | ```jsx 10 | import Keybinds, { binds, loadWithDefaults, condition } from './Keybinds.svelte' 11 | 12 | 13 | ``` 14 | - `clickable` - runs functions when the user clicks the key in the UI 15 | - `condition` - async callback function any time a keybind is ran, if it returns true the keybind is ran, if it returns false it isnt 16 | - `binds` - store/writable, binds object 17 | - `autosave` - automatically saves to localstorage when a user changes binds, requires `id` in binds object 18 | - `loadWithDefaults(defaults)` - loads the stored keybinds from autosave, using specific defaults, if a new keybind was added it will be properly created 19 | 20 | On browsers which support the [keyboard API](https://caniuse.com/mdn-api_navigator_keyboard) this module will respect the user's keyboard layout [dworak etc]. 21 | 22 | ## Usage: 23 | 24 | Simple example: 25 | ```html 26 | 44 | 45 | 46 |
{item?.label || ''}
47 |
48 | 49 | 60 | ``` 61 | 62 | Example with autosave: 63 | ```html 64 | 86 | 87 | 88 |
{item?.id || ''}
89 |
90 | 91 | 102 | 103 | ``` 104 | -------------------------------------------------------------------------------- /Keybinds.svelte: -------------------------------------------------------------------------------- 1 | 61 | 62 | 106 | 107 |
108 | {#each Object.values(keys) as key} 109 | {@const { size, dark, name } = key} 110 |
clickable && runBind(Object.assign(e, { code: name }))}> 118 | 119 |
120 | {/each} 121 |
122 | 123 | 185 | -------------------------------------------------------------------------------- /maps.js: -------------------------------------------------------------------------------- 1 | // Risky as objects dont guarantee order 2 | export const keys = { 3 | Escape: { 4 | dark: true, 5 | name: 'Escape' 6 | }, 7 | Digit1: { 8 | name: 'Digit1' 9 | }, 10 | Digit2: { 11 | name: 'Digit2' 12 | }, 13 | Digit3: { 14 | name: 'Digit3' 15 | }, 16 | Digit4: { 17 | name: 'Digit4' 18 | }, 19 | Digit5: { 20 | name: 'Digit5' 21 | }, 22 | Digit6: { 23 | name: 'Digit6' 24 | }, 25 | Digit7: { 26 | name: 'Digit7' 27 | }, 28 | Digit8: { 29 | name: 'Digit8' 30 | }, 31 | Digit9: { 32 | name: 'Digit9' 33 | }, 34 | Digit0: { 35 | name: 'Digit0' 36 | }, 37 | Minus: { 38 | name: 'Minus' 39 | }, 40 | Equal: { 41 | name: 'Equal' 42 | }, 43 | Backspace: { 44 | dark: true, 45 | size: 100, 46 | name: 'Backspace' 47 | }, 48 | Delete: { 49 | dark: true, 50 | name: 'Delete' 51 | }, 52 | Tab: { 53 | dark: true, 54 | size: 75, 55 | name: 'Tab' 56 | }, 57 | KeyQ: { 58 | name: 'KeyQ' 59 | }, 60 | KeyW: { 61 | name: 'KeyW' 62 | }, 63 | KeyE: { 64 | name: 'KeyE' 65 | }, 66 | KeyR: { 67 | name: 'KeyR' 68 | }, 69 | KeyT: { 70 | name: 'KeyT' 71 | }, 72 | KeyY: { 73 | name: 'KeyY' 74 | }, 75 | KeyU: { 76 | name: 'KeyU' 77 | }, 78 | KeyI: { 79 | name: 'KeyI' 80 | }, 81 | KeyO: { 82 | name: 'KeyO' 83 | }, 84 | KeyP: { 85 | name: 'KeyP' 86 | }, 87 | BracketLeft: { 88 | name: 'BracketLeft' 89 | }, 90 | BracketRight: { 91 | name: 'BracketRight' 92 | }, 93 | Backslash: { 94 | dark: true, 95 | size: 75, 96 | name: 'Backslash' 97 | }, 98 | Home: { 99 | dark: true, 100 | name: 'Home' 101 | }, 102 | CapsLock: { 103 | dark: true, 104 | size: 90, 105 | name: 'CapsLock' 106 | }, 107 | KeyA: { 108 | name: 'KeyA' 109 | }, 110 | KeyS: { 111 | name: 'KeyS' 112 | }, 113 | KeyD: { 114 | name: 'KeyD' 115 | }, 116 | KeyF: { 117 | name: 'KeyF' 118 | }, 119 | KeyG: { 120 | name: 'KeyG' 121 | }, 122 | KeyH: { 123 | name: 'KeyH' 124 | }, 125 | KeyJ: { 126 | name: 'KeyJ' 127 | }, 128 | KeyK: { 129 | name: 'KeyK' 130 | }, 131 | KeyL: { 132 | name: 'KeyL' 133 | }, 134 | Semicolon: { 135 | name: 'Semicolon' 136 | }, 137 | Quote: { 138 | name: 'Quote' 139 | }, 140 | Enter: { 141 | dark: true, 142 | size: 110, 143 | name: 'Enter' 144 | }, 145 | PageUp: { 146 | dark: true, 147 | name: 'PageUp' 148 | }, 149 | ShiftLeft: { 150 | dark: true, 151 | size: 115, 152 | name: 'ShiftLeft' 153 | }, 154 | KeyZ: { 155 | name: 'KeyZ' 156 | }, 157 | KeyX: { 158 | name: 'KeyX' 159 | }, 160 | KeyC: { 161 | name: 'KeyC' 162 | }, 163 | KeyV: { 164 | name: 'KeyV' 165 | }, 166 | KeyB: { 167 | name: 'KeyB' 168 | }, 169 | KeyN: { 170 | name: 'KeyN' 171 | }, 172 | KeyM: { 173 | name: 'KeyM' 174 | }, 175 | Comma: { 176 | name: 'Comma' 177 | }, 178 | Period: { 179 | name: 'Period' 180 | }, 181 | Slash: { 182 | name: 'Slash' 183 | }, 184 | ShiftRight: { 185 | dark: true, 186 | size: 85, 187 | name: 'ShiftRight' 188 | }, 189 | ArrowUp: { 190 | dark: true, 191 | name: 'ArrowUp' 192 | }, 193 | PageDown: { 194 | dark: true, 195 | name: 'PageDown' 196 | }, 197 | ControlLeft: { 198 | dark: true, 199 | size: 75, 200 | name: 'ControlLeft' 201 | }, 202 | MetaLeft: { 203 | dark: true, 204 | name: 'MetaLeft' 205 | }, 206 | AltLeft: { 207 | dark: true, 208 | size: 75, 209 | name: 'AltLeft' 210 | }, 211 | Space: { 212 | dark: true, 213 | size: 300, 214 | name: 'Space' 215 | }, 216 | AltRight: { 217 | dark: true, 218 | size: 75, 219 | name: 'AltRight' 220 | }, 221 | ContextMenu: { 222 | dark: true, 223 | size: 75, 224 | name: 'ContextMenu' 225 | }, 226 | ArrowLeft: { 227 | dark: true, 228 | name: 'ArrowLeft' 229 | }, 230 | ArrowDown: { 231 | dark: true, 232 | name: 'ArrowDown' 233 | }, 234 | ArrowRight: { 235 | dark: true, 236 | name: 'ArrowRight' 237 | } 238 | } 239 | // char => code for navigator.keyboard API 240 | const codeMap = { 241 | 0: 'Digit0', 242 | 1: 'Digit1', 243 | 2: 'Digit2', 244 | 3: 'Digit3', 245 | 4: 'Digit4', 246 | 5: 'Digit5', 247 | 6: 'Digit6', 248 | 7: 'Digit7', 249 | 8: 'Digit8', 250 | 9: 'Digit9', 251 | e: 'KeyE', 252 | d: 'KeyD', 253 | '-': 'Minus', 254 | h: 'KeyH', 255 | z: 'KeyZ', 256 | '=': 'Equal', 257 | n: 'KeyN', 258 | p: 'KeyP', 259 | ']': 'BracketRight', 260 | '[': 'BracketLeft', 261 | s: 'KeyS', 262 | ';': 'Semicolon', 263 | q: 'KeyQ', 264 | o: 'KeyO', 265 | '.': 'Period', 266 | v: 'KeyV', 267 | l: 'KeyL', 268 | '`': 'Backquote', 269 | g: 'KeyG', 270 | j: 'KeyJ', 271 | t: 'KeyT', 272 | "'": 'Quote', 273 | y: 'KeyY', 274 | '\\': 'Backslash', 275 | r: 'KeyR', 276 | u: 'KeyU', 277 | k: 'KeyK', 278 | '/': 'Slash', 279 | f: 'KeyF', 280 | i: 'KeyI', 281 | x: 'KeyX', 282 | a: 'KeyA', 283 | m: 'KeyM', 284 | w: 'KeyW', 285 | b: 'KeyB', 286 | c: 'KeyC', 287 | ',': 'Comma' 288 | } 289 | export const layout = {} 290 | if (navigator.keyboard) { 291 | navigator.keyboard.getLayoutMap().then((map) => { 292 | for (const [key, value] of map.entries()) { 293 | layout[key] = codeMap[value] 294 | } 295 | }) 296 | } 297 | --------------------------------------------------------------------------------