UNPKG

@wix/design-system

Version:

@wix/design-system

91 lines 4.58 kB
import React, { Children, useEffect, useMemo, useState, useRef, } from 'react'; import PropTypes from 'prop-types'; import { TransitionGroup, Transition as ReactTransition, } from 'react-transition-group'; import { dataHooks } from './constants'; import { getTimeout, getTransitionStyles } from './utils/utils'; /** Transition is a wrapper that allows animations of other components. */ const Transition = ({ animateOnLoad = false, dataHook, children, enterAnimation, exitAnimation, mountOnEnter, unmountOnExit, onEnd, onStart, show, className, }) => { const [dimensions, setDimensions] = useState({}); const [stateRef, setStateRef] = useState(null); const ref = useRef(null); useEffect(() => { if (stateRef) { setDimensions({ height: stateRef.scrollHeight, width: stateRef.scrollWidth, }); } }, [stateRef]); const { fade, move, scale, toggle } = useMemo(() => { if (dimensions) { return getTransitionStyles(dimensions, enterAnimation, exitAnimation); } return { fade: {}, move: {}, scale: {}, toggle: {}, }; }, [enterAnimation, exitAnimation, dimensions]); const timeout = useMemo(() => { return getTimeout(enterAnimation, exitAnimation); }, [enterAnimation, exitAnimation]); const childrenClone = Children.map(children, child => { if (React.isValidElement(child) && (show === undefined || !!show)) { return React.cloneElement(child); } return; }); const handleStart = (animationTiming) => { onStart?.(animationTiming); }; const handleEnd = (animationTiming) => { onEnd?.(animationTiming); }; return (React.createElement("div", { "data-hook": dataHook, className: className }, React.createElement(TransitionGroup, { appear: animateOnLoad }, childrenClone && childrenClone.map(child => { return (React.createElement(ReactTransition // Transition component needs React key property to find correct child in the list , { // Transition component needs React key property to find correct child in the list key: child.key, "data-hook": dataHooks.transition, mountOnEnter: mountOnEnter, unmountOnExit: unmountOnExit, in: show, timeout: { // Transition component won't show enter animation when enter timeout is set enter: 0, exit: timeout.exit, }, onEntering: () => handleStart('enter'), onExiting: () => handleStart('exit'), onEntered: () => handleEnd('enter'), onExited: () => handleEnd('exit'), nodeRef: ref }, (state) => { return (React.createElement("div", { "data-hook": dataHooks.fadeStyles, style: fade[state] }, React.createElement("div", { "data-hook": dataHooks.moveStyles, style: move[state] }, React.createElement("div", { "data-hook": dataHooks.scaleStyles, style: scale[state] }, React.createElement("div", { "data-hook": dataHooks.toggleStyles, style: toggle[state], ref: callback => { setStateRef(callback); ref.current = callback; } }, child))))); })); })))); }; Transition.displayName = 'Transition'; Transition.propTypes = { animateOnLoad: PropTypes.bool, children: PropTypes.node, dataHook: PropTypes.string, enterAnimation: PropTypes.shape({ fadeIn: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), moveIn: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), expand: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), scaleUp: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), }), exitAnimation: PropTypes.shape({ fadeOut: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), moveOut: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), collapse: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), scaleDown: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]), }), mountOnEnter: PropTypes.bool, onStart: PropTypes.func, onEnd: PropTypes.func, show: PropTypes.bool, unmountOnExit: PropTypes.bool, }; export default Transition; //# sourceMappingURL=Transition.js.map