import { useEffect, useCallback } from 'react' interface ShortcutConfig { key: string ctrl?: boolean shift?: boolean alt?: boolean handler: () => void enabled?: boolean } export function useKeyboardShortcuts(shortcuts: ShortcutConfig[]) { const handleKeyDown = useCallback( (e: KeyboardEvent) => { // Don't trigger shortcuts when typing in inputs const target = e.target as HTMLElement if ( target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable ) { return } for (const shortcut of shortcuts) { if (shortcut.enabled === false) continue const keyMatch = e.key === shortcut.key || e.key === shortcut.key.toLowerCase() const ctrlMatch = !!shortcut.ctrl === (e.ctrlKey || e.metaKey) const shiftMatch = !!shortcut.shift === e.shiftKey const altMatch = !!shortcut.alt === e.altKey if (keyMatch && ctrlMatch && shiftMatch && altMatch) { e.preventDefault() shortcut.handler() return } } }, [shortcuts] ) useEffect(() => { document.addEventListener('keydown', handleKeyDown) return () => document.removeEventListener('keydown', handleKeyDown) }, [handleKeyDown]) } // Convenience hook for tree navigation specifically export interface TreeNavigationShortcutsConfig { onSelectOption: (index: number) => void onGoBack: () => void onContinue: () => void optionCount: number canGoBack: boolean canContinue: boolean } export function useTreeNavigationShortcuts({ onSelectOption, onGoBack, onContinue, optionCount, canGoBack, canContinue, }: TreeNavigationShortcutsConfig) { const shortcuts: ShortcutConfig[] = [ // Number keys 1-9 for options ...Array.from({ length: Math.min(optionCount, 9) }, (_, i) => ({ key: String(i + 1), handler: () => onSelectOption(i), })), // Escape to go back { key: 'Escape', handler: onGoBack, enabled: canGoBack, }, // Enter to continue (for action nodes) { key: 'Enter', handler: onContinue, enabled: canContinue, }, // Tab to focus notes { key: 'Tab', handler: () => { document.getElementById('session-notes')?.focus() }, }, ] useKeyboardShortcuts(shortcuts) } export default useKeyboardShortcuts