// Based on https://gist.github.com/adamwathan/3b9f3ad1a285a2d1b482769aeb862467 import { CSSTransition as ReactCSSTransition } from 'react-transition-group' import React, { useContext, useEffect, useRef } from 'react' type TransitionContextProps = { parent: { show: boolean isInitialRender: boolean appear?: boolean } } const TransitionContext = React.createContext>({ parent: { show: false, isInitialRender: true, }, }) function useIsInitialRender() { const isInitialRender = useRef(true) useEffect(() => { isInitialRender.current = false }, []) return isInitialRender.current } interface TransitionProps { show?: boolean enter?: string enterFrom?: string enterTo?: string leave?: string leaveFrom?: string leaveTo?: string appear?: boolean children: React.ReactNode } function CSSTransition({ show, enter = '', enterFrom = '', enterTo = '', leave = '', leaveFrom = '', leaveTo = '', appear, children, }: TransitionProps) { const enterClasses = enter.split(' ').filter(s => s.length) const enterFromClasses = enterFrom.split(' ').filter(s => s.length) const enterToClasses = enterTo.split(' ').filter(s => s.length) const leaveClasses = leave.split(' ').filter(s => s.length) const leaveFromClasses = leaveFrom.split(' ').filter(s => s.length) const leaveToClasses = leaveTo.split(' ').filter(s => s.length) function addClasses(node: HTMLElement, classes: string[]): void { if (classes.length) { node.classList.add(...classes) } } function removeClasses(node: HTMLElement, classes: string[]): void { if (classes.length) { node.classList.remove(...classes) } } return ( { node.addEventListener('transitionend', done, false) }} onEnter={(node: any) => { addClasses(node, [...enterClasses, ...enterFromClasses]) }} onEntering={(node: any) => { removeClasses(node, enterFromClasses) addClasses(node, enterToClasses) }} onEntered={(node: any) => { removeClasses(node, [...enterToClasses, ...enterClasses]) }} onExit={node => { addClasses(node, [...leaveClasses, ...leaveFromClasses]) }} onExiting={node => { removeClasses(node, leaveFromClasses) addClasses(node, leaveToClasses) }} onExited={node => { removeClasses(node, [...leaveToClasses, ...leaveClasses]) }} > {children} ) } function Transition({ show, appear, ...rest }: TransitionProps) { const { parent } = useContext(TransitionContext) const isInitialRender = useIsInitialRender() const isChild = show === undefined if (isChild) { return ( ) } return ( ) } export default Transition