import * as React from 'react'; import { isKeyboardFocusingStarted } from '../lib/accessibility'; import { useDOM } from '../lib/dom'; import { useIsomorphicLayoutEffect } from '../lib/useIsomorphicLayoutEffect'; export const ENABLE_KEYBOARD_INPUT_EVENT_NAME = 'enableKeyboardInput'; export const DISABLE_KEYBOARD_INPUT_EVENT_NAME = 'disableKeyboardInput'; const EVENT_OPTIONS = { passive: true, capture: true, }; /** * Чтобы оптимизировать рендер, сохраняем в ref. * * В контекст можно передать через getter, подробнее в примере ниже. * * ```tsx * const keyboardInputTrackerRef = useKeyboardInputTracker(); * * {children} * * ``` * * @private */ export function useKeyboardInputTracker(): React.RefObject { const { document } = useDOM(); const keyboardFocusingStartedRef = React.useRef(false); useIsomorphicLayoutEffect(() => { /* istanbul ignore if: невозможный кейс, т.к. в SSR эффекты не вызываются. Проверка на будущее, если вдруг эффект будет вызываться. */ if (!document) { return; } const handleKeydown = (event: KeyboardEvent) => { if (isKeyboardFocusingStarted(event)) { keyboardFocusingStartedRef.current = true; } }; const handleCustomEnableKeyboardEvent = () => { keyboardFocusingStartedRef.current = true; }; const handleCustomDisableKeyboardEvent = () => { keyboardFocusingStartedRef.current = false; }; document.addEventListener('keydown', handleKeydown, EVENT_OPTIONS); document.addEventListener( ENABLE_KEYBOARD_INPUT_EVENT_NAME, handleCustomEnableKeyboardEvent, EVENT_OPTIONS, ); document.addEventListener( DISABLE_KEYBOARD_INPUT_EVENT_NAME, handleCustomDisableKeyboardEvent, EVENT_OPTIONS, ); document.addEventListener('mousedown', handleCustomDisableKeyboardEvent, EVENT_OPTIONS); document.addEventListener('touchstart', handleCustomDisableKeyboardEvent, EVENT_OPTIONS); return () => { document.removeEventListener('keydown', handleKeydown, EVENT_OPTIONS); document.removeEventListener( ENABLE_KEYBOARD_INPUT_EVENT_NAME, handleCustomEnableKeyboardEvent, EVENT_OPTIONS, ); document.removeEventListener( DISABLE_KEYBOARD_INPUT_EVENT_NAME, handleCustomDisableKeyboardEvent, EVENT_OPTIONS, ); document.removeEventListener('mousedown', handleCustomDisableKeyboardEvent, EVENT_OPTIONS); document.removeEventListener('touchstart', handleCustomDisableKeyboardEvent, EVENT_OPTIONS); }; }, [document]); return keyboardFocusingStartedRef; }