jsx import { Interpolation , jsx , SerializedStyles , Theme } from "@emotion/react" ; import React , { useState , useEffect } from "react" ; import { style , getAnimation } from "./style" ; export interface ToastProps extends Omit < React . HTMLProps < HTMLDivElement > , "content" > { onHide ? : ( ) => void ; content ? : React . ReactNode ; position ? : "top" | "middle" | "bottom" ; offsetTop ? : number ; offsetBottom ? : number ; duration ? : number ; radius ? : number ; containerStyle ? : Interpolation < Theme > ; contentStyle ? : Interpolation < Theme > ; } export function Toast ( props ) { const { content = "" , position = "middle" , duration = 2000 , radius = 16 , offsetTop = 50 , offsetBottom = 50 , onHide = ( ) => undefined , containerStyle , contentStyle , ... attributes } = props ; const getResult = getAnimation ( position , "show" ) ; const [ animation , setAnimation ] = useState < SerializedStyles > ( getResult . animation ) ; useEffect ( ( ) => { const timer = window . setTimeout ( ( ) => { const { animation } = getAnimation ( position , "hide" ) ; setAnimation ( animation ) ; } , duration ) ; return ( ) => { window . clearInterval ( timer ) ; } ; } , [ position ] ) ; let showContent ; const middleStyle = position === "middle" ? style . contentMiddle : undefined ; if ( React . isValidElement ( content ) ) { showContent = < div css = { [ middleStyle , contentStyle ] } > { content } < /div>; } else { showContent = ( < p css = { [ style . content ( radius ) , middleStyle , contentStyle ] } > { content } < /p>); } const animationEnd = ( event ) => { const { keyframes } = getAnimation ( position , "hide" ) ; if ( event . animationName === keyframes . name ) { onHide ?. ( ) ; } } ; let positionStyle ; if ( position === "top" ) { positionStyle = style . top ( offsetTop ) ; } else if ( position === "bottom" ) { positionStyle = style . bottom ( offsetBottom ) ; } else { positionStyle = style . middle ; } return ( < div css = { [ style . container ( ) , positionStyle , animation , containerStyle ] } onAnimationEnd = { animationEnd } { ... attributes } > { showContent } < /div>); }