@douyinfe/semi-foundation 2.22.3 → 2.23.0-beta.1

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 (54) hide show
  1. package/cascader/cascader.scss +15 -0
  2. package/cascader/variables.scss +1 -0
  3. package/form/interface.ts +8 -4
  4. package/image/imageFoundation.ts +1 -1
  5. package/image/previewFooterFoundation.ts +2 -2
  6. package/image/previewImageFoundation.ts +0 -1
  7. package/image/previewInnerFoundation.ts +2 -2
  8. package/lib/cjs/cascader/cascader.css +12 -0
  9. package/lib/cjs/cascader/cascader.scss +15 -0
  10. package/lib/cjs/cascader/variables.scss +1 -0
  11. package/lib/cjs/form/interface.d.ts +8 -6
  12. package/lib/cjs/image/imageFoundation.js +1 -1
  13. package/lib/cjs/image/previewFooterFoundation.js +2 -2
  14. package/lib/cjs/image/previewInnerFoundation.d.ts +1 -1
  15. package/lib/cjs/image/previewInnerFoundation.js +1 -1
  16. package/lib/cjs/navigation/navigation.css +6 -0
  17. package/lib/cjs/navigation/navigation.scss +9 -0
  18. package/lib/cjs/table/constants.d.ts +1 -0
  19. package/lib/cjs/table/constants.js +4 -2
  20. package/lib/cjs/table/table.css +2 -1
  21. package/lib/cjs/table/table.scss +2 -1
  22. package/lib/cjs/tooltip/constants.d.ts +1 -0
  23. package/lib/cjs/tooltip/constants.js +2 -2
  24. package/lib/cjs/tooltip/foundation.d.ts +21 -2
  25. package/lib/cjs/tooltip/foundation.js +352 -77
  26. package/lib/cjs/transfer/foundation.d.ts +1 -1
  27. package/lib/cjs/transfer/foundation.js +3 -4
  28. package/lib/es/cascader/cascader.css +12 -0
  29. package/lib/es/cascader/cascader.scss +15 -0
  30. package/lib/es/cascader/variables.scss +1 -0
  31. package/lib/es/form/interface.d.ts +8 -6
  32. package/lib/es/image/imageFoundation.js +1 -1
  33. package/lib/es/image/previewFooterFoundation.js +2 -2
  34. package/lib/es/image/previewInnerFoundation.d.ts +1 -1
  35. package/lib/es/image/previewInnerFoundation.js +1 -1
  36. package/lib/es/navigation/navigation.css +6 -0
  37. package/lib/es/navigation/navigation.scss +9 -0
  38. package/lib/es/table/constants.d.ts +1 -0
  39. package/lib/es/table/constants.js +4 -2
  40. package/lib/es/table/table.css +2 -1
  41. package/lib/es/table/table.scss +2 -1
  42. package/lib/es/tooltip/constants.d.ts +1 -0
  43. package/lib/es/tooltip/constants.js +2 -2
  44. package/lib/es/tooltip/foundation.d.ts +21 -2
  45. package/lib/es/tooltip/foundation.js +352 -77
  46. package/lib/es/transfer/foundation.d.ts +1 -1
  47. package/lib/es/transfer/foundation.js +3 -4
  48. package/navigation/navigation.scss +9 -0
  49. package/package.json +2 -2
  50. package/table/constants.ts +2 -0
  51. package/table/table.scss +2 -1
  52. package/tooltip/constants.ts +1 -0
  53. package/tooltip/foundation.ts +318 -78
  54. package/transfer/foundation.ts +3 -3
@@ -80,9 +80,11 @@ class Tooltip extends _foundation.default {
80
80
  this._togglePortalVisible(true);
81
81
  });
82
82
 
83
- const position = this.calcPosition(null, null, null, false);
83
+ this._adapter.insertPortal(content, {
84
+ left: -9990,
85
+ top: -9999
86
+ }); // offscreen rendering
84
87
 
85
- this._adapter.insertPortal(content, position);
86
88
 
