hotkeys

Keyboard shortcuts from keydown / keyup. subscribeToHotkey/Key/Code/Command fire a callback on match; the live key/code combination is exposed as global atoms.

Install

bun add @valdres/hotkeys

Live example

Loading demo…

Usage

React has a useHotkeys hook family. Every other framework calls subscribeToHotkey(...) inside its own effect primitive and returns the unsubscribe.

<script>
import { onMount } from "svelte"
import { getValdresContext } from "valdres-svelte"
import { subscribeToHotkey } from "@valdres/hotkeys"

const store = getValdresContext()
onMount(() => subscribeToHotkey("meta+s", () => save(), { preventDefault: true }, store))
</script>

Exports

ExportKindType
currentCodeCombinationAtomatom (read-only)KeyboardCode[]event.codes currently held
currentKeyCombinationAtomatom (read-only)string[] — lowercased event.keys currently held
eventByCodeAtomatomFamily(code: KeyboardCode[]) => Atom<KeyboardEvent | null>
eventByKeyAtomatomFamily(key: string[]) => Atom<KeyboardEvent | null>
subscribeToHotkeyutil fn(hotkey: string, cb: (e: KeyboardEvent) => void, options: Options, store: Store) => () => void
subscribeToKeyutil fn(key: string | string[], cb, options, store) => () => void
subscribeToCodeutil fn(code: KeyboardCode | KeyboardCode[], cb, options, store) => () => void
subscribeToCommandutil fn(command: KeyboardCommand, cb, options, store) => () => void
registerListenersutil fn() => void — attaches the document key listeners
eventHandlerutil fn(event: KeyboardEvent) => void
DEFAULT_OPTIONSconstfrozen Options
Optionstype{ keyup, keydown, enabled, enableOnFormTags, enableOnContentEditable, preventDefault, repeat }
KeyboardCodetypere-exported from @valdres/browser-keyboard
KeyboardCommandtype"Save" | "Undo" | "Redo" | "Cut" | "Copy" | "ZoomIn" | "ZoomOut" | "ZoomReset"

enabled accepts a boolean, () => boolean, Atom<boolean>, or Selector<boolean>. subscribeToCommand maps a command to the OS-specific chord (e.g. Savemeta+s on Apple, ctrl+s elsewhere).

Cross-framework

The combination atoms are global — read them with the framework's primitive (useValue / createValue / injectValue / watch, or store.get / store.sub). The subscribeToX callbacks take store explicitly, so they work anywhere.