|
|
typescript |
|
|
import React, { createContext, useContext, useState, ReactNode } from 'react' |
|
|
|
|
|
export type ToastType = 'success' | 'error' | 'warning' | 'info' |
|
|
|
|
|
interface Toast { |
|
|
id: string |
|
|
type: ToastType |
|
|
title: string |
|
|
message?: string |
|
|
} |
|
|
|
|
|
interface ToastContextType { |
|
|
toasts: Toast[] |
|
|
addToast: (toast: Omit<Toast, 'id'>) => void |
|
|
removeToast: (id: string) => void |
|
|
} |
|
|
|
|
|
const ToastContext = createContext<ToastContextType | undefined>(undefined) |
|
|
|
|
|
export const useToast = () => { |
|
|
const context = useContext(ToastContext) |
|
|
if (context === undefined) { |
|
|
throw new Error('useToast must be used within a ToastProvider') |
|
|
} |
|
|
return context |
|
|
} |
|
|
|
|
|
interface ToastProviderProps { |
|
|
children: ReactNode |
|
|
} |
|
|
|
|
|
export const ToastProvider: React.FC<ToastProviderProps> = ({ children }) => { |
|
|
const [toasts, setToasts] = useState<Toast[]>([]) |
|
|
|
|
|
const addToast = (toast: Omit<Toast, 'id'>) => { |
|
|
const id = Math.random().toString(36).substr(2, 9) |
|
|
setToasts(prev => [...prev, { ...toast, id }]) |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
removeToast(id) |
|
|
}, 5000) |
|
|
} |
|
|
|
|
|
const removeToast = (id: string) => { |
|
|
setToasts(prev => prev.filter(toast => toast.id !== id)) |
|
|
} |
|
|
|
|
|
return ( |
|
|
<ToastContext.Provider value={{ toasts, addToast, removeToast }}> |
|
|
{children} |
|
|
</ToastContext.Provider> |
|
|
) |
|
|
} |
|
|
|
|
|
</html> |