87
89
  if (trigger === 'custom') {
88
90
  // eslint-disable-next-line
@@ -128,17 +130,32 @@ class Tooltip extends _foundation.default {
128
130
  containerRect = ((0, _isEmpty2.default)(containerRect) ? _this._adapter.getPopupContainerRect() : containerRect) || Object.assign({}, defaultRect);
129
131
  wrapperRect = ((0, _isEmpty2.default)(wrapperRect) ? _this._adapter.getWrapperBounding() : wrapperRect) || Object.assign({}, defaultRect); // console.log('containerRect: ', containerRect, 'triggerRect: ', triggerRect, 'wrapperRect: ', wrapperRect);
130
132
 
131
- let style = _this.calcPosStyle(triggerRect, wrapperRect, containerRect);
133
+ let style = _this.calcPosStyle({
134
+ triggerRect,
135
+ wrapperRect,
136
+ containerRect
137
+ });
132
138
 
133
139
  let position = _this.getProp('position');
134
140
 
135
141
  if (_this.getProp('autoAdjustOverflow')) {
136
142
  // console.log('style: ', style, '\ntriggerRect: ', triggerRect, '\nwrapperRect: ', wrapperRect);
137
- const adjustedPos = _this.adjustPosIfNeed(position, style, triggerRect, wrapperRect, containerRect);
143
+ const {
144
+ position: adjustedPos,
145
+ isHeightOverFlow,
146
+ isWidthOverFlow
147
+ } = _this.adjustPosIfNeed(position, style, triggerRect, wrapperRect, containerRect);
138
148
 
139
- if (position !== adjustedPos) {
149
+ if (position !== adjustedPos || isHeightOverFlow || isWidthOverFlow) {
140
150
  position = adjustedPos;
141
- style = _this.calcPosStyle(triggerRect, wrapperRect, containerRect, position);
151
+ style = _this.calcPosStyle({
152
+ triggerRect,
153
+ wrapperRect,
154
+ containerRect,
155
+ position,
156
+ spacing: null,
157
+ isOverFlow: [isHeightOverFlow, isWidthOverFlow]
158
+ });
142
159
  }
143
160
  }
144
161
 
@@ -276,6 +293,29 @@ class Tooltip extends _foundation.default {
276
293
  this._adapter.unregisterResizeHandler(this.onResize);
277
294
  }
278
295
 
296
+ _adjustPos() {
297
+ let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
298
+ let isVertical = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
299
+ let adjustType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'reverse';
300
+ let concatPos = arguments.length > 3 ? arguments[3] : undefined;
301
+
302
+ switch (adjustType) {
303
+ case 'reverse':
304
+ return this._reversePos(position, isVertical);
305
+
306
+ case 'expand':
307
+ // only happens when position is top/bottom/left/right
308
+ return this._expandPos(position, concatPos);
309
+
310
+ case 'reduce':
311
+ // only happens when position other than top/bottom/left/right
312
+ return this._reducePos(position);
313
+
314
+ default:
315
+ return this._reversePos(position, isVertical);
316
+ }
317
+ }
318
+
279
319
  _reversePos() {
280
320
  let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
281
321
  let isVertical = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
@@ -295,6 +335,19 @@ class Tooltip extends _foundation.default {
295
335
  return position;
296
336
  }
297
337
 
338
+ _expandPos() {
339
+ let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
340
+ let concatPos = arguments.length > 1 ? arguments[1] : undefined;
341
+ return position.concat(concatPos);
342
+ }
343
+
344
+ _reducePos() {
345
+ let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
346
+ // if cur position consists of two directions, remove the last position
347
+ const found = ['Top', 'Bottom', 'Left', 'Right'].find(pos => position.endsWith(pos));
348
+ return found ? position.replace(found, '') : position;
349
+ }
350
+
298
351
  clearDelayTimer() {
299
352
  if (this._timer) {
300
353
  clearTimeout(this._timer);
@@ -455,12 +508,16 @@ class Tooltip extends _foundation.default {
455
508
  return null;
456
509
  }
457
510
 
458
- calcPosStyle(triggerRect, wrapperRect, containerRect, position, spacing) {
459
- triggerRect = ((0, _isEmpty2.default)(triggerRect) ? triggerRect : this._adapter.getTriggerBounding()) || Object.assign({}, defaultRect);
460
- containerRect = ((0, _isEmpty2.default)(containerRect) ? containerRect : this._adapter.getPopupContainerRect()) || Object.assign({}, defaultRect);
461
- wrapperRect = ((0, _isEmpty2.default)(wrapperRect) ? wrapperRect : this._adapter.getWrapperBounding()) || Object.assign({}, defaultRect); // eslint-disable-next-line
511
+ calcPosStyle(props) {
512
+ const {
513
+ spacing,
514
+ isOverFlow
515
+ } = props;
516
+ const triggerRect = ((0, _isEmpty2.default)(props.triggerRect) ? props.triggerRect : this._adapter.getTriggerBounding()) || Object.assign({}, defaultRect);
517
+ const containerRect = ((0, _isEmpty2.default)(props.containerRect) ? props.containerRect : this._adapter.getPopupContainerRect()) || Object.assign({}, defaultRect);
518
+ const wrapperRect = ((0, _isEmpty2.default)(props.wrapperRect) ? props.wrapperRect : this._adapter.getWrapperBounding()) || Object.assign({}, defaultRect); // eslint-disable-next-line
462
519
 
463
- position = position != null ? position : this.getProp('position'); // eslint-disable-next-line
520
+ const position = props.position != null ? props.position : this.getProp('position'); // eslint-disable-next-line
464
521
 
465
522
  const SPACING = spacing != null ? spacing : this.getProp('spacing');
466
523
  const {
@@ -486,79 +543,112 @@ class Tooltip extends _foundation.default {
486
543
  const middleY = triggerRect.top + triggerRect.height / 2;
487
544
  const offsetXWithArrow = positionOffsetX + horizontalArrowWidth / 2;
488
545
  const offsetYWithArrow = positionOffsetY + verticalArrowHeight / 2;
546
+ const heightDifference = wrapperRect.height - containerRect.height;
547
+ const widthDifference = wrapperRect.width - containerRect.width;
548
+ const offsetHeight = heightDifference > 0 ? heightDifference : 0;
549
+ const offsetWidth = widthDifference > 0 ? widthDifference : 0;
550
+ const isHeightOverFlow = isOverFlow && isOverFlow[0];
551
+ const isWidthOverFlow = isOverFlow && isOverFlow[1];
552
+ const isTriggerNearLeft = middleX - containerRect.left < containerRect.right - middleX;
553
+ const isTriggerNearTop = middleY - containerRect.top < containerRect.bottom - middleY;
489
554
 
490
555
  switch (position) {
491
556
  case 'top':
492
- left = middleX;
493
- top = triggerRect.top - SPACING;
557
+ // left = middleX;
558
+ // top = triggerRect.top - SPACING;
559
+ left = isWidthOverFlow ? isTriggerNearLeft ? containerRect.left + wrapperRect.width / 2 : containerRect.right - wrapperRect.width / 2 + offsetWidth : middleX;
560
+ top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
494
561
  translateX = -0.5;
495
562
  translateY = -1;
496
563
  break;
497
564
 
498
565
  case 'topLeft':
499
- left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
500
- top = triggerRect.top - SPACING;
566
+ // left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
567
+ // top = triggerRect.top - SPACING;
568
+ left = isWidthOverFlow ? containerRect.left : pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
569
+ top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
501
570
  translateY = -1;
502
571
  break;
503
572
 
504
573
  case 'topRight':
505
- left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
506
- top = triggerRect.top - SPACING;
574
+ // left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
575
+ // top = triggerRect.top - SPACING;
576
+ left = isWidthOverFlow ? containerRect.right + offsetWidth : pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
577
+ top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
507
578
  translateY = -1;
508
579
  translateX = -1;
509
580
  break;
510
581
 
511
582
  case 'left':
512
- left = triggerRect.left - SPACING;
513
- top = middleY;
583
+ // left = triggerRect.left - SPACING;
584
+ // top = middleY;
585
+ // left = isWidthOverFlow? containerRect.right - SPACING : triggerRect.left - SPACING;
586
+ left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
587
+ top = isHeightOverFlow ? isTriggerNearTop ? containerRect.top + wrapperRect.height / 2 : containerRect.bottom - wrapperRect.height / 2 + offsetHeight : middleY;
514
588
  translateX = -1;
515
589
  translateY = -0.5;
516
590
  break;
517
591
 
518
592
  case 'leftTop':
519
- left = triggerRect.left - SPACING;
520
- top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
593
+ // left = triggerRect.left - SPACING;
594
+ // top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
595
+ left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
596
+ top = isHeightOverFlow ? containerRect.top : pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
521
597
  translateX = -1;
522
598
  break;
523
599
 
524
600
  case 'leftBottom':
525
- left = triggerRect.left - SPACING;
526
- top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
601
+ // left = triggerRect.left - SPACING;
602
+ // top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
603
+ left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
604
+ top = isHeightOverFlow ? containerRect.bottom + offsetHeight : pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
527
605
  translateX = -1;
528
606
  translateY = -1;
529
607
  break;
530
608
 
531
609
  case 'bottom':
532
- left = middleX;
533
- top = triggerRect.top + triggerRect.height + SPACING;
610
+ // left = middleX;
611
+ // top = triggerRect.top + triggerRect.height + SPACING;
612
+ left = isWidthOverFlow ? isTriggerNearLeft ? containerRect.left + wrapperRect.width / 2 : containerRect.right - wrapperRect.width / 2 + offsetWidth : middleX;
613
+ top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
534
614
  translateX = -0.5;
535
615
  break;
536
616
 
537
617
  case 'bottomLeft':
538
- left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
539
- top = triggerRect.bottom + SPACING;
618
+ // left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
619
+ // top = triggerRect.bottom + SPACING;
620
+ left = isWidthOverFlow ? containerRect.left : pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
621
+ top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
540
622
  break;
541
623
 
542
624
  case 'bottomRight':
543
- left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
544
- top = triggerRect.bottom + SPACING;
625
+ // left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
626
+ // top = triggerRect.bottom + SPACING;
627
+ left = isWidthOverFlow ? containerRect.right + offsetWidth : pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
628
+ top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
545
629
  translateX = -1;
546
630
  break;
547
631
 
548
632
  case 'right':
549
- left = triggerRect.right + SPACING;
550
- top = middleY;
633
+ // left = triggerRect.right + SPACING;
634
+ // top = middleY;
635
+ left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
636
+ top = isHeightOverFlow ? isTriggerNearTop ? containerRect.top + wrapperRect.height / 2 : containerRect.bottom - wrapperRect.height / 2 + offsetHeight : middleY;
551
637
  translateY = -0.5;
552
638
  break;
553
639
 
554
640
  case 'rightTop':
555
- left = triggerRect.right + SPACING;
556
- top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
641
+ // left = triggerRect.right + SPACING;
642
+ // top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
643
+ left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
644
+ top = isHeightOverFlow ? containerRect.top : pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
557
645
  break;
558
646
 
559
647
  case 'rightBottom':
560
- left = triggerRect.right + SPACING;
561
- top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
648
+ // left = triggerRect.right + SPACING;
649
+ // top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
650
+ left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
651
+ top = isHeightOverFlow ? containerRect.bottom + offsetHeight : pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
562
652
  translateY = -1;
563
653
  break;
564
654
 
@@ -665,12 +755,53 @@ class Tooltip extends _foundation.default {
665
755
 
666
756
  isLR() {
667
757
  let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
668
- return position.indexOf('left') === 0 || position.indexOf('right') === 0;
758
+ return position.includes('left') || position.includes('right');
669
759
  }
670
760
 
671
761
  isTB() {
672
762
  let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
673
- return position.indexOf('top') === 0 || position.indexOf('bottom') === 0;
763
+ return position.includes('top') || position.includes('bottom');
764
+ }
765
+
766
+ isReverse(rowSpace, reverseSpace, size) {
767
+ // 原空间不足,反向空间足够
768
+ // Insufficient original space, enough reverse space
769
+ return rowSpace < size && reverseSpace > size;
770
+ }
771
+
772
+ isOverFlow(rowSpace, reverseSpace, size) {
773
+ // 原空间且反向空间都不足
774
+ // The original space and the reverse space are not enough
775
+ return rowSpace < size && reverseSpace < size;
776
+ }
777
+
778
+ isHalfOverFlow(posSpace, negSpace, size) {
779
+ // 正半空间或者负半空间不足,即表示有遮挡,需要偏移
780
+ // Insufficient positive half space or negative half space means that there is occlusion and needs to be offset
781
+ return posSpace < size || negSpace < size;
782
+ }
783
+
784
+ isHalfAllEnough(posSpace, negSpace, size) {
785
+ // 正半空间和负半空间都足够,即表示可以从 topLeft/topRight 变成 top
786
+ // Both positive and negative half-spaces are sufficient, which means you can change from topLeft/topRight to top
787
+ return posSpace >= size || negSpace >= size;
788
+ }
789
+
790
+ getReverse(viewOverFlow, containerOverFlow, shouldReverseView, shouldReverseContainer) {
791
+ /**
792
+ * 基于视口和容器一起判断,以下几种情况允许从原方向转到反方向,以判断是否应该由top->bottom为例子
793
+ *
794
+ * 1. 视口上下空间不足 且 容器上空间❌下空间✅
795
+ * 2. 视口上空间❌下空间✅ 且 容器上下空间不足
796
+ * 3. 视口上空间❌下空间✅ 且 容器上空间❌下空间✅
797
+ *
798
+ * Based on the judgment of the viewport and the container, the following situations are allowed to turn from the original direction to the opposite direction
799
+ * to judge whether it should be top->bottom as an example
800
+ * 1. There is insufficient space above and below the viewport and the space above the container ❌ the space below ✅
801
+ * 2. The space above the viewport ❌ the space below ✅ and the space above and below the container is insufficient
802
+ * 3. Viewport upper space ❌ lower space✅ and container upper space ❌ lower space✅
803
+ */
804
+ return viewOverFlow && shouldReverseContainer || shouldReverseView && containerOverFlow || shouldReverseView && shouldReverseContainer;
674
805
  } // place the dom correctly
675
806
 
676
807
 
@@ -680,8 +811,15 @@ class Tooltip extends _foundation.default {
680
811
  innerHeight
681
812
  } = window;
682
813
  const {
683
- spacing
814
+ spacing,
815
+ margin
684
816
  } = this.getProps();
817
+ const marginLeft = typeof margin === 'number' ? margin : margin.marginLeft;
818
+ const marginTop = typeof margin === 'number' ? margin : margin.marginTop;
819
+ const marginRight = typeof margin === 'number' ? margin : margin.marginRight;
820
+ const marginBottom = typeof margin === 'number' ? margin : margin.marginBottom;
821
+ let isHeightOverFlow = false;
822
+ let isWidthOverFlow = false;
685
823
 
686
824
  if (wrapperRect.width > 0 && wrapperRect.height > 0) {
687
825
  // let clientLeft = left + translateX * wrapperRect.width - containerRect.scrollLeft;
@@ -704,187 +842,324 @@ class Tooltip extends _foundation.default {
704
842
  const restClientBottom = innerHeight - clientBottom;
705
843
  const widthIsBigger = wrapperRect.width > triggerRect.width;
706
844
  const heightIsBigger = wrapperRect.height > triggerRect.height; // The wrapperR ect.top|bottom equivalent cannot be directly used here for comparison, which is easy to cause jitter
707
-
708
- const shouldReverseTop = clientTop < wrapperRect.height + spacing && restClientBottom > wrapperRect.height + spacing;
709
- const shouldReverseLeft = clientLeft < wrapperRect.width + spacing && restClientRight > wrapperRect.width + spacing;
710
- const shouldReverseBottom = restClientBottom < wrapperRect.height + spacing && clientTop > wrapperRect.height + spacing;
711
- const shouldReverseRight = restClientRight < wrapperRect.width + spacing && clientLeft > wrapperRect.width + spacing;
845
+ // 基于视口的微调判断
846
+ // Fine-tuning judgment based on viewport
847
+
848
+ const shouldViewReverseTop = clientTop - marginTop < wrapperRect.height + spacing && restClientBottom - marginBottom > wrapperRect.height + spacing;
849
+ const shouldViewReverseLeft = clientLeft - marginLeft < wrapperRect.width + spacing && restClientRight - marginRight > wrapperRect.width + spacing;
850
+ const shouldViewReverseBottom = restClientBottom - marginBottom < wrapperRect.height + spacing && clientTop - marginTop > wrapperRect.height + spacing;
851
+ const shouldViewReverseRight = restClientRight - marginRight < wrapperRect.width + spacing && clientLeft - marginLeft > wrapperRect.width + spacing;
852
+ const shouldViewReverseTopOver = restClientTop - marginBottom < wrapperRect.height + spacing && clientBottom - marginTop > wrapperRect.height + spacing;
853
+ const shouldViewReverseBottomOver = clientBottom - marginTop < wrapperRect.height + spacing && restClientTop - marginBottom > wrapperRect.height + spacing;
854
+ const shouldViewReverseTopSide = restClientTop < wrapperRect.height && clientBottom > wrapperRect.height;
855
+ const shouldViewReverseBottomSide = clientBottom < wrapperRect.height && restClientTop > wrapperRect.height;
856
+ const shouldViewReverseLeftSide = restClientLeft < wrapperRect.width && clientRight > wrapperRect.width;
857
+ const shouldViewReverseRightSide = clientRight < wrapperRect.width && restClientLeft > wrapperRect.width;
712
858
  const shouldReverseTopOver = restClientTop < wrapperRect.height + spacing && clientBottom > wrapperRect.height + spacing;
713
859
  const shouldReverseBottomOver = clientBottom < wrapperRect.height + spacing && restClientTop > wrapperRect.height + spacing;
714
- const shouldReverseTopSide = restClientTop < wrapperRect.height && clientBottom > wrapperRect.height;
715
- const shouldReverseBottomSide = clientBottom < wrapperRect.height && restClientTop > wrapperRect.height;
716
- const shouldReverseLeftSide = restClientLeft < wrapperRect.width && clientRight > wrapperRect.width;
717
- const shouldReverseRightSide = clientRight < wrapperRect.width && restClientLeft > wrapperRect.width;
718
860
  const shouldReverseLeftOver = restClientLeft < wrapperRect.width && clientRight > wrapperRect.width;
719
- const shouldReverseRightOver = clientRight < wrapperRect.width && restClientLeft > wrapperRect.width;
861
+ const shouldReverseRightOver = clientRight < wrapperRect.width && restClientLeft > wrapperRect.width; // 基于容器的微调判断
862
+ // Fine-tuning judgment based on container
863
+
864
+ const clientTopInContainer = clientTop - containerRect.top;
865
+ const clientLeftInContainer = clientLeft - containerRect.left;
866
+ const clientBottomInContainer = clientTopInContainer + triggerRect.height;
867
+ const clientRightInContainer = clientLeftInContainer + triggerRect.width;
868
+ const restClientBottomInContainer = containerRect.bottom - clientBottom;
869
+ const restClientRightInContainer = containerRect.right - clientRight;
870
+ const restClientTopInContainer = restClientBottomInContainer + triggerRect.height;
871
+ const restClientLeftInContainer = restClientRightInContainer + triggerRect.width; // 当原空间不足,反向空间足够时,可以反向。
872
+ // When the original space is insufficient and the reverse space is sufficient, the reverse can be performed.
873
+
874
+ const shouldContainerReverseTop = this.isReverse(clientTopInContainer - marginTop, restClientBottomInContainer - marginBottom, wrapperRect.height + spacing);
875
+ const shouldContainerReverseLeft = this.isReverse(clientLeftInContainer - marginLeft, restClientRightInContainer - marginRight, wrapperRect.width + spacing);
876
+ const shouldContainerReverseBottom = this.isReverse(restClientBottomInContainer - marginBottom, clientTopInContainer - marginTop, wrapperRect.height + spacing);
877
+ const shouldContainerReverseRight = this.isReverse(restClientRightInContainer - marginRight, clientLeftInContainer - marginLeft, wrapperRect.width + spacing);
878
+ const shouldContainerReverseTopOver = this.isReverse(restClientTopInContainer - marginBottom, clientBottomInContainer - marginTop, wrapperRect.height + spacing);
879
+ const shouldContainerReverseBottomOver = this.isReverse(clientBottomInContainer - marginTop, restClientTopInContainer - marginBottom, wrapperRect.height + spacing);
880
+ const shouldContainerReverseTopSide = this.isReverse(restClientTopInContainer, clientBottomInContainer, wrapperRect.height);
881
+ const shouldContainerReverseBottomSide = this.isReverse(clientBottomInContainer, restClientTopInContainer, wrapperRect.height);
882
+ const shouldContainerReverseLeftSide = this.isReverse(restClientLeftInContainer, clientRightInContainer, wrapperRect.width);
883
+ const shouldContainerReverseRightSide = this.isReverse(clientRightInContainer, restClientLeftInContainer, wrapperRect.width);
884
+ const halfHeight = triggerRect.height / 2;
885
+ const halfWidth = triggerRect.width / 2; // 视口, 原空间与反向空间是否都不足判断
886
+ // Viewport, whether the original space and the reverse space are insufficient to judge
887
+
888
+ const isViewYOverFlow = this.isOverFlow(clientTop - marginTop, restClientBottom - marginBottom, wrapperRect.height + spacing);
889
+ const isViewXOverFlow = this.isOverFlow(clientLeft - marginLeft, restClientRight - marginRight, wrapperRect.width + spacing);
890
+ const isViewYOverFlowSide = this.isOverFlow(clientBottom - marginTop, restClientTop - marginBottom, wrapperRect.height + spacing);
891
+ const isViewXOverFlowSide = this.isOverFlow(clientRight - marginLeft, restClientLeft - marginRight, wrapperRect.width + spacing);
892
+ const isViewYOverFlowSideHalf = this.isHalfOverFlow(clientBottom - halfHeight, restClientTop - halfHeight, wrapperRect.height / 2);
893
+ const isViewXOverFlowSideHalf = this.isHalfOverFlow(clientRight - halfWidth, restClientLeft - halfWidth, wrapperRect.width / 2);
894
+ const isViewYEnoughSideHalf = this.isHalfAllEnough(clientBottom - halfHeight, restClientTop - halfHeight, wrapperRect.height / 2);
895
+ const isViewXEnoughSideHalf = this.isHalfAllEnough(clientRight - halfWidth, restClientLeft - halfWidth, wrapperRect.width / 2); // 容器, 原空间与反向空间是否都不足判断
896
+ // container, whether the original space and the reverse space are insufficient to judge
897
+
898
+ const isContainerYOverFlow = this.isOverFlow(clientTopInContainer - marginTop, restClientBottomInContainer - marginBottom, wrapperRect.height + spacing);
899
+ const isContainerXOverFlow = this.isOverFlow(clientLeftInContainer - marginLeft, restClientRightInContainer - marginRight, wrapperRect.width + spacing);
900
+ const isContainerYOverFlowSide = this.isOverFlow(clientBottomInContainer - marginTop, restClientTopInContainer - marginBottom, wrapperRect.height + spacing);
901
+ const isContainerXOverFlowSide = this.isOverFlow(clientRightInContainer - marginLeft, restClientLeftInContainer - marginRight, wrapperRect.width + spacing);
902
+ const isContainerYOverFlowSideHalf = this.isHalfOverFlow(clientBottomInContainer - halfHeight, restClientTopInContainer - halfHeight, wrapperRect.height / 2);
903
+ const isContainerXOverFlowSideHalf = this.isHalfOverFlow(clientRightInContainer - halfWidth, restClientLeftInContainer - halfWidth, wrapperRect.width / 2);
904
+ const isContainerYEnoughSideHalf = this.isHalfAllEnough(clientBottomInContainer - halfHeight, restClientTopInContainer - halfHeight, wrapperRect.height / 2);
905
+ const isContainerXEnoughSideHalf = this.isHalfAllEnough(clientRightInContainer - halfWidth, restClientLeftInContainer - halfWidth, wrapperRect.width / 2); // 综合 viewport + container 判断微调,即视口 + 容器都放置不行时才能考虑位置调整
906
+ // Comprehensive viewport + container judgment fine-tuning, that is, the position adjustment can only be considered when the viewport + container cannot be placed.
907
+
908
+ const shouldReverseTop = this.getReverse(isViewYOverFlow, isContainerYOverFlow, shouldViewReverseTop, shouldContainerReverseTop);
909
+ const shouldReverseLeft = this.getReverse(isViewXOverFlow, isContainerXOverFlow, shouldViewReverseLeft, shouldContainerReverseLeft);
910
+ const shouldReverseBottom = this.getReverse(isViewYOverFlow, isContainerYOverFlow, shouldViewReverseBottom, shouldContainerReverseBottom);
911
+ const shouldReverseRight = this.getReverse(isViewXOverFlow, isContainerXOverFlow, shouldViewReverseRight, shouldContainerReverseRight); // const shouldReverseTopOver = this.getReverse(isViewYOverFlowSide, isContainerYOverFlowSide, shouldViewReverseTopOver, shouldContainerReverseTopOver);
912
+ // const shouldReverseBottomOver = this.getReverse(isViewYOverFlowSide, isContainerYOverFlowSide, shouldViewReverseBottomOver, shouldContainerReverseBottomOver);
913
+
914
+ const shouldReverseTopSide = this.getReverse(isViewYOverFlowSide, isContainerYOverFlowSide, shouldViewReverseTopSide, shouldContainerReverseTopSide);
915
+ const shouldReverseBottomSide = this.getReverse(isViewYOverFlowSide, isContainerYOverFlowSide, shouldViewReverseBottomSide, shouldContainerReverseBottomSide);
916
+ const shouldReverseLeftSide = this.getReverse(isViewXOverFlowSide, isContainerXOverFlowSide, shouldViewReverseLeftSide, shouldContainerReverseLeftSide);
917
+ const shouldReverseRightSide = this.getReverse(isViewXOverFlowSide, isContainerXOverFlowSide, shouldViewReverseRightSide, shouldContainerReverseRightSide);
918
+ const isYOverFlowSideHalf = isViewYOverFlowSideHalf && isContainerYOverFlowSideHalf;
919
+ const isXOverFlowSideHalf = isViewXOverFlowSideHalf && isContainerXOverFlowSideHalf;
720
920
 
721
921
  switch (position) {
722
922
  case 'top':
723
923
  if (shouldReverseTop) {
724
- position = this._reversePos(position, true);
924
+ position = this._adjustPos(position, true);
925
+ }
926
+
927
+ if (isXOverFlowSideHalf && (shouldReverseLeftSide || shouldReverseRightSide)) {
928
+ position = this._adjustPos(position, true, 'expand', shouldReverseLeftSide ? 'Right' : 'Left');
725
929
  }
726
930
 
727
931
  break;
728
932
 
729
933
  case 'topLeft':
730
934
  if (shouldReverseTop) {
731
- position = this._reversePos(position, true);
935
+ position = this._adjustPos(position, true);
732
936
  }
733
937
 
734
938
  if (shouldReverseLeftSide && widthIsBigger) {
735
- position = this._reversePos(position);
939
+ position = this._adjustPos(position, true);
940
+ }
941
+
942
+ if (isWidthOverFlow && (isViewXEnoughSideHalf || isContainerXEnoughSideHalf)) {
943
+ position = this._adjustPos(position, true, 'reduce');
736
944
  }
737
945
 
738
946
  break;
739
947
 
740
948
  case 'topRight':
741
949
  if (shouldReverseTop) {
742
- position = this._reversePos(position, true);
950
+ position = this._adjustPos(position, true);
743
951
  }
744
952
 
745
953
  if (shouldReverseRightSide && widthIsBigger) {
746
- position = this._reversePos(position);
954
+ position = this._adjustPos(position);
955
+ }
956
+
957
+ if (isWidthOverFlow && (isViewXEnoughSideHalf || isContainerXEnoughSideHalf)) {
958
+ position = this._adjustPos(position, true, 'reduce');
747
959
  }
748
960
 
749
961
  break;
750
962
 
751
963
  case 'left':
752
964
  if (shouldReverseLeft) {
753
- position = this._reversePos(position);
965
+ position = this._adjustPos(position);
966
+ }
967
+
968
+ if (isYOverFlowSideHalf && (shouldReverseTopSide || shouldReverseBottomSide)) {
969
+ position = this._adjustPos(position, false, 'expand', shouldReverseTopSide ? 'Bottom' : 'Top');
754
970
  }
755
971
 
756
972
  break;
757
973
 
758
974
  case 'leftTop':
759
975
  if (shouldReverseLeft) {
760
- position = this._reversePos(position);
976
+ position = this._adjustPos(position);
761
977
  }
762
978
 
763
979
  if (shouldReverseTopSide && heightIsBigger) {
764
- position = this._reversePos(position, true);
980
+ position = this._adjustPos(position, true);
981
+ }
982
+
983
+ if (isHeightOverFlow && (isViewYEnoughSideHalf || isContainerYEnoughSideHalf)) {
984
+ position = this._adjustPos(position, false, 'reduce');
765
985
  }
766
986
 
767
987
  break;
768
988
 
769
989
  case 'leftBottom':
770
990
  if (shouldReverseLeft) {
771
- position = this._reversePos(position);
991
+ position = this._adjustPos(position);
772
992
  }
773
993
 
774
994
  if (shouldReverseBottomSide && heightIsBigger) {
775
- position = this._reversePos(position, true);
995
+ position = this._adjustPos(position, true);
996
+ }
997
+
998
+ if (isHeightOverFlow && (isViewYEnoughSideHalf || isContainerYEnoughSideHalf)) {
999
+ position = this._adjustPos(position, false, 'reduce');
776
1000
  }
777
1001
 
778
1002
  break;
779
1003
 
780
1004
  case 'bottom':
781
1005
  if (shouldReverseBottom) {
782
- position = this._reversePos(position, true);
1006
+ position = this._adjustPos(position, true);
1007
+ }
1008
+
1009
+ if (isXOverFlowSideHalf && (shouldReverseLeftSide || shouldReverseRightSide)) {
1010
+ position = this._adjustPos(position, true, 'expand', shouldReverseLeftSide ? 'Right' : 'Left');
783
1011
  }
784
1012
 
785
1013
  break;
786
1014
 
787
1015
  case 'bottomLeft':
788
1016
  if (shouldReverseBottom) {
789
- position = this._reversePos(position, true);
1017
+ position = this._adjustPos(position, true);
790
1018
  }
791
1019
 
792
1020
  if (shouldReverseLeftSide && widthIsBigger) {
793
- position = this._reversePos(position);
1021
+ position = this._adjustPos(position);
1022
+ }
1023
+
1024
+ if (isWidthOverFlow && (isViewXEnoughSideHalf || isContainerXEnoughSideHalf)) {
1025
+ position = this._adjustPos(position, true, 'reduce');
794
1026
  }
795
1027
 
796
1028
  break;
797
1029
 
798
1030
  case 'bottomRight':
799
1031
  if (shouldReverseBottom) {
800
- position = this._reversePos(position, true);
1032
+ position = this._adjustPos(position, true);
801
1033
  }
802
1034
 
803
1035
  if (shouldReverseRightSide && widthIsBigger) {
804
- position = this._reversePos(position);
1036
+ position = this._adjustPos(position);
1037
+ }
1038
+
1039
+ if (isWidthOverFlow && (isViewXEnoughSideHalf || isContainerXEnoughSideHalf)) {
1040
+ position = this._adjustPos(position, true, 'reduce');
805
1041
  }
806
1042
 
807
1043
  break;
808
1044
 
809
1045
  case 'right':
810
1046
  if (shouldReverseRight) {
811
- position = this._reversePos(position);
1047
+ position = this._adjustPos(position);
1048
+ }
1049
+
1050
+ if (isYOverFlowSideHalf && (shouldReverseTopSide || shouldReverseBottomSide)) {
1051
+ position = this._adjustPos(position, false, 'expand', shouldReverseTopSide ? 'Bottom' : 'Top');
812
1052
  }
813
1053
 
814
1054
  break;
815
1055
 
816
1056
  case 'rightTop':
817
1057
  if (shouldReverseRight) {
818
- position = this._reversePos(position);
1058
+ position = this._adjustPos(position);
819
1059
  }
820
1060
 
821
1061
  if (shouldReverseTopSide && heightIsBigger) {
822
- position = this._reversePos(position, true);
1062
+ position = this._adjustPos(position, true);
1063
+ }
1064
+
1065
+ if (isHeightOverFlow && (isViewYEnoughSideHalf || isContainerYEnoughSideHalf)) {
1066
+ position = this._adjustPos(position, false, 'reduce');
823
1067
  }
824
1068
 
825
1069
  break;
826
1070
 
827
1071
  case 'rightBottom':
828
1072
  if (shouldReverseRight) {
829
- position = this._reversePos(position);
1073
+ position = this._adjustPos(position);
830
1074
  }
831
1075
 
832
1076
  if (shouldReverseBottomSide && heightIsBigger) {
833
- position = this._reversePos(position, true);
1077
+ position = this._adjustPos(position, true);
1078
+ }
1079
+
1080
+ if (isHeightOverFlow && (isViewYEnoughSideHalf || isContainerYEnoughSideHalf)) {
1081
+ position = this._adjustPos(position, false, 'reduce');
834
1082
  }
835
1083
 
836
1084
  break;
837
1085
 
838
1086
  case 'leftTopOver':
839
1087
  if (shouldReverseTopOver) {
840
- position = this._reversePos(position, true);
1088
+ position = this._adjustPos(position, true);
841
1089
  }
842
1090
 
843
1091
  if (shouldReverseLeftOver) {
844
- position = this._reversePos(position);
1092
+ position = this._adjustPos(position);
845
1093
  }
846
1094
 
847
1095
  break;
848
1096
 
849
1097
  case 'leftBottomOver':
850
1098
  if (shouldReverseBottomOver) {
851
- position = this._reversePos(position, true);
1099
+ position = this._adjustPos(position, true);
852
1100
  }
853
1101
 
854
1102
  if (shouldReverseLeftOver) {
855
- position = this._reversePos(position);
1103
+ position = this._adjustPos(position);
856
1104
  }
857
1105
 
858
1106
  break;
859
1107
 
860
1108
  case 'rightTopOver':
861
1109
  if (shouldReverseTopOver) {
862
- position = this._reversePos(position, true);
1110
+ position = this._adjustPos(position, true);
863
1111
  }
864
1112
 
865
1113
  if (shouldReverseRightOver) {
866
- position = this._reversePos(position);
1114
+ position = this._adjustPos(position);
867
1115
  }
868
1116
 
869
1117
  break;
870
1118
 
871
1119
  case 'rightBottomOver':
872
1120
  if (shouldReverseBottomOver) {
873
- position = this._reversePos(position, true);
1121
+ position = this._adjustPos(position, true);
874
1122
  }
875
1123
 
876
1124
  if (shouldReverseRightOver) {
877
- position = this._reversePos(position);
1125
+ position = this._adjustPos(position);
878
1126
  }
879
1127
 
880
1128
  break;
881
1129
 
882
1130
  default:
883
1131
  break;
1132
+ } // 判断溢出 Judgment overflow
1133
+ // 上下方向 top and bottom
1134
+
1135
+
1136
+ if (this.isTB(position)) {
1137
+ isHeightOverFlow = isViewYOverFlow && isContainerYOverFlow;
1138
+
1139
+ if (position === 'top' || position === 'bottom') {
1140
+ isWidthOverFlow = isViewXOverFlowSideHalf && isContainerXOverFlowSideHalf;
1141
+ } else {
1142
+ isWidthOverFlow = isViewXOverFlowSide && isContainerXOverFlowSide;
1143
+ }
1144
+ } // 左右方向 left and right
1145
+
1146
+
1147
+ if (this.isLR(position)) {
1148
+ isWidthOverFlow = isViewXOverFlow && isContainerXOverFlow;
1149
+
1150
+ if (position === 'left' || position === 'right') {
1151
+ isHeightOverFlow = isViewYOverFlowSideHalf && isContainerYOverFlowSideHalf;
1152
+ } else {
1153
+ isHeightOverFlow = isViewYOverFlowSide && isContainerYOverFlowSide;
1154
+ }
884
1155
  }
885
1156
  }
886
1157
 
887
- return position;
1158
+ return {
1159
+ position,
1160
+ isHeightOverFlow,
1161
+ isWidthOverFlow
1162
+ };
888
1163
  }
889
1164
 
890
1165
  _bindScrollEvent() {