'use client'; import * as React from 'react'; import { clsx } from 'clsx'; import { X, CheckCircle, AlertTriangle, Info, AlertCircle } from 'lucide-react'; export interface ToastMessage { id: string; type: 'success' | 'error' | 'warning' | 'info'; title: string; description?: string; duration?: number; } type ToastListener = (toasts: ToastMessage[]) => void; let globalToasts: ToastMessage[] = []; const listeners = new Set(); function notifyListeners() { listeners.forEach(l => l([...globalToasts])); } export function toast(msg: Omit) { const id = `toast-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`; globalToasts = [...globalToasts, { ...msg, id }]; notifyListeners(); const duration = msg.duration ?? 5000; if (duration > 0) setTimeout(() => dismissToast(id), duration); } export function dismissToast(id: string) { globalToasts = globalToasts.filter(t => t.id !== id); notifyListeners(); } export function useToast() { return { toast, dismiss: dismissToast }; } const icons: Record = { success: , error: , warning: , info: , }; export function Toast({ message, onDismiss }: { message: ToastMessage; onDismiss: () => void }) { return (
{icons[message.type]}

{message.title}

{message.description && (

{message.description}

)}
); } export function ToastProvider({ children }: { children: React.ReactNode }) { const [toasts, setToasts] = React.useState([]); React.useEffect(() => { listeners.add(setToasts); return () => { listeners.delete(setToasts); }; }, []); return ( <> {children}
{toasts.map(t => ( dismissToast(t.id)} /> ))}
); }