import { useEffect, useRef } from "react"; export interface ShortcutHandlers { onNew?: () => void; onSaveDraft?: () => void; onIssue?: () => void; onAddLine?: () => void; onHelp?: () => void; } const isTyping = (target: EventTarget | null) => { const el = target as HTMLElement | null; if (!el) return false; return el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT" || el.isContentEditable; }; /** * Global keyboard shortcuts. Ctrl combinations work everywhere; the bare `?` is ignored * while typing. F5 / Ctrl+R are blocked in production builds because a webview reload * would discard in-memory state. */ export function useShortcuts(handlers: ShortcutHandlers) { const ref = useRef(handlers); ref.current = handlers; useEffect(() => { const onKey = (event: KeyboardEvent) => { const ctrl = event.ctrlKey || event.metaKey; const key = event.key.toLowerCase(); if (import.meta.env.PROD && (event.key === "F5" || (ctrl && key === "r"))) { event.preventDefault(); return; } const run = (fn?: () => void) => { event.preventDefault(); fn?.(); }; if (ctrl && !event.shiftKey && !event.altKey) { if (key === "n") return run(ref.current.onNew); if (key === "s") return run(ref.current.onSaveDraft); if (key === "l") return run(ref.current.onAddLine); if (key === "enter") return run(ref.current.onIssue); } if (!ctrl && !event.altKey && event.key === "?" && !isTyping(event.target)) { run(ref.current.onHelp); } }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, []); } export const SHORTCUT_LIST: { keys: string; action: string }[] = [ { keys: "Ctrl + N", action: "New invoice" }, { keys: "Ctrl + S", action: "Save draft" }, { keys: "Ctrl + Enter", action: "Issue and export PDF" }, { keys: "Ctrl + L", action: "Add line item" }, { keys: "?", action: "Show this list" }, ];