raise-common-lib 0.0.221 → 0.0.222

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.
@@ -23927,22 +23927,91 @@ var SmartPopupComponent = /** @class */ (function () {
23927
23927
  if (this.opened === "yes" &&
23928
23928
  previousTrigger !== this.currentTriggerElement &&
23929
23929
  this.currentTriggerElement) {
23930
- // 使用新的打开方式更新位置
23931
- this.positioning = "yes";
23932
- this.ref.markForCheck();
23933
- requestAnimationFrame((/**
23934
- * @return {?}
23935
- */
23936
- function () {
23930
+ // 如果提供了固定尺寸,直接重新计算位置(避免位置跳动)
23931
+ if (this._width !== null && this._height !== null) {
23932
+ // 先隐藏弹窗(positioning = yes)
23933
+ this.positioning = "yes";
23934
+ this.ref.markForCheck();
23935
+ this.ref.detectChanges(); // 立即应用隐藏状态
23937
23936
  requestAnimationFrame((/**
23938
23937
  * @return {?}
23939
23938
  */
23940
23939
  function () {
23941
- _this.updatePopupPosition();
23942
- _this.positioning = "no";
23943
- _this.ref.markForCheck();
23940
+ if (_this.currentTriggerElement) {
23941
+ /** @type {?} */
23942
+ var triggerRect = _this.currentTriggerElement.getBoundingClientRect();
23943
+ /** @type {?} */
23944
+ var popupSize = {
23945
+ width: (/** @type {?} */ (_this._width)),
23946
+ height: (/** @type {?} */ (_this._height)),
23947
+ };
23948
+ /** @type {?} */
23949
+ var targetInfo = _this.placementInfo;
23950
+ /** @type {?} */
23951
+ var finalPlacement = targetInfo.placement;
23952
+ /** @type {?} */
23953
+ var finalPosition = targetInfo.position;
23954
+ if (_this.autoAdjust) {
23955
+ /** @type {?} */
23956
+ var popupRect = (/** @type {?} */ ({
23957
+ width: popupSize.width,
23958
+ height: popupSize.height,
23959
+ top: 0,
23960
+ left: 0,
23961
+ right: popupSize.width,
23962
+ bottom: popupSize.height,
23963
+ x: 0,
23964
+ y: 0,
23965
+ toJSON: (/**
23966
+ * @return {?}
23967
+ */
23968
+ function () { return ({}); }),
23969
+ }));
23970
+ /** @type {?} */
23971
+ var optimal = _this.calculateOptimalPlacement(triggerRect, popupRect, window.innerWidth, window.innerHeight);
23972
+ finalPlacement = optimal.placement;
23973
+ }
23974
+ _this.actualPlacement = finalPlacement;
23975
+ _this.actualPosition = finalPosition;
23976
+ /** @type {?} */
23977
+ var position = _this.calculatePositionCoordinates(triggerRect, finalPlacement, finalPosition, popupSize);
23978
+ if (_this.popupElement && _this.popupElement.nativeElement) {
23979
+ /** @type {?} */
23980
+ var popupEl = _this.popupElement.nativeElement;
23981
+ popupEl.style.top = position.top;
23982
+ popupEl.style.left = position.left;
23983
+ popupEl.style.transform = "translate(" + position.translateX + ", " + position.translateY + ")";
23984
+ popupEl.offsetHeight; // 强制同步应用样式
23985
+ // 位置设置完成后,再显示弹窗
23986
+ requestAnimationFrame((/**
23987
+ * @return {?}
23988
+ */
23989
+ function () {
23990
+ _this.positioning = "no";
23991
+ _this.ref.markForCheck();
23992
+ }));
23993
+ }
23994
+ }
23944
23995
  }));
23945
- }));
23996
+ }
23997
+ else {
23998
+ // 使用新的打开方式更新位置
23999
+ this.positioning = "yes";
24000
+ this.ref.markForCheck();
24001
+ requestAnimationFrame((/**
24002
+ * @return {?}
24003
+ */
24004
+ function () {
24005
+ requestAnimationFrame((/**
24006
+ * @return {?}
24007
+ */
24008
+ function () {
24009
+ _this.updatePopupPosition();
24010
+ _this.positioning = "no";
24011
+ _this.ref.markForCheck();
24012
+ }));
24013
+ }));
24014
+ }
23946
24015
  }
23947
24016
  }
23948
24017
  // 处理 open 变化(确保在触发元素更新后处理)
@@ -24072,22 +24141,92 @@ var SmartPopupComponent = /** @class */ (function () {
24072
24141
  console.warn("SmartPopupComponent: No trigger element found");
24073
24142
  return;
24074
24143
  }
24075
- // 如果已经打开,先关闭再打开(更新位置)
24144
+ // 如果已经打开,且提供了固定尺寸,直接重新计算位置(避免关闭再打开导致的跳动)
24076
24145
  if (this.opened === "yes") {
24077
- // 先关闭弹窗
24078
- this.opened = "no";
24079
- this.positioning = "no";
24080
- this.ref.markForCheck();
24081
- // 立即在新位置打开
24082
- requestAnimationFrame((/**
24083
- * @return {?}
24084
- */
24085
- function () {
24086
- // 再次确保触发元素已更新
24087
- _this.updateTriggerElement();
24088
- _this.openPopup();
24089
- }));
24090
- return;
24146
+ if (this._width !== null && this._height !== null) {
24147
+ // 有固定尺寸,直接重新计算位置,不关闭弹窗
24148
+ // 先隐藏弹窗(positioning = yes)
24149
+ this.positioning = "yes";
24150
+ this.ref.markForCheck();
24151
+ this.ref.detectChanges(); // 立即应用隐藏状态
24152
+ requestAnimationFrame((/**
24153
+ * @return {?}
24154
+ */
24155
+ function () {
24156
+ // 再次确保触发元素已更新
24157
+ _this.updateTriggerElement();
24158
+ if (_this.currentTriggerElement) {
24159
+ /** @type {?} */
24160
+ var triggerRect = _this.currentTriggerElement.getBoundingClientRect();
24161
+ /** @type {?} */
24162
+ var popupSize = {
24163
+ width: (/** @type {?} */ (_this._width)),
24164
+ height: (/** @type {?} */ (_this._height)),
24165
+ };
24166
+ /** @type {?} */
24167
+ var targetInfo = _this.placementInfo;
24168
+ /** @type {?} */
24169
+ var finalPlacement = targetInfo.placement;
24170
+ /** @type {?} */
24171
+ var finalPosition = targetInfo.position;
24172
+ if (_this.autoAdjust) {
24173
+ /** @type {?} */
24174
+ var popupRect = (/** @type {?} */ ({
24175
+ width: popupSize.width,
24176
+ height: popupSize.height,
24177
+ top: 0,
24178
+ left: 0,
24179
+ right: popupSize.width,
24180
+ bottom: popupSize.height,
24181
+ x: 0,
24182
+ y: 0,
24183
+ toJSON: (/**
24184
+ * @return {?}
24185
+ */
24186
+ function () { return ({}); }),
24187
+ }));
24188
+ /** @type {?} */
24189
+ var optimal = _this.calculateOptimalPlacement(triggerRect, popupRect, window.innerWidth, window.innerHeight);
24190
+ finalPlacement = optimal.placement;
24191
+ }
24192
+ _this.actualPlacement = finalPlacement;
24193
+ _this.actualPosition = finalPosition;
24194
+ /** @type {?} */
24195
+ var position = _this.calculatePositionCoordinates(triggerRect, finalPlacement, finalPosition, popupSize);
24196
+ if (_this.popupElement && _this.popupElement.nativeElement) {
24197
+ /** @type {?} */
24198
+ var popupEl = _this.popupElement.nativeElement;
24199
+ popupEl.style.top = position.top;
24200
+ popupEl.style.left = position.left;
24201
+ popupEl.style.transform = "translate(" + position.translateX + ", " + position.translateY + ")";
24202
+ popupEl.offsetHeight; // 强制同步应用样式
24203
+ // 位置设置完成后,再显示弹窗
24204
+ requestAnimationFrame((/**
24205
+ * @return {?}
24206
+ */
24207
+ function () {
24208
+ _this.positioning = "no";
24209
+ _this.ref.markForCheck();
24210
+ }));
24211
+ }
24212
+ }
24213
+ }));
24214
+ return;
24215
+ }
24216
+ else {
24217
+ // 没有固定尺寸,先关闭再打开
24218
+ this.opened = "no";
24219
+ this.positioning = "no";
24220
+ this.ref.markForCheck();
24221
+ requestAnimationFrame((/**
24222
+ * @return {?}
24223
+ */
24224
+ function () {
24225
+ _this.updateTriggerElement();
24226
+ _this.openPopup();
24227
+ }));
24228
+ return;
24229
+ }
24091
24230
  }
24092
24231
  // 确保触发元素已更新
24093
24232
  this.updateTriggerElement();
@@ -24142,13 +24281,15 @@ var SmartPopupComponent = /** @class */ (function () {
24142
24281
  var targetInfo = this.placementInfo;
24143
24282
  /** @type {?} */
24144
24283
  var finalPlacement = targetInfo.placement;
24284
+ // 始终使用用户指定的 position,autoAdjust 只调整 placement(方向),不改变对齐方式
24145
24285
  /** @type {?} */
24146
24286
  var finalPosition = targetInfo.position;
24147
24287
  if (this.autoAdjust) {
24148
24288
  /** @type {?} */
24149
24289
  var optimal = this.calculateOptimalPlacement(triggerRect, popupRect, viewportWidth, viewportHeight);
24290
+ // autoAdjust 只调整 placement(上下左右),保持用户指定的 position(对齐方式)
24150
24291
  finalPlacement = optimal.placement;
24151
- finalPosition = optimal.position;
24292
+ // finalPosition 保持用户指定的值,不改变
24152
24293
  }
24153
24294
  this.actualPlacement = finalPlacement;
24154
24295
  this.actualPosition = finalPosition;
@@ -24156,56 +24297,57 @@ var SmartPopupComponent = /** @class */ (function () {
24156
24297
  /** @type {?} */
24157
24298
  var position_1 = this.calculatePositionCoordinates(triggerRect, finalPlacement, finalPosition, popupSize);
24158
24299
  // 先设置打开状态,但保持隐藏(positioning = yes)
24159
- this.opened = "yes";
24300
+ // 注意:先设置 positioning = yes,再设置 opened = yes,确保弹窗在位置计算完成前始终隐藏
24160
24301
  this.positioning = "yes";
24302
+ this.opened = "yes";
24161
24303
  this.openChange.emit(true);
24162
24304
  this.ref.markForCheck();
24163
- // 强制更新视图,确保DOM已更新
24305
+ // 强制更新视图,确保DOM已更新,但弹窗仍然隐藏(因为 positioning = yes)
24164
24306
  this.ref.detectChanges();
24165
- // 如果元素已经存在,立即设置位置(不等待 requestAnimationFrame)
24307
+ // 设置位置的函数
24308
+ /** @type {?} */
24309
+ var setPosition_1 = (/**
24310
+ * @return {?}
24311
+ */
24312
+ function () {
24313
+ if (_this.popupElement && _this.popupElement.nativeElement) {
24314
+ /** @type {?} */
24315
+ var popupEl = _this.popupElement.nativeElement;
24316
+ // 立即设置尺寸和位置
24317
+ popupEl.style.width = _this._width + "px";
24318
+ popupEl.style.height = _this._height + "px";
24319
+ popupEl.style.minWidth = _this._width + "px";
24320
+ popupEl.style.maxWidth = _this._width + "px";
24321
+ popupEl.style.minHeight = _this._height + "px";
24322
+ popupEl.style.maxHeight = _this._height + "px";
24323
+ popupEl.style.top = position_1.top;
24324
+ popupEl.style.left = position_1.left;
24325
+ popupEl.style.transform = "translate(" + position_1.translateX + ", " + position_1.translateY + ")";
24326
+ // 强制同步应用样式,确保位置已设置
24327
+ popupEl.offsetHeight;
24328
+ // 位置设置完成后,再显示弹窗(设置 positioning = no)
24329
+ // 使用 requestAnimationFrame 确保样式已应用
24330
+ requestAnimationFrame((/**
24331
+ * @return {?}
24332
+ */
24333
+ function () {
24334
+ _this.positioning = "no";
24335
+ _this.ref.markForCheck();
24336
+ }));
24337
+ }
24338
+ });
24339
+ // 如果元素已经存在,立即设置位置
24166
24340
  if (this.popupElement && this.popupElement.nativeElement) {
24167
- /** @type {?} */
24168
- var popupEl = this.popupElement.nativeElement;
24169
- // 立即设置尺寸和位置
24170
- popupEl.style.width = this._width + "px";
24171
- popupEl.style.height = this._height + "px";
24172
- popupEl.style.minWidth = this._width + "px";
24173
- popupEl.style.maxWidth = this._width + "px";
24174
- popupEl.style.minHeight = this._height + "px";
24175
- popupEl.style.maxHeight = this._height + "px";
24176
- popupEl.style.top = position_1.top;
24177
- popupEl.style.left = position_1.left;
24178
- popupEl.style.transform = "translate(" + position_1.translateX + ", " + position_1.translateY + ")";
24179
- // 强制同步应用样式
24180
- popupEl.offsetHeight;
24181
- // 位置设置完成后,立即显示弹窗
24182
- this.positioning = "no";
24183
- this.ref.markForCheck();
24341
+ setPosition_1();
24184
24342
  }
24185
24343
  else {
24186
- // 如果元素还不存在,等待渲染
24344
+ // 如果元素还不存在,等待渲染后再设置位置
24187
24345
  requestAnimationFrame((/**
24188
24346
  * @return {?}
24189
24347
  */
24190
24348
  function () {
24191
24349
  if (_this.popupElement && _this.popupElement.nativeElement) {
24192
- /** @type {?} */
24193
- var popupEl = _this.popupElement.nativeElement;
24194
- // 立即设置尺寸和位置
24195
- popupEl.style.width = _this._width + "px";
24196
- popupEl.style.height = _this._height + "px";
24197
- popupEl.style.minWidth = _this._width + "px";
24198
- popupEl.style.maxWidth = _this._width + "px";
24199
- popupEl.style.minHeight = _this._height + "px";
24200
- popupEl.style.maxHeight = _this._height + "px";
24201
- popupEl.style.top = position_1.top;
24202
- popupEl.style.left = position_1.left;
24203
- popupEl.style.transform = "translate(" + position_1.translateX + ", " + position_1.translateY + ")";
24204
- // 强制同步应用样式
24205
- popupEl.offsetHeight;
24206
- // 位置设置完成后,立即显示弹窗
24207
- _this.positioning = "no";
24208
- _this.ref.markForCheck();
24350
+ setPosition_1();
24209
24351
  }
24210
24352
  }));
24211
24353
  }
@@ -24369,13 +24511,15 @@ var SmartPopupComponent = /** @class */ (function () {
24369
24511
  var targetInfo = this.placementInfo;
24370
24512
  /** @type {?} */
24371
24513
  var finalPlacement = targetInfo.placement;
24514
+ // 始终使用用户指定的 position,autoAdjust 只调整 placement(方向),不改变对齐方式
24372
24515
  /** @type {?} */
24373
24516
  var finalPosition = targetInfo.position;
24374
24517
  if (this.autoAdjust) {
24375
24518
  /** @type {?} */
24376
24519
  var optimal = this.calculateOptimalPlacement(triggerRect, popupRect, viewportWidth, viewportHeight);
24520
+ // autoAdjust 只调整 placement(上下左右),保持用户指定的 position(对齐方式)
24377
24521
  finalPlacement = optimal.placement;
24378
- finalPosition = optimal.position;
24522
+ // finalPosition 保持用户指定的值,不改变
24379
24523
  }
24380
24524
  this.actualPlacement = finalPlacement;
24381
24525
  this.actualPosition = finalPosition;
@@ -24429,13 +24573,15 @@ var SmartPopupComponent = /** @class */ (function () {
24429
24573
  var targetInfo = this.placementInfo;
24430
24574
  /** @type {?} */
24431
24575
  var finalPlacement = targetInfo.placement;
24576
+ // 始终使用用户指定的 position,autoAdjust 只调整 placement(方向),不改变对齐方式
24432
24577
  /** @type {?} */
24433
24578
  var finalPosition = targetInfo.position;
24434
24579
  if (this.autoAdjust) {
24435
24580
  /** @type {?} */
24436
24581
  var optimal = this.calculateOptimalPlacement(triggerRect, popupRect, viewportWidth, viewportHeight);
24582
+ // autoAdjust 只调整 placement(上下左右),保持用户指定的 position(对齐方式)
24437
24583
  finalPlacement = optimal.placement;
24438
- finalPosition = optimal.position;
24584
+ // finalPosition 保持用户指定的值,不改变
24439
24585
  }
24440
24586
  this.actualPlacement = finalPlacement;
24441
24587
  this.actualPosition = finalPosition;
@@ -24605,17 +24751,12 @@ var SmartPopupComponent = /** @class */ (function () {
24605
24751
  });
24606
24752
  // 如果首选位置有足够空间,优先使用用户指定的position
24607
24753
  if (hasEnoughSpace(preferred)) {
24608
- // 检查用户指定的position是否有足够空间
24609
- if (checkPositionSpace(preferred, preferredPosition)) {
24610
- return {
24611
- placement: preferred,
24612
- position: preferredPosition,
24613
- };
24614
- }
24615
- // 如果指定的position空间不足,自动计算最佳position
24754
+ // 即使指定的position空间不足,也尽量保持用户指定的position
24755
+ // 边界约束逻辑会在 calculatePositionCoordinates 中处理位置调整
24756
+ // 这样可以保持用户期望的对齐方式
24616
24757
  return {
24617
24758
  placement: preferred,
24618
- position: calculatePosition(preferred),
24759
+ position: preferredPosition,
24619
24760
  };
24620
24761
  }
24621
24762
  // 根据首选位置选择备选位置
@@ -24666,7 +24807,9 @@ var SmartPopupComponent = /** @class */ (function () {
24666
24807
  };
24667
24808
  };
24668
24809
  // 计算位置坐标(纯计算,不依赖DOM,包含边界约束)
24810
+ // 注意:弹窗使用 position: fixed,所以坐标应该是相对于视口的,不需要加上滚动偏移
24669
24811
  // 计算位置坐标(纯计算,不依赖DOM,包含边界约束)
24812
+ // 注意:弹窗使用 position: fixed,所以坐标应该是相对于视口的,不需要加上滚动偏移
24670
24813
  /**
24671
24814
  * @private
24672
24815
  * @param {?} triggerRect
@@ -24677,6 +24820,7 @@ var SmartPopupComponent = /** @class */ (function () {
24677
24820
  */
24678
24821
  SmartPopupComponent.prototype.calculatePositionCoordinates =
24679
24822
  // 计算位置坐标(纯计算,不依赖DOM,包含边界约束)
24823
+ // 注意:弹窗使用 position: fixed,所以坐标应该是相对于视口的,不需要加上滚动偏移
24680
24824
  /**
24681
24825
  * @private
24682
24826
  * @param {?} triggerRect
@@ -24695,10 +24839,6 @@ var SmartPopupComponent = /** @class */ (function () {
24695
24839
  /** @type {?} */
24696
24840
  var viewportHeight = window.innerHeight;
24697
24841
  /** @type {?} */
24698
- var scrollX = window.scrollX;
24699
- /** @type {?} */
24700
- var scrollY = window.scrollY;
24701
- /** @type {?} */
24702
24842
  var top = 0;
24703
24843
  /** @type {?} */
24704
24844
  var left = 0;
@@ -24708,109 +24848,268 @@ var SmartPopupComponent = /** @class */ (function () {
24708
24848
  var translateY = "0";
24709
24849
  switch (placement) {
24710
24850
  case "top":
24711
- top = triggerRect.top + scrollY - this.offset;
24851
+ // 弹窗在触发元素上方
24852
+ top = triggerRect.top - this.offset;
24712
24853
  translateY = "-100%";
24713
24854
  if (position === "start") {
24714
- left = triggerRect.left + scrollX;
24855
+ // 左对齐
24856
+ left = triggerRect.left;
24857
+ translateX = "0";
24715
24858
  }
24716
24859
  else if (position === "center") {
24717
- left = triggerRect.left + scrollX + triggerWidth / 2;
24860
+ // 居中对齐
24861
+ left = triggerRect.left + triggerWidth / 2;
24718
24862
  translateX = "-50%";
24719
24863
  }
24720
24864
  else {
24721
- left = triggerRect.left + scrollX + triggerWidth;
24865
+ // 右对齐(end)
24866
+ left = triggerRect.right;
24722
24867
  translateX = "-100%";
24723
24868
  }
24724
24869
  // 边界约束:确保弹窗不超出视口
24725
- if (top - popupSize.height < scrollY) {
24726
- top = scrollY + 8; // 距离顶部至少8px
24870
+ /** @type {?} */
24871
+ var popupTop = top - popupSize.height;
24872
+ if (popupTop < 0) {
24873
+ top = popupSize.height + 8; // 距离顶部至少8px
24874
+ translateY = "0"; // 取消向上偏移
24727
24875
  }
24728
- if (left < scrollX) {
24729
- left = scrollX + 8;
24730
- translateX = "0";
24876
+ // 水平边界约束:尽量保持原始对齐方式
24877
+ if (position === "start") {
24878
+ // 左对齐:如果超出右边界,调整到右边界;如果超出左边界,调整到左边界
24879
+ if (left + popupSize.width > viewportWidth) {
24880
+ left = viewportWidth - popupSize.width - 8;
24881
+ }
24882
+ if (left < 8) {
24883
+ left = 8;
24884
+ }
24731
24885
  }
24732
- else if (left + popupSize.width > scrollX + viewportWidth) {
24733
- left = scrollX + viewportWidth - popupSize.width - 8;
24734
- translateX = "0";
24886
+ else if (position === "center") {
24887
+ // 居中对齐:计算实际左边界
24888
+ /** @type {?} */
24889
+ var actualLeft = left - popupSize.width / 2;
24890
+ if (actualLeft < 8) {
24891
+ // 左边界不足,尽量保持居中,但调整到不超出左边界
24892
+ left = 8 + popupSize.width / 2;
24893
+ translateX = "-50%";
24894
+ }
24895
+ else if (actualLeft + popupSize.width > viewportWidth - 8) {
24896
+ // 右边界不足,尽量保持居中,但调整到不超出右边界
24897
+ left = viewportWidth - 8 - popupSize.width / 2;
24898
+ translateX = "-50%";
24899
+ }
24900
+ }
24901
+ else {
24902
+ // 右对齐(end):弹窗右边缘与触发元素右边缘对齐
24903
+ // left 是弹窗的右边缘位置(因为 translateX = "-100%")
24904
+ // 弹窗的左边缘在 left - popupSize.width
24905
+ /** @type {?} */
24906
+ var popupLeftEdge = left - popupSize.width;
24907
+ // 如果弹窗左边缘超出左边界,调整位置但保持右对齐
24908
+ if (popupLeftEdge < 8) {
24909
+ left = 8 + popupSize.width;
24910
+ translateX = "-100%";
24911
+ }
24912
+ // 如果弹窗右边缘超出右边界,调整位置但保持右对齐
24913
+ if (left > viewportWidth - 8) {
24914
+ left = viewportWidth - 8;
24915
+ translateX = "-100%";
24916
+ }
24735
24917
  }
24736
24918
  break;
24737
24919
  case "bottom":
24738
- top = triggerRect.bottom + scrollY + this.offset;
24920
+ // 弹窗在触发元素下方
24921
+ top = triggerRect.bottom + this.offset;
24739
24922
  if (position === "start") {
24740
- left = triggerRect.left + scrollX;
24923
+ // 左对齐
24924
+ left = triggerRect.left;
24925
+ translateX = "0";
24741
24926
  }
24742
24927
  else if (position === "center") {
24743
- left = triggerRect.left + scrollX + triggerWidth / 2;
24928
+ // 居中对齐
24929
+ left = triggerRect.left + triggerWidth / 2;
24744
24930
  translateX = "-50%";
24745
24931
  }
24746
24932
  else {
24747
- left = triggerRect.left + scrollX + triggerWidth;
24933
+ // 右对齐(end)
24934
+ left = triggerRect.right;
24748
24935
  translateX = "-100%";
24749
24936
  }
24750
24937
  // 边界约束:确保弹窗不超出视口
24751
- if (top + popupSize.height > scrollY + viewportHeight) {
24752
- top = scrollY + viewportHeight - popupSize.height - 8; // 距离底部至少8px
24938
+ if (top + popupSize.height > viewportHeight) {
24939
+ top = viewportHeight - popupSize.height - 8; // 距离底部至少8px
24753
24940
  }
24754
- if (left < scrollX) {
24755
- left = scrollX + 8;
24756
- translateX = "0";
24941
+ // 水平边界约束:尽量保持原始对齐方式
24942
+ if (position === "start") {
24943
+ // 左对齐:如果超出右边界,调整到右边界;如果超出左边界,调整到左边界
24944
+ if (left + popupSize.width > viewportWidth) {
24945
+ left = viewportWidth - popupSize.width - 8;
24946
+ }
24947
+ if (left < 8) {
24948
+ left = 8;
24949
+ }
24757
24950
  }
24758
- else if (left + popupSize.width > scrollX + viewportWidth) {
24759
- left = scrollX + viewportWidth - popupSize.width - 8;
24760
- translateX = "0";
24951
+ else if (position === "center") {
24952
+ // 居中对齐:计算实际左边界
24953
+ /** @type {?} */
24954
+ var actualLeft = left - popupSize.width / 2;
24955
+ if (actualLeft < 8) {
24956
+ // 左边界不足,尽量保持居中,但调整到不超出左边界
24957
+ left = 8 + popupSize.width / 2;
24958
+ translateX = "-50%";
24959
+ }
24960
+ else if (actualLeft + popupSize.width > viewportWidth - 8) {
24961
+ // 右边界不足,尽量保持居中,但调整到不超出右边界
24962
+ left = viewportWidth - 8 - popupSize.width / 2;
24963
+ translateX = "-50%";
24964
+ }
24965
+ }
24966
+ else {
24967
+ // 右对齐(end):弹窗右边缘与触发元素右边缘对齐
24968
+ // left 是弹窗的右边缘位置(因为 translateX = "-100%")
24969
+ // 弹窗的左边缘在 left - popupSize.width
24970
+ /** @type {?} */
24971
+ var popupLeftEdge = left - popupSize.width;
24972
+ // 优先保持与触发元素右对齐,只在必要时调整
24973
+ // 如果弹窗右边缘超出右边界,调整位置但保持右对齐
24974
+ if (left > viewportWidth - 8) {
24975
+ left = viewportWidth - 8;
24976
+ translateX = "-100%";
24977
+ }
24978
+ // 如果弹窗左边缘超出左边界,且弹窗可以完全显示在视口内,才调整位置
24979
+ // 这样可以确保在可能的情况下,弹窗始终与触发元素右对齐
24980
+ if (popupLeftEdge < 8 && popupSize.width < viewportWidth - 16) {
24981
+ // 只有当弹窗可以完全显示在视口内时,才调整位置
24982
+ // 否则保持与触发元素右对齐,即使部分超出左边界
24983
+ left = 8 + popupSize.width;
24984
+ translateX = "-100%";
24985
+ }
24761
24986
  }
24762
24987
  break;
24763
24988
  case "left":
24764
- left = triggerRect.left + scrollX - this.offset;
24989
+ // 弹窗在触发元素左侧
24990
+ left = triggerRect.left - this.offset;
24765
24991
  translateX = "-100%";
24766
24992
  if (position === "start") {
24767
- top = triggerRect.top + scrollY;
24993
+ // 上对齐
24994
+ top = triggerRect.top;
24995
+ translateY = "0";
24768
24996
  }
24769
24997
  else if (position === "center") {
24770
- top = triggerRect.top + scrollY + triggerHeight / 2;
24998
+ // 居中对齐
24999
+ top = triggerRect.top + triggerHeight / 2;
24771
25000
  translateY = "-50%";
24772
25001
  }
24773
25002
  else {
24774
- top = triggerRect.top + scrollY + triggerHeight;
25003
+ // 下对齐(end)
25004
+ top = triggerRect.bottom;
24775
25005
  translateY = "-100%";
24776
25006
  }
24777
25007
  // 边界约束:确保弹窗不超出视口
24778
- if (left - popupSize.width < scrollX) {
24779
- left = scrollX + 8; // 距离左侧至少8px
25008
+ /** @type {?} */
25009
+ var popupLeftSide = left - popupSize.width;
25010
+ if (popupLeftSide < 0) {
25011
+ left = 8; // 距离左侧至少8px
25012
+ translateX = "0"; // 取消向左偏移
24780
25013
  }
24781
- if (top < scrollY) {
24782
- top = scrollY + 8;
24783
- translateY = "0";
25014
+ // 垂直边界约束:尽量保持原始对齐方式
25015
+ if (position === "start") {
25016
+ // 上对齐:如果超出下边界,调整到下边界;如果超出上边界,调整到上边界
25017
+ if (top + popupSize.height > viewportHeight) {
25018
+ top = viewportHeight - popupSize.height - 8;
25019
+ }
25020
+ if (top < 8) {
25021
+ top = 8;
25022
+ }
24784
25023
  }
24785
- else if (top + popupSize.height > scrollY + viewportHeight) {
24786
- top = scrollY + viewportHeight - popupSize.height - 8;
24787
- translateY = "0";
25024
+ else if (position === "center") {
25025
+ // 居中对齐:计算实际上边界
25026
+ /** @type {?} */
25027
+ var actualTop = top - popupSize.height / 2;
25028
+ if (actualTop < 8) {
25029
+ // 上边界不足,尽量保持居中,但调整到不超出上边界
25030
+ top = 8 + popupSize.height / 2;
25031
+ translateY = "-50%";
25032
+ }
25033
+ else if (actualTop + popupSize.height > viewportHeight - 8) {
25034
+ // 下边界不足,尽量保持居中,但调整到不超出下边界
25035
+ top = viewportHeight - 8 - popupSize.height / 2;
25036
+ translateY = "-50%";
25037
+ }
25038
+ }
25039
+ else {
25040
+ // 下对齐(end):如果超出上边界,调整到上边界;如果超出下边界,调整到下边界
25041
+ /** @type {?} */
25042
+ var actualTop = top - popupSize.height;
25043
+ if (actualTop < 8) {
25044
+ top = 8 + popupSize.height;
25045
+ translateY = "-100%";
25046
+ }
25047
+ if (top > viewportHeight - 8) {
25048
+ top = viewportHeight - 8;
25049
+ translateY = "-100%";
25050
+ }
24788
25051
  }
24789
25052
  break;
24790
25053
  case "right":
24791
- left = triggerRect.right + scrollX + this.offset;
25054
+ // 弹窗在触发元素右侧
25055
+ left = triggerRect.right + this.offset;
25056
+ translateX = "0";
24792
25057
  if (position === "start") {
24793
- top = triggerRect.top + scrollY;
25058
+ // 上对齐
25059
+ top = triggerRect.top;
25060
+ translateY = "0";
24794
25061
  }
24795
25062
  else if (position === "center") {
24796
- top = triggerRect.top + scrollY + triggerHeight / 2;
25063
+ // 居中对齐
25064
+ top = triggerRect.top + triggerHeight / 2;
24797
25065
  translateY = "-50%";
24798
25066
  }
24799
25067
  else {
24800
- top = triggerRect.top + scrollY + triggerHeight;
25068
+ // 下对齐(end)
25069
+ top = triggerRect.bottom;
24801
25070
  translateY = "-100%";
24802
25071
  }
24803
25072
  // 边界约束:确保弹窗不超出视口
24804
- if (left + popupSize.width > scrollX + viewportWidth) {
24805
- left = scrollX + viewportWidth - popupSize.width - 8; // 距离右侧至少8px
25073
+ if (left + popupSize.width > viewportWidth) {
25074
+ left = viewportWidth - popupSize.width - 8; // 距离右侧至少8px
24806
25075
  }
24807
- if (top < scrollY) {
24808
- top = scrollY + 8;
24809
- translateY = "0";
25076
+ // 垂直边界约束:尽量保持原始对齐方式
25077
+ if (position === "start") {
25078
+ // 上对齐:如果超出下边界,调整到下边界;如果超出上边界,调整到上边界
25079
+ if (top + popupSize.height > viewportHeight) {
25080
+ top = viewportHeight - popupSize.height - 8;
25081
+ }
25082
+ if (top < 8) {
25083
+ top = 8;
25084
+ }
24810
25085
  }
24811
- else if (top + popupSize.height > scrollY + viewportHeight) {
24812
- top = scrollY + viewportHeight - popupSize.height - 8;
24813
- translateY = "0";
25086
+ else if (position === "center") {
25087
+ // 居中对齐:计算实际上边界
25088
+ /** @type {?} */
25089
+ var actualTop = top - popupSize.height / 2;
25090
+ if (actualTop < 8) {
25091
+ // 上边界不足,尽量保持居中,但调整到不超出上边界
25092
+ top = 8 + popupSize.height / 2;
25093
+ translateY = "-50%";
25094
+ }
25095
+ else if (actualTop + popupSize.height > viewportHeight - 8) {
25096
+ // 下边界不足,尽量保持居中,但调整到不超出下边界
25097
+ top = viewportHeight - 8 - popupSize.height / 2;
25098
+ translateY = "-50%";
25099
+ }
25100
+ }
25101
+ else {
25102
+ // 下对齐(end):如果超出上边界,调整到上边界;如果超出下边界,调整到下边界
25103
+ /** @type {?} */
25104
+ var actualTop = top - popupSize.height;
25105
+ if (actualTop < 8) {
25106
+ top = 8 + popupSize.height;
25107
+ translateY = "-100%";
25108
+ }
25109
+ if (top > viewportHeight - 8) {
25110
+ top = viewportHeight - 8;
25111
+ translateY = "-100%";
25112
+ }
24814
25113
  }
24815
25114
  break;
24816
25115
  }
@@ -24875,7 +25174,7 @@ var SmartPopupComponent = /** @class */ (function () {
24875
25174
  { type: Component, args: [{
24876
25175
  selector: "rs-smart-popup",
24877
25176
  template: "<!-- \u89E6\u53D1\u5143\u7D20\u63D2\u69FD -->\r\n<ng-container #trigger>\r\n <ng-content select=\"[trigger]\"></ng-content>\r\n</ng-container>\r\n\r\n<!-- \u5F39\u7A97\u5185\u5BB9 -->\r\n<div\r\n #popup\r\n class=\"rs-smart-popup-content\"\r\n [attr.data-opened]=\"opened\"\r\n [attr.data-positioning]=\"positioning\"\r\n (wheel)=\"onPopupWheel($event)\"\r\n (scroll)=\"onPopupScroll($event)\"\r\n>\r\n <div *ngIf=\"loading\" class=\"rs-smart-popup-loading\">\r\n <div class=\"loading-spinner\"></div>\r\n </div>\r\n <div *ngIf=\"!loading\" class=\"rs-smart-popup-body\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n\r\n",
24878
- styles: [".rs-smart-popup-trigger{display:inline-block;cursor:pointer}::ng-deep #rs-smart-popup-fixed-container{width:0;height:0;z-index:100000;pointer-events:none}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content{pointer-events:auto;position:fixed;z-index:100001;padding:8px;border-radius:8px;background:#fff;box-shadow:0 0 8px 0 rgba(0,0,0,.25);min-width:200px;max-width:400px;max-height:500px;overflow:auto}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content[data-opened=no]{display:none}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content[data-opened=yes]{display:block}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content[data-opened=yes][data-positioning=yes]{display:none!important}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content[data-opened=yes][data-positioning=no]{display:block;visibility:visible;opacity:1;pointer-events:auto;-webkit-animation:.2s ease-out popup-fade-in;animation:.2s ease-out popup-fade-in}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content .rs-smart-popup-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;min-height:100px}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content .rs-smart-popup-loading .loading-spinner{width:24px;height:24px;border:3px solid #f3f3f3;border-top:3px solid #3498db;border-radius:50%;-webkit-animation:1s linear infinite spin;animation:1s linear infinite spin;margin-bottom:12px}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content .rs-smart-popup-loading .loading-text{color:#666;font-size:14px}@-webkit-keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content .rs-smart-popup-body{width:100%}@-webkit-keyframes popup-fade-in{from{opacity:0;transform:translate(var(--translate-x,0),var(--translate-y,0)) scale(.95)}to{opacity:1;transform:translate(var(--translate-x,0),var(--translate-y,0)) scale(1)}}@keyframes popup-fade-in{from{opacity:0;transform:translate(var(--translate-x,0),var(--translate-y,0)) scale(.95)}to{opacity:1;transform:translate(var(--translate-x,0),var(--translate-y,0)) scale(1)}}"]
25177
+ styles: [".rs-smart-popup-trigger{display:inline-block;cursor:pointer}::ng-deep #rs-smart-popup-fixed-container{width:0;height:0;z-index:100000;pointer-events:none}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content{pointer-events:auto;position:fixed;z-index:100001;padding:8px;border-radius:8px;background:#fff;box-shadow:0 0 8px 0 rgba(0,0,0,.25);min-width:200px;max-width:400px;max-height:500px;overflow:auto}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content[data-opened=no]{display:none}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content[data-opened=yes]{display:block}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content[data-opened=yes][data-positioning=yes]{display:none!important}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content[data-opened=yes][data-positioning=no]{display:block;visibility:visible;opacity:1;pointer-events:auto}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content .rs-smart-popup-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;min-height:100px}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content .rs-smart-popup-loading .loading-spinner{width:24px;height:24px;border:3px solid #f3f3f3;border-top:3px solid #3498db;border-radius:50%;-webkit-animation:1s linear infinite spin;animation:1s linear infinite spin;margin-bottom:12px}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content .rs-smart-popup-loading .loading-text{color:#666;font-size:14px}@-webkit-keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}::ng-deep #rs-smart-popup-fixed-container .rs-smart-popup-content .rs-smart-popup-body{width:100%}"]
24879
25178
  }] }
24880
25179
  ];
24881
25180
  /** @nocollapse */