import type { IToastProps } from '@gluestack-ui/core/lib/esm/toast/creator/types' import React, { createContext, useContext, useRef } from 'react' import { Toast, ToastDescription, ToastTitle, useToast as useGluestackToast } from '@/components/ui/toast' type ToastVariant = 'solid' | 'outline' type ToastAction = 'error' | 'warning' | 'success' | 'info' | 'muted' interface ShowToastOptions extends IToastProps { title?: React.ReactNode description?: React.ReactNode variant?: ToastVariant action?: ToastAction } // 创建全局 toast 实例 let globalToast: any = null // 创建 Context 用于在组件内部使用 const ToastContext = createContext | null>(null) export function ToastProviderWrapper({ children }: { children: React.ReactNode }) { const toast = useGluestackToast() const toastRef = useRef(toast) toastRef.current = toast // 设置全局实例 React.useEffect(() => { globalToast = { show: (options: ShowToastOptions) => { const id = Math.random().toString() toast.show({ id, placement: options.placement ?? 'top', duration: options.duration !== undefined ? options.duration : 3000, avoidKeyboard: options.avoidKeyboard ?? false, containerStyle: options.containerStyle, onCloseComplete: options.onCloseComplete, render: options.render ? () => options.render!({ id }) : ({ id }) => ( {options.title && {options.title}} {options.description && {options.description}} ), }) return id }, close: (id: string) => { toast.close(id) }, closeAll: () => { toast.closeAll() }, isActive: (id: string) => toast.isActive(id), } }, [toast]) return ( {children} ) } /** * 自定义 Hook,用于 React 组件内部 */ export function useToast() { const toast = useContext(ToastContext) if (!toast) { throw new Error('useToast must be used within a ToastProviderWrapper') } return { show: (options: ShowToastOptions) => { const id = Math.random().toString() toast.show({ id, placement: options.placement ?? 'top', duration: options.duration !== undefined ? options.duration : 3000, avoidKeyboard: options.avoidKeyboard ?? false, containerStyle: options.containerStyle, onCloseComplete: options.onCloseComplete, render: options.render ? () => options.render!({ id }) : ({ id }) => ( {options.title && {options.title}} {options.description && {options.description}} ), }) return id }, close: (id: string) => { toast.close(id) }, closeAll: () => { toast.closeAll() }, isActive: (id: string) => toast.isActive(id), } } /** * 全局 toast 实例,可在组件外部使用 */ export const toast = { show: (options: ShowToastOptions) => { if (!globalToast) { console.warn('Toast not initialized. Make sure ToastProviderWrapper is rendered.') return '' } return globalToast.show(options) }, close: (id: string) => { if (globalToast) { globalToast.close(id) } }, closeAll: () => { if (globalToast) { globalToast.closeAll() } }, isActive: (id: string) => { return globalToast ? globalToast.isActive(id) : false }, }