'use client'; import React, { useState, createContext, useContext, useCallback } from 'react'; import { QaheraTone, QaheraIconName } from './types'; import { Icon } from './Icon'; export interface ToastItem { id: string; title: string; message?: string; tone?: QaheraTone; duration?: number; } interface ToastContextType { toasts: ToastItem[]; showToast: (toast: Omit) => string; dismissToast: (id: string) => void; } const ToastContext = createContext(null); const DEFAULT_TOAST_ICONS: Record = { info: 'info', success: 'check', warning: 'alert-circle', danger: 'x-circle', neutral: 'info', }; export const ToastProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [toasts, setToasts] = useState([]); const dismissToast = useCallback((id: string) => { setToasts((prev) => prev.filter((t) => t.id !== id)); }, []); const showToast = useCallback( (toast: Omit) => { const id = Math.random().toString(36).substring(2, 9); const newToast: ToastItem = { ...toast, id }; setToasts((prev) => [...prev, newToast]); const duration = toast.duration ?? 4000; if (duration > 0) { setTimeout(() => { dismissToast(id); }, duration); } return id; }, [dismissToast] ); return ( {children}
{toasts.map((t) => { const tone: QaheraTone = t.tone || 'info'; const iconName = DEFAULT_TOAST_ICONS[tone] || 'info'; return (
{t.title}
{t.message &&
{t.message}
}
); })}
); }; export const useToast = () => { const ctx = useContext(ToastContext); if (!ctx) { throw new Error('useToast must be used within a ToastProvider'); } return ctx; };