import { useEffect, useRef, useState } from 'react' import styles from './Notification.module.css' type Status = 'success' | 'error' | 'info' | 'warning' interface Props { message: string status: Status onClose: () => void title?: string duration?: number } const ICONS: Record = { success: '✓', error: '✕', info: 'i', warning: '!', } const DEFAULT_TITLES: Record = { success: 'Успех', error: 'Ошибка', info: 'Информация', warning: 'Внимание', } export function Notification({ message, status, onClose, title, duration }: Props) { const [closing, setClosing] = useState(false) const timerRef = useRef | null>(null) function handleClose() { setClosing(true) } function handleAnimationEnd() { if (closing) onClose() } function clearTimer() { if (timerRef.current !== null) { clearTimeout(timerRef.current) timerRef.current = null } } function startTimer() { if (duration) { clearTimer() timerRef.current = setTimeout(() => setClosing(true), duration) } } useEffect(() => { startTimer() function handleKeyDown(e: KeyboardEvent) { if (e.key === 'Escape') setClosing(true) } window.addEventListener('keydown', handleKeyDown) return () => { clearTimer() window.removeEventListener('keydown', handleKeyDown) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [duration]) const heading = title ?? DEFAULT_TITLES[status] const ariaLive = status === 'error' || status === 'warning' ? 'assertive' : 'polite' return (
{ICONS[status]}

{heading}

{message}

) }