@rc-component/trigger 2.2.6 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/Popup/Arrow.js +23 -20
- package/es/Popup/Mask.d.ts +1 -1
- package/es/Popup/Mask.js +17 -16
- package/es/Popup/PopupContent.js +3 -6
- package/es/Popup/index.d.ts +1 -1
- package/es/Popup/index.js +83 -78
- package/es/TriggerWrapper.js +9 -7
- package/es/context.js +1 -1
- package/es/hooks/useAction.js +5 -5
- package/es/hooks/useAlign.js +205 -215
- package/es/hooks/useWatch.js +11 -12
- package/es/hooks/useWinClick.js +14 -16
- package/es/index.d.ts +2 -14
- package/es/index.js +167 -244
- package/es/interface.d.ts +1 -1
- package/es/mock.js +10 -13
- package/es/util.d.ts +1 -4
- package/es/util.js +57 -75
- package/lib/Popup/Arrow.js +26 -22
- package/lib/Popup/Mask.d.ts +1 -1
- package/lib/Popup/Mask.js +21 -19
- package/lib/Popup/PopupContent.js +5 -7
- package/lib/Popup/index.d.ts +1 -1
- package/lib/Popup/index.js +89 -83
- package/lib/TriggerWrapper.js +11 -8
- package/lib/context.js +3 -2
- package/lib/hooks/useAction.js +7 -6
- package/lib/hooks/useAlign.js +208 -217
- package/lib/hooks/useWatch.js +12 -13
- package/lib/hooks/useWinClick.js +16 -17
- package/lib/index.d.ts +2 -14
- package/lib/index.js +172 -248
- package/lib/interface.d.ts +1 -1
- package/lib/mock.js +12 -15
- package/lib/util.d.ts +1 -4
- package/lib/util.js +57 -77
- package/package.json +10 -11
package/lib/hooks/useAlign.js
CHANGED
|
@@ -1,44 +1,38 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
|
4
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
5
3
|
Object.defineProperty(exports, "__esModule", {
|
|
6
4
|
value: true
|
|
7
5
|
});
|
|
8
6
|
exports.default = useAlign;
|
|
9
|
-
var
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
var _useEvent = _interopRequireDefault(require("rc-util/lib/hooks/useEvent"));
|
|
14
|
-
var _useLayoutEffect = _interopRequireDefault(require("rc-util/lib/hooks/useLayoutEffect"));
|
|
7
|
+
var _findDOMNode = require("@rc-component/util/lib/Dom/findDOMNode");
|
|
8
|
+
var _isVisible = _interopRequireDefault(require("@rc-component/util/lib/Dom/isVisible"));
|
|
9
|
+
var _useEvent = _interopRequireDefault(require("@rc-component/util/lib/hooks/useEvent"));
|
|
10
|
+
var _useLayoutEffect = _interopRequireDefault(require("@rc-component/util/lib/hooks/useLayoutEffect"));
|
|
15
11
|
var React = _interopRequireWildcard(require("react"));
|
|
16
12
|
var _util = require("../util");
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
14
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
15
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
|
+
function getUnitOffset(size, offset = 0) {
|
|
17
|
+
const offsetStr = `${offset}`;
|
|
18
|
+
const cells = offsetStr.match(/^(.*)\%$/);
|
|
21
19
|
if (cells) {
|
|
22
20
|
return size * (parseFloat(cells[1]) / 100);
|
|
23
21
|
}
|
|
24
22
|
return parseFloat(offsetStr);
|
|
25
23
|
}
|
|
26
24
|
function getNumberOffset(rect, offset) {
|
|
27
|
-
|
|
28
|
-
_ref2 = (0, _slicedToArray2.default)(_ref, 2),
|
|
29
|
-
offsetX = _ref2[0],
|
|
30
|
-
offsetY = _ref2[1];
|
|
25
|
+
const [offsetX, offsetY] = offset || [];
|
|
31
26
|
return [getUnitOffset(rect.width, offsetX), getUnitOffset(rect.height, offsetY)];
|
|
32
27
|
}
|
|
33
|
-
function splitPoints() {
|
|
34
|
-
var points = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
|
28
|
+
function splitPoints(points = '') {
|
|
35
29
|
return [points[0], points[1]];
|
|
36
30
|
}
|
|
37
31
|
function getAlignPoint(rect, points) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
const topBottom = points[0];
|
|
33
|
+
const leftRight = points[1];
|
|
34
|
+
let x;
|
|
35
|
+
let y;
|
|
42
36
|
|
|
43
37
|
// Top & Bottom
|
|
44
38
|
if (topBottom === 't') {
|
|
@@ -58,18 +52,18 @@ function getAlignPoint(rect, points) {
|
|
|
58
52
|
x = rect.x + rect.width / 2;
|
|
59
53
|
}
|
|
60
54
|
return {
|
|
61
|
-
x
|
|
62
|
-
y
|
|
55
|
+
x,
|
|
56
|
+
y
|
|
63
57
|
};
|
|
64
58
|
}
|
|
65
59
|
function reversePoints(points, index) {
|
|
66
|
-
|
|
60
|
+
const reverseMap = {
|
|
67
61
|
t: 'b',
|
|
68
62
|
b: 't',
|
|
69
63
|
l: 'r',
|
|
70
64
|
r: 'l'
|
|
71
65
|
};
|
|
72
|
-
return points.map(
|
|
66
|
+
return points.map((point, i) => {
|
|
73
67
|
if (i === index) {
|
|
74
68
|
return reverseMap[point] || 'c';
|
|
75
69
|
}
|
|
@@ -77,23 +71,20 @@ function reversePoints(points, index) {
|
|
|
77
71
|
}).join('');
|
|
78
72
|
}
|
|
79
73
|
function useAlign(open, popupEle, target, placement, builtinPlacements, popupAlign, onPopupAlign) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
setOffsetInfo = _React$useState2[1];
|
|
95
|
-
var alignCountRef = React.useRef(0);
|
|
96
|
-
var scrollerList = React.useMemo(function () {
|
|
74
|
+
const [offsetInfo, setOffsetInfo] = React.useState({
|
|
75
|
+
ready: false,
|
|
76
|
+
offsetX: 0,
|
|
77
|
+
offsetY: 0,
|
|
78
|
+
offsetR: 0,
|
|
79
|
+
offsetB: 0,
|
|
80
|
+
arrowX: 0,
|
|
81
|
+
arrowY: 0,
|
|
82
|
+
scaleX: 1,
|
|
83
|
+
scaleY: 1,
|
|
84
|
+
align: builtinPlacements[placement] || {}
|
|
85
|
+
});
|
|
86
|
+
const alignCountRef = React.useRef(0);
|
|
87
|
+
const scrollerList = React.useMemo(() => {
|
|
97
88
|
if (!popupEle) {
|
|
98
89
|
return [];
|
|
99
90
|
}
|
|
@@ -103,8 +94,8 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
103
94
|
// ========================= Flip ==========================
|
|
104
95
|
// We will memo flip info.
|
|
105
96
|
// If size change to make flip, it will memo the flip info and use it in next align.
|
|
106
|
-
|
|
107
|
-
|
|
97
|
+
const prevFlipRef = React.useRef({});
|
|
98
|
+
const resetFlipCache = () => {
|
|
108
99
|
prevFlipRef.current = {};
|
|
109
100
|
};
|
|
110
101
|
if (!open) {
|
|
@@ -112,33 +103,36 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
112
103
|
}
|
|
113
104
|
|
|
114
105
|
// ========================= Align =========================
|
|
115
|
-
|
|
106
|
+
const onAlign = (0, _useEvent.default)(() => {
|
|
116
107
|
if (popupEle && target && open) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
108
|
+
const popupElement = popupEle;
|
|
109
|
+
const doc = popupElement.ownerDocument;
|
|
110
|
+
const win = (0, _util.getWin)(popupElement);
|
|
111
|
+
const {
|
|
112
|
+
width,
|
|
113
|
+
height,
|
|
114
|
+
position: popupPosition
|
|
115
|
+
} = win.getComputedStyle(popupElement);
|
|
116
|
+
const originLeft = popupElement.style.left;
|
|
117
|
+
const originTop = popupElement.style.top;
|
|
118
|
+
const originRight = popupElement.style.right;
|
|
119
|
+
const originBottom = popupElement.style.bottom;
|
|
120
|
+
const originOverflow = popupElement.style.overflow;
|
|
130
121
|
|
|
131
122
|
// Placement
|
|
132
|
-
|
|
123
|
+
const placementInfo = {
|
|
124
|
+
...builtinPlacements[placement],
|
|
125
|
+
...popupAlign
|
|
126
|
+
};
|
|
133
127
|
|
|
134
128
|
// placeholder element
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
placeholderElement.style.left =
|
|
138
|
-
placeholderElement.style.top =
|
|
129
|
+
const placeholderElement = doc.createElement('div');
|
|
130
|
+
popupElement.parentElement?.appendChild(placeholderElement);
|
|
131
|
+
placeholderElement.style.left = `${popupElement.offsetLeft}px`;
|
|
132
|
+
placeholderElement.style.top = `${popupElement.offsetTop}px`;
|
|
139
133
|
placeholderElement.style.position = popupPosition;
|
|
140
|
-
placeholderElement.style.height =
|
|
141
|
-
placeholderElement.style.width =
|
|
134
|
+
placeholderElement.style.height = `${popupElement.offsetHeight}px`;
|
|
135
|
+
placeholderElement.style.width = `${popupElement.offsetWidth}px`;
|
|
142
136
|
|
|
143
137
|
// Reset first
|
|
144
138
|
popupElement.style.left = '0';
|
|
@@ -148,7 +142,7 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
148
142
|
popupElement.style.overflow = 'hidden';
|
|
149
143
|
|
|
150
144
|
// Calculate align style, we should consider `transform` case
|
|
151
|
-
|
|
145
|
+
let targetRect;
|
|
152
146
|
if (Array.isArray(target)) {
|
|
153
147
|
targetRect = {
|
|
154
148
|
x: target[0],
|
|
@@ -157,10 +151,9 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
157
151
|
height: 0
|
|
158
152
|
};
|
|
159
153
|
} else {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
rect.
|
|
163
|
-
rect.y = (_rect$y = rect.y) !== null && _rect$y !== void 0 ? _rect$y : rect.top;
|
|
154
|
+
const rect = target.getBoundingClientRect();
|
|
155
|
+
rect.x = rect.x ?? rect.left;
|
|
156
|
+
rect.y = rect.y ?? rect.top;
|
|
164
157
|
targetRect = {
|
|
165
158
|
x: rect.x,
|
|
166
159
|
y: rect.y,
|
|
@@ -168,55 +161,58 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
168
161
|
height: rect.height
|
|
169
162
|
};
|
|
170
163
|
}
|
|
171
|
-
|
|
172
|
-
popupRect.x =
|
|
173
|
-
popupRect.y =
|
|
174
|
-
|
|
175
|
-
clientWidth
|
|
176
|
-
clientHeight
|
|
177
|
-
scrollWidth
|
|
178
|
-
scrollHeight
|
|
179
|
-
scrollTop
|
|
180
|
-
scrollLeft
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
164
|
+
const popupRect = popupElement.getBoundingClientRect();
|
|
165
|
+
popupRect.x = popupRect.x ?? popupRect.left;
|
|
166
|
+
popupRect.y = popupRect.y ?? popupRect.top;
|
|
167
|
+
const {
|
|
168
|
+
clientWidth,
|
|
169
|
+
clientHeight,
|
|
170
|
+
scrollWidth,
|
|
171
|
+
scrollHeight,
|
|
172
|
+
scrollTop,
|
|
173
|
+
scrollLeft
|
|
174
|
+
} = doc.documentElement;
|
|
175
|
+
const popupHeight = popupRect.height;
|
|
176
|
+
const popupWidth = popupRect.width;
|
|
177
|
+
const targetHeight = targetRect.height;
|
|
178
|
+
const targetWidth = targetRect.width;
|
|
185
179
|
|
|
186
180
|
// Get bounding of visible area
|
|
187
|
-
|
|
181
|
+
const visibleRegion = {
|
|
188
182
|
left: 0,
|
|
189
183
|
top: 0,
|
|
190
184
|
right: clientWidth,
|
|
191
185
|
bottom: clientHeight
|
|
192
186
|
};
|
|
193
|
-
|
|
187
|
+
const scrollRegion = {
|
|
194
188
|
left: -scrollLeft,
|
|
195
189
|
top: -scrollTop,
|
|
196
190
|
right: scrollWidth - scrollLeft,
|
|
197
191
|
bottom: scrollHeight - scrollTop
|
|
198
192
|
};
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
193
|
+
let {
|
|
194
|
+
htmlRegion
|
|
195
|
+
} = placementInfo;
|
|
196
|
+
const VISIBLE = 'visible';
|
|
197
|
+
const VISIBLE_FIRST = 'visibleFirst';
|
|
202
198
|
if (htmlRegion !== 'scroll' && htmlRegion !== VISIBLE_FIRST) {
|
|
203
199
|
htmlRegion = VISIBLE;
|
|
204
200
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
201
|
+
const isVisibleFirst = htmlRegion === VISIBLE_FIRST;
|
|
202
|
+
const scrollRegionArea = (0, _util.getVisibleArea)(scrollRegion, scrollerList);
|
|
203
|
+
const visibleRegionArea = (0, _util.getVisibleArea)(visibleRegion, scrollerList);
|
|
204
|
+
const visibleArea = htmlRegion === VISIBLE ? visibleRegionArea : scrollRegionArea;
|
|
209
205
|
|
|
210
206
|
// When set to `visibleFirst`,
|
|
211
207
|
// the check `adjust` logic will use `visibleRegion` for check first.
|
|
212
|
-
|
|
208
|
+
const adjustCheckVisibleArea = isVisibleFirst ? visibleRegionArea : visibleArea;
|
|
213
209
|
|
|
214
210
|
// Record right & bottom align data
|
|
215
211
|
popupElement.style.left = 'auto';
|
|
216
212
|
popupElement.style.top = 'auto';
|
|
217
213
|
popupElement.style.right = '0';
|
|
218
214
|
popupElement.style.bottom = '0';
|
|
219
|
-
|
|
215
|
+
const popupMirrorRect = popupElement.getBoundingClientRect();
|
|
220
216
|
|
|
221
217
|
// Reset back
|
|
222
218
|
popupElement.style.left = originLeft;
|
|
@@ -224,78 +220,74 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
224
220
|
popupElement.style.right = originRight;
|
|
225
221
|
popupElement.style.bottom = originBottom;
|
|
226
222
|
popupElement.style.overflow = originOverflow;
|
|
227
|
-
|
|
223
|
+
popupElement.parentElement?.removeChild(placeholderElement);
|
|
228
224
|
|
|
229
225
|
// Calculate scale
|
|
230
|
-
|
|
231
|
-
|
|
226
|
+
const scaleX = (0, _util.toNum)(Math.round(popupWidth / parseFloat(width) * 1000) / 1000);
|
|
227
|
+
const scaleY = (0, _util.toNum)(Math.round(popupHeight / parseFloat(height) * 1000) / 1000);
|
|
232
228
|
|
|
233
229
|
// No need to align since it's not visible in view
|
|
234
|
-
if (
|
|
230
|
+
if (scaleX === 0 || scaleY === 0 || (0, _findDOMNode.isDOM)(target) && !(0, _isVisible.default)(target)) {
|
|
235
231
|
return;
|
|
236
232
|
}
|
|
237
233
|
|
|
238
234
|
// Offset
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
var _getNumberOffset3 = getNumberOffset(targetRect, targetOffset),
|
|
246
|
-
_getNumberOffset4 = (0, _slicedToArray2.default)(_getNumberOffset3, 2),
|
|
247
|
-
targetOffsetX = _getNumberOffset4[0],
|
|
248
|
-
targetOffsetY = _getNumberOffset4[1];
|
|
235
|
+
const {
|
|
236
|
+
offset,
|
|
237
|
+
targetOffset
|
|
238
|
+
} = placementInfo;
|
|
239
|
+
let [popupOffsetX, popupOffsetY] = getNumberOffset(popupRect, offset);
|
|
240
|
+
const [targetOffsetX, targetOffsetY] = getNumberOffset(targetRect, targetOffset);
|
|
249
241
|
targetRect.x -= targetOffsetX;
|
|
250
242
|
targetRect.y -= targetOffsetY;
|
|
251
243
|
|
|
252
244
|
// Points
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
var popupPoints = splitPoints(popupPoint);
|
|
259
|
-
var targetAlignPoint = getAlignPoint(targetRect, targetPoints);
|
|
260
|
-
var popupAlignPoint = getAlignPoint(popupRect, popupPoints);
|
|
245
|
+
const [popupPoint, targetPoint] = placementInfo.points || [];
|
|
246
|
+
const targetPoints = splitPoints(targetPoint);
|
|
247
|
+
const popupPoints = splitPoints(popupPoint);
|
|
248
|
+
const targetAlignPoint = getAlignPoint(targetRect, targetPoints);
|
|
249
|
+
const popupAlignPoint = getAlignPoint(popupRect, popupPoints);
|
|
261
250
|
|
|
262
251
|
// Real align info may not same as origin one
|
|
263
|
-
|
|
252
|
+
const nextAlignInfo = {
|
|
253
|
+
...placementInfo
|
|
254
|
+
};
|
|
264
255
|
|
|
265
256
|
// Next Offset
|
|
266
|
-
|
|
267
|
-
|
|
257
|
+
let nextOffsetX = targetAlignPoint.x - popupAlignPoint.x + popupOffsetX;
|
|
258
|
+
let nextOffsetY = targetAlignPoint.y - popupAlignPoint.y + popupOffsetY;
|
|
268
259
|
|
|
269
260
|
// ============== Intersection ===============
|
|
270
261
|
// Get area by position. Used for check if flip area is better
|
|
271
|
-
function getIntersectionVisibleArea(offsetX, offsetY) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
var visibleB = Math.min(b, area.bottom);
|
|
262
|
+
function getIntersectionVisibleArea(offsetX, offsetY, area = visibleArea) {
|
|
263
|
+
const l = popupRect.x + offsetX;
|
|
264
|
+
const t = popupRect.y + offsetY;
|
|
265
|
+
const r = l + popupWidth;
|
|
266
|
+
const b = t + popupHeight;
|
|
267
|
+
const visibleL = Math.max(l, area.left);
|
|
268
|
+
const visibleT = Math.max(t, area.top);
|
|
269
|
+
const visibleR = Math.min(r, area.right);
|
|
270
|
+
const visibleB = Math.min(b, area.bottom);
|
|
281
271
|
return Math.max(0, (visibleR - visibleL) * (visibleB - visibleT));
|
|
282
272
|
}
|
|
283
|
-
|
|
273
|
+
const originIntersectionVisibleArea = getIntersectionVisibleArea(nextOffsetX, nextOffsetY);
|
|
284
274
|
|
|
285
275
|
// As `visibleFirst`, we prepare this for check
|
|
286
|
-
|
|
276
|
+
const originIntersectionRecommendArea = getIntersectionVisibleArea(nextOffsetX, nextOffsetY, visibleRegionArea);
|
|
287
277
|
|
|
288
278
|
// ========================== Overflow ===========================
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
279
|
+
const targetAlignPointTL = getAlignPoint(targetRect, ['t', 'l']);
|
|
280
|
+
const popupAlignPointTL = getAlignPoint(popupRect, ['t', 'l']);
|
|
281
|
+
const targetAlignPointBR = getAlignPoint(targetRect, ['b', 'r']);
|
|
282
|
+
const popupAlignPointBR = getAlignPoint(popupRect, ['b', 'r']);
|
|
283
|
+
const overflow = placementInfo.overflow || {};
|
|
284
|
+
const {
|
|
285
|
+
adjustX,
|
|
286
|
+
adjustY,
|
|
287
|
+
shiftX,
|
|
288
|
+
shiftY
|
|
289
|
+
} = overflow;
|
|
290
|
+
const supportAdjust = val => {
|
|
299
291
|
if (typeof val === 'boolean') {
|
|
300
292
|
return val;
|
|
301
293
|
}
|
|
@@ -303,10 +295,10 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
303
295
|
};
|
|
304
296
|
|
|
305
297
|
// Prepare position
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
298
|
+
let nextPopupY;
|
|
299
|
+
let nextPopupBottom;
|
|
300
|
+
let nextPopupX;
|
|
301
|
+
let nextPopupRight;
|
|
310
302
|
function syncNextPopupPosition() {
|
|
311
303
|
nextPopupY = popupRect.y + nextOffsetY;
|
|
312
304
|
nextPopupBottom = nextPopupY + popupHeight;
|
|
@@ -316,19 +308,19 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
316
308
|
syncNextPopupPosition();
|
|
317
309
|
|
|
318
310
|
// >>>>>>>>>> Top & Bottom
|
|
319
|
-
|
|
320
|
-
|
|
311
|
+
const needAdjustY = supportAdjust(adjustY);
|
|
312
|
+
const sameTB = popupPoints[0] === targetPoints[0];
|
|
321
313
|
|
|
322
314
|
// Bottom to Top
|
|
323
315
|
if (needAdjustY && popupPoints[0] === 't' && (nextPopupBottom > adjustCheckVisibleArea.bottom || prevFlipRef.current.bt)) {
|
|
324
|
-
|
|
316
|
+
let tmpNextOffsetY = nextOffsetY;
|
|
325
317
|
if (sameTB) {
|
|
326
318
|
tmpNextOffsetY -= popupHeight - targetHeight;
|
|
327
319
|
} else {
|
|
328
320
|
tmpNextOffsetY = targetAlignPointTL.y - popupAlignPointBR.y - popupOffsetY;
|
|
329
321
|
}
|
|
330
|
-
|
|
331
|
-
|
|
322
|
+
const newVisibleArea = getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY);
|
|
323
|
+
const newVisibleRecommendArea = getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY, visibleRegionArea);
|
|
332
324
|
if (
|
|
333
325
|
// Of course use larger one
|
|
334
326
|
newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst ||
|
|
@@ -345,21 +337,21 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
345
337
|
|
|
346
338
|
// Top to Bottom
|
|
347
339
|
if (needAdjustY && popupPoints[0] === 'b' && (nextPopupY < adjustCheckVisibleArea.top || prevFlipRef.current.tb)) {
|
|
348
|
-
|
|
340
|
+
let tmpNextOffsetY = nextOffsetY;
|
|
349
341
|
if (sameTB) {
|
|
350
|
-
|
|
342
|
+
tmpNextOffsetY += popupHeight - targetHeight;
|
|
351
343
|
} else {
|
|
352
|
-
|
|
344
|
+
tmpNextOffsetY = targetAlignPointBR.y - popupAlignPointTL.y - popupOffsetY;
|
|
353
345
|
}
|
|
354
|
-
|
|
355
|
-
|
|
346
|
+
const newVisibleArea = getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY);
|
|
347
|
+
const newVisibleRecommendArea = getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY, visibleRegionArea);
|
|
356
348
|
if (
|
|
357
349
|
// Of course use larger one
|
|
358
|
-
|
|
350
|
+
newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst ||
|
|
359
351
|
// Choose recommend one
|
|
360
|
-
|
|
352
|
+
newVisibleRecommendArea >= originIntersectionRecommendArea)) {
|
|
361
353
|
prevFlipRef.current.tb = true;
|
|
362
|
-
nextOffsetY =
|
|
354
|
+
nextOffsetY = tmpNextOffsetY;
|
|
363
355
|
popupOffsetY = -popupOffsetY;
|
|
364
356
|
nextAlignInfo.points = [reversePoints(popupPoints, 0), reversePoints(targetPoints, 0)];
|
|
365
357
|
} else {
|
|
@@ -368,26 +360,26 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
368
360
|
}
|
|
369
361
|
|
|
370
362
|
// >>>>>>>>>> Left & Right
|
|
371
|
-
|
|
363
|
+
const needAdjustX = supportAdjust(adjustX);
|
|
372
364
|
|
|
373
365
|
// >>>>> Flip
|
|
374
|
-
|
|
366
|
+
const sameLR = popupPoints[1] === targetPoints[1];
|
|
375
367
|
|
|
376
368
|
// Right to Left
|
|
377
369
|
if (needAdjustX && popupPoints[1] === 'l' && (nextPopupRight > adjustCheckVisibleArea.right || prevFlipRef.current.rl)) {
|
|
378
|
-
|
|
370
|
+
let tmpNextOffsetX = nextOffsetX;
|
|
379
371
|
if (sameLR) {
|
|
380
372
|
tmpNextOffsetX -= popupWidth - targetWidth;
|
|
381
373
|
} else {
|
|
382
374
|
tmpNextOffsetX = targetAlignPointTL.x - popupAlignPointBR.x - popupOffsetX;
|
|
383
375
|
}
|
|
384
|
-
|
|
385
|
-
|
|
376
|
+
const newVisibleArea = getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY);
|
|
377
|
+
const newVisibleRecommendArea = getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY, visibleRegionArea);
|
|
386
378
|
if (
|
|
387
379
|
// Of course use larger one
|
|
388
|
-
|
|
380
|
+
newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst ||
|
|
389
381
|
// Choose recommend one
|
|
390
|
-
|
|
382
|
+
newVisibleRecommendArea >= originIntersectionRecommendArea)) {
|
|
391
383
|
prevFlipRef.current.rl = true;
|
|
392
384
|
nextOffsetX = tmpNextOffsetX;
|
|
393
385
|
popupOffsetX = -popupOffsetX;
|
|
@@ -399,21 +391,21 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
399
391
|
|
|
400
392
|
// Left to Right
|
|
401
393
|
if (needAdjustX && popupPoints[1] === 'r' && (nextPopupX < adjustCheckVisibleArea.left || prevFlipRef.current.lr)) {
|
|
402
|
-
|
|
394
|
+
let tmpNextOffsetX = nextOffsetX;
|
|
403
395
|
if (sameLR) {
|
|
404
|
-
|
|
396
|
+
tmpNextOffsetX += popupWidth - targetWidth;
|
|
405
397
|
} else {
|
|
406
|
-
|
|
398
|
+
tmpNextOffsetX = targetAlignPointBR.x - popupAlignPointTL.x - popupOffsetX;
|
|
407
399
|
}
|
|
408
|
-
|
|
409
|
-
|
|
400
|
+
const newVisibleArea = getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY);
|
|
401
|
+
const newVisibleRecommendArea = getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY, visibleRegionArea);
|
|
410
402
|
if (
|
|
411
403
|
// Of course use larger one
|
|
412
|
-
|
|
404
|
+
newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst ||
|
|
413
405
|
// Choose recommend one
|
|
414
|
-
|
|
406
|
+
newVisibleRecommendArea >= originIntersectionRecommendArea)) {
|
|
415
407
|
prevFlipRef.current.lr = true;
|
|
416
|
-
nextOffsetX =
|
|
408
|
+
nextOffsetX = tmpNextOffsetX;
|
|
417
409
|
popupOffsetX = -popupOffsetX;
|
|
418
410
|
nextAlignInfo.points = [reversePoints(popupPoints, 1), reversePoints(targetPoints, 1)];
|
|
419
411
|
} else {
|
|
@@ -423,7 +415,7 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
423
415
|
|
|
424
416
|
// ============================ Shift ============================
|
|
425
417
|
syncNextPopupPosition();
|
|
426
|
-
|
|
418
|
+
const numShiftX = shiftX === true ? 0 : shiftX;
|
|
427
419
|
if (typeof numShiftX === 'number') {
|
|
428
420
|
// Left
|
|
429
421
|
if (nextPopupX < visibleRegionArea.left) {
|
|
@@ -441,7 +433,7 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
441
433
|
}
|
|
442
434
|
}
|
|
443
435
|
}
|
|
444
|
-
|
|
436
|
+
const numShiftY = shiftY === true ? 0 : shiftY;
|
|
445
437
|
if (typeof numShiftY === 'number') {
|
|
446
438
|
// Top
|
|
447
439
|
if (nextPopupY < visibleRegionArea.top) {
|
|
@@ -465,56 +457,56 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
465
457
|
|
|
466
458
|
// ============================ Arrow ============================
|
|
467
459
|
// Arrow center align
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
onPopupAlign
|
|
460
|
+
const popupLeft = popupRect.x + nextOffsetX;
|
|
461
|
+
const popupRight = popupLeft + popupWidth;
|
|
462
|
+
const popupTop = popupRect.y + nextOffsetY;
|
|
463
|
+
const popupBottom = popupTop + popupHeight;
|
|
464
|
+
const targetLeft = targetRect.x;
|
|
465
|
+
const targetRight = targetLeft + targetWidth;
|
|
466
|
+
const targetTop = targetRect.y;
|
|
467
|
+
const targetBottom = targetTop + targetHeight;
|
|
468
|
+
const maxLeft = Math.max(popupLeft, targetLeft);
|
|
469
|
+
const minRight = Math.min(popupRight, targetRight);
|
|
470
|
+
const xCenter = (maxLeft + minRight) / 2;
|
|
471
|
+
const nextArrowX = xCenter - popupLeft;
|
|
472
|
+
const maxTop = Math.max(popupTop, targetTop);
|
|
473
|
+
const minBottom = Math.min(popupBottom, targetBottom);
|
|
474
|
+
const yCenter = (maxTop + minBottom) / 2;
|
|
475
|
+
const nextArrowY = yCenter - popupTop;
|
|
476
|
+
onPopupAlign?.(popupEle, nextAlignInfo);
|
|
485
477
|
|
|
486
478
|
// Additional calculate right & bottom position
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
if (
|
|
479
|
+
let offsetX4Right = popupMirrorRect.right - popupRect.x - (nextOffsetX + popupRect.width);
|
|
480
|
+
let offsetY4Bottom = popupMirrorRect.bottom - popupRect.y - (nextOffsetY + popupRect.height);
|
|
481
|
+
if (scaleX === 1) {
|
|
490
482
|
nextOffsetX = Math.round(nextOffsetX);
|
|
491
483
|
offsetX4Right = Math.round(offsetX4Right);
|
|
492
484
|
}
|
|
493
|
-
if (
|
|
485
|
+
if (scaleY === 1) {
|
|
494
486
|
nextOffsetY = Math.round(nextOffsetY);
|
|
495
487
|
offsetY4Bottom = Math.round(offsetY4Bottom);
|
|
496
488
|
}
|
|
497
|
-
|
|
489
|
+
const nextOffsetInfo = {
|
|
498
490
|
ready: true,
|
|
499
|
-
offsetX: nextOffsetX /
|
|
500
|
-
offsetY: nextOffsetY /
|
|
501
|
-
offsetR: offsetX4Right /
|
|
502
|
-
offsetB: offsetY4Bottom /
|
|
503
|
-
arrowX: nextArrowX /
|
|
504
|
-
arrowY: nextArrowY /
|
|
505
|
-
scaleX
|
|
506
|
-
scaleY
|
|
491
|
+
offsetX: nextOffsetX / scaleX,
|
|
492
|
+
offsetY: nextOffsetY / scaleY,
|
|
493
|
+
offsetR: offsetX4Right / scaleX,
|
|
494
|
+
offsetB: offsetY4Bottom / scaleY,
|
|
495
|
+
arrowX: nextArrowX / scaleX,
|
|
496
|
+
arrowY: nextArrowY / scaleY,
|
|
497
|
+
scaleX,
|
|
498
|
+
scaleY,
|
|
507
499
|
align: nextAlignInfo
|
|
508
500
|
};
|
|
509
501
|
setOffsetInfo(nextOffsetInfo);
|
|
510
502
|
}
|
|
511
503
|
});
|
|
512
|
-
|
|
504
|
+
const triggerAlign = () => {
|
|
513
505
|
alignCountRef.current += 1;
|
|
514
|
-
|
|
506
|
+
const id = alignCountRef.current;
|
|
515
507
|
|
|
516
508
|
// Merge all align requirement into one frame
|
|
517
|
-
Promise.resolve().then(
|
|
509
|
+
Promise.resolve().then(() => {
|
|
518
510
|
if (alignCountRef.current === id) {
|
|
519
511
|
onAlign();
|
|
520
512
|
}
|
|
@@ -522,15 +514,14 @@ function useAlign(open, popupEle, target, placement, builtinPlacements, popupAli
|
|
|
522
514
|
};
|
|
523
515
|
|
|
524
516
|
// Reset ready status when placement & open changed
|
|
525
|
-
|
|
526
|
-
setOffsetInfo(
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
});
|
|
517
|
+
const resetReady = () => {
|
|
518
|
+
setOffsetInfo(ori => ({
|
|
519
|
+
...ori,
|
|
520
|
+
ready: false
|
|
521
|
+
}));
|
|
531
522
|
};
|
|
532
523
|
(0, _useLayoutEffect.default)(resetReady, [placement]);
|
|
533
|
-
(0, _useLayoutEffect.default)(
|
|
524
|
+
(0, _useLayoutEffect.default)(() => {
|
|
534
525
|
if (!open) {
|
|
535
526
|
resetReady();
|
|
536
527
|
}
|