You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
372 lines
12 KiB
372 lines
12 KiB
"use strict";
|
|
|
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.genCSSMotion = genCSSMotion;
|
|
exports.default = void 0;
|
|
|
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
|
|
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
|
|
|
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 _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
|
|
|
|
var _react = _interopRequireDefault(require("react"));
|
|
|
|
var _findDOMNode = _interopRequireDefault(require("rc-util/lib/Dom/findDOMNode"));
|
|
|
|
var _ref2 = require("rc-util/lib/ref");
|
|
|
|
var _classnames = _interopRequireDefault(require("classnames"));
|
|
|
|
var _raf = _interopRequireDefault(require("raf"));
|
|
|
|
var _motion = require("./util/motion");
|
|
|
|
/* eslint-disable react/default-props-match-prop-types, react/no-multi-comp, react/prop-types */
|
|
var STATUS_NONE = 'none';
|
|
var STATUS_APPEAR = 'appear';
|
|
var STATUS_ENTER = 'enter';
|
|
var STATUS_LEAVE = 'leave';
|
|
/**
|
|
* `transitionSupport` is used for none transition test case.
|
|
* Default we use browser transition event support check.
|
|
*/
|
|
|
|
function genCSSMotion(config) {
|
|
var transitionSupport = config;
|
|
var forwardRef = !!_react.default.forwardRef;
|
|
|
|
if ((0, _typeof2.default)(config) === 'object') {
|
|
transitionSupport = config.transitionSupport;
|
|
forwardRef = 'forwardRef' in config ? config.forwardRef : forwardRef;
|
|
}
|
|
|
|
function isSupportTransition(props) {
|
|
return !!(props.motionName && transitionSupport);
|
|
}
|
|
|
|
var CSSMotion = /*#__PURE__*/function (_React$Component) {
|
|
(0, _inherits2.default)(CSSMotion, _React$Component);
|
|
|
|
var _super = (0, _createSuper2.default)(CSSMotion);
|
|
|
|
function CSSMotion() {
|
|
var _this;
|
|
|
|
(0, _classCallCheck2.default)(this, CSSMotion);
|
|
_this = _super.apply(this, arguments);
|
|
_this.$cacheEle = null;
|
|
_this.node = null;
|
|
_this.raf = null;
|
|
_this.destroyed = false;
|
|
_this.deadlineId = null;
|
|
_this.state = {
|
|
status: STATUS_NONE,
|
|
statusActive: false,
|
|
newStatus: false,
|
|
statusStyle: null
|
|
};
|
|
|
|
_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) {
|
|
if (event && !event.deadline && event.target !== _this.getElement()) {
|
|
// event exists
|
|
// not initiated by deadline
|
|
// transitionend not fired by inner elements
|
|
return;
|
|
}
|
|
|
|
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;
|
|
(0, _ref2.fillRef)(internalRef, node);
|
|
};
|
|
|
|
_this.getElement = function () {
|
|
try {
|
|
return (0, _findDOMNode.default)(_this.node || (0, _assertThisInitialized2.default)(_this));
|
|
} catch (e) {
|
|
/**
|
|
* Fallback to cache element.
|
|
* This is only happen when `motionDeadline` trigger but element removed.
|
|
*/
|
|
return _this.$cacheEle;
|
|
}
|
|
};
|
|
|
|
_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;
|
|
|
|
if (callback) {
|
|
nextStep = function nextStep() {
|
|
_this.nextFrame(callback);
|
|
};
|
|
}
|
|
|
|
_this.setState((0, _objectSpread2.default)({
|
|
statusStyle: (0, _typeof2.default)(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;
|
|
var motionDeadline = _this.props.motionDeadline;
|
|
|
|
_this.updateStatus(styleFunc, {
|
|
statusActive: true
|
|
});
|
|
|
|
if (motionDeadline > 0) {
|
|
_this.deadlineId = setTimeout(function () {
|
|
_this.onMotionEnd({
|
|
deadline: true
|
|
});
|
|
}, motionDeadline);
|
|
}
|
|
});
|
|
};
|
|
|
|
_this.nextFrame = function (func) {
|
|
_this.cancelNextFrame();
|
|
|
|
_this.raf = (0, _raf.default)(func);
|
|
};
|
|
|
|
_this.cancelNextFrame = function () {
|
|
if (_this.raf) {
|
|
_raf.default.cancel(_this.raf);
|
|
|
|
_this.raf = null;
|
|
}
|
|
};
|
|
|
|
return _this;
|
|
}
|
|
|
|
(0, _createClass2.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();
|
|
clearTimeout(this.deadlineId);
|
|
}
|
|
}, {
|
|
key: "render",
|
|
value: function render() {
|
|
var _classNames;
|
|
|
|
var _this$state3 = this.state,
|
|
status = _this$state3.status,
|
|
statusActive = _this$state3.statusActive,
|
|
statusStyle = _this$state3.statusStyle;
|
|
var _this$props3 = this.props,
|
|
children = _this$props3.children,
|
|
motionName = _this$props3.motionName,
|
|
visible = _this$props3.visible,
|
|
removeOnLeave = _this$props3.removeOnLeave,
|
|
leavedClassName = _this$props3.leavedClassName,
|
|
eventProps = _this$props3.eventProps;
|
|
if (!children) return null;
|
|
|
|
if (status === STATUS_NONE || !isSupportTransition(this.props)) {
|
|
if (visible) {
|
|
return children((0, _objectSpread2.default)({}, eventProps), this.setNodeRef);
|
|
}
|
|
|
|
if (!removeOnLeave) {
|
|
return children((0, _objectSpread2.default)((0, _objectSpread2.default)({}, eventProps), {}, {
|
|
className: leavedClassName
|
|
}), this.setNodeRef);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
return children((0, _objectSpread2.default)((0, _objectSpread2.default)({}, eventProps), {}, {
|
|
className: (0, _classnames.default)((0, _motion.getTransitionName)(motionName, status), (_classNames = {}, (0, _defineProperty2.default)(_classNames, (0, _motion.getTransitionName)(motionName, "".concat(status, "-active")), statusActive), (0, _defineProperty2.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;
|
|
}(_react.default.Component);
|
|
|
|
CSSMotion.defaultProps = {
|
|
visible: true,
|
|
motionEnter: true,
|
|
motionAppear: true,
|
|
motionLeave: true,
|
|
removeOnLeave: true
|
|
};
|
|
|
|
if (!forwardRef) {
|
|
return CSSMotion;
|
|
}
|
|
|
|
return _react.default.forwardRef(function (props, ref) {
|
|
return _react.default.createElement(CSSMotion, Object.assign({
|
|
internalRef: ref
|
|
}, props));
|
|
});
|
|
}
|
|
|
|
var _default = genCSSMotion(_motion.supportTransition);
|
|
|
|
exports.default = _default; |