"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); 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 _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _createSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/createSuper")); var _react = _interopRequireWildcard(require("react")); var _raf = _interopRequireDefault(require("raf")); var _rcAlign = _interopRequireDefault(require("rc-align")); var _ref5 = require("rc-util/lib/ref"); var _classnames = _interopRequireDefault(require("classnames")); var _rcMotion = _interopRequireDefault(require("rc-motion")); var _PopupInner = _interopRequireDefault(require("./PopupInner")); var _legacyUtil = require("./utils/legacyUtil"); /* eslint-disable no-param-reassign */ function supportMotion(motion) { return motion && motion.motionName; } var Popup = /*#__PURE__*/function (_Component) { (0, _inherits2.default)(Popup, _Component); var _super = (0, _createSuper2.default)(Popup); function Popup() { var _this; (0, _classCallCheck2.default)(this, Popup); _this = _super.apply(this, arguments); _this.state = { targetWidth: undefined, targetHeight: undefined, status: null, prevVisible: null, alignClassName: null, inMotion: false }; _this.popupRef = _react.default.createRef(); _this.alignRef = _react.default.createRef(); _this.nextFrameState = null; _this.nextFrameId = null; _this.onAlign = function (popupDomNode, align) { var status = _this.state.status; var _this$props = _this.props, getClassNameFromAlign = _this$props.getClassNameFromAlign, onAlign = _this$props.onAlign; var alignClassName = getClassNameFromAlign(align); if (status === 'align') { _this.setState({ alignClassName: alignClassName, status: 'aligned' }, function () { _this.alignRef.current.forceAlign(); }); } else if (status === 'aligned') { _this.setState({ alignClassName: alignClassName, status: 'afterAlign' }); onAlign(popupDomNode, align); } else { _this.setState({ alignClassName: alignClassName }); } }; _this.onMotionEnd = function () { var visible = _this.props.visible; _this.setState({ status: visible ? 'AfterMotion' : 'stable', inMotion: false }); }; _this.setStateOnNextFrame = function (state) { _this.cancelFrameState(); _this.nextFrameState = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, _this.nextFrameState), state); _this.nextFrameId = (0, _raf.default)(function () { var submitState = (0, _objectSpread2.default)({}, _this.nextFrameState); _this.nextFrameState = null; _this.setState(submitState); }); }; _this.getMotion = function () { return (0, _objectSpread2.default)({}, (0, _legacyUtil.getMotion)(_this.props)); }; // `target` on `rc-align` can accept as a function to get the bind element or a point. // ref: https://www.npmjs.com/package/rc-align _this.getAlignTarget = function () { var _this$props2 = _this.props, point = _this$props2.point, getRootDomNode = _this$props2.getRootDomNode; if (point) { return point; } return getRootDomNode; }; _this.cancelFrameState = function () { _raf.default.cancel(_this.nextFrameId); }; _this.renderPopupElement = function () { var _this$state = _this.state, status = _this$state.status, targetHeight = _this$state.targetHeight, targetWidth = _this$state.targetWidth, alignClassName = _this$state.alignClassName; var _this$props3 = _this.props, prefixCls = _this$props3.prefixCls, className = _this$props3.className, style = _this$props3.style, stretch = _this$props3.stretch, visible = _this$props3.visible, align = _this$props3.align, destroyPopupOnHide = _this$props3.destroyPopupOnHide, onMouseEnter = _this$props3.onMouseEnter, onMouseLeave = _this$props3.onMouseLeave, onMouseDown = _this$props3.onMouseDown, onTouchStart = _this$props3.onTouchStart, children = _this$props3.children; var mergedClassName = (0, _classnames.default)(prefixCls, className, alignClassName); var hiddenClassName = "".concat(prefixCls, "-hidden"); // ================== Style ================== var sizeStyle = {}; if (stretch) { // Stretch with target if (stretch.indexOf('height') !== -1) { sizeStyle.height = targetHeight; } else if (stretch.indexOf('minHeight') !== -1) { sizeStyle.minHeight = targetHeight; } if (stretch.indexOf('width') !== -1) { sizeStyle.width = targetWidth; } else if (stretch.indexOf('minWidth') !== -1) { sizeStyle.minWidth = targetWidth; } } var mergedStyle = (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, sizeStyle), _this.getZIndexStyle()), style), {}, { opacity: status === 'stable' || !visible ? undefined : 0 }); // ================= Motions ================= var mergedMotion = _this.getMotion(); var mergedMotionVisible = visible; if (visible && status !== 'beforeMotion' && status !== 'motion' && status !== 'stable') { mergedMotion.motionAppear = false; mergedMotion.motionEnter = false; mergedMotion.motionLeave = false; } if (status === 'afterAlign' || status === 'beforeMotion') { mergedMotionVisible = false; } // Update trigger to tell if is in motion ['onEnterStart', 'onAppearStart', 'onLeaveStart'].forEach(function (event) { var originFunc = mergedMotion === null || mergedMotion === void 0 ? void 0 : mergedMotion[event]; mergedMotion[event] = function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } originFunc === null || originFunc === void 0 ? void 0 : originFunc.apply(void 0, args); _this.setState({ inMotion: true }); }; }); // ================== Align ================== var mergedAlignDisabled = !visible || status !== 'align' && status !== 'aligned' && status !== 'stable'; // ================== Popup ================== var mergedPopupVisible = true; if (status === 'stable') { mergedPopupVisible = visible; } // Only remove popup since mask may still need animation if (destroyPopupOnHide && !mergedPopupVisible) { return null; } return _react.default.createElement(_rcMotion.default, Object.assign({ visible: mergedMotionVisible }, mergedMotion, { removeOnLeave: false, onEnterEnd: _this.onMotionEnd, onLeaveEnd: _this.onMotionEnd, leavedClassName: hiddenClassName }), function (_ref, motionRef) { var motionStyle = _ref.style, motionClassName = _ref.className; return _react.default.createElement(_rcAlign.default, { target: _this.getAlignTarget(), key: "popup", ref: _this.alignRef, monitorWindowResize: true, disabled: mergedAlignDisabled, align: align, onAlign: _this.onAlign }, _react.default.createElement(_PopupInner.default, { prefixCls: prefixCls, className: (0, _classnames.default)(mergedClassName, motionClassName), ref: (0, _ref5.composeRef)(motionRef, _this.popupRef), onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onTouchStart: onTouchStart, style: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, mergedStyle), motionStyle) }, children)); }); }; _this.renderMaskElement = function () { var _this$props4 = _this.props, mask = _this$props4.mask, maskMotion = _this$props4.maskMotion, maskTransitionName = _this$props4.maskTransitionName, maskAnimation = _this$props4.maskAnimation, prefixCls = _this$props4.prefixCls, visible = _this$props4.visible; if (!mask) { return null; } var motion = {}; if (maskMotion && maskMotion.motionName) { motion = (0, _objectSpread2.default)({ motionAppear: true }, (0, _legacyUtil.getMotion)({ motion: maskMotion, prefixCls: prefixCls, transitionName: maskTransitionName, animation: maskAnimation })); } return _react.default.createElement(_rcMotion.default, Object.assign({}, motion, { visible: visible, removeOnLeave: true }), function (_ref2) { var className = _ref2.className; return _react.default.createElement("div", { style: _this.getZIndexStyle(), key: "mask", className: (0, _classnames.default)("".concat(prefixCls, "-mask"), className) }); }); }; return _this; } (0, _createClass2.default)(Popup, [{ key: "componentDidMount", value: function componentDidMount() { this.componentDidUpdate(); } }, { key: "componentDidUpdate", value: function componentDidUpdate() { var status = this.state.status; var _this$props5 = this.props, getRootDomNode = _this$props5.getRootDomNode, visible = _this$props5.visible, stretch = _this$props5.stretch; // If there is a pending state update, cancel it, a new one will be set if necessary this.cancelFrameState(); if (visible && status !== 'stable') { switch (status) { case null: { this.setStateOnNextFrame({ status: stretch ? 'measure' : 'align' }); break; } case 'afterAlign': { this.setStateOnNextFrame({ status: supportMotion(this.getMotion()) ? 'beforeMotion' : 'stable' }); break; } case 'AfterMotion': { this.setStateOnNextFrame({ status: 'stable' }); break; } default: { // Go to next status var queue = ['measure', 'align', null, 'beforeMotion', 'motion']; var index = queue.indexOf(status); var nextStatus = queue[index + 1]; if (index !== -1 && nextStatus) { this.setStateOnNextFrame({ status: nextStatus }); } } } } // Measure stretch size if (status === 'measure') { var $ele = getRootDomNode(); if ($ele) { this.setStateOnNextFrame({ targetHeight: $ele.offsetHeight, targetWidth: $ele.offsetWidth }); } } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { this.cancelFrameState(); } }, { key: "getZIndexStyle", value: function getZIndexStyle() { var zIndex = this.props.zIndex; return { zIndex: zIndex }; } }, { key: "render", value: function render() { return _react.default.createElement("div", null, this.renderMaskElement(), this.renderPopupElement()); } }], [{ key: "getDerivedStateFromProps", value: function getDerivedStateFromProps(_ref3, _ref4) { var visible = _ref3.visible, props = (0, _objectWithoutProperties2.default)(_ref3, ["visible"]); var prevVisible = _ref4.prevVisible, status = _ref4.status, inMotion = _ref4.inMotion; var newState = { prevVisible: visible, status: status }; var mergedMotion = (0, _legacyUtil.getMotion)(props); if (prevVisible === null && visible === false) { // Init render should always be stable newState.status = 'stable'; newState.inMotion = false; } else if (visible !== prevVisible) { newState.inMotion = false; if (visible || supportMotion(mergedMotion) && inMotion) { newState.status = null; } else { newState.status = 'stable'; } if (visible) { newState.alignClassName = null; } } return newState; } }]); return Popup; }(_react.Component); var _default = Popup; /* eslint-enable */ exports.default = _default;