import { useEffect, forwardRef, useImperativeHandle, ForwardRefExoticComponent, ReactNode, CSSProperties, } from 'react' import classNames from 'classnames' import { Loading, LoadingProps } from '../loading/Loading' import { Popup, PopupProps } from '../popup/Popup' import { Icon } from '../icon/Icon' import { useSetTimeout } from '../../use' import './Toast.scss' import { show, text, success, fail, loading, hide, ToastShowMethod, ToastShortcutMethod, } from './ToastImperative' import { CommonComponentProps } from '../../utils/types' export interface ToastProps extends CommonComponentProps { className?: string style?: CSSProperties type?: 'text' | 'loading' | 'success' | 'fail' | 'custom' title?: ReactNode icon?: ReactNode loadingProps?: LoadingProps duration?: number onTimeout?: () => void visible?: boolean popupProps?: PopupProps } export interface Toast extends ForwardRefExoticComponent { show: ToastShowMethod text: ToastShortcutMethod success: ToastShortcutMethod fail: ToastShortcutMethod loading: ToastShortcutMethod hide(): void } export interface ToastImperativeHandle { clear: () => void reset: () => void } export const Toast = forwardRef( (props, ref) => { const { className, type = 'text', title, icon, loadingProps, duration = 1500, onTimeout, visible = false, popupProps = {}, ...restProps } = props const { mask = false, placement = 'center-fade', lockScroll = false, ...restPopupProps } = popupProps const { reset, clear } = useSetTimeout( () => { onTimeout?.() }, duration, () => type !== 'loading' ) useEffect(() => { if (visible) { reset() } else { clear() } }, [visible]) useEffect(() => { reset() }, [duration, type]) useImperativeHandle(ref, () => ({ reset, clear, })) const toastClass = classNames( 's-toast', { 's-toast-text': type === 'text', }, className ) return (
{type !== 'text' && (
{icon || (type === 'loading' ? ( ) : ( ))}
)}
{title}
) } ) as Toast Toast.show = show Toast.text = text Toast.success = success Toast.fail = fail Toast.loading = loading Toast.hide = hide export default Toast