|
import type {Accessor, Component, JSX} from "solid-js"; |
|
import {createMemo, onCleanup, onMount, splitProps} from "solid-js"; |
|
|
|
export type KbButtonProps = { |
|
combo: "ctrl" | "shift" | "alt" | "no-repeat" | string; |
|
} & JSX.HTMLAttributes<HTMLButtonElement>; |
|
|
|
type KeyBind = ((event: KeyboardEvent) => boolean); |
|
|
|
export const KbButton: Component<KbButtonProps> = (props) => { |
|
const [, rest] = splitProps(props, ["combo"]); |
|
const combo: Accessor<KeyBind[]> = createMemo(() => { |
|
let predicates: KeyBind[] = []; |
|
let ctrl = false, alt = false, shift = false; |
|
for (let key of props.combo.toLowerCase().split(" ")) { |
|
if (key == "alt") |
|
alt = true; |
|
else if (key == "shift") |
|
shift = true; |
|
else if (key == "ctrl") |
|
ctrl = true; |
|
else if (key == "no-repeat") |
|
predicates.push(e => !e.repeat); |
|
else |
|
predicates.push(e => e.key == key) |
|
} |
|
|
|
predicates.push(e => e.ctrlKey == ctrl); |
|
predicates.push(e => e.shiftKey == shift); |
|
predicates.push(e => e.altKey == alt); |
|
|
|
return predicates; |
|
}); |
|
let buttonRef: any | undefined = undefined; |
|
let listener: ((event: KeyboardEvent) => void) | undefined = undefined; |
|
onMount(() => { |
|
document.getElementById("key-listenable")?.addEventListener("keydown", listener = event => { |
|
if (combo().every(v => v(event))) |
|
buttonRef?.click(); |
|
}); |
|
}); |
|
onCleanup(() => { |
|
document.getElementById("key-listenable")?.removeEventListener("keydown", listener!); |
|
}) |
|
return ( |
|
<button {...rest} ref={buttonRef}/> |
|
); |
|
} |