@v-c/trigger 0.0.12 → 0.0.14

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.
Files changed (38) hide show
  1. package/dist/Popup/Arrow.cjs +60 -89
  2. package/dist/Popup/Arrow.js +58 -88
  3. package/dist/Popup/Mask.cjs +53 -64
  4. package/dist/Popup/Mask.js +49 -63
  5. package/dist/Popup/PopupContent.cjs +22 -27
  6. package/dist/Popup/PopupContent.js +18 -26
  7. package/dist/Popup/index.cjs +312 -366
  8. package/dist/Popup/index.d.ts +1 -1
  9. package/dist/Popup/index.js +304 -362
  10. package/dist/UniqueProvider/UniqueContainer.cjs +133 -150
  11. package/dist/UniqueProvider/UniqueContainer.js +128 -148
  12. package/dist/UniqueProvider/index.cjs +151 -213
  13. package/dist/UniqueProvider/index.js +144 -210
  14. package/dist/UniqueProvider/useTargetState.cjs +39 -39
  15. package/dist/UniqueProvider/useTargetState.js +37 -39
  16. package/dist/_virtual/rolldown_runtime.cjs +21 -0
  17. package/dist/context.cjs +17 -28
  18. package/dist/context.js +17 -33
  19. package/dist/hooks/useAction.cjs +19 -25
  20. package/dist/hooks/useAction.js +17 -25
  21. package/dist/hooks/useAlign.cjs +396 -486
  22. package/dist/hooks/useAlign.js +391 -484
  23. package/dist/hooks/useDelay.cjs +21 -24
  24. package/dist/hooks/useDelay.js +20 -25
  25. package/dist/hooks/useOffsetStyle.cjs +34 -33
  26. package/dist/hooks/useOffsetStyle.js +32 -33
  27. package/dist/hooks/useWatch.cjs +38 -34
  28. package/dist/hooks/useWatch.js +36 -34
  29. package/dist/hooks/useWinClick.cjs +54 -64
  30. package/dist/hooks/useWinClick.js +51 -63
  31. package/dist/index.cjs +605 -694
  32. package/dist/index.d.ts +1 -1
  33. package/dist/index.js +593 -689
  34. package/dist/interface.cjs +0 -1
  35. package/dist/interface.js +0 -1
  36. package/dist/util.cjs +65 -82
  37. package/dist/util.js +66 -87
  38. package/package.json +4 -4
@@ -1,499 +1,406 @@
1
+ import { collectScroller, getVisibleArea, getWin, toNum } from "../util.js";
2
+ import { computed, nextTick, reactive, ref, shallowRef, toRefs, watch } from "vue";
1
3
  import { isDOM } from "@v-c/util/dist/Dom/findDOMNode";
2
4
  import isVisible from "@v-c/util/dist/Dom/isVisible";
3
5
  import { rafDebounce } from "@v-c/util/dist/raf";
4
- import { reactive, shallowRef, computed, ref, watch, nextTick, watchEffect, toRefs } from "vue";
5
- import { collectScroller, getWin, getVisibleArea, toNum } from "../util.js";
6
6
  function getUnitOffset(size, offset = 0) {
7
- const offsetStr = `${offset}`;
8
- const cells = offsetStr.match(/^(.*)\%$/);
9
- if (cells) {
10
- return size * (parseFloat(cells[1]) / 100);
11
- }
12
- return parseFloat(offsetStr);
7
+ const offsetStr = `${offset}`;
8
+ const cells = offsetStr.match(/^(.*)\%$/);
9
+ if (cells) return size * (parseFloat(cells[1]) / 100);
10
+ return parseFloat(offsetStr);
13
11
  }
14
12
  function getNumberOffset(rect, offset) {
15
- const [offsetX, offsetY] = offset || [];
16
- return [
17
- getUnitOffset(rect.width, offsetX),
18
- getUnitOffset(rect.height, offsetY)
19
- ];
13
+ const [offsetX, offsetY] = offset || [];
14
+ return [getUnitOffset(rect.width, offsetX), getUnitOffset(rect.height, offsetY)];
20
15
  }
21
16
  function splitPoints(points = "") {
22
- return [points[0], points[1]];
17
+ return [points[0], points[1]];
23
18
  }
24
19
  function getAlignPoint(rect, points) {
25
- const topBottom = points[0];
26
- const leftRight = points[1];
27
- let x;
28
- let y;
29
- if (topBottom === "t") {
30
- y = rect.y;
31
- } else if (topBottom === "b") {
32
- y = rect.y + rect.height;
33
- } else {
34
- y = rect.y + rect.height / 2;
35
- }
36
- if (leftRight === "l") {
37
- x = rect.x;
38
- } else if (leftRight === "r") {
39
- x = rect.x + rect.width;
40
- } else {
41
- x = rect.x + rect.width / 2;
42
- }
43
- return { x, y };
20
+ const topBottom = points[0];
21
+ const leftRight = points[1];
22
+ let x;
23
+ let y;
24
+ if (topBottom === "t") y = rect.y;
25
+ else if (topBottom === "b") y = rect.y + rect.height;
26
+ else y = rect.y + rect.height / 2;
27
+ if (leftRight === "l") x = rect.x;
28
+ else if (leftRight === "r") x = rect.x + rect.width;
29
+ else x = rect.x + rect.width / 2;
30
+ return {
31
+ x,
32
+ y
33
+ };
44
34
  }
