useMagicKeys
Reactive key-press state — access any key as a ReadonlyObservable<boolean> that is true while the key is held down.
Press keys to see their reactive state change in real-time.
Modifier Keys
Combos
Currently Pressed
(none)
import { const useMagicKeys: (options?: DeepMaybeObservable<UseMagicKeysOptions>) => UseMagicKeysReturn
useMagicKeys } from "@usels/web";
function function KeyboardDemo(): JSX.Element
KeyboardDemo() { const const keys: UseMagicKeysReturn
keys = function useMagicKeys(options?: DeepMaybeObservable<UseMagicKeysOptions>): UseMagicKeysReturn
Framework-agnostic magic keys tracker.
Tracks keyboard state via keydown/keyup/blur events on window.
Returns a Proxy that exposes any key as a reactive boolean observable,
and supports combo keys (e.g. ctrl+a).
useMagicKeys();
return ( <JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> {/* Single key — true while held */} <JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p>A: {const keys: UseMagicKeysReturn
keys["a"].ImmutableObservableBase<boolean>.get(trackingType?: TrackingType | GetOptions): {}
get() ? "pressed" : "released"}</JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p> {/* Modifier keys (aliases: ctrl, cmd, alt, esc, etc.) */} <JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p>Ctrl: {const keys: UseMagicKeysReturn
keys["ctrl"].ImmutableObservableBase<boolean>.get(trackingType?: TrackingType | GetOptions): {}
get() ? "pressed" : "released"}</JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p> {/* Combo — true only when all parts are pressed simultaneously */} <JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p>Ctrl+S: {const keys: UseMagicKeysReturn
keys["ctrl+s"].ImmutableObservableBase<boolean>.get(trackingType?: TrackingType | GetOptions): {}
get() ? "pressed" : "released"}</JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p> {/* Current pressed keys set */} <JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p>Pressed: {[...const keys: UseMagicKeysReturn
keys.current$: ReadonlyObservable<Set<string>>
Set of currently pressed key names (lowercase)
current$.ImmutableObservableBase<Set<string>>.get(trackingType?: TrackingType | GetOptions): any
get()].any
join(", ")}</JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p> </JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> );}import { createMagicKeys } from "@usels/web";
function KeyboardDemo() { "use scope" const keys = createMagicKeys();
return ( <div> <p>A: {keys["a"].get() ? "pressed" : "released"}</p> <p>Ctrl: {keys["ctrl"].get() ? "pressed" : "released"}</p> <p>Ctrl+S: {keys["ctrl+s"].get() ? "pressed" : "released"}</p> <p>Pressed: {[...keys.current$.get()].join(", ")}</p> </div> );}Destructuring with $ suffix
Section titled “Destructuring with $ suffix”Since JavaScript destructuring cannot use + or bracket notation, append $ to key names and use _ instead of + for combos:
// @noErrorsimport { useMagicKeys } from "@usels/web";
function DestructuredDemo() { const { shift$, space$, Ctrl_S$ } = useMagicKeys();
return ( <div> <p>Shift: {shift$.get() ? "pressed" : "released"}</p> <p>Ctrl+S: {Ctrl_S$.get() ? "pressed" : "released"}</p> </div> );}Built-in Aliases
Section titled “Built-in Aliases”| Alias | Resolves to |
|---|---|
ctrl | control |
cmd | meta |
command | meta |
option | alt |
esc | escape |
del | delete |
space | (space) |
up | arrowup |
down | arrowdown |
left | arrowleft |
right | arrowright |
Key names are lowercased and resolved through the alias map. Combo keys are specified with + separator (e.g., "ctrl+a", "shift+enter").
For destructuring, append $ to any key name (e.g., shift$) and use _ instead of + for combos (e.g., Ctrl_A$). The $ suffix is stripped and _ is converted to + internally.
export interface UseMagicKeysOptions extends ConfigurableWindow { /** Custom alias map for key names */ aliasMap?: Record<string, string>; /** Event handler called on every keydown/keyup. Return false to skip tracking. */ onEventFired?: (e: KeyboardEvent) => boolean | void; /** Options passed to the underlying addEventListener calls. @default { passive: true } */ eventListenerOptions?: AddEventListenerOptions;}export type UseMagicKeysReturn = { /** Set of currently pressed key names (lowercase) */ current$: ReadonlyObservable<Set<string>>;} & { /** Access any key as a reactive boolean. e.g., keys["a"], keys["shift"], keys["ctrl+a"] */ [key: string]: ReadonlyObservable<boolean>;};/** * Framework-agnostic magic keys tracker. * * Tracks keyboard state via `keydown`/`keyup`/`blur` events on window. * Returns a Proxy that exposes any key as a reactive boolean observable, * and supports combo keys (e.g. `ctrl+a`). */export declare function createMagicKeys(options?: DeepMaybeObservable<UseMagicKeysOptions>): UseMagicKeysReturn;