text: 'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _extends2 = require('babel-runtime/helpers/extends');
  
  var _extends3 = _interopRequireDefault(_extends2);
  
  var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
  
  var _defineProperty3 = _interopRequireDefault(_defineProperty2);
  
  var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
  
  var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  
  var _createClass2 = require('babel-runtime/helpers/createClass');
  
  var _createClass3 = _interopRequireDefault(_createClass2);
  
  var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
  
  var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
  
  var _inherits2 = require('babel-runtime/helpers/inherits');
  
  var _inherits3 = _interopRequireDefault(_inherits2);
  
  var _react = require('react');
  
  var _react2 = _interopRequireDefault(_react);
  
  var _propTypes = require('prop-types');
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _ChildrenUtils = require('./ChildrenUtils');
  
  var _AnimateChild = require('./AnimateChild');
  
  var _AnimateChild2 = _interopRequireDefault(_AnimateChild);
  
  var _animate = require('./util/animate');
  
  var _animate2 = _interopRequireDefault(_animate);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  
  var defaultKey = 'rc_animate_' + Date.now();
  
  function getChildrenFromProps(props) {
    var children = props.children;
    if (_react2['default'].isValidElement(children)) {
      if (!children.key) {
        return _react2['default'].cloneElement(children, {
          key: defaultKey
        });
      }
    }
    return children;
  }
  
  function noop() {}
  
  var Animate = function (_React$Component) {
    (0, _inherits3['default'])(Animate, _React$Component);
  
    // eslint-disable-line
  
    function Animate(props) {
      (0, _classCallCheck3['default'])(this, Animate);
  
      var _this = (0, _possibleConstructorReturn3['default'])(this, (Animate.__proto__ || Object.getPrototypeOf(Animate)).call(this, props));
  
      _initialiseProps.call(_this);
  
      _this.currentlyAnimatingKeys = {};
      _this.keysToEnter = [];
      _this.keysToLeave = [];
  
      _this.state = {
        children: (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(props))
      };
  
      _this.childrenRefs = {};
      return _this;
    }
  
    (0, _createClass3['default'])(Animate, [{
      key: 'componentDidMount',
      value: function componentDidMount() {
        var _this2 = this;
  
        var showProp = this.props.showProp;
        var children = this.state.children;
        if (showProp) {
          children = children.filter(function (child) {
            return !!child.props[showProp];
          });
        }
        children.forEach(function (child) {
          if (child) {
            _this2.performAppear(child.key);
          }
        });
      }
    }, {
      key: 'componentWillReceiveProps',
      value: function componentWillReceiveProps(nextProps) {
        var _this3 = this;
  
        this.nextProps = nextProps;
        var nextChildren = (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(nextProps));
        var props = this.props;
        // exclusive needs immediate response
        if (props.exclusive) {
          Object.keys(this.currentlyAnimatingKeys).forEach(function (key) {
            _this3.stop(key);
          });
        }
        var showProp = props.showProp;
        var currentlyAnimatingKeys = this.currentlyAnimatingKeys;
        // last props children if exclusive
        var currentChildren = props.exclusive ? (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(props)) : this.state.children;
        // in case destroy in showProp mode
        var newChildren = [];
        if (showProp) {
          currentChildren.forEach(function (currentChild) {
            var nextChild = currentChild && (0, _ChildrenUtils.findChildInChildrenByKey)(nextChildren, currentChild.key);
            var newChild = void 0;
            if ((!nextChild || !nextChild.props[showProp]) && currentChild.props[showProp]) {
              newChild = _react2['default'].cloneElement(nextChild || currentChild, (0, _defineProperty3['default'])({}, showProp, true));
            } else {
              newChild = nextChild;
            }
            if (newChild) {
              newChildren.push(newChild);
            }
          });
          nextChildren.forEach(function (nextChild) {
            if (!nextChild || !(0, _ChildrenUtils.findChildInChildrenByKey)(currentChildren, nextChild.key)) {
              newChildren.push(nextChild);
            }
          });
        } else {
          newChildren = (0, _ChildrenUtils.mergeChildren)(currentChildren, nextChildren);
        }
  
        // need render to avoid update
        this.setState({
          children: newChildren
        });
  
        nextChildren.forEach(function (child) {
          var key = child && child.key;
          if (child && currentlyAnimatingKeys[key]) {
            return;
          }
          var hasPrev = child && (0, _ChildrenUtils.findChildInChildrenByKey)(currentChildren, key);
          if (showProp) {
            var showInNext = child.props[showProp];
            if (hasPrev) {
              var showInNow = (0, _ChildrenUtils.findShownChildInChildrenByKey)(currentChildren, key, showProp);
              if (!showInNow && showInNext) {
                _this3.keysToEnter.push(key);
              }
            } else if (showInNext) {
              _this3.keysToEnter.push(key);
            }
          } else if (!hasPrev) {
            _this3.keysToEnter.push(key);
          }
        });
  
        currentChildren.forEach(function (child) {
          var key = child && child.key;
          if (child && currentlyAnimatingKeys[key]) {
            return;
          }
          var hasNext = child && (0, _ChildrenUtils.findChildInChildrenByKey)(nextChildren, key);
          if (showProp) {
            var showInNow = child.props[showProp];
            if (hasNext) {
              var showInNext = (0, _ChildrenUtils.findShownChildInChildrenByKey)(nextChildren, key, showProp);
              if (!showInNext && showInNow) {
                _this3.keysToLeave.push(key);
              }
            } else if (showInNow) {
              _this3.keysToLeave.push(key);
            }
          } else if (!hasNext) {
            _this3.keysToLeave.push(key);
          }
        });
      }
    }, {
      key: 'componentDidUpdate',
      value: function componentDidUpdate() {
        var keysToEnter = this.keysToEnter;
        this.keysToEnter = [];
        keysToEnter.forEach(this.performEnter);
        var keysToLeave = this.keysToLeave;
        this.keysToLeave = [];
        keysToLeave.forEach(this.performLeave);
      }
    }, {
      key: 'isValidChildByKey',
      value: function isValidChildByKey(currentChildren, key) {
        var showProp = this.props.showProp;
        if (showProp) {
          return (0, _ChildrenUtils.findShownChildInChildrenByKey)(currentChildren, key, showProp);
        }
        return (0, _ChildrenUtils.findChildInChildrenByKey)(currentChildren, key);
      }
    }, {
      key: 'stop',
      value: function stop(key) {
        delete this.currentlyAnimatingKeys[key];
        var component = this.childrenRefs[key];
        if (component) {
          component.stop();
        }
      }
    }, {
      key: 'render',
      value: function render() {
        var _this4 = this;
  
        var props = this.props;
        this.nextProps = props;
        var stateChildren = this.state.children;
        var children = null;
        if (stateChildren) {
          children = stateChildren.map(function (child) {
            if (child === null || child === undefined) {
              return child;
            }
            if (!child.key) {
              throw new Error('must set key for <rc-animate> children');
            }
            return _react2['default'].createElement(
              _AnimateChild2['default'],
              {
                key: child.key,
                ref: function ref(node) {
                  _this4.childrenRefs[child.key] = node;
                },
                animation: props.animation,
                transitionName: props.transitionName,
                transitionEnter: props.transitionEnter,
                transitionAppear: props.transitionAppear,
                transitionLeave: props.transitionLeave
              },
              child
            );
          });
        }
        var Component = props.component;
        if (Component) {
          var passedProps = props;
          if (typeof Component === 'string') {
            passedProps = (0, _extends3['default'])({
              className: props.className,
              style: props.style
            }, props.componentProps);
          }
          return _react2['default'].createElement(
            Component,
            passedProps,
            children
          );
        }
        return children[0] || null;
      }
    }]);
    return Animate;
  }(_react2['default'].Component);
  
  Animate.isAnimate = true;
  Animate.propTypes = {
    component: _propTypes2['default'].any,
    componentProps: _propTypes2['default'].object,
    animation: _propTypes2['default'].object,
    transitionName: _propTypes2['default'].oneOfType([_propTypes2['default'].string, _propTypes2['default'].object]),
    transitionEnter: _propTypes2['default'].bool,
    transitionAppear: _propTypes2['default'].bool,
    exclusive: _propTypes2['default'].bool,
    transitionLeave: _propTypes2['default'].bool,
    onEnd: _propTypes2['default'].func,
    onEnter: _propTypes2['default'].func,
    onLeave: _propTypes2['default'].func,
    onAppear: _propTypes2['default'].func,
    showProp: _propTypes2['default'].string,
    children: _propTypes2['default'].node
  };
  Animate.defaultProps = {
    animation: {},
    component: 'span',
    componentProps: {},
    transitionEnter: true,
    transitionLeave: true,
    transitionAppear: false,
    onEnd: noop,
    onEnter: noop,
    onLeave: noop,
    onAppear: noop
  };
  
  var _initialiseProps = function _initialiseProps() {
    var _this5 = this;
  
    this.performEnter = function (key) {
      // may already remove by exclusive
      if (_this5.childrenRefs[key]) {
        _this5.currentlyAnimatingKeys[key] = true;
        _this5.childrenRefs[key].componentWillEnter(_this5.handleDoneAdding.bind(_this5, key, 'enter'));
      }
    };
  
    this.performAppear = function (key) {
      if (_this5.childrenRefs[key]) {
        _this5.currentlyAnimatingKeys[key] = true;
        _this5.childrenRefs[key].componentWillAppear(_this5.handleDoneAdding.bind(_this5, key, 'appear'));
      }
    };
  
    this.handleDoneAdding = function (key, type) {
      var props = _this5.props;
      delete _this5.currentlyAnimatingKeys[key];
      // if update on exclusive mode, skip check
      if (props.exclusive && props !== _this5.nextProps) {
        return;
      }
      var currentChildren = (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(props));
      if (!_this5.isValidChildByKey(currentChildren, key)) {
        // exclusive will not need this
        _this5.performLeave(key);
      } else if (type === 'appear') {
        if (_animate2['default'].allowAppearCallback(props)) {
          props.onAppear(key);
          props.onEnd(key, true);
        }
      } else if (_animate2['default'].allowEnterCallback(props)) {
        props.onEnter(key);
        props.onEnd(key, true);
      }
    };
  
    this.performLeave = function (key) {
      // may already remove by exclusive
      if (_this5.childrenRefs[key]) {
        _this5.currentlyAnimatingKeys[key] = true;
        _this5.childrenRefs[key].componentWillLeave(_this5.handleDoneLeaving.bind(_this5, key));
      }
    };
  
    this.handleDoneLeaving = function (key) {
      var props = _this5.props;
      delete _this5.currentlyAnimatingKeys[key];
      // if update on exclusive mode, skip check
      if (props.exclusive && props !== _this5.nextProps) {
        return;
      }
      var currentChildren = (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(props));
      // in case state change is too fast
      if (_this5.isValidChildByKey(currentChildren, key)) {
        _this5.performEnter(key);
      } else {
        var end = function end() {
          if (_animate2['default'].allowLeaveCallback(props)) {
            props.onLeave(key);
            props.onEnd(key, false);
          }
        };
        if (!(0, _ChildrenUtils.isSameChildren)(_this5.state.children, currentChildren, props.showProp)) {
          _this5.setState({
            children: currentChildren
          }, end);
        } else {
          end();
        }
      }
    };
  };
  
  exports['default'] = Animate;
  module.exports = exports['default'];