Skip to content

Instantly share code, notes, and snippets.

@Revxrsal
Last active January 5, 2023 15:52
Show Gist options
  • Save Revxrsal/105163383fa6e84448ff0ad733301b9b to your computer and use it in GitHub Desktop.
Save Revxrsal/105163383fa6e84448ff0ad733301b9b to your computer and use it in GitHub Desktop.
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}/>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment