Keyboard
Bindings for @solid-primitives/keyboard.
let useKeyDownEvent(): Accessor<KeyboardEvent> // the last keydown event
let useKeyDownList(): Accessor<string[]> // the keys held now, in press order
let useCurrentlyHeldKey(): Accessor<string | null> // the single held key, or null for none or several
let useKeyDownSequence(): Accessor<string[][]> // the held-key lists since all keys were last released
let createKeyHold(key: string, ?preventDefault: bool): Accessor<bool>
let createShortcut(keys: string[], handler: unit -> unit, ?preventDefault: bool, ?requireReset: bool): unit
createShortcut fires when keys are pressed in the order given. The use primitives listen on window and are shared by every caller.
On Solid 2 today
useKeyDownList is a signal of the held keys, updated from keydown and keyup. Here it is in plain Partas.Solid, scoped to one element; the handlers are typed Dom.KeyboardEvent -> unit. Click the box and hold a few keys:
[<SolidComponent>]
let HeldKeys () =
let held, setHeld = createSignal ([||]: string array)
div (
tabindex = 0,
style = "display: flex; gap: .4rem; min-height: 3rem; padding: .75rem; border: 1px dashed var(--nacara-border); border-radius: var(--nacara-radius-sm)",
onKeyDown = (fun e ->
e.preventDefault ()
if not (Array.contains e.key (held ())) then setHeld (Array.append (held ()) [| e.key |])),
onKeyUp = (fun e -> setHeld (held () |> Array.filter (fun k -> k <> e.key))),
onBlur = fun _ -> setHeld [||]
) {
Show(when' = ((held ()).Length > 0), fallback = span () { "Click here, then hold some keys" }) {
For.Keyed(each = held ()) { yield fun key _ -> kbd () { if key = " " then "Space" else key } }
}
}
export function HeldKeys() {
const patternInput = createSignal([]);
const setHeld = patternInput[1];
const held = patternInput[0];
return <div tabindex={0}
onKeyDown={(e) => {
e.preventDefault();
if (!contains(e.key, held(), {
Equals: (x, y) => (x === y),
GetHashCode: (x) => (stringHash(x) | 0),
})) {
setHeld(append(held(), [e.key]));
}
}}
onKeyUp={(e_1) => {
let array;
setHeld((array = held(), array.filter((k) => (k !== e_1.key))));
}}
onBlur={(_arg_1) => {
setHeld([]);
}}>
<Show when={held().length > 0}
fallback={<span>
Click here, then hold some keys
</span>}>
<KeyedFor each={held()}>
{(key, _arg) => <kbd>
{(key === " ") ? ("Space") : (key)}
</kbd>}
</KeyedFor>
</Show>
</div>;
}
