import React from 'react'; import BaseToast, { TimoutTimer } from './Toast'; import type { ToastProps, ToastInstance, ToastOptions, ToastType, ToastReturnType } from './type'; import { PortalRef } from '../ConfigProvider'; const defaultOptions: ToastProps = { icon: '', message: '', type: 'info', position: 'middle', forbidClick: false, duration: 2000, }; const toastReturnMap: Record = {}; const defaultOptionsMap = new Map(); let currentOptions = { ...defaultOptions }; let currentKey = 0; // 清楚所有 toast const clearAll = () => { Object.values(toastReturnMap).forEach(it => { it.clear(); }); }; const ToastInner = (opts: ToastProps): ToastReturnType => { // 清楚上一个 toast (如果有) clearAll(); const key = `toast_${++currentKey}`; const clearTimer = React.createRef() as React.MutableRefObject; let options = { ...opts }; const clear = () => { delete toastReturnMap[key]; // 清除定时器 clearTimer.current && clearTimeout(clearTimer.current); PortalRef.current?.removePortal(key); }; const onClose = () => { clear(); options.onClose?.(); }; const renderToast = () => ( ); const updateConfig: ToastReturnType['config'] = nextState => { options = typeof nextState === 'function' ? { ...options, ...nextState(options) } : { ...options, ...nextState }; PortalRef.current?.updatePortal(key, renderToast()); }; PortalRef.current?.addPortal(key, renderToast()); const returnMap = { config: updateConfig, clear }; toastReturnMap[key] = returnMap; return returnMap; }; const parseOptions = (opts: ToastProps | string): ToastProps => { if (typeof opts === 'string') { return { message: opts }; } return opts; }; const InternalToast = (opts: ToastProps | string) => ToastInner({ ...parseOptions(opts), }); const Toast = InternalToast as ToastInstance; (['info', 'loading', 'success', 'fail'] as ToastType[]).forEach(method => { Toast[method] = (opts: ToastOptions) => ToastInner({ ...parseOptions(opts), type: method, }); }); Toast.setDefaultOptions = (type: ToastType | ToastProps, options?: ToastProps) => { if (typeof type === 'string' && options) { defaultOptionsMap.set(type, options); } else { Object.assign(currentOptions, type); } }; Toast.resetDefaultOptions = (type?: ToastType) => { if (typeof type === 'string') { defaultOptionsMap.delete(type); } else { currentOptions = { ...defaultOptions }; defaultOptionsMap.clear(); } }; Toast.clear = clearAll; export default Toast; export { Toast }; export type { ToastProps } from './type';