diff --git a/internal/web/source/lib/keyboard-shortcut-guard.ts b/internal/web/source/lib/keyboard-shortcut-guard.ts new file mode 100644 index 0000000..2d46940 --- /dev/null +++ b/internal/web/source/lib/keyboard-shortcut-guard.ts @@ -0,0 +1,46 @@ +function isEditableTarget(target: EventTarget | null): target is HTMLElement { + if (!(target instanceof HTMLElement)) { + return false + } + + if (target.isContentEditable) { + return true + } + + const tag = target.tagName + return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" +} + +function shouldIgnoreShortcut(event: KeyboardEvent): boolean { + if (event.ctrlKey || event.metaKey || event.altKey) { + return false + } + + if (event.isComposing) { + return false + } + + return isEditableTarget(event.target) && event.key.length === 1 +} + +function installGuard(): void { + window.addEventListener( + "keydown", + (event) => { + if (!shouldIgnoreShortcut(event)) { + return + } + + event.stopImmediatePropagation() + }, + true + ) +} + +if (typeof window !== "undefined") { + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", installGuard, { once: true }) + } else { + installGuard() + } +} diff --git a/internal/web/source/lib/utils.ts b/internal/web/source/lib/utils.ts index bd0c391..46920d6 100644 --- a/internal/web/source/lib/utils.ts +++ b/internal/web/source/lib/utils.ts @@ -1,5 +1,6 @@ import { clsx, type ClassValue } from "clsx" import { twMerge } from "tailwind-merge" +import "./keyboard-shortcut-guard" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs))