rc-trigger
Version:
base abstract trigger component for react
244 lines (195 loc) • 8.63 kB
JavaScript
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var React = _interopRequireWildcard(require("react"));
var _rcAlign = _interopRequireDefault(require("rc-align"));
var _useLayoutEffect = _interopRequireDefault(require("rc-util/lib/hooks/useLayoutEffect"));
var _rcMotion = _interopRequireDefault(require("rc-motion"));
var _classnames = _interopRequireDefault(require("classnames"));
var _useVisibleStatus3 = _interopRequireDefault(require("./useVisibleStatus"));
var _legacyUtil = require("../utils/legacyUtil");
var _useStretchStyle3 = _interopRequireDefault(require("./useStretchStyle"));
var PopupInner = /*#__PURE__*/React.forwardRef(function (props, ref) {
var visible = props.visible,
prefixCls = props.prefixCls,
className = props.className,
style = props.style,
children = props.children,
zIndex = props.zIndex,
stretch = props.stretch,
destroyPopupOnHide = props.destroyPopupOnHide,
forceRender = props.forceRender,
align = props.align,
point = props.point,
getRootDomNode = props.getRootDomNode,
getClassNameFromAlign = props.getClassNameFromAlign,
onAlign = props.onAlign,
onMouseEnter = props.onMouseEnter,
onMouseLeave = props.onMouseLeave,
onMouseDown = props.onMouseDown,
onTouchStart = props.onTouchStart,
onClick = props.onClick;
var alignRef = (0, React.useRef)();
var elementRef = (0, React.useRef)();
var _useState = (0, React.useState)(),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
alignedClassName = _useState2[0],
setAlignedClassName = _useState2[1]; // ======================= Measure ========================
var _useStretchStyle = (0, _useStretchStyle3.default)(stretch),
_useStretchStyle2 = (0, _slicedToArray2.default)(_useStretchStyle, 2),
stretchStyle = _useStretchStyle2[0],
measureStretchStyle = _useStretchStyle2[1];
function doMeasure() {
if (stretch) {
measureStretchStyle(getRootDomNode());
}
} // ======================== Status ========================
var _useVisibleStatus = (0, _useVisibleStatus3.default)(visible, doMeasure),
_useVisibleStatus2 = (0, _slicedToArray2.default)(_useVisibleStatus, 2),
status = _useVisibleStatus2[0],
goNextStatus = _useVisibleStatus2[1]; // ======================== Aligns ========================
/**
* `alignedClassName` may modify `source` size,
* which means one time align may not move to the correct position at once.
*
* We will reset `alignTimes` for each status switch to `alignPre`
* and let `rc-align` to align for multiple times to ensure get final stable place.
* Currently we mark `alignTimes < 2` repeat align, it will increase if user report for align issue.
*
* Update:
* In React 18. `rc-align` effect of align may faster than ref called trigger `forceAlign`.
* We adjust this to `alignTimes < 2`.
* We need refactor `rc-align` to support mark of `forceAlign` call if this still happen.
*/
var _useState3 = (0, React.useState)(0),
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
alignTimes = _useState4[0],
setAlignTimes = _useState4[1];
var prepareResolveRef = (0, React.useRef)();
(0, _useLayoutEffect.default)(function () {
if (status === 'alignPre') {
setAlignTimes(0);
}
}, [status]); // `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
function getAlignTarget() {
if (point) {
return point;
}
return getRootDomNode;
}
function forceAlign() {
var _alignRef$current;
(_alignRef$current = alignRef.current) === null || _alignRef$current === void 0 ? void 0 : _alignRef$current.forceAlign();
}
function onInternalAlign(popupDomNode, matchAlign) {
var nextAlignedClassName = getClassNameFromAlign(matchAlign);
if (alignedClassName !== nextAlignedClassName) {
setAlignedClassName(nextAlignedClassName);
} // We will retry multi times to make sure that the element has been align in the right position.
setAlignTimes(function (val) {
return val + 1;
});
if (status === 'align') {
onAlign === null || onAlign === void 0 ? void 0 : onAlign(popupDomNode, matchAlign);
}
} // Delay to go to next status
(0, _useLayoutEffect.default)(function () {
if (status === 'align') {
// Repeat until not more align needed
if (alignTimes < 3) {
forceAlign();
} else {
goNextStatus(function () {
var _prepareResolveRef$cu;
(_prepareResolveRef$cu = prepareResolveRef.current) === null || _prepareResolveRef$cu === void 0 ? void 0 : _prepareResolveRef$cu.call(prepareResolveRef);
});
}
}
}, [alignTimes]); // ======================== Motion ========================
var motion = (0, _objectSpread2.default)({}, (0, _legacyUtil.getMotion)(props));
['onAppearEnd', 'onEnterEnd', 'onLeaveEnd'].forEach(function (eventName) {
var originHandler = motion[eventName];
motion[eventName] = function (element, event) {
goNextStatus();
return originHandler === null || originHandler === void 0 ? void 0 : originHandler(element, event);
};
});
function onShowPrepare() {
return new Promise(function (resolve) {
prepareResolveRef.current = resolve;
});
} // Go to stable directly when motion not provided
React.useEffect(function () {
if (!motion.motionName && status === 'motion') {
goNextStatus();
}
}, [motion.motionName, status]); // ========================= Refs =========================
React.useImperativeHandle(ref, function () {
return {
forceAlign: forceAlign,
getElement: function getElement() {
return elementRef.current;
}
};
}); // ======================== Render ========================
var mergedStyle = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, stretchStyle), {}, {
zIndex: zIndex,
opacity: status === 'motion' || status === 'stable' || !visible ? undefined : 0,
// Cannot interact with disappearing elements
// https://github.com/ant-design/ant-design/issues/35051#issuecomment-1101340714
pointerEvents: !visible && status !== 'stable' ? 'none' : undefined
}, style); // Align status
var alignDisabled = true;
if (align !== null && align !== void 0 && align.points && (status === 'align' || status === 'stable')) {
alignDisabled = false;
}
var childNode = children; // Wrapper when multiple children
if (React.Children.count(children) > 1) {
childNode = /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls, "-content")
}, children);
}
return /*#__PURE__*/React.createElement(_rcMotion.default, (0, _extends2.default)({
visible: visible,
ref: elementRef,
leavedClassName: "".concat(prefixCls, "-hidden")
}, motion, {
onAppearPrepare: onShowPrepare,
onEnterPrepare: onShowPrepare,
removeOnLeave: destroyPopupOnHide,
forceRender: forceRender
}), function (_ref, motionRef) {
var motionClassName = _ref.className,
motionStyle = _ref.style;
var mergedClassName = (0, _classnames.default)(prefixCls, className, alignedClassName, motionClassName);
return /*#__PURE__*/React.createElement(_rcAlign.default, {
target: getAlignTarget(),
key: "popup",
ref: alignRef,
monitorWindowResize: true,
disabled: alignDisabled,
align: align,
onAlign: onInternalAlign
}, /*#__PURE__*/React.createElement("div", {
ref: motionRef,
className: mergedClassName,
onMouseEnter: onMouseEnter,
onMouseLeave: onMouseLeave,
onMouseDownCapture: onMouseDown,
onTouchStartCapture: onTouchStart,
onClick: onClick,
style: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, motionStyle), mergedStyle)
}, childNode));
});
});
PopupInner.displayName = 'PopupInner';
var _default = PopupInner;
exports.default = _default;