@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
@@ -66,9 +66,11 @@ export default class Tooltip extends BaseFoundation {
66
66
  this._togglePortalVisible(true);
67
67
  });
68
68
 
69
- const position = this.calcPosition(null, null, null, false);
69
+ this._adapter.insertPortal(content, {
70
+ left: -9990,
71
+ top: -9999
72
+ }); // offscreen rendering
70
73
 
71
- this._adapter.insertPortal(content, position);
72
74
 
73
75
  if (trigger === 'custom') {
74
76
  // eslint-disable-next-line
@@ -114,17 +116,32 @@ export default class Tooltip extends BaseFoundation {
114
116
  containerRect = (_isEmpty(containerRect) ? _this._adapter.getPopupContainerRect() : containerRect) || Object.assign({}, defaultRect);
115
117
  wrapperRect = (_isEmpty(wrapperRect) ? _this._adapter.getWrapperBounding() : wrapperRect) || Object.assign({}, defaultRect); // console.log('containerRect: ', containerRect, 'triggerRect: ', triggerRect, 'wrapperRect: ', wrapperRect);
116
118
 
117
- let style = _this.calcPosStyle(triggerRect, wrapperRect, containerRect);
119
+ let style = _this.calcPosStyle({
120
+ triggerRect,
121
+ wrapperRect,
122
+ containerRect
123
+ });
118
124
 
119
125
  let position = _this.getProp('position');
120
126
 
121
127
  if (_this.getProp('autoAdjustOverflow')) {
122
128
  // console.log('style: ', style, '\ntriggerRect: ', triggerRect, '\nwrapperRect: ', wrapperRect);
123
- const adjustedPos = _this.adjustPosIfNeed(position, style, triggerRect, wrapperRect, containerRect);
129
+ const {
130
+ position: adjustedPos,
131
+ isHeightOverFlow,
132
+ isWidthOverFlow
133
+ } = _this.adjustPosIfNeed(position, style, triggerRect, wrapperRect, containerRect);
124
134
 
125
- if (position !== adjustedPos) {
135
+ if (position !== adjustedPos || isHeightOverFlow || isWidthOverFlow) {
126
136
  position = adjustedPos;
127
- style = _this.calcPosStyle(triggerRect, wrapperRect, containerRect, position);
137
+ style = _this.calcPosStyle({
138
+ triggerRect,
139
+ wrapperRect,
140
+ containerRect,
141
+ position,
142
+ spacing: null,
143
+ isOverFlow: [isHeightOverFlow, isWidthOverFlow]
144
+ });
128
145
  }
129
146
  }
130
147
 
@@ -262,6 +279,29 @@ export default class Tooltip extends BaseFoundation {
262
279
  this._adapter.unregisterResizeHandler(this.onResize);
263
280
  }
264
281
 
282
+ _adjustPos() {
283
+ let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
284
+ let isVertical = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
285
+ let adjustType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'reverse';
286
+ let concatPos = arguments.length > 3 ? arguments[3] : undefined;
287
+
288
+ switch (adjustType) {
289
+ case 'reverse':
290
+ return this._reversePos(position, isVertical);
291
+
292
+ case 'expand':
293
+ // only happens when position is top/bottom/left/right
294
+ return this._expandPos(position, concatPos);
295
+
296
+ case 'reduce':
297
+ // only happens when position other than top/bottom/left/right
298
+ return this._reducePos(position);
299
+
300
+ default:
301
+ return this._reversePos(position, isVertical);
302
+ }
303
+ }
304
+
265
305
  _reversePos() {
266
306
  let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
267
307
  let isVertical = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
@@ -281,6 +321,19 @@ export default class Tooltip extends BaseFoundation {
281
321
  return position;
282
322
  }
283
323
 
324
+ _expandPos() {
325
+ let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
326
+ let concatPos = arguments.length > 1 ? arguments[1] : undefined;
327
+ return position.concat(concatPos);
328
+ }
329
+
330
+ _reducePos() {
331
+ let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
332
+ // if cur position consists of two directions, remove the last position
333
+ const found = ['Top', 'Bottom', 'Left', 'Right'].find(pos => position.endsWith(pos));
334
+ return found ? position.replace(found, '') : position;
335
+ }
336
+
284
337
  clearDelayTimer() {
285
338
  if (this._timer) {
286
339
  clearTimeout(this._timer);
@@ -441,12 +494,16 @@ export default class Tooltip extends BaseFoundation {
441
494
  return null;
442
495
  }
443
496
 
444
- calcPosStyle(triggerRect, wrapperRect, containerRect, position, spacing) {
445
- triggerRect = (_isEmpty(triggerRect) ? triggerRect : this._adapter.getTriggerBounding()) || Object.assign({}, defaultRect);
446
- containerRect = (_isEmpty(containerRect) ? containerRect : this._adapter.getPopupContainerRect()) || Object.assign({}, defaultRect);
447
- wrapperRect = (_isEmpty(wrapperRect) ? wrapperRect : this._adapter.getWrapperBounding()) || Object.assign({}, defaultRect); // eslint-disable-next-line
497
+ calcPosStyle(props) {
498
+ const {
499
+ spacing,
500
+ isOverFlow
501
+ } = props;
502
+ const triggerRect = (_isEmpty(props.triggerRect) ? props.triggerRect : this._adapter.getTriggerBounding()) || Object.assign({}, defaultRect);
503
+ const containerRect = (_isEmpty(props.containerRect) ? props.containerRect : this._adapter.getPopupContainerRect()) || Object.assign({}, defaultRect);
504
+ const wrapperRect = (_isEmpty(props.wrapperRect) ? props.wrapperRect : this._adapter.getWrapperBounding()) || Object.assign({}, defaultRect); // eslint-disable-next-line
448
505
 
449
- position = position != null ? position : this.getProp('position'); // eslint-disable-next-line
506
+ const position = props.position != null ? props.position : this.getProp('position'); // eslint-disable-next-line
450
507
 
451
508
  const SPACING = spacing != null ? spacing : this.getProp('spacing');
452
509
  const {
@@ -476,79 +533,112 @@ export default class Tooltip extends BaseFoundation {
476
533
  const middleY = triggerRect.top + triggerRect.height / 2;
477
534
  const offsetXWithArrow = positionOffsetX + horizontalArrowWidth / 2;
478
535
  const offsetYWithArrow = positionOffsetY + verticalArrowHeight / 2;
536
+ const heightDifference = wrapperRect.height - containerRect.height;
537
+ const widthDifference = wrapperRect.width - containerRect.width;
538
+ const offsetHeight = heightDifference > 0 ? heightDifference : 0;
539
+ const offsetWidth = widthDifference > 0 ? widthDifference : 0;
540
+ const isHeightOverFlow = isOverFlow && isOverFlow[0];
541
+ const isWidthOverFlow = isOverFlow && isOverFlow[1];
542
+ const isTriggerNearLeft = middleX - containerRect.left < containerRect.right - middleX;
543
+ const isTriggerNearTop = middleY - containerRect.top < containerRect.bottom - middleY;
479
544
 
480
545
  switch (position) {
481
546
  case 'top':
482
- left = middleX;
483
- top = triggerRect.top - SPACING;
547
+ // left = middleX;
548
+ // top = triggerRect.top - SPACING;
549
+ left = isWidthOverFlow ? isTriggerNearLeft ? containerRect.left + wrapperRect.width / 2 : containerRect.right - wrapperRect.width / 2 + offsetWidth : middleX;
550
+ top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
484
551
  translateX = -0.5;
485
552
  translateY = -1;
486
553
  break;
487
554
 
488
555
  case 'topLeft':
489
- left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
490
- top = triggerRect.top - SPACING;
556
+ // left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
557
+ // top = triggerRect.top - SPACING;
558
+ left = isWidthOverFlow ? containerRect.left : pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
559
+ top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
491
560
  translateY = -1;
492
561
  break;
493
562
 
494
563
  case 'topRight':
495
- left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
496
- top = triggerRect.top - SPACING;
564
+ // left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
565
+ // top = triggerRect.top - SPACING;
566
+ left = isWidthOverFlow ? containerRect.right + offsetWidth : pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
567
+ top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
497
568
  translateY = -1;
498
569
  translateX = -1;
499
570
  break;
500
571
 
501
572
  case 'left':
502
- left = triggerRect.left - SPACING;
503
- top = middleY;
573
+ // left = triggerRect.left - SPACING;
574
+ // top = middleY;
575
+ // left = isWidthOverFlow? containerRect.right - SPACING : triggerRect.left - SPACING;
576
+ left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
577
+ top = isHeightOverFlow ? isTriggerNearTop ? containerRect.top + wrapperRect.height / 2 : containerRect.bottom - wrapperRect.height / 2 + offsetHeight : middleY;
504
578
  translateX = -1;
505
579
  translateY = -0.5;
506
580
  break;
507
581
 
508
582
  case 'leftTop':
509
- left = triggerRect.left - SPACING;
510
- top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
583
+ // left = triggerRect.left - SPACING;
584
+ // top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
585
+ left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
586
+ top = isHeightOverFlow ? containerRect.top : pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
511
587
  translateX = -1;
512
588
  break;
513
589
 
514
590
  case 'leftBottom':
515
- left = triggerRect.left - SPACING;
516
- top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
591
+ // left = triggerRect.left - SPACING;
592
+ // top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
593
+ left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
594
+ top = isHeightOverFlow ? containerRect.bottom + offsetHeight : pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
517
595
  translateX = -1;
518
596
  translateY = -1;
519
597
  break;
520
598
 
521
599
  case 'bottom':
522
- left = middleX;
523
- top = triggerRect.top + triggerRect.height + SPACING;
600
+ // left = middleX;
601
+ // top = triggerRect.top + triggerRect.height + SPACING;
602
+ left = isWidthOverFlow ? isTriggerNearLeft ? containerRect.left + wrapperRect.width / 2 : containerRect.right - wrapperRect.width / 2 + offsetWidth : middleX;
603
+ top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
524
604
  translateX = -0.5;
525
605
  break;
526
606
 
527
607
  case 'bottomLeft':
528
- left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
529
- top = triggerRect.bottom + SPACING;
608
+ // left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
609
+ // top = triggerRect.bottom + SPACING;
610
+ left = isWidthOverFlow ? containerRect.left : pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
611
+ top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
530
612
  break;
531
613
 
532
614
  case 'bottomRight':
533
- left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
534
- top = triggerRect.bottom + SPACING;
615
+ // left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
616
+ // top = triggerRect.bottom + SPACING;
617
+ left = isWidthOverFlow ? containerRect.right + offsetWidth : pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
618
+ top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
535
619
  translateX = -1;
536
620
  break;
537
621
 
538
622
  case 'right':
539
- left = triggerRect.right + SPACING;
540
- top = middleY;
623
+ // left = triggerRect.right + SPACING;
624
+ // top = middleY;
625
+ left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
626
+ top = isHeightOverFlow ? isTriggerNearTop ? containerRect.top + wrapperRect.height / 2 : containerRect.bottom - wrapperRect.height / 2 + offsetHeight : middleY;
541
627
  translateY = -0.5;
542
628
  break;
543
629
 
544
630
  case 'rightTop':
545
- left = triggerRect.right + SPACING;
546
- top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
631
+ // left = triggerRect.right + SPACING;
632
+ // top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
633
+ left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
634
+ top = isHeightOverFlow ? containerRect.top : pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
547
635
  break;
548
636
 
549
637
  case 'rightBottom':
550
- left = triggerRect.right + SPACING;
551
- top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
638
+ // left = triggerRect.right + SPACING;
639
+ // top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
640
+ left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
641
+ top = isHeightOverFlow ? containerRect.bottom + offsetHeight : pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
552
642
  translateY = -1;
553
643
  break;
554
644
 
@@ -655,12 +745,53 @@ export default class Tooltip extends BaseFoundation {
655
745
 
656
746
  isLR() {
657
747
  let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
658
- return position.indexOf('left') === 0 || position.indexOf('right') === 0;
748
+ return position.includes('left') || position.includes('right');
659
749
  }
660
750
 
661
751
  isTB() {
662
752
  let position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
663
- return position.indexOf('top') === 0 || position.indexOf('bottom') === 0;
753
+ return position.includes('top') || position.includes('bottom');
754
+ }
755
+
756
+ isReverse(rowSpace, reverseSpace, size) {
757
+ // 原空间不足,反向空间足够
758
+ // Insufficient original space, enough reverse space
759
+ return rowSpace < size && reverseSpace > size;
760
+ }
761
+
762
+ isOverFlow(rowSpace, reverseSpace, size) {
763
+ // 原空间且反向空间都不足
764
+ // The original space and the reverse space are not enough
765
+ return rowSpace < size && reverseSpace < size;
766
+ }
767
+
768
+ isHalfOverFlow(posSpace, negSpace, size) {
769
+ // 正半空间或者负半空间不足,即表示有遮挡,需要偏移
770
+ // Insufficient positive half space or negative half space means that there is occlusion and needs to be offset
771
+ return posSpace < size || negSpace < size;
772
+ }
773
+
774
+ isHalfAllEnough(posSpace, negSpace, size) {
775
+ // 正半空间和负半空间都足够,即表示可以从 topLeft/topRight 变成 top
776
+ // Both positive and negative half-spaces are sufficient, which means you can change from topLeft/topRight to top
777
+ return posSpace >= size || negSpace >= size;
778
+ }
779
+
780
+ getReverse(viewOverFlow, containerOverFlow, shouldReverseView, shouldReverseContainer) {
781
+ /**
782
+ * 基于视口和容器一起判断,以下几种情况允许从原方向转到反方向,以判断是否应该由top->bottom为例子
783
+ *
784
+ * 1. 视口上下空间不足 且 容器上空间❌下空间✅
785
+ * 2. 视口上空间❌下空间✅ 且 容器上下空间不足
786
+ * 3. 视口上空间❌下空间✅ 且 容器上空间❌下空间✅
787
+ *
788
+ * 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
789
+ * to judge whether it should be top->bottom as an example
790
+ * 1. There is insufficient space above and below the viewport and the space above the container ❌ the space below ✅
791
+ * 2. The space above the viewport ❌ the space below ✅ and the space above and below the container is insufficient
792
+ * 3. Viewport upper space ❌ lower space✅ and container upper space ❌ lower space✅
793
+ */
794
+ return viewOverFlow && shouldReverseContainer || shouldReverseView && containerOverFlow || shouldReverseView && shouldReverseContainer;
664
795
  } // place the dom correctly
665
796
 
666
797
 
@@ -670,8 +801,15 @@ export default class Tooltip extends BaseFoundation {
670
801
  innerHeight
671
802
  } = window;
672
803
  const {
673
- spacing
804
+ spacing,
805
+ margin
674
806
  } = this.getProps();
807
+ const marginLeft = typeof margin === 'number' ? margin : margin.marginLeft;
808
+ const marginTop = typeof margin === 'number' ? margin : margin.marginTop;
809
+ const marginRight = typeof margin === 'number' ? margin : margin.marginRight;
810
+ const marginBottom = typeof margin === 'number' ? margin : margin.marginBottom;
811
+ let isHeightOverFlow = false;
812
+ let isWidthOverFlow = false;
675
813
 
676
814
  if (wrapperRect.width > 0 && wrapperRect.height > 0) {
677
815
  // let clientLeft = left + translateX * wrapperRect.width - containerRect.scrollLeft;
@@ -694,187 +832,324 @@ export default class Tooltip extends BaseFoundation {
694
832
  const restClientBottom = innerHeight - clientBottom;
695
833
  const widthIsBigger = wrapperRect.width > triggerRect.width;
696
834
  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
697
-
698
- const shouldReverseTop = clientTop < wrapperRect.height + spacing && restClientBottom > wrapperRect.height + spacing;
699
- const shouldReverseLeft = clientLeft < wrapperRect.width + spacing && restClientRight > wrapperRect.width + spacing;
700
- const shouldReverseBottom = restClientBottom < wrapperRect.height + spacing && clientTop > wrapperRect.height + spacing;
701
- const shouldReverseRight = restClientRight < wrapperRect.width + spacing && clientLeft > wrapperRect.width + spacing;
835
+ // 基于视口的微调判断
836
+ // Fine-tuning judgment based on viewport
837
+
838
+ const shouldViewReverseTop = clientTop - marginTop < wrapperRect.height + spacing && restClientBottom - marginBottom > wrapperRect.height + spacing;
839
+ const shouldViewReverseLeft = clientLeft - marginLeft < wrapperRect.width + spacing && restClientRight - marginRight > wrapperRect.width + spacing;
840
+ const shouldViewReverseBottom = restClientBottom - marginBottom < wrapperRect.height + spacing && clientTop - marginTop > wrapperRect.height + spacing;
841
+ const shouldViewReverseRight = restClientRight - marginRight < wrapperRect.width + spacing && clientLeft - marginLeft > wrapperRect.width + spacing;
842
+ const shouldViewReverseTopOver = restClientTop - marginBottom < wrapperRect.height + spacing && clientBottom - marginTop > wrapperRect.height + spacing;
843
+ const shouldViewReverseBottomOver = clientBottom - marginTop < wrapperRect.height + spacing && restClientTop - marginBottom > wrapperRect.height + spacing;
844
+ const shouldViewReverseTopSide = restClientTop < wrapperRect.height && clientBottom > wrapperRect.height;
845
+ const shouldViewReverseBottomSide = clientBottom < wrapperRect.height && restClientTop > wrapperRect.height;
846
+ const shouldViewReverseLeftSide = restClientLeft < wrapperRect.width && clientRight > wrapperRect.width;
847
+ const shouldViewReverseRightSide = clientRight < wrapperRect.width && restClientLeft > wrapperRect.width;
702
848
  const shouldReverseTopOver = restClientTop < wrapperRect.height + spacing && clientBottom > wrapperRect.height + spacing;
703
849
  const shouldReverseBottomOver = clientBottom < wrapperRect.height + spacing && restClientTop > wrapperRect.height + spacing;
704
- const shouldReverseTopSide = restClientTop < wrapperRect.height && clientBottom > wrapperRect.height;
705
- const shouldReverseBottomSide = clientBottom < wrapperRect.height && restClientTop > wrapperRect.height;
706
- const shouldReverseLeftSide = restClientLeft < wrapperRect.width && clientRight > wrapperRect.width;
707
- const shouldReverseRightSide = clientRight < wrapperRect.width && restClientLeft > wrapperRect.width;
708
850
  const shouldReverseLeftOver = restClientLeft < wrapperRect.width && clientRight > wrapperRect.width;
709
- const shouldReverseRightOver = clientRight < wrapperRect.width && restClientLeft > wrapperRect.width;
851
+ const shouldReverseRightOver = clientRight < wrapperRect.width && restClientLeft > wrapperRect.width; // 基于容器的微调判断
852
+ // Fine-tuning judgment based on container
853
+
854
+ const clientTopInContainer = clientTop - containerRect.top;
855
+ const clientLeftInContainer = clientLeft - containerRect.left;
856
+ const clientBottomInContainer = clientTopInContainer + triggerRect.height;
857
+ const clientRightInContainer = clientLeftInContainer + triggerRect.width;
858
+ const restClientBottomInContainer = containerRect.bottom - clientBottom;
859
+ const restClientRightInContainer = containerRect.right - clientRight;
860
+ const restClientTopInContainer = restClientBottomInContainer + triggerRect.height;
861
+ const restClientLeftInContainer = restClientRightInContainer + triggerRect.width; // 当原空间不足,反向空间足够时,可以反向。
862
+ // When the original space is insufficient and the reverse space is sufficient, the reverse can be performed.
863
+
864
+ const shouldContainerReverseTop = this.isReverse(clientTopInContainer - marginTop, restClientBottomInContainer - marginBottom, wrapperRect.height + spacing);
865
+ const shouldContainerReverseLeft = this.isReverse(clientLeftInContainer - marginLeft, restClientRightInContainer - marginRight, wrapperRect.width + spacing);
866
+ const shouldContainerReverseBottom = this.isReverse(restClientBottomInContainer - marginBottom, clientTopInContainer - marginTop, wrapperRect.height + spacing);
867
+ const shouldContainerReverseRight = this.isReverse(restClientRightInContainer - marginRight, clientLeftInContainer - marginLeft, wrapperRect.width + spacing);
868
+ const shouldContainerReverseTopOver = this.isReverse(restClientTopInContainer - marginBottom, clientBottomInContainer - marginTop, wrapperRect.height + spacing);
869
+ const shouldContainerReverseBottomOver = this.isReverse(clientBottomInContainer - marginTop, restClientTopInContainer - marginBottom, wrapperRect.height + spacing);
870
+ const shouldContainerReverseTopSide = this.isReverse(restClientTopInContainer, clientBottomInContainer, wrapperRect.height);
871
+ const shouldContainerReverseBottomSide = this.isReverse(clientBottomInContainer, restClientTopInContainer, wrapperRect.height);
872
+ const shouldContainerReverseLeftSide = this.isReverse(restClientLeftInContainer, clientRightInContainer, wrapperRect.width);
873
+ const shouldContainerReverseRightSide = this.isReverse(clientRightInContainer, restClientLeftInContainer, wrapperRect.width);
874
+ const halfHeight = triggerRect.height / 2;
875
+ const halfWidth = triggerRect.width / 2; // 视口, 原空间与反向空间是否都不足判断
876
+ // Viewport, whether the original space and the reverse space are insufficient to judge
877
+
878
+ const isViewYOverFlow = this.isOverFlow(clientTop - marginTop, restClientBottom - marginBottom, wrapperRect.height + spacing);
879
+ const isViewXOverFlow = this.isOverFlow(clientLeft - marginLeft, restClientRight - marginRight, wrapperRect.width + spacing);
880
+ const isViewYOverFlowSide = this.isOverFlow(clientBottom - marginTop, restClientTop - marginBottom, wrapperRect.height + spacing);
881
+ const isViewXOverFlowSide = this.isOverFlow(clientRight - marginLeft, restClientLeft - marginRight, wrapperRect.width + spacing);
882
+ const isViewYOverFlowSideHalf = this.isHalfOverFlow(clientBottom - halfHeight, restClientTop - halfHeight, wrapperRect.height / 2);
883
+ const isViewXOverFlowSideHalf = this.isHalfOverFlow(clientRight - halfWidth, restClientLeft - halfWidth, wrapperRect.width / 2);
884
+ const isViewYEnoughSideHalf = this.isHalfAllEnough(clientBottom - halfHeight, restClientTop - halfHeight, wrapperRect.height / 2);
885
+ const isViewXEnoughSideHalf = this.isHalfAllEnough(clientRight - halfWidth, restClientLeft - halfWidth, wrapperRect.width / 2); // 容器, 原空间与反向空间是否都不足判断
886
+ // container, whether the original space and the reverse space are insufficient to judge
887
+
888
+ const isContainerYOverFlow = this.isOverFlow(clientTopInContainer - marginTop, restClientBottomInContainer - marginBottom, wrapperRect.height + spacing);
889
+ const isContainerXOverFlow = this.isOverFlow(clientLeftInContainer - marginLeft, restClientRightInContainer - marginRight, wrapperRect.width + spacing);
890
+ const isContainerYOverFlowSide = this.isOverFlow(clientBottomInContainer - marginTop, restClientTopInContainer - marginBottom, wrapperRect.height + spacing);
891
+ const isContainerXOverFlowSide = this.isOverFlow(clientRightInContainer - marginLeft, restClientLeftInContainer - marginRight, wrapperRect.width + spacing);
892
+ const isContainerYOverFlowSideHalf = this.isHalfOverFlow(clientBottomInContainer - halfHeight, restClientTopInContainer - halfHeight, wrapperRect.height / 2);
893
+ const isContainerXOverFlowSideHalf = this.isHalfOverFlow(clientRightInContainer - halfWidth, restClientLeftInContainer - halfWidth, wrapperRect.width / 2);
894
+ const isContainerYEnoughSideHalf = this.isHalfAllEnough(clientBottomInContainer - halfHeight, restClientTopInContainer - halfHeight, wrapperRect.height / 2);
895
+ const isContainerXEnoughSideHalf = this.isHalfAllEnough(clientRightInContainer - halfWidth, restClientLeftInContainer - halfWidth, wrapperRect.width / 2); // 综合 viewport + container 判断微调,即视口 + 容器都放置不行时才能考虑位置调整
896
+ // Comprehensive viewport + container judgment fine-tuning, that is, the position adjustment can only be considered when the viewport + container cannot be placed.
897
+
898
+ const shouldReverseTop = this.getReverse(isViewYOverFlow, isContainerYOverFlow, shouldViewReverseTop, shouldContainerReverseTop);
899
+ const shouldReverseLeft = this.getReverse(isViewXOverFlow, isContainerXOverFlow, shouldViewReverseLeft, shouldContainerReverseLeft);
900
+ const shouldReverseBottom = this.getReverse(isViewYOverFlow, isContainerYOverFlow, shouldViewReverseBottom, shouldContainerReverseBottom);
901
+ const shouldReverseRight = this.getReverse(isViewXOverFlow, isContainerXOverFlow, shouldViewReverseRight, shouldContainerReverseRight); // const shouldReverseTopOver = this.getReverse(isViewYOverFlowSide, isContainerYOverFlowSide, shouldViewReverseTopOver, shouldContainerReverseTopOver);
902
+ // const shouldReverseBottomOver = this.getReverse(isViewYOverFlowSide, isContainerYOverFlowSide, shouldViewReverseBottomOver, shouldContainerReverseBottomOver);
903
+
904
+ const shouldReverseTopSide = this.getReverse(isViewYOverFlowSide, isContainerYOverFlowSide, shouldViewReverseTopSide, shouldContainerReverseTopSide);
905
+ const shouldReverseBottomSide = this.getReverse(isViewYOverFlowSide, isContainerYOverFlowSide, shouldViewReverseBottomSide, shouldContainerReverseBottomSide);
906
+ const shouldReverseLeftSide = this.getReverse(isViewXOverFlowSide, isContainerXOverFlowSide, shouldViewReverseLeftSide, shouldContainerReverseLeftSide);
907
+ const shouldReverseRightSide = this.getReverse(isViewXOverFlowSide, isContainerXOverFlowSide, shouldViewReverseRightSide, shouldContainerReverseRightSide);
908
+ const isYOverFlowSideHalf = isViewYOverFlowSideHalf && isContainerYOverFlowSideHalf;
909
+ const isXOverFlowSideHalf = isViewXOverFlowSideHalf && isContainerXOverFlowSideHalf;
710
910
 
711
911
  switch (position) {
712
912
  case 'top':
713
913
  if (shouldReverseTop) {
714
- position = this._reversePos(position, true);
914
+ position = this._adjustPos(position, true);
915
+ }
916
+
917
+ if (isXOverFlowSideHalf && (shouldReverseLeftSide || shouldReverseRightSide)) {
918
+ position = this._adjustPos(position, true, 'expand', shouldReverseLeftSide ? 'Right' : 'Left');
715
919
  }
716
920
 
717
921
  break;
718
922
 
719
923
  case 'topLeft':
720
924
  if (shouldReverseTop) {
721
- position = this._reversePos(position, true);
925
+ position = this._adjustPos(position, true);
722
926
  }
723
927
 
724
928
  if (shouldReverseLeftSide && widthIsBigger) {
725
- position = this._reversePos(position);
929
+ position = this._adjustPos(position, true);
930
+ }
931
+
932
+ if (isWidthOverFlow && (isViewXEnoughSideHalf || isContainerXEnoughSideHalf)) {
933
+ position = this._adjustPos(position, true, 'reduce');
726
934
  }
727
935
 
728
936
  break;
729
937
 
730
938
  case 'topRight':
731
939
  if (shouldReverseTop) {
732
- position = this._reversePos(position, true);
940
+ position = this._adjustPos(position, true);
733
941
  }
734
942
 
735
943
  if (shouldReverseRightSide && widthIsBigger) {
736
- position = this._reversePos(position);
944
+ position = this._adjustPos(position);
945
+ }
946
+
947
+ if (isWidthOverFlow && (isViewXEnoughSideHalf || isContainerXEnoughSideHalf)) {
948
+ position = this._adjustPos(position, true, 'reduce');
737
949
  }
738
950
 
739
951
  break;
740
952
 
741
953
  case 'left':
742
954
  if (shouldReverseLeft) {
743
- position = this._reversePos(position);
955
+ position = this._adjustPos(position);
956
+ }
957
+
958
+ if (isYOverFlowSideHalf && (shouldReverseTopSide || shouldReverseBottomSide)) {
959
+ position = this._adjustPos(position, false, 'expand', shouldReverseTopSide ? 'Bottom' : 'Top');
744
960
  }
745
961
 
746
962
  break;
747
963
 
748
964
  case 'leftTop':
749
965
  if (shouldReverseLeft) {
750
- position = this._reversePos(position);
966
+ position = this._adjustPos(position);
751
967
  }
752
968
 
753
969
  if (shouldReverseTopSide && heightIsBigger) {
754
- position = this._reversePos(position, true);
970
+ position = this._adjustPos(position, true);
971
+ }
972
+
973
+ if (isHeightOverFlow && (isViewYEnoughSideHalf || isContainerYEnoughSideHalf)) {
974
+ position = this._adjustPos(position, false, 'reduce');
755
975
  }
756
976
 
757
977
  break;
758
978
 
759
979
  case 'leftBottom':
760
980
  if (shouldReverseLeft) {
761
- position = this._reversePos(position);
981
+ position = this._adjustPos(position);
762
982
  }
763
983
 
764
984
  if (shouldReverseBottomSide && heightIsBigger) {
765
- position = this._reversePos(position, true);
985
+ position = this._adjustPos(position, true);
986
+ }
987
+
988
+ if (isHeightOverFlow && (isViewYEnoughSideHalf || isContainerYEnoughSideHalf)) {
989
+ position = this._adjustPos(position, false, 'reduce');
766
990
  }
767
991
 
768
992
  break;
769
993
 
770
994
  case 'bottom':
771
995
  if (shouldReverseBottom) {
772
- position = this._reversePos(position, true);
996
+ position = this._adjustPos(position, true);
997
+ }
998
+
999
+ if (isXOverFlowSideHalf && (shouldReverseLeftSide || shouldReverseRightSide)) {
1000
+ position = this._adjustPos(position, true, 'expand', shouldReverseLeftSide ? 'Right' : 'Left');
773
1001
  }
774
1002
 
775
1003
  break;
776
1004
 
777
1005
  case 'bottomLeft':
778
1006
  if (shouldReverseBottom) {
779
- position = this._reversePos(position, true);
1007
+ position = this._adjustPos(position, true);
780
1008
  }
781
1009
 
782
1010
  if (shouldReverseLeftSide && widthIsBigger) {
783
- position = this._reversePos(position);
1011
+ position = this._adjustPos(position);
1012
+ }
1013
+
1014
+ if (isWidthOverFlow && (isViewXEnoughSideHalf || isContainerXEnoughSideHalf)) {
1015
+ position = this._adjustPos(position, true, 'reduce');
784
1016
  }
785
1017
 
786
1018
  break;
787
1019
 
788
1020
  case 'bottomRight':
789
1021
  if (shouldReverseBottom) {
790
- position = this._reversePos(position, true);
1022
+ position = this._adjustPos(position, true);
791
1023
  }
792
1024
 
793
1025
  if (shouldReverseRightSide && widthIsBigger) {
794
- position = this._reversePos(position);
1026
+ position = this._adjustPos(position);
1027
+ }
1028
+
1029
+ if (isWidthOverFlow && (isViewXEnoughSideHalf || isContainerXEnoughSideHalf)) {
1030
+ position = this._adjustPos(position, true, 'reduce');
795
1031
  }
796
1032
 
797
1033
  break;
798
1034
 
799
1035
  case 'right':
800
1036
  if (shouldReverseRight) {
801
- position = this._reversePos(position);
1037
+ position = this._adjustPos(position);
1038
+ }
1039
+
1040
+ if (isYOverFlowSideHalf && (shouldReverseTopSide || shouldReverseBottomSide)) {
1041
+ position = this._adjustPos(position, false, 'expand', shouldReverseTopSide ? 'Bottom' : 'Top');
802
1042
  }
803
1043
 
804
1044
  break;
805
1045
 
806
1046
  case 'rightTop':
807
1047
  if (shouldReverseRight) {
808
- position = this._reversePos(position);
1048
+ position = this._adjustPos(position);
809
1049
  }
810
1050
 
811
1051
  if (shouldReverseTopSide && heightIsBigger) {
812
- position = this._reversePos(position, true);
1052
+ position = this._adjustPos(position, true);
1053
+ }
1054
+
1055
+ if (isHeightOverFlow && (isViewYEnoughSideHalf || isContainerYEnoughSideHalf)) {
1056
+ position = this._adjustPos(position, false, 'reduce');
813
1057
  }
814
1058
 
815
1059
  break;
816
1060
 
817
1061
  case 'rightBottom':
818
1062
  if (shouldReverseRight) {
819
- position = this._reversePos(position);
1063
+ position = this._adjustPos(position);
820
1064
  }
821
1065
 
822
1066
  if (shouldReverseBottomSide && heightIsBigger) {
823
- position = this._reversePos(position, true);
1067
+ position = this._adjustPos(position, true);
1068
+ }
1069
+
1070
+ if (isHeightOverFlow && (isViewYEnoughSideHalf || isContainerYEnoughSideHalf)) {
1071
+ position = this._adjustPos(position, false, 'reduce');
824
1072
  }
825
1073
 
826
1074
  break;
827
1075
 
828
1076
  case 'leftTopOver':
829
1077
  if (shouldReverseTopOver) {
830
- position = this._reversePos(position, true);
1078
+ position = this._adjustPos(position, true);
831
1079
  }
832
1080
 
833
1081
  if (shouldReverseLeftOver) {
834
- position = this._reversePos(position);
1082
+ position = this._adjustPos(position);
835
1083
  }
836
1084
 
837
1085
  break;
838
1086
 
839
1087
  case 'leftBottomOver':
840
1088
  if (shouldReverseBottomOver) {
841
- position = this._reversePos(position, true);
1089
+ position = this._adjustPos(position, true);
842
1090
  }
843
1091
 
844
1092
  if (shouldReverseLeftOver) {
845
- position = this._reversePos(position);
1093
+ position = this._adjustPos(position);
846
1094
  }
847
1095
 
848
1096
  break;
849
1097
 
850
1098
  case 'rightTopOver':
851
1099
  if (shouldReverseTopOver) {
852
- position = this._reversePos(position, true);
1100
+ position = this._adjustPos(position, true);
853
1101
  }
854
1102
 
855
1103
  if (shouldReverseRightOver) {
856
- position = this._reversePos(position);
1104
+ position = this._adjustPos(position);
857
1105
  }
858
1106
 
859
1107
  break;
860
1108
 
861
1109
  case 'rightBottomOver':
862
1110
  if (shouldReverseBottomOver) {
863
- position = this._reversePos(position, true);
1111
+ position = this._adjustPos(position, true);
864
1112
  }
865
1113
 
866
1114
  if (shouldReverseRightOver) {
867
- position = this._reversePos(position);
1115
+ position = this._adjustPos(position);
868
1116
  }
869
1117
 
870
1118
  break;
871
1119
 
872
1120
  default:
873
1121
  break;
1122
+ } // 判断溢出 Judgment overflow
1123
+ // 上下方向 top and bottom
1124
+
1125
+
1126
+ if (this.isTB(position)) {
1127
+ isHeightOverFlow = isViewYOverFlow && isContainerYOverFlow;
1128
+
1129
+ if (position === 'top' || position === 'bottom') {
1130
+ isWidthOverFlow = isViewXOverFlowSideHalf && isContainerXOverFlowSideHalf;
1131
+ } else {
1132
+ isWidthOverFlow = isViewXOverFlowSide && isContainerXOverFlowSide;
1133
+ }
1134
+ } // 左右方向 left and right
1135
+
1136
+
1137
+ if (this.isLR(position)) {
1138
+ isWidthOverFlow = isViewXOverFlow && isContainerXOverFlow;
1139
+
1140
+ if (position === 'left' || position === 'right') {
1141
+ isHeightOverFlow = isViewYOverFlowSideHalf && isContainerYOverFlowSideHalf;
1142
+ } else {
1143
+ isHeightOverFlow = isViewYOverFlowSide && isContainerYOverFlowSide;
1144
+ }
874
1145
  }
875
1146
  }
876
1147
 
877
- return position;
1148
+ return {
1149
+ position,
1150
+ isHeightOverFlow,
1151
+ isWidthOverFlow
1152
+ };
878
1153
  }
879
1154
 
880
1155
  _bindScrollEvent() {