2024-08-20 23:25:37 +04:00

544 lines
24 KiB
JavaScript

"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.generateTrigger = generateTrigger;
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _portal = _interopRequireDefault(require("@rc-component/portal"));
var _classnames = _interopRequireDefault(require("classnames"));
var _rcResizeObserver = _interopRequireDefault(require("rc-resize-observer"));
var _findDOMNode = require("rc-util/lib/Dom/findDOMNode");
var _shadow = require("rc-util/lib/Dom/shadow");
var _useEvent = _interopRequireDefault(require("rc-util/lib/hooks/useEvent"));
var _useId = _interopRequireDefault(require("rc-util/lib/hooks/useId"));
var _useLayoutEffect = _interopRequireDefault(require("rc-util/lib/hooks/useLayoutEffect"));
var _isMobile = _interopRequireDefault(require("rc-util/lib/isMobile"));
var React = _interopRequireWildcard(require("react"));
var _Popup = _interopRequireDefault(require("./Popup"));
var _TriggerWrapper = _interopRequireDefault(require("./TriggerWrapper"));
var _context = _interopRequireDefault(require("./context"));
var _useAction3 = _interopRequireDefault(require("./hooks/useAction"));
var _useAlign3 = _interopRequireDefault(require("./hooks/useAlign"));
var _useWatch = _interopRequireDefault(require("./hooks/useWatch"));
var _useWinClick = _interopRequireDefault(require("./hooks/useWinClick"));
var _util = require("./util");
var _excluded = ["prefixCls", "children", "action", "showAction", "hideAction", "popupVisible", "defaultPopupVisible", "onPopupVisibleChange", "afterPopupVisibleChange", "mouseEnterDelay", "mouseLeaveDelay", "focusDelay", "blurDelay", "mask", "maskClosable", "getPopupContainer", "forceRender", "autoDestroy", "destroyPopupOnHide", "popup", "popupClassName", "popupStyle", "popupPlacement", "builtinPlacements", "popupAlign", "zIndex", "stretch", "getPopupClassNameFromAlign", "fresh", "alignPoint", "onPopupClick", "onPopupAlign", "arrow", "popupMotion", "maskMotion", "popupTransitionName", "popupAnimation", "maskTransitionName", "maskAnimation", "className", "getTriggerDOMNode"];
// Removed Props List
// Seems this can be auto
// getDocument?: (element?: HTMLElement) => Document;
// New version will not wrap popup with `rc-trigger-popup-content` when multiple children
function generateTrigger() {
var PortalComponent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _portal.default;
var Trigger = /*#__PURE__*/React.forwardRef(function (props, ref) {
var _props$prefixCls = props.prefixCls,
prefixCls = _props$prefixCls === void 0 ? 'rc-trigger-popup' : _props$prefixCls,
children = props.children,
_props$action = props.action,
action = _props$action === void 0 ? 'hover' : _props$action,
showAction = props.showAction,
hideAction = props.hideAction,
popupVisible = props.popupVisible,
defaultPopupVisible = props.defaultPopupVisible,
onPopupVisibleChange = props.onPopupVisibleChange,
afterPopupVisibleChange = props.afterPopupVisibleChange,
mouseEnterDelay = props.mouseEnterDelay,
_props$mouseLeaveDela = props.mouseLeaveDelay,
mouseLeaveDelay = _props$mouseLeaveDela === void 0 ? 0.1 : _props$mouseLeaveDela,
focusDelay = props.focusDelay,
blurDelay = props.blurDelay,
mask = props.mask,
_props$maskClosable = props.maskClosable,
maskClosable = _props$maskClosable === void 0 ? true : _props$maskClosable,
getPopupContainer = props.getPopupContainer,
forceRender = props.forceRender,
autoDestroy = props.autoDestroy,
destroyPopupOnHide = props.destroyPopupOnHide,
popup = props.popup,
popupClassName = props.popupClassName,
popupStyle = props.popupStyle,
popupPlacement = props.popupPlacement,
_props$builtinPlaceme = props.builtinPlacements,
builtinPlacements = _props$builtinPlaceme === void 0 ? {} : _props$builtinPlaceme,
popupAlign = props.popupAlign,
zIndex = props.zIndex,
stretch = props.stretch,
getPopupClassNameFromAlign = props.getPopupClassNameFromAlign,
fresh = props.fresh,
alignPoint = props.alignPoint,
onPopupClick = props.onPopupClick,
onPopupAlign = props.onPopupAlign,
arrow = props.arrow,
popupMotion = props.popupMotion,
maskMotion = props.maskMotion,
popupTransitionName = props.popupTransitionName,
popupAnimation = props.popupAnimation,
maskTransitionName = props.maskTransitionName,
maskAnimation = props.maskAnimation,
className = props.className,
getTriggerDOMNode = props.getTriggerDOMNode,
restProps = (0, _objectWithoutProperties2.default)(props, _excluded);
var mergedAutoDestroy = autoDestroy || destroyPopupOnHide || false;
// =========================== Mobile ===========================
var _React$useState = React.useState(false),
_React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
mobile = _React$useState2[0],
setMobile = _React$useState2[1];
(0, _useLayoutEffect.default)(function () {
setMobile((0, _isMobile.default)());
}, []);
// ========================== Context ===========================
var subPopupElements = React.useRef({});
var parentContext = React.useContext(_context.default);
var context = React.useMemo(function () {
return {
registerSubPopup: function registerSubPopup(id, subPopupEle) {
subPopupElements.current[id] = subPopupEle;
parentContext === null || parentContext === void 0 || parentContext.registerSubPopup(id, subPopupEle);
}
};
}, [parentContext]);
// =========================== Popup ============================
var id = (0, _useId.default)();
var _React$useState3 = React.useState(null),
_React$useState4 = (0, _slicedToArray2.default)(_React$useState3, 2),
popupEle = _React$useState4[0],
setPopupEle = _React$useState4[1];
// Used for forwardRef popup. Not use internal
var externalPopupRef = React.useRef(null);
var setPopupRef = (0, _useEvent.default)(function (node) {
externalPopupRef.current = node;
if ((0, _findDOMNode.isDOM)(node) && popupEle !== node) {
setPopupEle(node);
}
parentContext === null || parentContext === void 0 || parentContext.registerSubPopup(id, node);
});
// =========================== Target ===========================
// Use state to control here since `useRef` update not trigger render
var _React$useState5 = React.useState(null),
_React$useState6 = (0, _slicedToArray2.default)(_React$useState5, 2),
targetEle = _React$useState6[0],
setTargetEle = _React$useState6[1];
// Used for forwardRef target. Not use internal
var externalForwardRef = React.useRef(null);
var setTargetRef = (0, _useEvent.default)(function (node) {
if ((0, _findDOMNode.isDOM)(node) && targetEle !== node) {
setTargetEle(node);
externalForwardRef.current = node;
}
});
// ========================== Children ==========================
var child = React.Children.only(children);
var originChildProps = (child === null || child === void 0 ? void 0 : child.props) || {};
var cloneProps = {};
var inPopupOrChild = (0, _useEvent.default)(function (ele) {
var _getShadowRoot, _getShadowRoot2;
var childDOM = targetEle;
return (childDOM === null || childDOM === void 0 ? void 0 : childDOM.contains(ele)) || ((_getShadowRoot = (0, _shadow.getShadowRoot)(childDOM)) === null || _getShadowRoot === void 0 ? void 0 : _getShadowRoot.host) === ele || ele === childDOM || (popupEle === null || popupEle === void 0 ? void 0 : popupEle.contains(ele)) || ((_getShadowRoot2 = (0, _shadow.getShadowRoot)(popupEle)) === null || _getShadowRoot2 === void 0 ? void 0 : _getShadowRoot2.host) === ele || ele === popupEle || Object.values(subPopupElements.current).some(function (subPopupEle) {
return (subPopupEle === null || subPopupEle === void 0 ? void 0 : subPopupEle.contains(ele)) || ele === subPopupEle;
});
});
// =========================== Motion ===========================
var mergePopupMotion = (0, _util.getMotion)(prefixCls, popupMotion, popupAnimation, popupTransitionName);
var mergeMaskMotion = (0, _util.getMotion)(prefixCls, maskMotion, maskAnimation, maskTransitionName);
// ============================ Open ============================
var _React$useState7 = React.useState(defaultPopupVisible || false),
_React$useState8 = (0, _slicedToArray2.default)(_React$useState7, 2),
internalOpen = _React$useState8[0],
setInternalOpen = _React$useState8[1];
// Render still use props as first priority
var mergedOpen = popupVisible !== null && popupVisible !== void 0 ? popupVisible : internalOpen;
// We use effect sync here in case `popupVisible` back to `undefined`
var setMergedOpen = (0, _useEvent.default)(function (nextOpen) {
if (popupVisible === undefined) {
setInternalOpen(nextOpen);
}
});
(0, _useLayoutEffect.default)(function () {
setInternalOpen(popupVisible || false);
}, [popupVisible]);
var openRef = React.useRef(mergedOpen);
openRef.current = mergedOpen;
var lastTriggerRef = React.useRef([]);
lastTriggerRef.current = [];
var internalTriggerOpen = (0, _useEvent.default)(function (nextOpen) {
var _lastTriggerRef$curre;
setMergedOpen(nextOpen);
// Enter or Pointer will both trigger open state change
// We only need take one to avoid duplicated change event trigger
// Use `lastTriggerRef` to record last open type
if (((_lastTriggerRef$curre = lastTriggerRef.current[lastTriggerRef.current.length - 1]) !== null && _lastTriggerRef$curre !== void 0 ? _lastTriggerRef$curre : mergedOpen) !== nextOpen) {
lastTriggerRef.current.push(nextOpen);
onPopupVisibleChange === null || onPopupVisibleChange === void 0 || onPopupVisibleChange(nextOpen);
}
});
// Trigger for delay
var delayRef = React.useRef();
var clearDelay = function clearDelay() {
clearTimeout(delayRef.current);
};
var triggerOpen = function triggerOpen(nextOpen) {
var delay = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
clearDelay();
if (delay === 0) {
internalTriggerOpen(nextOpen);
} else {
delayRef.current = setTimeout(function () {
internalTriggerOpen(nextOpen);
}, delay * 1000);
}
};
React.useEffect(function () {
return clearDelay;
}, []);
// ========================== Motion ============================
var _React$useState9 = React.useState(false),
_React$useState10 = (0, _slicedToArray2.default)(_React$useState9, 2),
inMotion = _React$useState10[0],
setInMotion = _React$useState10[1];
(0, _useLayoutEffect.default)(function (firstMount) {
if (!firstMount || mergedOpen) {
setInMotion(true);
}
}, [mergedOpen]);
var _React$useState11 = React.useState(null),
_React$useState12 = (0, _slicedToArray2.default)(_React$useState11, 2),
motionPrepareResolve = _React$useState12[0],
setMotionPrepareResolve = _React$useState12[1];
// =========================== Align ============================
var _React$useState13 = React.useState([0, 0]),
_React$useState14 = (0, _slicedToArray2.default)(_React$useState13, 2),
mousePos = _React$useState14[0],
setMousePos = _React$useState14[1];
var setMousePosByEvent = function setMousePosByEvent(event) {
setMousePos([event.clientX, event.clientY]);
};
var _useAlign = (0, _useAlign3.default)(mergedOpen, popupEle, alignPoint ? mousePos : targetEle, popupPlacement, builtinPlacements, popupAlign, onPopupAlign),
_useAlign2 = (0, _slicedToArray2.default)(_useAlign, 11),
ready = _useAlign2[0],
offsetX = _useAlign2[1],
offsetY = _useAlign2[2],
offsetR = _useAlign2[3],
offsetB = _useAlign2[4],
arrowX = _useAlign2[5],
arrowY = _useAlign2[6],
scaleX = _useAlign2[7],
scaleY = _useAlign2[8],
alignInfo = _useAlign2[9],
onAlign = _useAlign2[10];
var _useAction = (0, _useAction3.default)(mobile, action, showAction, hideAction),
_useAction2 = (0, _slicedToArray2.default)(_useAction, 2),
showActions = _useAction2[0],
hideActions = _useAction2[1];
var clickToShow = showActions.has('click');
var clickToHide = hideActions.has('click') || hideActions.has('contextMenu');
var triggerAlign = (0, _useEvent.default)(function () {
if (!inMotion) {
onAlign();
}
});
var onScroll = function onScroll() {
if (openRef.current && alignPoint && clickToHide) {
triggerOpen(false);
}
};
(0, _useWatch.default)(mergedOpen, targetEle, popupEle, triggerAlign, onScroll);
(0, _useLayoutEffect.default)(function () {
triggerAlign();
}, [mousePos, popupPlacement]);
// When no builtinPlacements and popupAlign changed
(0, _useLayoutEffect.default)(function () {
if (mergedOpen && !(builtinPlacements !== null && builtinPlacements !== void 0 && builtinPlacements[popupPlacement])) {
triggerAlign();
}
}, [JSON.stringify(popupAlign)]);
var alignedClassName = React.useMemo(function () {
var baseClassName = (0, _util.getAlignPopupClassName)(builtinPlacements, prefixCls, alignInfo, alignPoint);
return (0, _classnames.default)(baseClassName, getPopupClassNameFromAlign === null || getPopupClassNameFromAlign === void 0 ? void 0 : getPopupClassNameFromAlign(alignInfo));
}, [alignInfo, getPopupClassNameFromAlign, builtinPlacements, prefixCls, alignPoint]);
// ============================ Refs ============================
React.useImperativeHandle(ref, function () {
return {
nativeElement: externalForwardRef.current,
popupElement: externalPopupRef.current,
forceAlign: triggerAlign
};
});
// ========================== Stretch ===========================
var _React$useState15 = React.useState(0),
_React$useState16 = (0, _slicedToArray2.default)(_React$useState15, 2),
targetWidth = _React$useState16[0],
setTargetWidth = _React$useState16[1];
var _React$useState17 = React.useState(0),
_React$useState18 = (0, _slicedToArray2.default)(_React$useState17, 2),
targetHeight = _React$useState18[0],
setTargetHeight = _React$useState18[1];
var syncTargetSize = function syncTargetSize() {
if (stretch && targetEle) {
var rect = targetEle.getBoundingClientRect();
setTargetWidth(rect.width);
setTargetHeight(rect.height);
}
};
var onTargetResize = function onTargetResize() {
syncTargetSize();
triggerAlign();
};
// ========================== Motion ============================
var onVisibleChanged = function onVisibleChanged(visible) {
setInMotion(false);
onAlign();
afterPopupVisibleChange === null || afterPopupVisibleChange === void 0 || afterPopupVisibleChange(visible);
};
// We will trigger align when motion is in prepare
var onPrepare = function onPrepare() {
return new Promise(function (resolve) {
syncTargetSize();
setMotionPrepareResolve(function () {
return resolve;
});
});
};
(0, _useLayoutEffect.default)(function () {
if (motionPrepareResolve) {
onAlign();
motionPrepareResolve();
setMotionPrepareResolve(null);
}
}, [motionPrepareResolve]);
// =========================== Action ===========================
/**
* Util wrapper for trigger action
*/
function wrapperAction(eventName, nextOpen, delay, preEvent) {
cloneProps[eventName] = function (event) {
var _originChildProps$eve;
preEvent === null || preEvent === void 0 || preEvent(event);
triggerOpen(nextOpen, delay);
// Pass to origin
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
(_originChildProps$eve = originChildProps[eventName]) === null || _originChildProps$eve === void 0 || _originChildProps$eve.call.apply(_originChildProps$eve, [originChildProps, event].concat(args));
};
}
// ======================= Action: Click ========================
if (clickToShow || clickToHide) {
cloneProps.onClick = function (event) {
var _originChildProps$onC;
if (openRef.current && clickToHide) {
triggerOpen(false);
} else if (!openRef.current && clickToShow) {
setMousePosByEvent(event);
triggerOpen(true);
}
// Pass to origin
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
(_originChildProps$onC = originChildProps.onClick) === null || _originChildProps$onC === void 0 || _originChildProps$onC.call.apply(_originChildProps$onC, [originChildProps, event].concat(args));
};
}
// Click to hide is special action since click popup element should not hide
(0, _useWinClick.default)(mergedOpen, clickToHide, targetEle, popupEle, mask, maskClosable, inPopupOrChild, triggerOpen);
// ======================= Action: Hover ========================
var hoverToShow = showActions.has('hover');
var hoverToHide = hideActions.has('hover');
var onPopupMouseEnter;
var onPopupMouseLeave;
if (hoverToShow) {
// Compatible with old browser which not support pointer event
wrapperAction('onMouseEnter', true, mouseEnterDelay, function (event) {
setMousePosByEvent(event);
});
wrapperAction('onPointerEnter', true, mouseEnterDelay, function (event) {
setMousePosByEvent(event);
});
onPopupMouseEnter = function onPopupMouseEnter(event) {
// Only trigger re-open when popup is visible
if ((mergedOpen || inMotion) && popupEle !== null && popupEle !== void 0 && popupEle.contains(event.target)) {
triggerOpen(true, mouseEnterDelay);
}
};
// Align Point
if (alignPoint) {
cloneProps.onMouseMove = function (event) {
var _originChildProps$onM;
// setMousePosByEvent(event);
(_originChildProps$onM = originChildProps.onMouseMove) === null || _originChildProps$onM === void 0 || _originChildProps$onM.call(originChildProps, event);
};
}
}
if (hoverToHide) {
wrapperAction('onMouseLeave', false, mouseLeaveDelay);
wrapperAction('onPointerLeave', false, mouseLeaveDelay);
onPopupMouseLeave = function onPopupMouseLeave() {
triggerOpen(false, mouseLeaveDelay);
};
}
// ======================= Action: Focus ========================
if (showActions.has('focus')) {
wrapperAction('onFocus', true, focusDelay);
}
if (hideActions.has('focus')) {
wrapperAction('onBlur', false, blurDelay);
}
// ==================== Action: ContextMenu =====================
if (showActions.has('contextMenu')) {
cloneProps.onContextMenu = function (event) {
var _originChildProps$onC2;
if (openRef.current && hideActions.has('contextMenu')) {
triggerOpen(false);
} else {
setMousePosByEvent(event);
triggerOpen(true);
}
event.preventDefault();
// Pass to origin
for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
args[_key3 - 1] = arguments[_key3];
}
(_originChildProps$onC2 = originChildProps.onContextMenu) === null || _originChildProps$onC2 === void 0 || _originChildProps$onC2.call.apply(_originChildProps$onC2, [originChildProps, event].concat(args));
};
}
// ========================= ClassName ==========================
if (className) {
cloneProps.className = (0, _classnames.default)(originChildProps.className, className);
}
// =========================== Render ===========================
var mergedChildrenProps = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originChildProps), cloneProps);
// Pass props into cloneProps for nest usage
var passedProps = {};
var passedEventList = ['onContextMenu', 'onClick', 'onMouseDown', 'onTouchStart', 'onMouseEnter', 'onMouseLeave', 'onFocus', 'onBlur'];
passedEventList.forEach(function (eventName) {
if (restProps[eventName]) {
passedProps[eventName] = function () {
var _mergedChildrenProps$;
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
args[_key4] = arguments[_key4];
}
(_mergedChildrenProps$ = mergedChildrenProps[eventName]) === null || _mergedChildrenProps$ === void 0 || _mergedChildrenProps$.call.apply(_mergedChildrenProps$, [mergedChildrenProps].concat(args));
restProps[eventName].apply(restProps, args);
};
}
});
// Child Node
var triggerNode = /*#__PURE__*/React.cloneElement(child, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, mergedChildrenProps), passedProps));
var arrowPos = {
x: arrowX,
y: arrowY
};
var innerArrow = arrow ? (0, _objectSpread2.default)({}, arrow !== true ? arrow : {}) : null;
// Render
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(_rcResizeObserver.default, {
disabled: !mergedOpen,
ref: setTargetRef,
onResize: onTargetResize
}, /*#__PURE__*/React.createElement(_TriggerWrapper.default, {
getTriggerDOMNode: getTriggerDOMNode
}, triggerNode)), /*#__PURE__*/React.createElement(_context.default.Provider, {
value: context
}, /*#__PURE__*/React.createElement(_Popup.default, {
portal: PortalComponent,
ref: setPopupRef,
prefixCls: prefixCls,
popup: popup,
className: (0, _classnames.default)(popupClassName, alignedClassName),
style: popupStyle,
target: targetEle,
onMouseEnter: onPopupMouseEnter,
onMouseLeave: onPopupMouseLeave
// https://github.com/ant-design/ant-design/issues/43924
,
onPointerEnter: onPopupMouseEnter,
zIndex: zIndex
// Open
,
open: mergedOpen,
keepDom: inMotion,
fresh: fresh
// Click
,
onClick: onPopupClick
// Mask
,
mask: mask
// Motion
,
motion: mergePopupMotion,
maskMotion: mergeMaskMotion,
onVisibleChanged: onVisibleChanged,
onPrepare: onPrepare
// Portal
,
forceRender: forceRender,
autoDestroy: mergedAutoDestroy,
getPopupContainer: getPopupContainer
// Arrow
,
align: alignInfo,
arrow: innerArrow,
arrowPos: arrowPos
// Align
,
ready: ready,
offsetX: offsetX,
offsetY: offsetY,
offsetR: offsetR,
offsetB: offsetB,
onAlign: triggerAlign
// Stretch
,
stretch: stretch,
targetWidth: targetWidth / scaleX,
targetHeight: targetHeight / scaleY
})));
});
if (process.env.NODE_ENV !== 'production') {
Trigger.displayName = 'Trigger';
}
return Trigger;
}
var _default = exports.default = generateTrigger(_portal.default);