import { useEffect, useRef } 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 } /** * While W is held, a primary-button pointerdown anywhere (capture phase) calls onClose. * Ignores events when the target is an input/textarea/select or contenteditable. */ export function useCloseOnWClick(onClose?: () => void) { const onCloseRef = useRef(onClose) onCloseRef.current = onClose const wHeldRef = useRef(false) useEffect(() => { if (!onClose) return const onKeyDown = (e: KeyboardEvent) => { if (e.code === 'KeyW' && !e.repeat) wHeldRef.current = true } const onKeyUp = (e: KeyboardEvent) => { if (e.code === 'KeyW') wHeldRef.current = false } const resetW = () => { wHeldRef.current = false } const onPointerDownCapture = (e: PointerEvent) => { if (e.button !== 0 || !wHeldRef.current) return if (isTypingTarget(e.target)) return const cb = onCloseRef.current if (!cb) return cb() e.preventDefault() e.stopPropagation() } window.addEventListener('keydown', onKeyDown) window.addEventListener('keyup', onKeyUp) window.addEventListener('blur', resetW) document.addEventListener('pointerdown', onPointerDownCapture, true) return () => { window.removeEventListener('keydown', onKeyDown) window.removeEventListener('keyup', onKeyUp) window.removeEventListener('blur', resetW) document.removeEventListener('pointerdown', onPointerDownCapture, true) } }, [onClose]) }