chore(architecture): enforce layer boundaries
This commit is contained in:
48
input/keyboard.ts
Normal file
48
input/keyboard.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import type { Dispatch } from "@commands/dispatcher";
|
||||
|
||||
export type Keybind = string;
|
||||
|
||||
export type KeybindEvent = {
|
||||
key: string;
|
||||
code: string;
|
||||
altKey: boolean;
|
||||
ctrlKey: boolean;
|
||||
metaKey: boolean;
|
||||
shiftKey: boolean;
|
||||
};
|
||||
|
||||
export type GlobalKeybindConsumer = (event: KeybindEvent) => boolean;
|
||||
|
||||
export type CommandKeybind = {
|
||||
commandId: string;
|
||||
payload?: unknown;
|
||||
};
|
||||
|
||||
export type KeybindMap = ReadonlyMap<Keybind, CommandKeybind>;
|
||||
|
||||
export function keybindFromEvent(event: KeybindEvent): Keybind {
|
||||
const parts = [
|
||||
event.metaKey ? "Meta" : undefined,
|
||||
event.ctrlKey ? "Ctrl" : undefined,
|
||||
event.altKey ? "Alt" : undefined,
|
||||
event.shiftKey ? "Shift" : undefined,
|
||||
event.key,
|
||||
].filter(Boolean);
|
||||
|
||||
return parts.join("+");
|
||||
}
|
||||
|
||||
export function handleKeybind(options: {
|
||||
event: KeybindEvent;
|
||||
globalConsumer: GlobalKeybindConsumer;
|
||||
keybindMap: KeybindMap;
|
||||
dispatch: Dispatch;
|
||||
}): boolean {
|
||||
if (options.globalConsumer(options.event)) return true;
|
||||
|
||||
const command = options.keybindMap.get(keybindFromEvent(options.event));
|
||||
if (!command) return false;
|
||||
|
||||
options.dispatch(command.commandId, command.payload);
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user