import React, { Component, Children } from 'react'; import PropTypes from 'prop-types'; import { TransitionGroup } from 'react-transition-group'; import AnimateChild from './child'; const noop = () => {}; const FirstChild = props => { const childrenArray = React.Children.toArray(props.children); return childrenArray[0] || null; }; /** * Animate */ class Animate extends Component { static propTypes = { /** * 动画 className */ animation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), /** * 子元素第一次挂载时是否执行动画 */ animationAppear: PropTypes.bool, /** * 包裹子元素的标签 */ component: PropTypes.any, /** * 是否只有单个子元素,如果有多个子元素,请设置为 false */ singleMode: PropTypes.bool, /** * 子元素 */ children: PropTypes.oneOfType([ PropTypes.element, PropTypes.arrayOf(PropTypes.element), ]), /** * 执行第一次挂载动画前触发的回调函数 * @param {HTMLElement} node 执行动画的 dom 元素 */ beforeAppear: PropTypes.func, /** * 执行第一次挂载动画,添加 xxx-appear-active 类名后触发的回调函数 * @param {HTMLElement} node 执行动画的 dom 元素 */ onAppear: PropTypes.func, /** * 执行完第一次挂载动画后触发的函数 * @param {HTMLElement} node 执行动画的 dom 元素 */ afterAppear: PropTypes.func, /** * 执行进场动画前触发的回调函数 * @param {HTMLElement} node 执行动画的 dom 元素 */ beforeEnter: PropTypes.func, /** * 执行进场动画,添加 xxx-enter-active 类名后触发的回调函数 * @param {HTMLElement} node 执行动画的 dom 元素 */ onEnter: PropTypes.func, /** * 执行完进场动画后触发的回调函数 * @param {HTMLElement} node 执行动画的 dom 元素 */ afterEnter: PropTypes.func, /** * 执行离场动画前触发的回调函数 * @param {HTMLElement} node 执行动画的 dom 元素 */ beforeLeave: PropTypes.func, /** * 执行离场动画,添加 xxx-leave-active 类名后触发的回调函数 * @param {HTMLElement} node 执行动画的 dom 元素 */ onLeave: PropTypes.func, /** * 执行完离场动画后触发的回调函数 * @param {HTMLElement} node 执行动画的 dom 元素 */ afterLeave: PropTypes.func, }; static defaultProps = { animationAppear: true, component: 'div', singleMode: true, beforeAppear: noop, onAppear: noop, afterAppear: noop, beforeEnter: noop, onEnter: noop, afterEnter: noop, beforeLeave: noop, onLeave: noop, afterLeave: noop, }; normalizeNames(names) { if (typeof names === 'string') { return { appear: `${names}-appear`, appearActive: `${names}-appear-active`, enter: `${names}-enter`, enterActive: `${names}-enter-active`, leave: `${names}-leave`, leaveActive: `${names}-leave-active`, }; } if (typeof names === 'object') { return { appear: names.appear, appearActive: `${names.appear}-active`, enter: `${names.enter}`, enterActive: `${names.enter}-active`, leave: `${names.leave}`, leaveActive: `${names.leave}-active`, }; } } render() { /* eslint-disable no-unused-vars */ const { animation, children, animationAppear, singleMode, component, beforeAppear, onAppear, afterAppear, beforeEnter, onEnter, afterEnter, beforeLeave, onLeave, afterLeave, ...others } = this.props; /* eslint-enable no-unused-vars */ const animateChildren = Children.map(children, child => { return ( {child} ); }); return ( {animateChildren} ); } } export default Animate;