import { DangerMessageBlock, SuccessMessageBlock, WarningMessageBlock } from "$/component/message"; import Toaster from "$/component/toaster/Toaster"; import type { Toast, ToastProviderProps, ToastProviderState } from "$/types/ToasterTypes"; import moment from "moment"; import { createContext, useCallback, useContext, useMemo, useState } from "react"; const toastInitialState: ToastProviderState = { toast: [], hideToast: () => {}, addToast: () => "", addSuccess: () => "", addWarning: () => "", addDanger: () => "" }; const ToasterProviderContext = createContext(toastInitialState); export default function ToasterProvider({ className, children }: ToastProviderProps){ const [ toast, setToast ] = useState([]); const hideToast = useCallback((id: string) => { setToast((prev) => { if(prev.length === 1 && prev[0].id === id){ const current = prev[0].hideTime > moment(new Date()).subtract(600, "ms").toDate() ? [...prev] : []; if(current.length > 0){ setTimeout(() => hideToast(id), 600); } return current; } else{ return prev.filter((toast) => toast.id !== id); } }); }, []); const addToast = useCallback((message: React.ReactNode, duration?: number) => { if(!duration){ duration = 5000; } const id = crypto.randomUUID(); setToast((prev) => [ ...prev, { id, message, duration, hideTime: moment(new Date()).add(duration, "ms").toDate() } ]); setTimeout(() => hideToast(id), duration); return id; }, [hideToast]); const addSuccess = useCallback((message: React.ReactNode, duration?: number) => { return addToast({message}, duration); }, [ addToast ]); const addWarning = useCallback((message: React.ReactNode, duration?: number) => { return addToast({message}, duration); }, [ addToast ]); const addDanger = useCallback((message: React.ReactNode, duration?: number) => { return addToast({message}, duration); }, [ addToast ]); const value: ToastProviderState = useMemo(() => ({ toast, hideToast, addToast, addSuccess, addWarning, addDanger }), [ toast, hideToast, addToast, addSuccess, addWarning, addDanger ]); return ( {children} ); } // eslint-disable-next-line react-refresh/only-export-components export function useToaster(){ const context = useContext(ToasterProviderContext); if(!context){ throw new Error("useToaster must be used within a ToasterProvider"); } return context; }