import { createContext, useCallback, useContext, useMemo, useState } from 'react'
import { CheckCircle2, AlertTriangle, Info, X } from 'lucide-react'
const ToastContext = createContext(null)
const DEFAULT_DURATION = 3500
function ToastItem({ toast, onClose }) {
const icon = toast.type === 'success'
?
: toast.type === 'error'
?
:
const toneStyle = toast.type === 'success'
? { border: '1px solid rgba(37,211,102,0.3)', color: '#86efac' }
: toast.type === 'error'
? { border: '1px solid rgba(239,68,68,0.35)', color: '#fda4af' }
: { border: '1px solid rgba(148,163,184,0.35)', color: 'var(--color-text-secondary)' }
return (
{icon}
{toast.message}
onClose(toast.id)}
className="border-none bg-transparent text-text-muted hover:text-text-primary cursor-pointer p-0.5"
aria-label="Dismiss notification"
>
)
}
export function ToastProvider({ children }) {
const [toasts, setToasts] = useState([])
const dismiss = useCallback((id) => {
setToasts((prev) => prev.filter((toast) => toast.id !== id))
}, [])
const push = useCallback((message, type = 'info', duration = DEFAULT_DURATION) => {
const id = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
setToasts((prev) => [...prev, { id, message, type }])
window.setTimeout(() => dismiss(id), duration)
}, [dismiss])
const value = useMemo(() => ({
toast: (message, type = 'info', duration = DEFAULT_DURATION) => push(message, type, duration),
success: (message, duration = DEFAULT_DURATION) => push(message, 'success', duration),
error: (message, duration = DEFAULT_DURATION) => push(message, 'error', duration),
info: (message, duration = DEFAULT_DURATION) => push(message, 'info', duration),
}), [push])
return (
{children}
{toasts.map((toast) => (
))}
)
}
export function useToast() {
const context = useContext(ToastContext)
if (!context) {
throw new Error('useToast must be used within ToastProvider')
}
return context
}