"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;

var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));

var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));

var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));

var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));

var _createSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/createSuper"));

var _react = require("react");

var _omit = _interopRequireDefault(require("lodash/omit"));

var _noop = _interopRequireDefault(require("lodash/noop"));

var _ChildrenUtils = require("./ChildrenUtils");

var _AnimateChild = _interopRequireDefault(require("./AnimateChild"));

var _util = _interopRequireDefault(require("./util"));

var _excluded = ["animation", "transitionName", "transitionEnter", "transitionAppear", "transitionLeave", "component", "componentProps"];
var defaultKey = "animate_".concat(Date.now());

function getChildrenFromProps(props) {
  var children = props.children;

  if ( /*#__PURE__*/(0, _react.isValidElement)(children)) {
    if (!children.key) {
      return /*#__PURE__*/(0, _react.cloneElement)(children, {
        key: defaultKey
      });
    }
  }

  return children;
}

var Animate = /*#__PURE__*/function (_PureComponent) {
  (0, _inherits2["default"])(Animate, _PureComponent);

  var _super = (0, _createSuper2["default"])(Animate);

  function Animate() {
    var _this;

    (0, _classCallCheck2["default"])(this, Animate);
    _this = _super.apply(this, arguments);
    _this.currentlyAnimatingKeys = {};
    _this.keysToEnter = [];
    _this.keysToLeave = [];
    _this.state = {
      children: (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(_this.props))
    };
    _this.childrenRefs = {};

    _this.performEnter = function (key) {
      var childRef = _this.childrenRefs[key];

      if (childRef) {
        _this.currentlyAnimatingKeys[key] = true;
        childRef.componentWillEnter(_this.handleDoneAdding.bind((0, _assertThisInitialized2["default"])(_this), key, 'enter'));
      }
    };

    _this.performAppear = function (key) {
      var childRef = _this.childrenRefs[key];

      if (childRef) {
        _this.currentlyAnimatingKeys[key] = true;
        childRef.componentWillAppear(_this.handleDoneAdding.bind((0, _assertThisInitialized2["default"])(_this), key, 'appear'));
      }
    };

    _this.handleDoneAdding = function (key, type, childRef) {
      var _assertThisInitialize = (0, _assertThisInitialized2["default"])(_this),
          props = _assertThisInitialize.props;

      var exclusive = props.exclusive,
          _props$onAppear = props.onAppear,
          onAppear = _props$onAppear === void 0 ? _noop["default"] : _props$onAppear,
          _props$onEnd = props.onEnd,
          onEnd = _props$onEnd === void 0 ? _noop["default"] : _props$onEnd,
          _props$onEnter = props.onEnter,
          onEnter = _props$onEnter === void 0 ? _noop["default"] : _props$onEnter;
      delete _this.currentlyAnimatingKeys[key];

      if (exclusive && props !== _this.nextProps) {
        return;
      }

      if (!_this.isValidChildByKey((0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(props)), key)) {
        _this.performLeave(key);
      } else if (type === 'appear') {
        if (_util["default"].allowAppearCallback(props)) {
          onAppear(key, childRef);
          onEnd(key, true, childRef);
        }
      } else if (_util["default"].allowEnterCallback(props)) {
        onEnter(key, childRef);
        onEnd(key, true, childRef);
      }
    };

    _this.performLeave = function (key) {
      var childRef = _this.childrenRefs[key];

      if (childRef) {
        _this.currentlyAnimatingKeys[key] = true;
        childRef.componentWillLeave(_this.handleDoneLeaving.bind((0, _assertThisInitialized2["default"])(_this), key));
      }
    };

    _this.handleDoneLeaving = function (key, childRef) {
      var _assertThisInitialize2 = (0, _assertThisInitialized2["default"])(_this),
          props = _assertThisInitialize2.props,
          children = _assertThisInitialize2.state.children;

      var exclusive = props.exclusive,
          _props$onEnd2 = props.onEnd,
          onEnd = _props$onEnd2 === void 0 ? _noop["default"] : _props$onEnd2,
          _props$onLeave = props.onLeave,
          onLeave = _props$onLeave === void 0 ? _noop["default"] : _props$onLeave,
          hiddenProp = props.hiddenProp;
      delete _this.currentlyAnimatingKeys[key];

      if (exclusive && props !== _this.nextProps) {
        return;
      }

      var currentChildren = (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(props));

      if (_this.isValidChildByKey(currentChildren, key)) {
        _this.performEnter(key);
      } else {
        var end = function end() {
          if (_util["default"].allowLeaveCallback(props)) {
            onLeave(key, childRef);
            onEnd(key, false, childRef);
          }
        };

        if (!(0, _ChildrenUtils.isSameChildren)(children, currentChildren, hiddenProp)) {
          _this.setState({
            children: currentChildren
          }, end);
        } else {
          end();
        }
      }
    };

    return _this;
  }

  (0, _createClass2["default"])(Animate, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      var _this2 = this;

      var hiddenProp = this.props.hiddenProp;
      var children = this.state.children;

      if (hiddenProp) {
        children = children.filter(function (child) {
          return !child.props[hiddenProp];
        });
      }

      children.forEach(function (child) {
        if (child && child.key) {
          _this2.performAppear(child.key);
        }
      });
    }
  }, {
    key: "componentWillReceiveProps",
    value: function componentWillReceiveProps(nextProps) {
      var _this3 = this;

      this.nextProps = nextProps;
      var nextChildren = (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(nextProps));
      var _this$props = this.props,
          exclusive = _this$props.exclusive,
          hiddenProp = _this$props.hiddenProp;
      var children = this.state.children;
      var currentlyAnimatingKeys = this.currentlyAnimatingKeys;

      if (exclusive) {
        Object.keys(currentlyAnimatingKeys).forEach(function (key) {
          return _this3.stop(key);
        });
      }

      var currentChildren = exclusive ? (0, _ChildrenUtils.toArrayChildren)(getChildrenFromProps(this.props)) : children;
      var newChildren = [];

      if (hiddenProp) {
        nextChildren.forEach(function (nextChild) {
          if (nextChild) {
            var newChild;
            var currentChild = (0, _ChildrenUtils.findChildInChildrenByKey)(currentChildren, nextChild.key);

            if (nextChild.props[hiddenProp] && currentChild && !currentChild.props[hiddenProp]) {
              newChild = /*#__PURE__*/(0, _react.cloneElement)(nextChild, (0, _defineProperty2["default"])({}, hiddenProp, false));
            } else {
              newChild = nextChild;
            }

            if (newChild) {
              newChildren.push(newChild);
            }
          }
        });
        newChildren = (0, _ChildrenUtils.mergeChildren)(currentChildren, newChildren);
      } else {
        newChildren = (0, _ChildrenUtils.mergeChildren)(currentChildren, nextChildren);
      }

      this.setState({
        children: newChildren
      });
      nextChildren.forEach(function (child) {
        var key = child && child.key;

        if (key) {
          if (child && currentlyAnimatingKeys[key]) {
            return;
          }

          var hasPrev = child && (0, _ChildrenUtils.findChildInChildrenByKey)(currentChildren, key);

          if (hiddenProp) {
            var showInNext = !child.props[hiddenProp];

            if (hasPrev) {
              var showInNow = (0, _ChildrenUtils.findShownChildInChildrenByKey)(currentChildren, key, hiddenProp);

              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 (key) {
          if (child && currentlyAnimatingKeys[key]) {
            return;
          }

          var hasNext = child && (0, _ChildrenUtils.findChildInChildrenByKey)(nextChildren, key);

          if (hiddenProp) {
            var showInNow = !child.props[hiddenProp];

            if (hasNext) {
              var showInNext = (0, _ChildrenUtils.findShownChildInChildrenByKey)(nextChildren, key, hiddenProp);

              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 hiddenProp = this.props.hiddenProp;

      if (hiddenProp) {
        return !!(0, _ChildrenUtils.findShownChildInChildrenByKey)(currentChildren, key, hiddenProp);
      }

      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 animation = props.animation,
          transitionName = props.transitionName,
          transitionEnter = props.transitionEnter,
          transitionAppear = props.transitionAppear,
          transitionLeave = props.transitionLeave,
          Cmp = props.component,
          componentProps = props.componentProps,
          otherProps = (0, _objectWithoutProperties2["default"])(props, _excluded);
      var stateChildren = this.state.children;
      var children = [];

      if (stateChildren) {
        children = stateChildren.map(function (child) {
          if (child === null || child === undefined) {
            return child;
          }

          if (!child.key) {
            throw new Error('must set key for animate children');
          }

          return /*#__PURE__*/(0, _react.createElement)(_AnimateChild["default"], {
            key: child.key,
            ref: function ref(node) {
              if (child.key) {
                _this4.childrenRefs[child.key] = node;
              }
            },
            animation: animation,
            transitionName: transitionName,
            transitionEnter: transitionEnter,
            transitionAppear: transitionAppear,
            transitionLeave: transitionLeave
          }, child);
        });
      }

      if (Cmp) {
        var passedProps = (0, _omit["default"])(otherProps, ['exclusive', 'onEnd', 'onEnter', 'onLeave', 'onAppear', 'hiddenProp']);
        return /*#__PURE__*/(0, _react.createElement)(Cmp, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, passedProps), componentProps), children);
      }

      return children[0] || null;
    }
  }]);
  return Animate;
}(_react.PureComponent);

exports["default"] = Animate;
Animate.displayName = 'Animate';
Animate.defaultProps = {
  component: 'span',
  transitionEnter: true,
  transitionLeave: true,
  transitionAppear: false
};
//# sourceMappingURL=Animate.js.map