45
35
  function reversePoints(points, index) {
46
- const reverseMap = {
47
- t: "b",
48
- b: "t",
49
- l: "r",
50
- r: "l"
51
- };
52
- return points.map((point, i) => {
53
- if (i === index) {
54
- return reverseMap[point] || "c";
55
- }
56
- return point;
57
- }).join("");
36
+ const reverseMap = {
37
+ t: "b",
38
+ b: "t",
39
+ l: "r",
40
+ r: "l"
41
+ };
42
+ return points.map((point, i) => {
43
+ if (i === index) return reverseMap[point] || "c";
44
+ return point;
45
+ }).join("");
46
+ }
47
+ function parseOriginValue(value, size, axis) {
48
+ const fallback = size / 2;
49
+ if (!value) return fallback;
50
+ const val = value.trim();
51
+ if (!val) return fallback;
52
+ if (val.endsWith("%")) return size * (parseFloat(val) / 100);
53
+ if (val.endsWith("px")) return parseFloat(val);
54
+ if (val === "center") return fallback;
55
+ if (axis === "x") {
56
+ if (val === "left") return 0;
57
+ if (val === "right") return size;
58
+ } else if (axis === "y") {
59
+ if (val === "top") return 0;
60
+ if (val === "bottom") return size;
61
+ }
62
+ const num = parseFloat(val);
63
+ return Number.isNaN(num) ? fallback : num;
64
+ }
65
+ function getTransformOriginPoint(origin, width, height) {
66
+ const [originX = "50%", originY = "50%"] = origin?.split(/\s+/).filter(Boolean) ?? [];
67
+ return [parseOriginValue(originX, width, "x"), parseOriginValue(originY, height, "y")];
68
+ }
69
+ function normalizeRect(rect, scaleX, scaleY, originX, originY) {
70
+ const rawX = rect.x ?? rect.left;
71
+ const rawY = rect.y ?? rect.top;
72
+ const width = rect.width / scaleX;
73
+ const height = rect.height / scaleY;
74
+ const x = rawX - (1 - scaleX) * originX;
75
+ const y = rawY - (1 - scaleY) * originY;
76
+ return {
77
+ x,
78
+ y,
79
+ width,
80
+ height,
81
+ left: x,
82
+ top: y,
83
+ right: x + width,
84
+ bottom: y + height
85
+ };
86
+ }
87
+ function shouldSwitchPlacement(isOverflow, isVisibleFirst, newVisibleArea, originVisibleArea, newRecommendArea, originRecommendArea) {
88
+ if (isOverflow) return newVisibleArea > originVisibleArea || newVisibleArea === originVisibleArea && (!isVisibleFirst || newRecommendArea >= originRecommendArea);
89
+ return newVisibleArea > originVisibleArea || isVisibleFirst && newVisibleArea === originVisibleArea && newRecommendArea > originRecommendArea;
58
90
  }
