import { useEffect, useRef } from 'react' /** * Общее поведение модалок оболочки (`.modal-overlay`/`.modal-panel`): * закрытие по Escape и возврат фокуса на элемент, который был активен до * открытия модалки (обычно кнопка, её вызвавшая) — доступность по клавиатуре. */ export function useModalDismiss(onClose: () => void) { const previouslyFocused = useRef(null) // Всегда актуальный колбэк без пересоздания подписки на keydown при каждом // рендере (onClose у вызывающих обычно инлайновая функция). Синхронизация — // отдельным эффектом (не прямым присваиванием в теле рендера, см. // react-hooks/refs — рефы нельзя трогать во время рендера). const onCloseRef = useRef(onClose) useEffect(() => { onCloseRef.current = onClose }) useEffect(() => { previouslyFocused.current = document.activeElement function handleKeyDown(e: KeyboardEvent) { if (e.key === 'Escape') onCloseRef.current() } document.addEventListener('keydown', handleKeyDown) return () => { document.removeEventListener('keydown', handleKeyDown) if (previouslyFocused.current instanceof HTMLElement) previouslyFocused.current.focus() } }, []) }