import { React } from '@gravityforms/libraries';
const { useState, useEffect } = React;
/**
* @module FadeIn
* @description A simple util to fade in child elements, in a staggered animation. Available props listed below:
*
- **delay:** *Default: 50.* Delay between each child's animation in milliseconds.
- **transitionDuration:** *Default: 400.* Duration of each child's animation in milliseconds.
- **transformDistance:** *Default: 20.* Distance to apply the "pull up" animation.
- **className:** *No default.* Adds a className prop to the container div.
- **childClassName:** *No default.* Adds a className prop to each child div, allowing you to style the direct children of the FadeIn component.
- **wrapperTag:** *Default: "div".* Override the HTML element of the wrapping div.
- **childTag:** *Default: "div".* Override the HTML element wrapped around each child element.
- **visible:** If not undefined, the visible prop can be used to control when the fade in occurs. If set to false after the fade-in animation completes, the children will fade out one by one.
- **onComplete:** specifies a callback to be called when the animation completes.
*
* @param {object} props Props for fade in.
*
* @since 1.0.2
*
* @return {*}
*
* @example
* import { FadeIn } from '@gravityforms/react-utils';
*
* const Component = ( {
* endpoints,
* i18n,
* } ) => {
* return (
* <FadeIn delay={ 200 } transitionDuration={ 800 }>
* <Box customClasses={ [ 'gform-example__heading-container' ] }>
* CODE
* </Box>
* <Box customClasses={ [ 'gform-example__body-container' ] }>
* CODE
* </Box>
*
* <Box customClasses={ [ 'gform-example__license-container' ] }>
* CODE
* </Box>
* </FadeIn>
* );
* };
*
*/
export default function FadeIn( props ) {
const [ maxIsVisible, setMaxIsVisible ] = useState( 0 );
const transitionDuration = typeof props.transitionDuration === 'number' ? props.transitionDuration : 400;
const transformDistance = typeof props.transformDistance === 'number' ? props.transformDistance : 20;
const delay = typeof props.delay === 'number' ? props.delay : 50;
const WrapperTag = props.wrapperTag || 'div';
const ChildTag = props.childTag || 'div';
const visible = typeof props.visible === 'undefined' ? true : props.visible;
useEffect( () => {
let count = React.Children.count( props.children );
if ( ! visible ) {
// Animate all children out
count = 0;
}
if ( count === maxIsVisible ) {
// We're done updating maxVisible, notify when animation is done
const timeout = setTimeout( () => {
if ( props.onComplete ) {
props.onComplete();
}
}, transitionDuration );
return () => clearTimeout( timeout );
}
// Move maxIsVisible toward count
const increment = count > maxIsVisible ? 1 : -1;
const timeout = setTimeout( () => {
setMaxIsVisible( maxIsVisible + increment );
}, delay );
return () => clearTimeout( timeout );
}, [
React.Children.count( props.children ),
delay,
maxIsVisible,
visible,
transitionDuration,
] );
return ( React.createElement( WrapperTag, { className: props.className }, React.Children.map( props.children, ( child, i ) => {
return ( React.createElement( ChildTag, {
className: props.childClassName, style: {
transition: `opacity ${ transitionDuration }ms, transform ${ transitionDuration }ms`,
transform: maxIsVisible > i ? 'none' : `translateY(${ transformDistance }px)`,
opacity: maxIsVisible > i ? 1 : 0,
},
}, child ) );
} ) ) );
}