import React, { useEffect, useState } from 'react'; type Props = { visible?: boolean; enterTime?: number; leaveTime?: number; clearTime?: number; className?: string; name?: string; }; export type TransitionProps = Props; export const Transition: React.FC> = ({ children, className = '', visible = false, enterTime = 60, leaveTime = 60, clearTime = 60, name = 'transition', ...props }: React.PropsWithChildren) => { // !!! any const [classes, setClasses] = useState(''); const [renderable, setRenderable] = useState(visible); useEffect(() => { const statusClassName = visible ? 'enter' : 'leave'; const time = visible ? enterTime : leaveTime; if (visible && !renderable) { setRenderable(true); } setClasses(`${name}-${statusClassName}`); // set class to active const timer = setTimeout(() => { setClasses(`${name}-${statusClassName} ${name}-${statusClassName}-active`); clearTimeout(timer); }, time); // remove classess when animation over const clearClassesTimer = setTimeout(() => { if (!visible) { setClasses(''); setRenderable(false); } clearTimeout(clearClassesTimer); }, time + clearTime); return () => { clearTimeout(timer); clearTimeout(clearClassesTimer); }; }, [visible, renderable, enterTime, leaveTime, name, clearTime]); if (!React.isValidElement(children) || !renderable) { return null; } return React.cloneElement(children as React.ReactElement, { ...props, className: `${(children as React.ReactElement).props.className} ${className} ${classes}` }); }; Transition.displayName = 'Transition';