59
91
  function useAlign(open, popupEle, target, placement, builtinPlacements, popupAlign, onPopupAlign, mobile) {
60
- const offsetInfo = reactive({
61
- ready: false,
62
- offsetX: 0,
63
- offsetY: 0,
64
- offsetR: 0,
65
- offsetB: 0,
66
- arrowX: 0,
67
- arrowY: 0,
68
- scaleX: 1,
69
- scaleY: 1,
70
- align: builtinPlacements.value[placement.value] || {}
71
- });
72
- const alignCountRef = shallowRef(0);
73
- const scrollerList = computed(() => {
74
- if (!popupEle.value || mobile?.value) {
75
- return [];
76
- }
77
- return collectScroller(popupEle.value);
78
- });
79
- const prevFlipRef = ref({});
80
- const resetFlipCache = () => {
81
- prevFlipRef.value = {};
82
- };
83
- const _onAlign = () => {
84
- if (popupEle.value && target.value && open.value && !mobile?.value) {
85
- let getIntersectionVisibleArea = function(offsetX2, offsetY2, area = visibleArea) {
86
- const l = popupRect.x + offsetX2;
87
- const t = popupRect.y + offsetY2;
88
- const r = l + popupWidth;
89
- const b = t + popupHeight;
90
- const visibleL = Math.max(l, area.left);
91
- const visibleT = Math.max(t, area.top);
92
- const visibleR = Math.min(r, area.right);
93
- const visibleB = Math.min(b, area.bottom);
94
- return Math.max(0, (visibleR - visibleL) * (visibleB - visibleT));
95
- }, syncNextPopupPosition = function() {
96
- nextPopupY = popupRect.y + nextOffsetY;
97
- nextPopupBottom = nextPopupY + popupHeight;
98
- nextPopupX = popupRect.x + nextOffsetX;
99
- nextPopupRight = nextPopupX + popupWidth;
100
- };
101
- const popupElement = popupEle.value;
102
- const doc = popupElement.ownerDocument;
103
- const win = getWin(popupElement);
104
- const { position: popupPosition } = win.getComputedStyle(popupElement);
105
- const originLeft = popupElement.style.left;
106
- const originTop = popupElement.style.top;
107
- const originRight = popupElement.style.right;
108
- const originBottom = popupElement.style.bottom;
109
- const originOverflow = popupElement.style.overflow;
110
- const placementInfo = {
111
- ...builtinPlacements.value[placement.value],
112
- ...popupAlign?.value
113
- };
114
- const placeholderElement = doc.createElement("div");
115
- popupElement.parentElement?.appendChild(placeholderElement);
116
- placeholderElement.style.left = `${popupElement.offsetLeft}px`;
117
- placeholderElement.style.top = `${popupElement.offsetTop}px`;
118
- placeholderElement.style.position = popupPosition;
119
- placeholderElement.style.height = `${popupElement.offsetHeight}px`;
120
- placeholderElement.style.width = `${popupElement.offsetWidth}px`;
121
- popupElement.style.left = "0";
122
- popupElement.style.top = "0";
123
- popupElement.style.right = "auto";
124
- popupElement.style.bottom = "auto";
125
- popupElement.style.overflow = "hidden";
126
- let targetRect;
127
- if (Array.isArray(target.value)) {
128
- targetRect = {
129
- x: target.value[0],
130
- y: target.value[1],
131
- width: 0,
132
- height: 0
133
- };
134
- } else {
135
- const rect = target.value.getBoundingClientRect();
136
- rect.x = rect.x ?? rect.left;
137
- rect.y = rect.y ?? rect.top;
138
- targetRect = {
139
- x: rect.x,
140
- y: rect.y,
141
- width: rect.width,
142
- height: rect.height
143
- };
144
- }
145
- const popupRect = popupElement.getBoundingClientRect();
146
- const { height, width } = win.getComputedStyle(popupElement);
147
- popupRect.x = popupRect.x ?? popupRect.left;
148
- popupRect.y = popupRect.y ?? popupRect.top;
149
- const {
150
- clientWidth,
151
- clientHeight,
152
- scrollWidth,
153
- scrollHeight,
154
- scrollTop,
155
- scrollLeft
156
- } = doc.documentElement;
157
- const popupHeight = popupRect.height;
158
- const popupWidth = popupRect.width;
159
- const targetHeight = targetRect.height;
160
- const targetWidth = targetRect.width;
161
- const visibleRegion = {
162
- left: 0,
163
- top: 0,
164
- right: clientWidth,
165
- bottom: clientHeight
166
- };
167
- const scrollRegion = {
168
- left: -scrollLeft,
169
- top: -scrollTop,
170
- right: scrollWidth - scrollLeft,
171
- bottom: scrollHeight - scrollTop
172
- };
173
- let { htmlRegion } = placementInfo;
174
- const VISIBLE = "visible";
175
- const VISIBLE_FIRST = "visibleFirst";
176
- if (htmlRegion !== "scroll" && htmlRegion !== VISIBLE_FIRST) {
177
- htmlRegion = VISIBLE;
178
- }
179
- const isVisibleFirst = htmlRegion === VISIBLE_FIRST;
180
- const scrollRegionArea = getVisibleArea(scrollRegion, scrollerList.value);
181
- const visibleRegionArea = getVisibleArea(visibleRegion, scrollerList.value);
182
- const visibleArea = htmlRegion === VISIBLE ? visibleRegionArea : scrollRegionArea;
183
- const adjustCheckVisibleArea = isVisibleFirst ? visibleRegionArea : visibleArea;
184
- popupElement.style.left = "auto";
185
- popupElement.style.top = "auto";
186
- popupElement.style.right = "0";
187
- popupElement.style.bottom = "0";
188
- const popupMirrorRect = popupElement.getBoundingClientRect();
189
- popupElement.style.left = originLeft;
190
- popupElement.style.top = originTop;
191
- popupElement.style.right = originRight;
192
- popupElement.style.bottom = originBottom;
193
- popupElement.style.overflow = originOverflow;
194
- popupElement.parentElement?.removeChild(placeholderElement);
195
- const scaleX2 = toNum(
196
- Math.round(popupWidth / parseFloat(width) * 1e3) / 1e3
197
- );
198
- const scaleY2 = toNum(
199
- Math.round(popupHeight / parseFloat(height) * 1e3) / 1e3
200
- );
201
- if (scaleX2 === 0 || scaleY2 === 0 || isDOM(target) && !isVisible(target)) {
202
- return;
203
- }
204
- const { offset, targetOffset } = placementInfo;
205
- let [popupOffsetX, popupOffsetY] = getNumberOffset(popupRect, offset);
206
- const [targetOffsetX, targetOffsetY] = getNumberOffset(
207
- targetRect,
208
- targetOffset
209
- );
210
- targetRect.x -= targetOffsetX;
211
- targetRect.y -= targetOffsetY;
212
- const [popupPoint, targetPoint] = placementInfo.points || [];
213
- const targetPoints = splitPoints(targetPoint);
214
- const popupPoints = splitPoints(popupPoint);
215
- const targetAlignPoint = getAlignPoint(targetRect, targetPoints);
216
- const popupAlignPoint = getAlignPoint(popupRect, popupPoints);
217
- const nextAlignInfo = {
218
- ...placementInfo
219
- };
220
- let nextOffsetX = targetAlignPoint.x - popupAlignPoint.x + popupOffsetX;
221
- let nextOffsetY = targetAlignPoint.y - popupAlignPoint.y + popupOffsetY;
222
- const originIntersectionVisibleArea = getIntersectionVisibleArea(
223
- nextOffsetX,
224
- nextOffsetY
225
- );
226
- const originIntersectionRecommendArea = getIntersectionVisibleArea(
227
- nextOffsetX,
228
- nextOffsetY,
229
- visibleRegionArea
230
- );
231
- const targetAlignPointTL = getAlignPoint(targetRect, ["t", "l"]);
232
- const popupAlignPointTL = getAlignPoint(popupRect, ["t", "l"]);
233
- const targetAlignPointBR = getAlignPoint(targetRect, ["b", "r"]);
234
- const popupAlignPointBR = getAlignPoint(popupRect, ["b", "r"]);
235
- const overflow = placementInfo.overflow || {};
236
- const { adjustX, adjustY, shiftX, shiftY } = overflow;
237
- const supportAdjust = (val) => {
238
- if (typeof val === "boolean") {
239
- return val;
240
- }
241
- return val >= 0;
242
- };
243
- let nextPopupY;
244
- let nextPopupBottom;
245
- let nextPopupX;
246
- let nextPopupRight;
247
- syncNextPopupPosition();
248
- const needAdjustY = supportAdjust(adjustY);
249
- const sameTB = popupPoints[0] === targetPoints[0];
250
- if (needAdjustY && popupPoints[0] === "t" && (nextPopupBottom > adjustCheckVisibleArea.bottom || prevFlipRef.value.bt)) {
251
- let tmpNextOffsetY = nextOffsetY;
252
- if (sameTB) {
253
- tmpNextOffsetY -= popupHeight - targetHeight;
254
- } else {
255
- tmpNextOffsetY = targetAlignPointTL.y - popupAlignPointBR.y - popupOffsetY;
256
- }
257
- const newVisibleArea = getIntersectionVisibleArea(
258
- nextOffsetX,
259
- tmpNextOffsetY
260
- );
261
- const newVisibleRecommendArea = getIntersectionVisibleArea(
262
- nextOffsetX,
263
- tmpNextOffsetY,
264
- visibleRegionArea
265
- );
266
- if (
267
- // Of course use larger one
268
- newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst || newVisibleRecommendArea >= originIntersectionRecommendArea)
269
- ) {
270
- prevFlipRef.value.bt = true;
271
- nextOffsetY = tmpNextOffsetY;
272
- popupOffsetY = -popupOffsetY;
273
- nextAlignInfo.points = [
274
- reversePoints(popupPoints, 0),
275
- reversePoints(targetPoints, 0)
276
- ];
277
- } else {
278
- prevFlipRef.value.bt = false;
279
- }
280
- }
281
- if (needAdjustY && popupPoints[0] === "b" && (nextPopupY < adjustCheckVisibleArea.top || prevFlipRef.value.tb)) {
282
- let tmpNextOffsetY = nextOffsetY;
283
- if (sameTB) {
284
- tmpNextOffsetY += popupHeight - targetHeight;
285
- } else {
286
- tmpNextOffsetY = targetAlignPointBR.y - popupAlignPointTL.y - popupOffsetY;
287
- }
288
- const newVisibleArea = getIntersectionVisibleArea(
289
- nextOffsetX,
290
- tmpNextOffsetY
291
- );
292
- const newVisibleRecommendArea = getIntersectionVisibleArea(
293
- nextOffsetX,
294
- tmpNextOffsetY,
295
- visibleRegionArea
296
- );
297
- if (
298
- // Of course use larger one
299
- newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst || newVisibleRecommendArea >= originIntersectionRecommendArea)
300
- ) {
301
- prevFlipRef.value.tb = true;
302
- nextOffsetY = tmpNextOffsetY;
303
- popupOffsetY = -popupOffsetY;
304
- nextAlignInfo.points = [
305
- reversePoints(popupPoints, 0),
306
- reversePoints(targetPoints, 0)
307
- ];
308
- } else {
309
- prevFlipRef.value.tb = false;
310
- }
311
- }
312
- const needAdjustX = supportAdjust(adjustX);
313
- const sameLR = popupPoints[1] === targetPoints[1];
314
- if (needAdjustX && popupPoints[1] === "l" && (nextPopupRight > adjustCheckVisibleArea.right || prevFlipRef.value.rl)) {
315
- let tmpNextOffsetX = nextOffsetX;
316
- if (sameLR) {
317
- tmpNextOffsetX -= popupWidth - targetWidth;
318
- } else {
319
- tmpNextOffsetX = targetAlignPointTL.x - popupAlignPointBR.x - popupOffsetX;
320
- }
321
- const newVisibleArea = getIntersectionVisibleArea(
322
- tmpNextOffsetX,
323
- nextOffsetY
324
- );
325
- const newVisibleRecommendArea = getIntersectionVisibleArea(
326
- tmpNextOffsetX,
327
- nextOffsetY,
328
- visibleRegionArea
329
- );
330
- if (
331
- // Of course use larger one
332
- newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst || newVisibleRecommendArea >= originIntersectionRecommendArea)
333
- ) {
334
- prevFlipRef.value.rl = true;
335
- nextOffsetX = tmpNextOffsetX;
336
- popupOffsetX = -popupOffsetX;
337
- nextAlignInfo.points = [
338
- reversePoints(popupPoints, 1),
339
- reversePoints(targetPoints, 1)
340
- ];
341
- } else {
342
- prevFlipRef.value.rl = false;
343
- }
344
- }
345
- if (needAdjustX && popupPoints[1] === "r" && (nextPopupX < adjustCheckVisibleArea.left || prevFlipRef.value.lr)) {
346
- let tmpNextOffsetX = nextOffsetX;
347
- if (sameLR) {
348
- tmpNextOffsetX += popupWidth - targetWidth;
349
- } else {
350
- tmpNextOffsetX = targetAlignPointBR.x - popupAlignPointTL.x - popupOffsetX;
351
- }
352
- const newVisibleArea = getIntersectionVisibleArea(
353
- tmpNextOffsetX,
354
- nextOffsetY
355
- );
356
- const newVisibleRecommendArea = getIntersectionVisibleArea(
357
- tmpNextOffsetX,
358
- nextOffsetY,
359
- visibleRegionArea
360
- );
361
- if (
362
- // Of course use larger one
363
- newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst || newVisibleRecommendArea >= originIntersectionRecommendArea)
364
- ) {
365
- prevFlipRef.value.lr = true;
366
- nextOffsetX = tmpNextOffsetX;
367
- popupOffsetX = -popupOffsetX;
368
- nextAlignInfo.points = [
369
- reversePoints(popupPoints, 1),
370
- reversePoints(targetPoints, 1)
371
- ];
372
- } else {
373
- prevFlipRef.value.lr = false;
374
- }
375
- }
376
- syncNextPopupPosition();
377
- const numShiftX = shiftX === true ? 0 : shiftX;
378
- if (typeof numShiftX === "number") {
379
- if (nextPopupX < visibleRegionArea.left) {
380
- nextOffsetX -= nextPopupX - visibleRegionArea.left - popupOffsetX;
381
- if (targetRect.x + targetWidth < visibleRegionArea.left + numShiftX) {
382
- nextOffsetX += targetRect.x - visibleRegionArea.left + targetWidth - numShiftX;
383
- }
384
- }
385
- if (nextPopupRight > visibleRegionArea.right) {
386
- nextOffsetX -= nextPopupRight - visibleRegionArea.right - popupOffsetX;
387
- if (targetRect.x > visibleRegionArea.right - numShiftX) {
388
- nextOffsetX += targetRect.x - visibleRegionArea.right + numShiftX;
389
- }
390
- }
391
- }
392
- const numShiftY = shiftY === true ? 0 : shiftY;
393
- if (typeof numShiftY === "number") {
394
- if (nextPopupY < visibleRegionArea.top) {
395
- nextOffsetY -= nextPopupY - visibleRegionArea.top - popupOffsetY;
396
- if (targetRect.y + targetHeight < visibleRegionArea.top + numShiftY) {
397
- nextOffsetY += targetRect.y - visibleRegionArea.top + targetHeight - numShiftY;
398
- }
399
- }
400
- if (nextPopupBottom > visibleRegionArea.bottom) {
401
- nextOffsetY -= nextPopupBottom - visibleRegionArea.bottom - popupOffsetY;
402
- if (targetRect.y > visibleRegionArea.bottom - numShiftY) {
403
- nextOffsetY += targetRect.y - visibleRegionArea.bottom + numShiftY;
404
- }
405
- }
406
- }
407
- const popupLeft = popupRect.x + nextOffsetX;
408
- const popupRight = popupLeft + popupWidth;
409
- const popupTop = popupRect.y + nextOffsetY;
410
- const popupBottom = popupTop + popupHeight;
411
- const targetLeft = targetRect.x;
412
- const targetRight = targetLeft + targetWidth;
413
- const targetTop = targetRect.y;
414
- const targetBottom = targetTop + targetHeight;
415
- const maxLeft = Math.max(popupLeft, targetLeft);
416
- const minRight = Math.min(popupRight, targetRight);
417
- const xCenter = (maxLeft + minRight) / 2;
418
- const nextArrowX = xCenter - popupLeft;
419
- const maxTop = Math.max(popupTop, targetTop);
420
- const minBottom = Math.min(popupBottom, targetBottom);
421
- const yCenter = (maxTop + minBottom) / 2;
422
- const nextArrowY = yCenter - popupTop;
423
- onPopupAlign?.(popupEle.value, nextAlignInfo);
424
- let offsetX4Right = popupMirrorRect.right - popupRect.x - (nextOffsetX + popupRect.width);
425
- let offsetY4Bottom = popupMirrorRect.bottom - popupRect.y - (nextOffsetY + popupRect.height);
426
- if (scaleX2 === 1) {
427
- nextOffsetX = Math.round(nextOffsetX);
428
- offsetX4Right = Math.round(offsetX4Right);
429
- }
430
- if (scaleY2 === 1) {
431
- nextOffsetY = Math.round(nextOffsetY);
432
- offsetY4Bottom = Math.round(offsetY4Bottom);
433
- }
434
- const nextOffsetInfo = {
435
- ready: true,
436
- offsetX: nextOffsetX / scaleX2,
437
- offsetY: nextOffsetY / scaleY2,
438
- offsetR: offsetX4Right / scaleX2,
439
- offsetB: offsetY4Bottom / scaleY2,
440
- arrowX: nextArrowX / scaleX2,
441
- arrowY: nextArrowY / scaleY2,
442
- scaleX: scaleX2,
443
- scaleY: scaleY2,
444
- align: nextAlignInfo
445
- };
446
- Object.assign(offsetInfo, nextOffsetInfo);
447
- }
448
- };
449
- const onAlign = rafDebounce(_onAlign);
450
- const triggerAlign = () => {
451
- alignCountRef.value += 1;
452
- const id = alignCountRef.value;
453
- Promise.resolve().then(() => {
454
- if (alignCountRef.value === id) {
455
- onAlign();
456
- }
457
- });
458
- };
459
- watch(
460
- popupEle,
461
- async (ele) => {
462
- if (ele && open.value && !mobile?.value) {
463
- await nextTick();
464
- triggerAlign();
465
- }
466
- }
467
- );
468
- const resetReady = () => {
469
- offsetInfo.ready = false;
470
- };
471
- watch(placement, async () => {
472
- await nextTick();
473
- resetReady();
474
- });
475
- watchEffect(async () => {
476
- if (!open.value) {
477
- resetFlipCache();
478
- await nextTick();
479
- resetReady();
480
- }
481
- });
482
- const { ready, offsetX, offsetR, offsetY, offsetB, align, arrowY, arrowX, scaleY, scaleX } = toRefs(offsetInfo);
483
- return [
484
- ready,
485
- offsetX,
486
- offsetY,
487
- offsetR,
488
- offsetB,
489
- arrowX,
490
- arrowY,
491
- scaleX,
492
- scaleY,
493
- align,
494
- triggerAlign
495
- ];
92
+ const offsetInfo = reactive({
93
+ ready: false,
94
+ offsetX: 0,
95
+ offsetY: 0,
96
+ offsetR: 0,
97
+ offsetB: 0,
98
+ arrowX: 0,
99
+ arrowY: 0,
100
+ scaleX: 1,
101
+ scaleY: 1,
102
+ align: builtinPlacements.value[placement.value] || {}
103
+ });
104
+ const alignCountRef = shallowRef(0);
105
+ const scrollerList = computed(() => {
106
+ if (!popupEle.value || mobile?.value) return [];
107
+ return collectScroller(popupEle.value);
108
+ });
109
+ const prevFlipRef = ref({});
110
+ const resetFlipCache = () => {
111
+ prevFlipRef.value = {};
112
+ };
113
+ const _onAlign = () => {
114
+ if (popupEle.value && target.value && open.value && !mobile?.value) {
115
+ const popupElement = popupEle.value;
116
+ const doc = popupElement.ownerDocument;
117
+ const popupComputedStyle = getWin(popupElement).getComputedStyle(popupElement);
118
+ const { position: popupPosition } = popupComputedStyle;
119
+ const originLeft = popupElement.style.left;
120
+ const originTop = popupElement.style.top;
121
+ const originRight = popupElement.style.right;
122
+ const originBottom = popupElement.style.bottom;
123
+ const originOverflow = popupElement.style.overflow;
124
+ const placementInfo = {
125
+ ...builtinPlacements.value[placement.value],
126
+ ...popupAlign?.value
127
+ };
128
+ const placeholderElement = doc.createElement("div");
129
+ popupElement.parentElement?.appendChild(placeholderElement);
130
+ placeholderElement.style.left = `${popupElement.offsetLeft}px`;
131
+ placeholderElement.style.top = `${popupElement.offsetTop}px`;
132
+ placeholderElement.style.position = popupPosition;
133
+ placeholderElement.style.height = `${popupElement.offsetHeight}px`;
134
+ placeholderElement.style.width = `${popupElement.offsetWidth}px`;
135
+ popupElement.style.left = "0";
136
+ popupElement.style.top = "0";
137
+ popupElement.style.right = "auto";
138
+ popupElement.style.bottom = "auto";
139
+ popupElement.style.overflow = "hidden";
140
+ let targetRect;
141
+ if (Array.isArray(target.value)) targetRect = {
142
+ x: target.value[0],
143
+ y: target.value[1],
144
+ width: 0,
145
+ height: 0
146
+ };
147
+ else {
148
+ const rect = target.value.getBoundingClientRect();
149
+ rect.x = rect.x ?? rect.left;
150
+ rect.y = rect.y ?? rect.top;
151
+ targetRect = {
152
+ x: rect.x,
153
+ y: rect.y,
154
+ width: rect.width,
155
+ height: rect.height
156
+ };
157
+ }
158
+ const rawPopupRect = popupElement.getBoundingClientRect();
159
+ const { clientWidth, clientHeight, scrollWidth, scrollHeight, scrollTop, scrollLeft } = doc.documentElement;
160
+ const targetHeight = targetRect.height;
161
+ const targetWidth = targetRect.width;
162
+ const visibleRegion = {
163
+ left: 0,
164
+ top: 0,
165
+ right: clientWidth,
166
+ bottom: clientHeight
167
+ };
168
+ const scrollRegion = {
169
+ left: -scrollLeft,
170
+ top: -scrollTop,
171
+ right: scrollWidth - scrollLeft,
172
+ bottom: scrollHeight - scrollTop
173
+ };
174
+ let { htmlRegion } = placementInfo;
175
+ const VISIBLE = "visible";
176
+ const VISIBLE_FIRST = "visibleFirst";
177
+ if (htmlRegion !== "scroll" && htmlRegion !== VISIBLE_FIRST) htmlRegion = VISIBLE;
178
+ const isVisibleFirst = htmlRegion === VISIBLE_FIRST;
179
+ const scrollRegionArea = getVisibleArea(scrollRegion, scrollerList.value);
180
+ const visibleRegionArea = getVisibleArea(visibleRegion, scrollerList.value);
181
+ const visibleArea = htmlRegion === VISIBLE ? visibleRegionArea : scrollRegionArea;
182
+ const adjustCheckVisibleArea = isVisibleFirst ? visibleRegionArea : visibleArea;
183
+ popupElement.style.left = "auto";
184
+ popupElement.style.top = "auto";
185
+ popupElement.style.right = "0";
186
+ popupElement.style.bottom = "0";
187
+ const rawPopupMirrorRect = popupElement.getBoundingClientRect();
188
+ popupElement.style.left = originLeft;
189
+ popupElement.style.top = originTop;
190
+ popupElement.style.right = originRight;
191
+ popupElement.style.bottom = originBottom;
192
+ popupElement.style.overflow = originOverflow;
193
+ popupElement.parentElement?.removeChild(placeholderElement);
194
+ const widthValue = parseFloat(popupComputedStyle.width);
195
+ const heightValue = parseFloat(popupComputedStyle.height);
196
+ const baseWidth = !Number.isNaN(widthValue) && widthValue > 0 ? widthValue : popupElement.offsetWidth;
197
+ const baseHeight = !Number.isNaN(heightValue) && heightValue > 0 ? heightValue : popupElement.offsetHeight;
198
+ const safeBaseWidth = baseWidth || rawPopupRect.width || 1;
199
+ const safeBaseHeight = baseHeight || rawPopupRect.height || 1;
200
+ const scaleX$1 = toNum(Math.round(rawPopupRect.width / safeBaseWidth * 1e3) / 1e3);
201
+ const scaleY$1 = toNum(Math.round(rawPopupRect.height / safeBaseHeight * 1e3) / 1e3);
202
+ if (scaleX$1 === 0 || scaleY$1 === 0 || isDOM(target) && !isVisible(target)) return;
203
+ const [originX, originY] = getTransformOriginPoint(popupComputedStyle.transformOrigin, safeBaseWidth, safeBaseHeight);
204
+ const popupRect = normalizeRect(rawPopupRect, scaleX$1, scaleY$1, originX, originY);
205
+ const popupMirrorRect = normalizeRect(rawPopupMirrorRect, scaleX$1, scaleY$1, originX, originY);
206
+ const popupHeight = popupRect.height;
207
+ const popupWidth = popupRect.width;
208
+ const { offset, targetOffset } = placementInfo;
209
+ let [popupOffsetX, popupOffsetY] = getNumberOffset(popupRect, offset);
210
+ const [targetOffsetX, targetOffsetY] = getNumberOffset(targetRect, targetOffset);
211
+ targetRect.x -= targetOffsetX;
212
+ targetRect.y -= targetOffsetY;
213
+ const [popupPoint, targetPoint] = placementInfo.points || [];
214
+ const targetPoints = splitPoints(targetPoint);
215
+ const popupPoints = splitPoints(popupPoint);
216
+ const targetAlignPoint = getAlignPoint(targetRect, targetPoints);
217
+ const popupAlignPoint = getAlignPoint(popupRect, popupPoints);
218
+ const nextAlignInfo = { ...placementInfo };
219
+ let nextOffsetX = targetAlignPoint.x - popupAlignPoint.x + popupOffsetX;
220
+ let nextOffsetY = targetAlignPoint.y - popupAlignPoint.y + popupOffsetY;
221
+ function getIntersectionVisibleArea(offsetX$1, offsetY$1, area = visibleArea) {
222
+ const l = popupRect.x + offsetX$1;
223
+ const t = popupRect.y + offsetY$1;
224
+ const r = l + popupWidth;
225
+ const b = t + popupHeight;
226
+ const visibleL = Math.max(l, area.left);
227
+ const visibleT = Math.max(t, area.top);
228
+ const visibleR = Math.min(r, area.right);
229
+ const visibleB = Math.min(b, area.bottom);
230
+ return Math.max(0, (visibleR - visibleL) * (visibleB - visibleT));
231
+ }
232
+ const originIntersectionVisibleArea = getIntersectionVisibleArea(nextOffsetX, nextOffsetY);
233
+ const originIntersectionRecommendArea = getIntersectionVisibleArea(nextOffsetX, nextOffsetY, visibleRegionArea);
234
+ const targetAlignPointTL = getAlignPoint(targetRect, ["t", "l"]);
235
+ const popupAlignPointTL = getAlignPoint(popupRect, ["t", "l"]);
236
+ const targetAlignPointBR = getAlignPoint(targetRect, ["b", "r"]);
237
+ const popupAlignPointBR = getAlignPoint(popupRect, ["b", "r"]);
238
+ const { adjustX, adjustY, shiftX, shiftY } = placementInfo.overflow || {};
239
+ const supportAdjust = (val) => {
240
+ if (typeof val === "boolean") return val;
241
+ return val >= 0;
242
+ };
243
+ let nextPopupY;
244
+ let nextPopupBottom;
245
+ let nextPopupX;
246
+ let nextPopupRight;
247
+ function syncNextPopupPosition() {
248
+ nextPopupY = popupRect.y + nextOffsetY;
249
+ nextPopupBottom = nextPopupY + popupHeight;
250
+ nextPopupX = popupRect.x + nextOffsetX;
251
+ nextPopupRight = nextPopupX + popupWidth;
252
+ }
253
+ syncNextPopupPosition();
254
+ const needAdjustY = supportAdjust(adjustY);
255
+ const sameTB = popupPoints[0] === targetPoints[0];
256
+ const overflowBottom = nextPopupBottom > adjustCheckVisibleArea.bottom;
257
+ if (needAdjustY && popupPoints[0] === "t" && (overflowBottom || prevFlipRef.value.bt)) {
258
+ let tmpNextOffsetY = nextOffsetY;
259
+ if (sameTB) tmpNextOffsetY -= popupHeight - targetHeight;
260
+ else tmpNextOffsetY = targetAlignPointTL.y - popupAlignPointBR.y - popupOffsetY;
261
+ if (shouldSwitchPlacement(overflowBottom, isVisibleFirst, getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY), originIntersectionVisibleArea, getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY, visibleRegionArea), originIntersectionRecommendArea)) {
262
+ prevFlipRef.value.bt = true;
263
+ nextOffsetY = tmpNextOffsetY;
264
+ popupOffsetY = -popupOffsetY;
265
+ nextAlignInfo.points = [reversePoints(popupPoints, 0), reversePoints(targetPoints, 0)];
266
+ } else prevFlipRef.value.bt = false;
267
+ }
268
+ const overflowTop = nextPopupY < adjustCheckVisibleArea.top;
269
+ if (needAdjustY && popupPoints[0] === "b" && (overflowTop || prevFlipRef.value.tb)) {
270
+ let tmpNextOffsetY = nextOffsetY;
271
+ if (sameTB) tmpNextOffsetY += popupHeight - targetHeight;
272
+ else tmpNextOffsetY = targetAlignPointBR.y - popupAlignPointTL.y - popupOffsetY;
273
+ if (shouldSwitchPlacement(overflowTop, isVisibleFirst, getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY), originIntersectionVisibleArea, getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY, visibleRegionArea), originIntersectionRecommendArea)) {
274
+ prevFlipRef.value.tb = true;
275
+ nextOffsetY = tmpNextOffsetY;
276
+ popupOffsetY = -popupOffsetY;
277
+ nextAlignInfo.points = [reversePoints(popupPoints, 0), reversePoints(targetPoints, 0)];
278
+ } else prevFlipRef.value.tb = false;
279
+ }
280
+ const needAdjustX = supportAdjust(adjustX);
281
+ const sameLR = popupPoints[1] === targetPoints[1];
282
+ const overflowRight = nextPopupRight > adjustCheckVisibleArea.right;
283
+ if (needAdjustX && popupPoints[1] === "l" && (overflowRight || prevFlipRef.value.rl)) {
284
+ let tmpNextOffsetX = nextOffsetX;
285
+ if (sameLR) tmpNextOffsetX -= popupWidth - targetWidth;
286
+ else tmpNextOffsetX = targetAlignPointTL.x - popupAlignPointBR.x - popupOffsetX;
287
+ if (shouldSwitchPlacement(overflowRight, isVisibleFirst, getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY), originIntersectionVisibleArea, getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY, visibleRegionArea), originIntersectionRecommendArea)) {
288
+ prevFlipRef.value.rl = true;
289
+ nextOffsetX = tmpNextOffsetX;
290
+ popupOffsetX = -popupOffsetX;
291
+ nextAlignInfo.points = [reversePoints(popupPoints, 1), reversePoints(targetPoints, 1)];
292
+ } else prevFlipRef.value.rl = false;
293
+ }
294
+ const overflowLeft = nextPopupX < adjustCheckVisibleArea.left;
295
+ if (needAdjustX && popupPoints[1] === "r" && (overflowLeft || prevFlipRef.value.lr)) {
296
+ let tmpNextOffsetX = nextOffsetX;
297
+ if (sameLR) tmpNextOffsetX += popupWidth - targetWidth;
298
+ else tmpNextOffsetX = targetAlignPointBR.x - popupAlignPointTL.x - popupOffsetX;
299
+ if (shouldSwitchPlacement(overflowLeft, isVisibleFirst, getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY), originIntersectionVisibleArea, getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY, visibleRegionArea), originIntersectionRecommendArea)) {
300
+ prevFlipRef.value.lr = true;
301
+ nextOffsetX = tmpNextOffsetX;
302
+ popupOffsetX = -popupOffsetX;
303
+ nextAlignInfo.points = [reversePoints(popupPoints, 1), reversePoints(targetPoints, 1)];
304
+ } else prevFlipRef.value.lr = false;
305
+ }
306
+ syncNextPopupPosition();
307
+ const numShiftX = shiftX === true ? 0 : shiftX;
308
+ if (typeof numShiftX === "number") {
309
+ if (nextPopupX < visibleRegionArea.left) {
310
+ nextOffsetX -= nextPopupX - visibleRegionArea.left - popupOffsetX;
311
+ if (targetRect.x + targetWidth < visibleRegionArea.left + numShiftX) nextOffsetX += targetRect.x - visibleRegionArea.left + targetWidth - numShiftX;
312
+ }
313
+ if (nextPopupRight > visibleRegionArea.right) {
314
+ nextOffsetX -= nextPopupRight - visibleRegionArea.right - popupOffsetX;
315
+ if (targetRect.x > visibleRegionArea.right - numShiftX) nextOffsetX += targetRect.x - visibleRegionArea.right + numShiftX;
316
+ }
317
+ }
318
+ const numShiftY = shiftY === true ? 0 : shiftY;
319
+ if (typeof numShiftY === "number") {
320
+ if (nextPopupY < visibleRegionArea.top) {
321
+ nextOffsetY -= nextPopupY - visibleRegionArea.top - popupOffsetY;
322
+ if (targetRect.y + targetHeight < visibleRegionArea.top + numShiftY) nextOffsetY += targetRect.y - visibleRegionArea.top + targetHeight - numShiftY;
323
+ }
324
+ if (nextPopupBottom > visibleRegionArea.bottom) {
325
+ nextOffsetY -= nextPopupBottom - visibleRegionArea.bottom - popupOffsetY;
326
+ if (targetRect.y > visibleRegionArea.bottom - numShiftY) nextOffsetY += targetRect.y - visibleRegionArea.bottom + numShiftY;
327
+ }
328
+ }
329
+ const popupLeft = popupRect.x + nextOffsetX;
330
+ const popupRight = popupLeft + popupWidth;
331
+ const popupTop = popupRect.y + nextOffsetY;
332
+ const popupBottom = popupTop + popupHeight;
333
+ const targetLeft = targetRect.x;
334
+ const targetRight = targetLeft + targetWidth;
335
+ const targetTop = targetRect.y;
336
+ const targetBottom = targetTop + targetHeight;
337
+ const nextArrowX = (Math.max(popupLeft, targetLeft) + Math.min(popupRight, targetRight)) / 2 - popupLeft;
338
+ const nextArrowY = (Math.max(popupTop, targetTop) + Math.min(popupBottom, targetBottom)) / 2 - popupTop;
339
+ onPopupAlign?.(popupEle.value, nextAlignInfo);
340
+ let offsetX4Right = popupMirrorRect.right - popupRect.x - (nextOffsetX + popupRect.width);
341
+ let offsetY4Bottom = popupMirrorRect.bottom - popupRect.y - (nextOffsetY + popupRect.height);
342
+ if (scaleX$1 === 1) {
343
+ nextOffsetX = Math.round(nextOffsetX);
344
+ offsetX4Right = Math.round(offsetX4Right);
345
+ }
346
+ if (scaleY$1 === 1) {
347
+ nextOffsetY = Math.round(nextOffsetY);
348
+ offsetY4Bottom = Math.round(offsetY4Bottom);
349
+ }
350
+ const nextOffsetInfo = {
351
+ ready: true,
352
+ offsetX: nextOffsetX,
353
+ offsetY: nextOffsetY,
354
+ offsetR: offsetX4Right,
355
+ offsetB: offsetY4Bottom,
356
+ arrowX: nextArrowX,
357
+ arrowY: nextArrowY,
358
+ scaleX: scaleX$1,
359
+ scaleY: scaleY$1,
360
+ align: nextAlignInfo
361
+ };
362
+ Object.assign(offsetInfo, nextOffsetInfo);
363
+ }
364
+ };
365
+ const onAlign = rafDebounce(_onAlign);
366
+ const triggerAlign = () => {
367
+ alignCountRef.value += 1;
368
+ const id = alignCountRef.value;
369
+ Promise.resolve().then(() => {
370
+ if (alignCountRef.value === id) onAlign();
371
+ });
372
+ };
373
+ watch(popupEle, async (ele) => {
374
+ if (ele && open.value && !mobile?.value) {
375
+ await nextTick();
376
+ triggerAlign();
377
+ }
378
+ });
379
+ const resetReady = () => {
380
+ offsetInfo.ready = false;
381
+ };
382
+ watch(placement, () => {
383
+ resetReady();
384
+ });
385
+ watch(open, () => {
386
+ if (!open.value) {
387
+ resetFlipCache();
388
+ resetReady();
389
+ }
390
+ }, { immediate: true });
391
+ const { ready, offsetX, offsetR, offsetY, offsetB, align, arrowY, arrowX, scaleY, scaleX } = toRefs(offsetInfo);
392
+ return [
393
+ ready,
394
+ offsetX,
395
+ offsetY,
396
+ offsetR,
397
+ offsetB,
398
+ arrowX,
399
+ arrowY,
400
+ scaleX,
401
+ scaleY,
402
+ align,
403
+ triggerAlign
404
+ ];
496
405
  }
497
- export {
498
- useAlign as default
499
- };
406
+ export { useAlign as default };