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