2020-05-19 11:43:42 +03:00

387 lines
13 KiB
JavaScript

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MotionPropTypes = undefined;
var _defineProperty2 = require('babel-runtime/helpers/defineProperty');
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
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);
exports.genCSSMotion = genCSSMotion;
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _reactLifecyclesCompat = require('react-lifecycles-compat');
var _findDOMNode = require('rc-util/lib/Dom/findDOMNode');
var _findDOMNode2 = _interopRequireDefault(_findDOMNode);
var _classnames = require('classnames');
var _classnames2 = _interopRequireDefault(_classnames);
var _raf = require('raf');
var _raf2 = _interopRequireDefault(_raf);
var _motion = require('./util/motion');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var STATUS_NONE = 'none'; /* eslint-disable react/default-props-match-prop-types, react/no-multi-comp */
var STATUS_APPEAR = 'appear';
var STATUS_ENTER = 'enter';
var STATUS_LEAVE = 'leave';
var MotionPropTypes = exports.MotionPropTypes = {
eventProps: _propTypes2['default'].object, // Internal usage. Only pass by CSSMotionList
visible: _propTypes2['default'].bool,
children: _propTypes2['default'].func,
motionName: _propTypes2['default'].oneOfType([_propTypes2['default'].string, _propTypes2['default'].object]),
motionAppear: _propTypes2['default'].bool,
motionEnter: _propTypes2['default'].bool,
motionLeave: _propTypes2['default'].bool,
motionLeaveImmediately: _propTypes2['default'].bool, // Trigger leave motion immediately
removeOnLeave: _propTypes2['default'].bool,
leavedClassName: _propTypes2['default'].string,
onAppearStart: _propTypes2['default'].func,
onAppearActive: _propTypes2['default'].func,
onAppearEnd: _propTypes2['default'].func,
onEnterStart: _propTypes2['default'].func,
onEnterActive: _propTypes2['default'].func,
onEnterEnd: _propTypes2['default'].func,
onLeaveStart: _propTypes2['default'].func,
onLeaveActive: _propTypes2['default'].func,
onLeaveEnd: _propTypes2['default'].func
};
/**
* `transitionSupport` is used for none transition test case.
* Default we use browser transition event support check.
*/
function genCSSMotion(config) {
var transitionSupport = config;
var forwardRef = !!_react2['default'].forwardRef;
if (typeof config === 'object') {
transitionSupport = config.transitionSupport;
forwardRef = 'forwardRef' in config ? config.forwardRef : forwardRef;
}
function isSupportTransition(props) {
return !!(props.motionName && transitionSupport);
}
var CSSMotion = function (_React$Component) {
(0, _inherits3['default'])(CSSMotion, _React$Component);
function CSSMotion() {
(0, _classCallCheck3['default'])(this, CSSMotion);
var _this = (0, _possibleConstructorReturn3['default'])(this, (CSSMotion.__proto__ || Object.getPrototypeOf(CSSMotion)).call(this));
_this.onDomUpdate = function () {
var _this$state = _this.state,
status = _this$state.status,
newStatus = _this$state.newStatus;
var _this$props = _this.props,
onAppearStart = _this$props.onAppearStart,
onEnterStart = _this$props.onEnterStart,
onLeaveStart = _this$props.onLeaveStart,
onAppearActive = _this$props.onAppearActive,
onEnterActive = _this$props.onEnterActive,
onLeaveActive = _this$props.onLeaveActive,
motionAppear = _this$props.motionAppear,
motionEnter = _this$props.motionEnter,
motionLeave = _this$props.motionLeave;
if (!isSupportTransition(_this.props)) {
return;
}
// Event injection
var $ele = _this.getElement();
if (_this.$cacheEle !== $ele) {
_this.removeEventListener(_this.$cacheEle);
_this.addEventListener($ele);
_this.$cacheEle = $ele;
}
// Init status
if (newStatus && status === STATUS_APPEAR && motionAppear) {
_this.updateStatus(onAppearStart, null, null, function () {
_this.updateActiveStatus(onAppearActive, STATUS_APPEAR);
});
} else if (newStatus && status === STATUS_ENTER && motionEnter) {
_this.updateStatus(onEnterStart, null, null, function () {
_this.updateActiveStatus(onEnterActive, STATUS_ENTER);
});
} else if (newStatus && status === STATUS_LEAVE && motionLeave) {
_this.updateStatus(onLeaveStart, null, null, function () {
_this.updateActiveStatus(onLeaveActive, STATUS_LEAVE);
});
}
};
_this.onMotionEnd = function (event) {
var _this$state2 = _this.state,
status = _this$state2.status,
statusActive = _this$state2.statusActive;
var _this$props2 = _this.props,
onAppearEnd = _this$props2.onAppearEnd,
onEnterEnd = _this$props2.onEnterEnd,
onLeaveEnd = _this$props2.onLeaveEnd;
if (status === STATUS_APPEAR && statusActive) {
_this.updateStatus(onAppearEnd, { status: STATUS_NONE }, event);
} else if (status === STATUS_ENTER && statusActive) {
_this.updateStatus(onEnterEnd, { status: STATUS_NONE }, event);
} else if (status === STATUS_LEAVE && statusActive) {
_this.updateStatus(onLeaveEnd, { status: STATUS_NONE }, event);
}
};
_this.setNodeRef = function (node) {
var internalRef = _this.props.internalRef;
_this.node = node;
if (typeof internalRef === 'function') {
internalRef(node);
} else if (internalRef && 'current' in internalRef) {
internalRef.current = node;
}
};
_this.getElement = function () {
return (0, _findDOMNode2['default'])(_this.node || _this);
};
_this.addEventListener = function ($ele) {
if (!$ele) return;
$ele.addEventListener(_motion.transitionEndName, _this.onMotionEnd);
$ele.addEventListener(_motion.animationEndName, _this.onMotionEnd);
};
_this.removeEventListener = function ($ele) {
if (!$ele) return;
$ele.removeEventListener(_motion.transitionEndName, _this.onMotionEnd);
$ele.removeEventListener(_motion.animationEndName, _this.onMotionEnd);
};
_this.updateStatus = function (styleFunc, additionalState, event, callback) {
var statusStyle = styleFunc ? styleFunc(_this.getElement(), event) : null;
if (statusStyle === false || _this._destroyed) return;
var nextStep = void 0;
if (callback) {
nextStep = function nextStep() {
_this.nextFrame(callback);
};
}
_this.setState((0, _extends3['default'])({
statusStyle: typeof statusStyle === 'object' ? statusStyle : null,
newStatus: false
}, additionalState), nextStep); // Trigger before next frame & after `componentDidMount`
};
_this.updateActiveStatus = function (styleFunc, currentStatus) {
// `setState` use `postMessage` to trigger at the end of frame.
// Let's use requestAnimationFrame to update new state in next frame.
_this.nextFrame(function () {
var status = _this.state.status;
if (status !== currentStatus) return;
_this.updateStatus(styleFunc, { statusActive: true });
});
};
_this.nextFrame = function (func) {
_this.cancelNextFrame();
_this.raf = (0, _raf2['default'])(func);
};
_this.cancelNextFrame = function () {
if (_this.raf) {
_raf2['default'].cancel(_this.raf);
_this.raf = null;
}
};
_this.state = {
status: STATUS_NONE,
statusActive: false,
newStatus: false,
statusStyle: null
};
_this.$cacheEle = null;
_this.node = null;
_this.raf = null;
return _this;
}
(0, _createClass3['default'])(CSSMotion, [{
key: 'componentDidMount',
value: function componentDidMount() {
this.onDomUpdate();
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate() {
this.onDomUpdate();
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this._destroyed = true;
this.removeEventListener(this.$cacheEle);
this.cancelNextFrame();
}
}, {
key: 'render',
value: function render() {
var _classNames;
var _state = this.state,
status = _state.status,
statusActive = _state.statusActive,
statusStyle = _state.statusStyle;
var _props = this.props,
children = _props.children,
motionName = _props.motionName,
visible = _props.visible,
removeOnLeave = _props.removeOnLeave,
leavedClassName = _props.leavedClassName,
eventProps = _props.eventProps;
if (!children) return null;
if (status === STATUS_NONE || !isSupportTransition(this.props)) {
if (visible) {
return children((0, _extends3['default'])({}, eventProps), this.setNodeRef);
} else if (!removeOnLeave) {
return children((0, _extends3['default'])({}, eventProps, { className: leavedClassName }), this.setNodeRef);
}
return null;
}
return children((0, _extends3['default'])({}, eventProps, {
className: (0, _classnames2['default'])((_classNames = {}, (0, _defineProperty3['default'])(_classNames, (0, _motion.getTransitionName)(motionName, status), status !== STATUS_NONE), (0, _defineProperty3['default'])(_classNames, (0, _motion.getTransitionName)(motionName, status + '-active'), status !== STATUS_NONE && statusActive), (0, _defineProperty3['default'])(_classNames, motionName, typeof motionName === 'string'), _classNames)),
style: statusStyle
}), this.setNodeRef);
}
}], [{
key: 'getDerivedStateFromProps',
value: function getDerivedStateFromProps(props, _ref) {
var prevProps = _ref.prevProps,
prevStatus = _ref.status;
if (!isSupportTransition(props)) return {};
var visible = props.visible,
motionAppear = props.motionAppear,
motionEnter = props.motionEnter,
motionLeave = props.motionLeave,
motionLeaveImmediately = props.motionLeaveImmediately;
var newState = {
prevProps: props
};
// Clean up status if prop set to false
if (prevStatus === STATUS_APPEAR && !motionAppear || prevStatus === STATUS_ENTER && !motionEnter || prevStatus === STATUS_LEAVE && !motionLeave) {
newState.status = STATUS_NONE;
newState.statusActive = false;
newState.newStatus = false;
}
// Appear
if (!prevProps && visible && motionAppear) {
newState.status = STATUS_APPEAR;
newState.statusActive = false;
newState.newStatus = true;
}
// Enter
if (prevProps && !prevProps.visible && visible && motionEnter) {
newState.status = STATUS_ENTER;
newState.statusActive = false;
newState.newStatus = true;
}
// Leave
if (prevProps && prevProps.visible && !visible && motionLeave || !prevProps && motionLeaveImmediately && !visible && motionLeave) {
newState.status = STATUS_LEAVE;
newState.statusActive = false;
newState.newStatus = true;
}
return newState;
}
}]);
return CSSMotion;
}(_react2['default'].Component);
CSSMotion.propTypes = (0, _extends3['default'])({}, MotionPropTypes, {
internalRef: _propTypes2['default'].oneOfType([_propTypes2['default'].object, _propTypes2['default'].func])
});
CSSMotion.defaultProps = {
visible: true,
motionEnter: true,
motionAppear: true,
motionLeave: true,
removeOnLeave: true
};
(0, _reactLifecyclesCompat.polyfill)(CSSMotion);
if (!forwardRef) {
return CSSMotion;
}
return _react2['default'].forwardRef(function (props, ref) {
return _react2['default'].createElement(CSSMotion, (0, _extends3['default'])({ internalRef: ref }, props));
});
}
exports['default'] = genCSSMotion(_motion.supportTransition);