import { atom, getDefaultStore } from 'jotai'; import type { SnackbarVariant } from '../atoms/Snackbar'; export interface Toast { id: string; message: string; variant: SnackbarVariant; duration?: number; actionLabel?: string; onActionPress?: () => void; } /** * Atom con la pila de toasts visibles. El organism `Toaster` lo suscribe. * * Para mostrar un toast: * const showToast = useSetAtom(addToastAtom); * showToast({ message: 'OK', variant: 'success' }); * * Para dismissar: * const dismiss = useSetAtom(dismissToastAtom); * dismiss(toastId); */ export const toastsAtom = atom([]); /** * Write-only atom para añadir un toast nuevo. Devuelve el id generado y * agenda el auto-dismiss según `duration` (4000ms por defecto). */ export const addToastAtom = atom(null, (get, set, toast: Omit & { id?: string }) => { const id = toast.id || `toast-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const newToast: Toast = { id, duration: 4000, ...toast, }; set(toastsAtom, [...get(toastsAtom), newToast]); if (newToast.duration && newToast.duration > 0) { setTimeout(() => { const store = getDefaultStore(); const currentToasts = store.get(toastsAtom); if (currentToasts.some((t) => t.id === id)) { store.set( toastsAtom, currentToasts.filter((t) => t.id !== id), ); } }, newToast.duration); } return id; }); /** Write-only atom para dismissar un toast por id. */ export const dismissToastAtom = atom(null, (get, set, id: string) => { const currentToasts = get(toastsAtom); set( toastsAtom, currentToasts.filter((toast) => toast.id !== id), ); }); /** Write-only atom para dismissar todos los toasts. */ export const dismissAllToastsAtom = atom(null, (_get, set) => { set(toastsAtom, []); });