UNPKG

7.76 kBJavaScriptView Raw
1import _extends from "@babel/runtime/helpers/esm/extends";
2import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
3import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4import * as React from 'react';
5import { useRef, useState } from 'react';
6import Align from 'rc-align';
7import useLayoutEffect from "rc-util/es/hooks/useLayoutEffect";
8import CSSMotion from 'rc-motion';
9import classNames from 'classnames';
10import useVisibleStatus from "./useVisibleStatus";
11import { getMotion } from "../utils/legacyUtil";
12import useStretchStyle from "./useStretchStyle";
13var PopupInner = /*#__PURE__*/React.forwardRef(function (props, ref) {
14 var visible = props.visible,
15 prefixCls = props.prefixCls,
16 className = props.className,
17 style = props.style,
18 children = props.children,
19 zIndex = props.zIndex,
20 stretch = props.stretch,
21 destroyPopupOnHide = props.destroyPopupOnHide,
22 forceRender = props.forceRender,
23 align = props.align,
24 point = props.point,
25 getRootDomNode = props.getRootDomNode,
26 getClassNameFromAlign = props.getClassNameFromAlign,
27 onAlign = props.onAlign,
28 onMouseEnter = props.onMouseEnter,
29 onMouseLeave = props.onMouseLeave,
30 onMouseDown = props.onMouseDown,
31 onTouchStart = props.onTouchStart,
32 onClick = props.onClick;
33 var alignRef = useRef();
34 var elementRef = useRef();
35
36 var _useState = useState(),
37 _useState2 = _slicedToArray(_useState, 2),
38 alignedClassName = _useState2[0],
39 setAlignedClassName = _useState2[1]; // ======================= Measure ========================
40
41
42 var _useStretchStyle = useStretchStyle(stretch),
43 _useStretchStyle2 = _slicedToArray(_useStretchStyle, 2),
44 stretchStyle = _useStretchStyle2[0],
45 measureStretchStyle = _useStretchStyle2[1];
46
47 function doMeasure() {
48 if (stretch) {
49 measureStretchStyle(getRootDomNode());
50 }
51 } // ======================== Status ========================
52
53
54 var _useVisibleStatus = useVisibleStatus(visible, doMeasure),
55 _useVisibleStatus2 = _slicedToArray(_useVisibleStatus, 2),
56 status = _useVisibleStatus2[0],
57 goNextStatus = _useVisibleStatus2[1]; // ======================== Aligns ========================
58
59 /**
60 * `alignedClassName` may modify `source` size,
61 * which means one time align may not move to the correct position at once.
62 *
63 * We will reset `alignTimes` for each status switch to `alignPre`
64 * and let `rc-align` to align for multiple times to ensure get final stable place.
65 * Currently we mark `alignTimes < 2` repeat align, it will increase if user report for align issue.
66 *
67 * Update:
68 * In React 18. `rc-align` effect of align may faster than ref called trigger `forceAlign`.
69 * We adjust this to `alignTimes < 2`.
70 * We need refactor `rc-align` to support mark of `forceAlign` call if this still happen.
71 */
72
73
74 var _useState3 = useState(0),
75 _useState4 = _slicedToArray(_useState3, 2),
76 alignTimes = _useState4[0],
77 setAlignTimes = _useState4[1];
78
79 var prepareResolveRef = useRef();
80 useLayoutEffect(function () {
81 if (status === 'alignPre') {
82 setAlignTimes(0);
83 }
84 }, [status]); // `target` on `rc-align` can accept as a function to get the bind element or a point.
85 // ref: https://www.npmjs.com/package/rc-align
86
87 function getAlignTarget() {
88 if (point) {
89 return point;
90 }
91
92 return getRootDomNode;
93 }
94
95 function forceAlign() {
96 var _alignRef$current;
97
98 (_alignRef$current = alignRef.current) === null || _alignRef$current === void 0 ? void 0 : _alignRef$current.forceAlign();
99 }
100
101 function onInternalAlign(popupDomNode, matchAlign) {
102 var nextAlignedClassName = getClassNameFromAlign(matchAlign);
103
104 if (alignedClassName !== nextAlignedClassName) {
105 setAlignedClassName(nextAlignedClassName);
106 } // We will retry multi times to make sure that the element has been align in the right position.
107
108
109 setAlignTimes(function (val) {
110 return val + 1;
111 });
112
113 if (status === 'align') {
114 onAlign === null || onAlign === void 0 ? void 0 : onAlign(popupDomNode, matchAlign);
115 }
116 } // Delay to go to next status
117
118
119 useLayoutEffect(function () {
120 if (status === 'align') {
121 // Repeat until not more align needed
122 if (alignTimes < 3) {
123 forceAlign();
124 } else {
125 goNextStatus(function () {
126 var _prepareResolveRef$cu;
127
128 (_prepareResolveRef$cu = prepareResolveRef.current) === null || _prepareResolveRef$cu === void 0 ? void 0 : _prepareResolveRef$cu.call(prepareResolveRef);
129 });
130 }
131 }
132 }, [alignTimes]); // ======================== Motion ========================
133
134 var motion = _objectSpread({}, getMotion(props));
135
136 ['onAppearEnd', 'onEnterEnd', 'onLeaveEnd'].forEach(function (eventName) {
137 var originHandler = motion[eventName];
138
139 motion[eventName] = function (element, event) {
140 goNextStatus();
141 return originHandler === null || originHandler === void 0 ? void 0 : originHandler(element, event);
142 };
143 });
144
145 function onShowPrepare() {
146 return new Promise(function (resolve) {
147 prepareResolveRef.current = resolve;
148 });
149 } // Go to stable directly when motion not provided
150
151
152 React.useEffect(function () {
153 if (!motion.motionName && status === 'motion') {
154 goNextStatus();
155 }
156 }, [motion.motionName, status]); // ========================= Refs =========================
157
158 React.useImperativeHandle(ref, function () {
159 return {
160 forceAlign: forceAlign,
161 getElement: function getElement() {
162 return elementRef.current;
163 }
164 };
165 }); // ======================== Render ========================
166
167 var mergedStyle = _objectSpread(_objectSpread({}, stretchStyle), {}, {
168 zIndex: zIndex,
169 opacity: status === 'motion' || status === 'stable' || !visible ? undefined : 0,
170 // Cannot interact with disappearing elements
171 // https://github.com/ant-design/ant-design/issues/35051#issuecomment-1101340714
172 pointerEvents: !visible && status !== 'stable' ? 'none' : undefined
173 }, style); // Align status
174
175
176 var alignDisabled = true;
177
178 if (align !== null && align !== void 0 && align.points && (status === 'align' || status === 'stable')) {
179 alignDisabled = false;
180 }
181
182 var childNode = children; // Wrapper when multiple children
183
184 if (React.Children.count(children) > 1) {
185 childNode = /*#__PURE__*/React.createElement("div", {
186 className: "".concat(prefixCls, "-content")
187 }, children);
188 }
189
190 return /*#__PURE__*/React.createElement(CSSMotion, _extends({
191 visible: visible,
192 ref: elementRef,
193 leavedClassName: "".concat(prefixCls, "-hidden")
194 }, motion, {
195 onAppearPrepare: onShowPrepare,
196 onEnterPrepare: onShowPrepare,
197 removeOnLeave: destroyPopupOnHide,
198 forceRender: forceRender
199 }), function (_ref, motionRef) {
200 var motionClassName = _ref.className,
201 motionStyle = _ref.style;
202 var mergedClassName = classNames(prefixCls, className, alignedClassName, motionClassName);
203 return /*#__PURE__*/React.createElement(Align, {
204 target: getAlignTarget(),
205 key: "popup",
206 ref: alignRef,
207 monitorWindowResize: true,
208 disabled: alignDisabled,
209 align: align,
210 onAlign: onInternalAlign
211 }, /*#__PURE__*/React.createElement("div", {
212 ref: motionRef,
213 className: mergedClassName,
214 onMouseEnter: onMouseEnter,
215 onMouseLeave: onMouseLeave,
216 onMouseDownCapture: onMouseDown,
217 onTouchStartCapture: onTouchStart,
218 onClick: onClick,
219 style: _objectSpread(_objectSpread({}, motionStyle), mergedStyle)
220 }, childNode));
221 });
222});
223PopupInner.displayName = 'PopupInner';
224export default PopupInner;
\No newline at end of file