import React, { useState, useCallback, useRef, useEffect, useMemo } from 'react'; import type { AnnounceOptions } from '~/common'; import AnnouncerContext from '~/Providers/AnnouncerContext'; import { useLocalize } from '~/hooks'; import Announcer from './Announcer'; interface LiveAnnouncerProps { children: React.ReactNode; } const LiveAnnouncer: React.FC = ({ children }) => { const [statusMessage, setStatusMessage] = useState(''); const [logMessage, setLogMessage] = useState(''); const statusTimeoutRef = useRef(null); const localize = useLocalize(); const events: Record = useMemo( () => ({ start: localize('com_a11y_start'), end: localize('com_a11y_end'), composing: localize('com_a11y_ai_composing'), }), [localize], ); const announceStatus = useCallback((message: string) => { if (statusTimeoutRef.current) { clearTimeout(statusTimeoutRef.current); } setStatusMessage(message); statusTimeoutRef.current = setTimeout(() => { setStatusMessage(''); }, 1000); }, []); const announceLog = useCallback((message: string) => { setLogMessage(message); }, []); const announcePolite = useCallback( ({ message, isStatus = false }: AnnounceOptions) => { const finalMessage = (events[message] ?? message).replace(/[*`_]/g, ''); if (isStatus) { announceStatus(finalMessage); } else { announceLog(finalMessage); } }, [events, announceStatus, announceLog], ); const announceAssertive = announcePolite; const contextValue = { announcePolite, announceAssertive, }; useEffect(() => { return () => { if (statusTimeoutRef.current) { clearTimeout(statusTimeoutRef.current); } }; }, []); return ( {children} ); }; export default LiveAnnouncer;