/**
* WordPress dependencies
*/
import { useState } from '@safe-wordpress/element';
/**
* External dependencies
*/
import clsx from 'clsx';
import { flattenDeep, union, without } from 'lodash';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
export type AnimatedListProps = {
readonly className?: string;
readonly disableAnimations?: boolean;
readonly enter?: number;
readonly exit?: number;
readonly children: ReadonlyArray< JSX.Element >;
};
export const AnimatedList = ( {
className,
disableAnimations,
enter = 0,
exit = 0,
children,
}: AnimatedListProps ): JSX.Element => {
const [ enteringItems, setEnteringItems ] = useStringList();
const [ exitingItems, setExitingItems ] = useStringList();
if ( disableAnimations ) {
return (
{ children.map( ( child ) => (
{ child }
) ) }
);
}
const addEnteringItem = ( item: string ) =>
setEnteringItems( union( enteringItems, [ item ] ) );
const removeEnteringItem = ( item: string ) =>
setEnteringItems( without( enteringItems, item ) );
const addExitingItem = ( item: string ) =>
setExitingItems( union( exitingItems, [ item ] ) );
const removeExitingItem = ( item: string ) =>
setExitingItems( without( exitingItems, item ) );
const flattenedChildren = flattenDeep( children );
return (
{ flattenedChildren.map( ( child ) => (
addEnteringItem( str( child.key ) ) }
onEntered={ () =>
removeEnteringItem( str( child.key ) )
}
onExit={ () => addExitingItem( str( child.key ) ) }
onExited={ () => removeExitingItem( str( child.key ) ) }
>
{ child }
) ) }
);
};
// =======
// HELPERS
// =======
const str = ( a: unknown ): string => ( typeof a === 'string' ? a : '' );
// =====
// HOOKS
// =====
const useStringList = () => useState< ReadonlyArray< string > >( [] );