import { useEffect, useMemo, type RefObject } from 'react' function isTypingTarget(el: EventTarget | null): boolean { if (!el || !(el instanceof HTMLElement)) return false const tag = el.tagName if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return true if (el.isContentEditable) return true return false } const SLASH_KEYS = ['Slash', 'NumpadDivide'] as const /** * Focus the input when one of the given keys is pressed; prevents the key from being typed. * Skips when focus is in another input/textarea/select/contenteditable (same idea as useCloseOnWClick). */ export function useFocusInputShortcut( inputRef: RefObject, keyCodes: readonly string[], enabled = true, ) { const codesSet = useMemo(() => new Set(keyCodes), [keyCodes]) useEffect(() => { if (!enabled) return const onKeyDown = (e: KeyboardEvent) => { if (!codesSet.has(e.code)) return if (e.repeat) return if (e.ctrlKey || e.metaKey || e.altKey) return if (isTypingTarget(e.target)) return const el = inputRef.current if (!el || el.disabled) return e.preventDefault() el.focus() } window.addEventListener('keydown', onKeyDown) return () => window.removeEventListener('keydown', onKeyDown) }, [enabled, inputRef, codesSet]) } /** `/` or numpad `/` — focus JEI search (when JEI is mounted). */ export function useSlashFocusInput(inputRef: RefObject, enabled = true) { useFocusInputShortcut(inputRef, SLASH_KEYS, enabled) }