import { useEffect, type HTMLAttributes } from "react"; import { createPortal } from "react-dom"; import { cn } from "./cn.js"; import { Icon, type IconName } from "./Icon.js"; export type ToastTone = "success" | "error" | "warning" | "info" | "loading"; export type ToastItem = { id: string; tone: ToastTone; title: string; description?: string; durationMs?: number | null; }; const toastIcons: Record = { success: "check", error: "alert", warning: "alert", info: "activity", loading: "refresh", }; export interface ToastCardProps extends HTMLAttributes { item: ToastItem; onDismiss?: (id: string) => void; } export function ToastCard({ item, onDismiss, className, ...props }: ToastCardProps) { return (
{item.title} {item.description ? {item.description} : null} {onDismiss ? ( ) : null}
); } export function ToastStack({ items, onDismiss }: { items: ToastItem[]; onDismiss: (id: string) => void }) { useEffect(() => { const timers = items.flatMap((item) => { const duration = item.durationMs === undefined ? 4200 : item.durationMs; return typeof duration === "number" && duration > 0 ? [window.setTimeout(() => onDismiss(item.id), duration)] : []; }); return () => timers.forEach((timer) => window.clearTimeout(timer)); }, [items, onDismiss]); if (typeof document === "undefined" || items.length === 0) return null; return createPortal(
{items.map((item) => )}
, document.body, ); }