import { createContext, useCallback, useContext, useMemo, useRef, useState, type ReactNode, } from 'react'; export type ToastKind = 'info' | 'success' | 'error'; export interface Toast { id: number; message: string; kind: ToastKind; } interface ToastContextValue { toasts: Toast[]; push: (message: string, kind?: ToastKind) => void; dismiss: (id: number) => void; } const ToastContext = createContext(null); const DEFAULT_DURATION_MS = 4000; export function ToastProvider({ children }: { children: ReactNode }): JSX.Element { const [toasts, setToasts] = useState([]); const counterRef = useRef(0); const dismiss = useCallback((id: number) => { setToasts((prev) => prev.filter((t) => t.id !== id)); }, []); const push = useCallback( (message: string, kind: ToastKind = 'info') => { counterRef.current += 1; const id = counterRef.current; setToasts((prev) => [...prev, { id, message, kind }]); setTimeout(() => dismiss(id), DEFAULT_DURATION_MS); }, [dismiss], ); const value = useMemo(() => ({ toasts, push, dismiss }), [toasts, push, dismiss]); return {children}; } export function useToast(): ToastContextValue { const ctx = useContext(ToastContext); if (!ctx) { throw new Error('useToast must be used inside ToastProvider'); } return ctx; }