import { useCallback, useEffect, useState } from "react"; import { CheckCircle, AlertTriangle, Info, X } from "lucide-react"; type ToastType = "success" | "error" | "info"; interface ToastItem { id: number; type: ToastType; message: string; } let nextId = 0; let addToastFn: ((type: ToastType, message: string) => void) | null = null; export function toast(type: ToastType, message: string) { addToastFn?.(type, message); } toast.success = (message: string) => toast("success", message); toast.error = (message: string) => toast("error", message); toast.info = (message: string) => toast("info", message); const icons: Record = { success: CheckCircle, error: AlertTriangle, info: Info, }; const styles: Record = { success: "border-emerald-500/30 bg-emerald-500/10 text-emerald-300", error: "border-red-500/30 bg-red-500/10 text-red-300", info: "border-accent-500/30 bg-accent-500/10 text-accent-300", }; export function ToastContainer() { const [toasts, setToasts] = useState([]); const addToast = useCallback((type: ToastType, message: string) => { const id = nextId++; setToasts((prev) => [...prev, { id, type, message }]); }, []); const removeToast = useCallback((id: number) => { setToasts((prev) => prev.filter((t) => t.id !== id)); }, []); useEffect(() => { addToastFn = addToast; return () => { addToastFn = null; }; }, [addToast]); return (
{toasts.map((item) => ( ))}
); } function ToastNotification({ item, onDismiss }: { item: ToastItem; onDismiss: (id: number) => void }) { const Icon = icons[item.type]; useEffect(() => { const timer = window.setTimeout(() => onDismiss(item.id), 4000); return () => clearTimeout(timer); }, [item.id, onDismiss]); return (
{item.message}
); }