@douyinfe/semi-foundation 2.95.1 → 2.96.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -74,11 +74,24 @@ export function transformText(obj: any) {
74
74
  };
75
75
  }
76
76
 
77
+ // hardBreak 来源于 Shift+Enter 软换行,或某些剪贴板 HTML 中的 <br>。
78
+ // 不处理时,单 paragraph + hardBreak 与多 paragraph 在 onContentChange 输出上会不一致(前者丢换行)。
79
+ // hardBreak originates from Shift+Enter soft line breaks, or <br> in some clipboard HTML payloads.
80
+ // Without handling, "single paragraph + hardBreak" and "multiple paragraphs"
81
+ // would yield inconsistent onContentChange output (the former drops the line break).
82
+ export function transformHardBreak() {
83
+ return {
84
+ type: 'text',
85
+ text: '\n',
86
+ };
87
+ }
88
+
77
89
  export const transformMap = new Map<string, any>([
78
90
  ['text', transformText],
79
91
  ['selectSlot', transformSelectSlot],
80
92
  ['inputSlot', transformInputSlot],
81
93
  ['skillSlot', transformSkillSlot],
94
+ ['hardBreak', transformHardBreak],
82
95
  ]);
83
96
 
84
97
  export function transformJSONResult(input: any, customTransformObj: Map<string, (obj: any) => any> = new Map()) {
@@ -229,7 +229,11 @@ class InputNumberFoundation extends BaseFoundation<InputNumberAdapter> {
229
229
  formattedNum = this.doFormat(valueAfterParser as unknown as number, false);
230
230
  }
231
231
 
232
- notifyVal = valueAfterParser;
232
+ // Fix issue #2396: In controlled mode, when input is invalid,
233
+ // we should notify the filtered value instead of the raw invalid input.
234
+ // This ensures formatter is applied consistently in both controlled and uncontrolled modes.
235
+ // When notifyVal is the filtered value, parent component will receive the correct value.
236
+ notifyVal = this.isControlled() ? formattedNum : valueAfterParser;
233
237
  }
234
238
 
235
239
  if (!this.isControlled() && (num === null || (typeof num === 'number' && !isNaN(num)))) {
@@ -1,7 +1,7 @@
1
- import { JsonViewer, JsonViewerOptions, CustomRenderRule } from '@douyinfe/semi-json-viewer-core';
1
+ import { JsonViewer, JsonViewerOptions, CustomRenderRule, TokenRenderType } from '@douyinfe/semi-json-viewer-core';
2
2
  import BaseFoundation, { DefaultAdapter } from '../base/foundation';
3
3
  import { cssClasses } from './constants';
4
- export type { JsonViewerOptions, CustomRenderRule };
4
+ export type { JsonViewerOptions, CustomRenderRule, TokenRenderType };
5
5
 
6
6
  export interface JsonViewerAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
7
7
  getEditorRef: () => HTMLElement;
@@ -17,6 +17,10 @@ export declare function transformText(obj: any): {
17
17
  type: string;
18
18
  text: any;
19
19
  };
20
+ export declare function transformHardBreak(): {
21
+ type: string;
22
+ text: string;
23
+ };
20
24
  export declare const transformMap: Map<string, any>;
21
25
  export declare function transformJSONResult(input: any, customTransformObj?: Map<string, (obj: any) => any>): any[];
22
26
  export declare function getCustomSlotAttribute(): {
@@ -9,6 +9,7 @@ exports.getContentType = getContentType;
9
9
  exports.getCustomSlotAttribute = getCustomSlotAttribute;
10
10
  exports.getSkillSlotString = getSkillSlotString;
11
11
  exports.isImageType = isImageType;
12
+ exports.transformHardBreak = transformHardBreak;
12
13
  exports.transformInputSlot = transformInputSlot;
13
14
  exports.transformJSONResult = transformJSONResult;
14
15
  exports.transformMap = void 0;
@@ -108,7 +109,18 @@ function transformText(obj) {
108
109
  text: text !== _constants.strings.ZERO_WIDTH_CHAR ? text : ''
109
110
  };
110
111
  }
111
- const transformMap = exports.transformMap = new Map([['text', transformText], ['selectSlot', transformSelectSlot], ['inputSlot', transformInputSlot], ['skillSlot', transformSkillSlot]]);
112
+ // hardBreak 来源于 Shift+Enter 软换行,或某些剪贴板 HTML 中的 <br>。
113
+ // 不处理时,单 paragraph + hardBreak 与多 paragraph 在 onContentChange 输出上会不一致(前者丢换行)。
114
+ // hardBreak originates from Shift+Enter soft line breaks, or <br> in some clipboard HTML payloads.
115
+ // Without handling, "single paragraph + hardBreak" and "multiple paragraphs"
116
+ // would yield inconsistent onContentChange output (the former drops the line break).
117
+ function transformHardBreak() {
118
+ return {
119
+ type: 'text',
120
+ text: '\n'
121
+ };
122
+ }
123
+ const transformMap = exports.transformMap = new Map([['text', transformText], ['selectSlot', transformSelectSlot], ['inputSlot', transformInputSlot], ['skillSlot', transformSkillSlot], ['hardBreak', transformHardBreak]]);
112
124
  function transformJSONResult(input) {
113
125
  let customTransformObj = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Map();
114
126
  const output = [];
@@ -194,7 +194,11 @@ class InputNumberFoundation extends _foundation.default {
194
194
  */
195
195
  formattedNum = this.doFormat(valueAfterParser, false);
196
196
  }
197
- notifyVal = valueAfterParser;
197
+ // Fix issue #2396: In controlled mode, when input is invalid,
198
+ // we should notify the filtered value instead of the raw invalid input.
199
+ // This ensures formatter is applied consistently in both controlled and uncontrolled modes.
200
+ // When notifyVal is the filtered value, parent component will receive the correct value.
201
+ notifyVal = this.isControlled() ? formattedNum : valueAfterParser;
198
202
  }
199
203
  if (!this.isControlled() && (num === null || typeof num === 'number' && !isNaN(num))) {
200
204
  this._adapter.setNumber(num);
@@ -1,6 +1,6 @@
1
- import { JsonViewer, JsonViewerOptions, CustomRenderRule } from '@douyinfe/semi-json-viewer-core';
1
+ import { JsonViewer, JsonViewerOptions, CustomRenderRule, TokenRenderType } from '@douyinfe/semi-json-viewer-core';
2
2
  import BaseFoundation, { DefaultAdapter } from '../base/foundation';
3
- export type { JsonViewerOptions, CustomRenderRule };
3
+ export type { JsonViewerOptions, CustomRenderRule, TokenRenderType };
4
4
  export interface JsonViewerAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
5
5
  getEditorRef: () => HTMLElement;
6
6
  getSearchRef: () => HTMLInputElement;
@@ -82,6 +82,9 @@ class PinCodeFoundation extends _foundation.default {
82
82
  this._adapter.updateValueList(newValueList);
83
83
  });
84
84
  this.handlePaste = (e, startInputIndex) => __awaiter(this, void 0, void 0, function* () {
85
+ // 在 Firefox 中,需要在函数开始时立即阻止默认粘贴行为
86
+ // 否则 Firefox 可能在 preventDefault 调用前就执行默认粘贴,导致双重写入
87
+ e.preventDefault();
85
88
  const textWillPaste = e.clipboardData.getData("text");
86
89
  const count = this.getProp("count");
87
90
  for (let i = startInputIndex, charIndex = 0; i < count && charIndex < textWillPaste.length; i++, charIndex++) {
@@ -92,7 +95,6 @@ class PinCodeFoundation extends _foundation.default {
92
95
  break;
93
96
  }
94
97
  }
95
- e.preventDefault();
96
98
  });
97
99
  this.handleKeyDownOnSingleInput = (e, index) => {
98
100
  const valueList = [...this.getState("valueList")];
@@ -513,106 +513,132 @@ class Tooltip extends _foundation.default {
513
513
  // left = middleX;
514
514
  // top = triggerRect.top - SPACING;
515
515
  left = isWidthOverFlow ? isTriggerNearLeft ? containerRect.left + wrapperRect.width / 2 : containerRect.right - wrapperRect.width / 2 + offsetWidth : middleX + ANO_SPACING;
516
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
516
+ // When height overflows, pin popover top to container top so it stays inside the container
517
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
517
518
  translateX = -0.5;
518
- translateY = -1;
519
+ // Drop the upward translateY when overflowing so popover does not get pushed outside the top edge
520
+ translateY = isHeightOverFlow ? 0 : -1;
519
521
  break;
520
522
  case 'topLeft':
521
523
  // left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
522
524
  // top = triggerRect.top - SPACING;
523
525
  left = isWidthOverFlow ? isWrapperWidthOverflow ? containerRect.left : containerRect.right - wrapperRect.width : pointAtCenter ? middleX - offsetXWithArrow + ANO_SPACING : triggerRect.left + ANO_SPACING;
524
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
525
- translateY = -1;
526
+ // When height overflows, pin popover top to container top so it stays inside the container
527
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
528
+ translateY = isHeightOverFlow ? 0 : -1;
526
529
  break;
527
530
  case 'topRight':
528
531
  // left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
529
532
  // top = triggerRect.top - SPACING;
530
533
  left = isWidthOverFlow ? containerRect.right + offsetWidth : pointAtCenter ? middleX + offsetXWithArrow + ANO_SPACING : triggerRect.right + ANO_SPACING;
531
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
532
- translateY = -1;
534
+ // When height overflows, pin popover top to container top so it stays inside the container
535
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
536
+ translateY = isHeightOverFlow ? 0 : -1;
533
537
  translateX = -1;
534
538
  break;
535
539
  case 'left':
536
540
  // left = triggerRect.left - SPACING;
537
541
  // top = middleY;
538
542
  // left = isWidthOverFlow? containerRect.right - SPACING : triggerRect.left - SPACING;
539
- left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
543
+ // When width overflows, pin popover left to container left so it stays inside the container
544
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
540
545
  top = isHeightOverFlow ? isTriggerNearTop ? containerRect.top + wrapperRect.height / 2 : containerRect.bottom - wrapperRect.height / 2 + offsetHeight : middleY + ANO_SPACING;
541
- translateX = -1;
546
+ // Drop the leftward translateX when overflowing so popover does not get pushed outside the left edge
547
+ translateX = isWidthOverFlow ? 0 : -1;
542
548
  translateY = -0.5;
543
549
  break;
544
550
  case 'leftTop':
545
551
  // left = triggerRect.left - SPACING;
546
552
  // top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
547
- left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
553
+ // When width overflows, pin popover left to container left so it stays inside the container
554
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
548
555
  top = isHeightOverFlow ? containerRect.top : pointAtCenter ? middleY - offsetYWithArrow + ANO_SPACING : triggerRect.top + ANO_SPACING;
549
- translateX = -1;
556
+ translateX = isWidthOverFlow ? 0 : -1;
550
557
  break;
551
558
  case 'leftBottom':
552
559
  // left = triggerRect.left - SPACING;
553
560
  // top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
554
- left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
555
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING;
556
- translateX = -1;
561
+ // When width overflows, pin popover left to container left so it stays inside the container
562
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
563
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 keeps it stuck to bottom edge)
564
+ top = isHeightOverFlow ? containerRect.bottom : pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING;
565
+ translateX = isWidthOverFlow ? 0 : -1;
557
566
  translateY = -1;
558
567
  break;
559
568
  case 'bottom':
560
569
  // left = middleX;
561
570
  // top = triggerRect.top + triggerRect.height + SPACING;
562
571
  left = isWidthOverFlow ? isTriggerNearLeft ? containerRect.left + wrapperRect.width / 2 : containerRect.right - wrapperRect.width / 2 + offsetWidth : middleX + ANO_SPACING;
563
- top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
572
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
573
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.top + triggerRect.height + SPACING;
564
574
  translateX = -0.5;
575
+ translateY = isHeightOverFlow ? -1 : 0;
565
576
  break;
566
577
  case 'bottomLeft':
567
578
  // left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
568
579
  // top = triggerRect.bottom + SPACING;
569
580
  left = isWidthOverFlow ? isWrapperWidthOverflow ? containerRect.left : containerRect.right - wrapperRect.width : pointAtCenter ? middleX - offsetXWithArrow + ANO_SPACING : triggerRect.left + ANO_SPACING;
570
- top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
581
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
582
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.top + triggerRect.height + SPACING;
583
+ translateY = isHeightOverFlow ? -1 : 0;
571
584
  break;
572
585
  case 'bottomRight':
573
586
  // left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
574
587
  // top = triggerRect.bottom + SPACING;
575
588
  left = isWidthOverFlow ? containerRect.right + offsetWidth : pointAtCenter ? middleX + offsetXWithArrow + ANO_SPACING : triggerRect.right + ANO_SPACING;
576
- top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
589
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
590
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.top + triggerRect.height + SPACING;
577
591
  translateX = -1;
592
+ translateY = isHeightOverFlow ? -1 : 0;
578
593
  break;
579
594
  case 'right':
580
595
  // left = triggerRect.right + SPACING;
581
596
  // top = middleY;
582
- left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
597
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
598
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
583
599
  top = isHeightOverFlow ? isTriggerNearTop ? containerRect.top + wrapperRect.height / 2 : containerRect.bottom - wrapperRect.height / 2 + offsetHeight : middleY + ANO_SPACING;
600
+ translateX = isWidthOverFlow ? -1 : 0;
584
601
  translateY = -0.5;
585
602
  break;
586
603
  case 'rightTop':
587
604
  // left = triggerRect.right + SPACING;
588
605
  // top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
589
- left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
606
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
607
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
590
608
  top = isHeightOverFlow ? containerRect.top : pointAtCenter ? middleY - offsetYWithArrow + ANO_SPACING : triggerRect.top + ANO_SPACING;
609
+ translateX = isWidthOverFlow ? -1 : 0;
591
610
  break;
592
611
  case 'rightBottom':
593
612
  // left = triggerRect.right + SPACING;
594
613
  // top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
595
- left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
596
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING;
614
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
615
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
616
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 keeps it stuck to bottom edge)
617
+ top = isHeightOverFlow ? containerRect.bottom : pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING;
618
+ translateX = isWidthOverFlow ? -1 : 0;
597
619
  translateY = -1;
598
620
  break;
599
621
  case 'leftTopOver':
600
- left = triggerRect.left - SPACING;
601
- top = triggerRect.top - SPACING;
622
+ // When width overflows, pin popover left to container left (translateX=0 keeps default)
623
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
624
+ // When height overflows, pin popover top to container top (translateY=0 keeps default)
625
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
602
626
  break;
603
627
  case 'rightTopOver':
604
- left = triggerRect.right + SPACING;
605
- top = triggerRect.top - SPACING;
628
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
629
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
630
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
606
631
  translateX = -1;
607
632
  break;
608
633
  case 'leftBottomOver':
609
- left = triggerRect.left - SPACING;
610
- top = triggerRect.bottom + SPACING;
634
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
635
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
636
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.bottom + SPACING;
611
637
  translateY = -1;
612
638
  break;
613
639
  case 'rightBottomOver':
614
- left = triggerRect.right + SPACING;
615
- top = triggerRect.bottom + SPACING;
640
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
641
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.bottom + SPACING;
616
642
  translateX = -1;
617
643
  translateY = -1;
618
644
  break;
@@ -276,6 +276,12 @@ class VideoPlayerFoundation extends _foundation.default {
276
276
  video.addEventListener('loadeddata', handleLoaded);
277
277
  }
278
278
  handleBodyKeyDown(e) {
279
+ const videoWrapper = this._adapter.getVideoWrapper();
280
+ // Only respond to keyboard events when focus is within the video player
281
+ // This prevents interference with other interactive elements on the page
282
+ if (videoWrapper && !videoWrapper.contains(document.activeElement)) {
283
+ return;
284
+ }
279
285
  const {
280
286
  currentTime,
281
287
  volume
@@ -17,6 +17,10 @@ export declare function transformText(obj: any): {
17
17
  type: string;
18
18
  text: any;
19
19
  };
20
+ export declare function transformHardBreak(): {
21
+ type: string;
22
+ text: string;
23
+ };
20
24
  export declare const transformMap: Map<string, any>;
21
25
  export declare function transformJSONResult(input: any, customTransformObj?: Map<string, (obj: any) => any>): any[];
22
26
  export declare function getCustomSlotAttribute(): {
@@ -91,7 +91,18 @@ export function transformText(obj) {
91
91
  text: text !== strings.ZERO_WIDTH_CHAR ? text : ''
92
92
  };
93
93
  }
94
- export const transformMap = new Map([['text', transformText], ['selectSlot', transformSelectSlot], ['inputSlot', transformInputSlot], ['skillSlot', transformSkillSlot]]);
94
+ // hardBreak 来源于 Shift+Enter 软换行,或某些剪贴板 HTML 中的 <br>。
95
+ // 不处理时,单 paragraph + hardBreak 与多 paragraph 在 onContentChange 输出上会不一致(前者丢换行)。
96
+ // hardBreak originates from Shift+Enter soft line breaks, or <br> in some clipboard HTML payloads.
97
+ // Without handling, "single paragraph + hardBreak" and "multiple paragraphs"
98
+ // would yield inconsistent onContentChange output (the former drops the line break).
99
+ export function transformHardBreak() {
100
+ return {
101
+ type: 'text',
102
+ text: '\n'
103
+ };
104
+ }
105
+ export const transformMap = new Map([['text', transformText], ['selectSlot', transformSelectSlot], ['inputSlot', transformInputSlot], ['skillSlot', transformSkillSlot], ['hardBreak', transformHardBreak]]);
95
106
  export function transformJSONResult(input) {
96
107
  let customTransformObj = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Map();
97
108
  const output = [];
@@ -187,7 +187,11 @@ class InputNumberFoundation extends BaseFoundation {
187
187
  */
188
188
  formattedNum = this.doFormat(valueAfterParser, false);
189
189
  }
190
- notifyVal = valueAfterParser;
190
+ // Fix issue #2396: In controlled mode, when input is invalid,
191
+ // we should notify the filtered value instead of the raw invalid input.
192
+ // This ensures formatter is applied consistently in both controlled and uncontrolled modes.
193
+ // When notifyVal is the filtered value, parent component will receive the correct value.
194
+ notifyVal = this.isControlled() ? formattedNum : valueAfterParser;
191
195
  }
192
196
  if (!this.isControlled() && (num === null || typeof num === 'number' && !isNaN(num))) {
193
197
  this._adapter.setNumber(num);
@@ -1,6 +1,6 @@
1
- import { JsonViewer, JsonViewerOptions, CustomRenderRule } from '@douyinfe/semi-json-viewer-core';
1
+ import { JsonViewer, JsonViewerOptions, CustomRenderRule, TokenRenderType } from '@douyinfe/semi-json-viewer-core';
2
2
  import BaseFoundation, { DefaultAdapter } from '../base/foundation';
3
- export type { JsonViewerOptions, CustomRenderRule };
3
+ export type { JsonViewerOptions, CustomRenderRule, TokenRenderType };
4
4
  export interface JsonViewerAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
5
5
  getEditorRef: () => HTMLElement;
6
6
  getSearchRef: () => HTMLInputElement;
@@ -75,6 +75,9 @@ class PinCodeFoundation extends BaseFoundation {
75
75
  this._adapter.updateValueList(newValueList);
76
76
  });
77
77
  this.handlePaste = (e, startInputIndex) => __awaiter(this, void 0, void 0, function* () {
78
+ // 在 Firefox 中,需要在函数开始时立即阻止默认粘贴行为
79
+ // 否则 Firefox 可能在 preventDefault 调用前就执行默认粘贴,导致双重写入
80
+ e.preventDefault();
78
81
  const textWillPaste = e.clipboardData.getData("text");
79
82
  const count = this.getProp("count");
80
83
  for (let i = startInputIndex, charIndex = 0; i < count && charIndex < textWillPaste.length; i++, charIndex++) {
@@ -85,7 +88,6 @@ class PinCodeFoundation extends BaseFoundation {
85
88
  break;
86
89
  }
87
90
  }
88
- e.preventDefault();
89
91
  });
90
92
  this.handleKeyDownOnSingleInput = (e, index) => {
91
93
  const valueList = [...this.getState("valueList")];
@@ -506,106 +506,132 @@ export default class Tooltip extends BaseFoundation {
506
506
  // left = middleX;
507
507
  // top = triggerRect.top - SPACING;
508
508
  left = isWidthOverFlow ? isTriggerNearLeft ? containerRect.left + wrapperRect.width / 2 : containerRect.right - wrapperRect.width / 2 + offsetWidth : middleX + ANO_SPACING;
509
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
509
+ // When height overflows, pin popover top to container top so it stays inside the container
510
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
510
511
  translateX = -0.5;
511
- translateY = -1;
512
+ // Drop the upward translateY when overflowing so popover does not get pushed outside the top edge
513
+ translateY = isHeightOverFlow ? 0 : -1;
512
514
  break;
513
515
  case 'topLeft':
514
516
  // left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
515
517
  // top = triggerRect.top - SPACING;
516
518
  left = isWidthOverFlow ? isWrapperWidthOverflow ? containerRect.left : containerRect.right - wrapperRect.width : pointAtCenter ? middleX - offsetXWithArrow + ANO_SPACING : triggerRect.left + ANO_SPACING;
517
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
518
- translateY = -1;
519
+ // When height overflows, pin popover top to container top so it stays inside the container
520
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
521
+ translateY = isHeightOverFlow ? 0 : -1;
519
522
  break;
520
523
  case 'topRight':
521
524
  // left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
522
525
  // top = triggerRect.top - SPACING;
523
526
  left = isWidthOverFlow ? containerRect.right + offsetWidth : pointAtCenter ? middleX + offsetXWithArrow + ANO_SPACING : triggerRect.right + ANO_SPACING;
524
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
525
- translateY = -1;
527
+ // When height overflows, pin popover top to container top so it stays inside the container
528
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
529
+ translateY = isHeightOverFlow ? 0 : -1;
526
530
  translateX = -1;
527
531
  break;
528
532
  case 'left':
529
533
  // left = triggerRect.left - SPACING;
530
534
  // top = middleY;
531
535
  // left = isWidthOverFlow? containerRect.right - SPACING : triggerRect.left - SPACING;
532
- left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
536
+ // When width overflows, pin popover left to container left so it stays inside the container
537
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
533
538
  top = isHeightOverFlow ? isTriggerNearTop ? containerRect.top + wrapperRect.height / 2 : containerRect.bottom - wrapperRect.height / 2 + offsetHeight : middleY + ANO_SPACING;
534
- translateX = -1;
539
+ // Drop the leftward translateX when overflowing so popover does not get pushed outside the left edge
540
+ translateX = isWidthOverFlow ? 0 : -1;
535
541
  translateY = -0.5;
536
542
  break;
537
543
  case 'leftTop':
538
544
  // left = triggerRect.left - SPACING;
539
545
  // top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
540
- left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
546
+ // When width overflows, pin popover left to container left so it stays inside the container
547
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
541
548
  top = isHeightOverFlow ? containerRect.top : pointAtCenter ? middleY - offsetYWithArrow + ANO_SPACING : triggerRect.top + ANO_SPACING;
542
- translateX = -1;
549
+ translateX = isWidthOverFlow ? 0 : -1;
543
550
  break;
544
551
  case 'leftBottom':
545
552
  // left = triggerRect.left - SPACING;
546
553
  // top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
547
- left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
548
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING;
549
- translateX = -1;
554
+ // When width overflows, pin popover left to container left so it stays inside the container
555
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
556
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 keeps it stuck to bottom edge)
557
+ top = isHeightOverFlow ? containerRect.bottom : pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING;
558
+ translateX = isWidthOverFlow ? 0 : -1;
550
559
  translateY = -1;
551
560
  break;
552
561
  case 'bottom':
553
562
  // left = middleX;
554
563
  // top = triggerRect.top + triggerRect.height + SPACING;
555
564
  left = isWidthOverFlow ? isTriggerNearLeft ? containerRect.left + wrapperRect.width / 2 : containerRect.right - wrapperRect.width / 2 + offsetWidth : middleX + ANO_SPACING;
556
- top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
565
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
566
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.top + triggerRect.height + SPACING;
557
567
  translateX = -0.5;
568
+ translateY = isHeightOverFlow ? -1 : 0;
558
569
  break;
559
570
  case 'bottomLeft':
560
571
  // left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
561
572
  // top = triggerRect.bottom + SPACING;
562
573
  left = isWidthOverFlow ? isWrapperWidthOverflow ? containerRect.left : containerRect.right - wrapperRect.width : pointAtCenter ? middleX - offsetXWithArrow + ANO_SPACING : triggerRect.left + ANO_SPACING;
563
- top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
574
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
575
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.top + triggerRect.height + SPACING;
576
+ translateY = isHeightOverFlow ? -1 : 0;
564
577
  break;
565
578
  case 'bottomRight':
566
579
  // left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
567
580
  // top = triggerRect.bottom + SPACING;
568
581
  left = isWidthOverFlow ? containerRect.right + offsetWidth : pointAtCenter ? middleX + offsetXWithArrow + ANO_SPACING : triggerRect.right + ANO_SPACING;
569
- top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
582
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
583
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.top + triggerRect.height + SPACING;
570
584
  translateX = -1;
585
+ translateY = isHeightOverFlow ? -1 : 0;
571
586
  break;
572
587
  case 'right':
573
588
  // left = triggerRect.right + SPACING;
574
589
  // top = middleY;
575
- left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
590
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
591
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
576
592
  top = isHeightOverFlow ? isTriggerNearTop ? containerRect.top + wrapperRect.height / 2 : containerRect.bottom - wrapperRect.height / 2 + offsetHeight : middleY + ANO_SPACING;
593
+ translateX = isWidthOverFlow ? -1 : 0;
577
594
  translateY = -0.5;
578
595
  break;
579
596
  case 'rightTop':
580
597
  // left = triggerRect.right + SPACING;
581
598
  // top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
582
- left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
599
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
600
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
583
601
  top = isHeightOverFlow ? containerRect.top : pointAtCenter ? middleY - offsetYWithArrow + ANO_SPACING : triggerRect.top + ANO_SPACING;
602
+ translateX = isWidthOverFlow ? -1 : 0;
584
603
  break;
585
604
  case 'rightBottom':
586
605
  // left = triggerRect.right + SPACING;
587
606
  // top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
588
- left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
589
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING;
607
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
608
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
609
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 keeps it stuck to bottom edge)
610
+ top = isHeightOverFlow ? containerRect.bottom : pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING;
611
+ translateX = isWidthOverFlow ? -1 : 0;
590
612
  translateY = -1;
591
613
  break;
592
614
  case 'leftTopOver':
593
- left = triggerRect.left - SPACING;
594
- top = triggerRect.top - SPACING;
615
+ // When width overflows, pin popover left to container left (translateX=0 keeps default)
616
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
617
+ // When height overflows, pin popover top to container top (translateY=0 keeps default)
618
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
595
619
  break;
596
620
  case 'rightTopOver':
597
- left = triggerRect.right + SPACING;
598
- top = triggerRect.top - SPACING;
621
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
622
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
623
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
599
624
  translateX = -1;
600
625
  break;
601
626
  case 'leftBottomOver':
602
- left = triggerRect.left - SPACING;
603
- top = triggerRect.bottom + SPACING;
627
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
628
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
629
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.bottom + SPACING;
604
630
  translateY = -1;
605
631
  break;
606
632
  case 'rightBottomOver':
607
- left = triggerRect.right + SPACING;
608
- top = triggerRect.bottom + SPACING;
633
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
634
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.bottom + SPACING;
609
635
  translateX = -1;
610
636
  translateY = -1;
611
637
  break;
@@ -269,6 +269,12 @@ export default class VideoPlayerFoundation extends BaseFoundation {
269
269
  video.addEventListener('loadeddata', handleLoaded);
270
270
  }
271
271
  handleBodyKeyDown(e) {
272
+ const videoWrapper = this._adapter.getVideoWrapper();
273
+ // Only respond to keyboard events when focus is within the video player
274
+ // This prevents interference with other interactive elements on the page
275
+ if (videoWrapper && !videoWrapper.contains(document.activeElement)) {
276
+ return;
277
+ }
272
278
  const {
273
279
  currentTime,
274
280
  volume
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@douyinfe/semi-foundation",
3
- "version": "2.95.1",
3
+ "version": "2.96.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "clean": "rimraf lib",
@@ -14210,8 +14210,8 @@
14210
14210
  }
14211
14211
  },
14212
14212
  "dependencies": {
14213
- "@douyinfe/semi-animation": "2.95.1",
14214
- "@douyinfe/semi-json-viewer-core": "2.95.1",
14213
+ "@douyinfe/semi-animation": "2.96.0",
14214
+ "@douyinfe/semi-json-viewer-core": "2.96.0",
14215
14215
  "@mdx-js/mdx": "^3.0.1",
14216
14216
  "async-validator": "^3.5.0",
14217
14217
  "classnames": "^2.2.6",
@@ -14232,7 +14232,7 @@
14232
14232
  "*.scss",
14233
14233
  "*.css"
14234
14234
  ],
14235
- "gitHead": "2a3f86116f503105a95f32045127b82a4f03c08d",
14235
+ "gitHead": "25977da675cef6d8dd70e92531b2441030991952",
14236
14236
  "devDependencies": {
14237
14237
  "@babel/plugin-transform-runtime": "^7.15.8",
14238
14238
  "@babel/preset-env": "^7.15.8",
@@ -83,6 +83,10 @@ class PinCodeFoundation<P = Record<string, any>, S = Record<string, any>> extend
83
83
  }
84
84
 
85
85
  handlePaste = async (e: ClipboardEvent, startInputIndex: number)=>{
86
+ // 在 Firefox 中,需要在函数开始时立即阻止默认粘贴行为
87
+ // 否则 Firefox 可能在 preventDefault 调用前就执行默认粘贴,导致双重写入
88
+ e.preventDefault();
89
+
86
90
  const textWillPaste = e.clipboardData.getData("text");
87
91
  const count = this.getProp("count");
88
92
  for (let i = startInputIndex, charIndex = 0;i < count && charIndex < textWillPaste.length;i++, charIndex++) {
@@ -93,7 +97,6 @@ class PinCodeFoundation<P = Record<string, any>, S = Record<string, any>> extend
93
97
  break;
94
98
  }
95
99
  }
96
- e.preventDefault();
97
100
  }
98
101
 
99
102
  handleKeyDownOnSingleInput = (e: KeyboardEvent, index: number)=>{
@@ -490,106 +490,132 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
490
490
  // left = middleX;
491
491
  // top = triggerRect.top - SPACING;
492
492
  left = isWidthOverFlow ? (isTriggerNearLeft ? containerRect.left + wrapperRect.width / 2 : containerRect.right - wrapperRect.width / 2 + offsetWidth) : middleX + ANO_SPACING;
493
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
493
+ // When height overflows, pin popover top to container top so it stays inside the container
494
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
494
495
  translateX = -0.5;
495
- translateY = -1;
496
+ // Drop the upward translateY when overflowing so popover does not get pushed outside the top edge
497
+ translateY = isHeightOverFlow ? 0 : -1;
496
498
  break;
497
499
  case 'topLeft':
498
500
  // left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
499
501
  // top = triggerRect.top - SPACING;
500
502
  left = isWidthOverFlow ? (isWrapperWidthOverflow ? containerRect.left : containerRect.right - wrapperRect.width ) : (pointAtCenter ? middleX - offsetXWithArrow + ANO_SPACING : triggerRect.left + ANO_SPACING);
501
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
502
- translateY = -1;
503
+ // When height overflows, pin popover top to container top so it stays inside the container
504
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
505
+ translateY = isHeightOverFlow ? 0 : -1;
503
506
  break;
504
507
  case 'topRight':
505
508
  // left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
506
509
  // top = triggerRect.top - SPACING;
507
510
  left = isWidthOverFlow ? containerRect.right + offsetWidth : (pointAtCenter ? middleX + offsetXWithArrow + ANO_SPACING : triggerRect.right + ANO_SPACING);
508
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : triggerRect.top - SPACING;
509
- translateY = -1;
511
+ // When height overflows, pin popover top to container top so it stays inside the container
512
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
513
+ translateY = isHeightOverFlow ? 0 : -1;
510
514
  translateX = -1;
511
515
  break;
512
516
  case 'left':
513
517
  // left = triggerRect.left - SPACING;
514
518
  // top = middleY;
515
519
  // left = isWidthOverFlow? containerRect.right - SPACING : triggerRect.left - SPACING;
516
- left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
520
+ // When width overflows, pin popover left to container left so it stays inside the container
521
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
517
522
  top = isHeightOverFlow ? (isTriggerNearTop ? containerRect.top + wrapperRect.height / 2 : containerRect.bottom - wrapperRect.height / 2 + offsetHeight) : middleY + ANO_SPACING;
518
- translateX = -1;
523
+ // Drop the leftward translateX when overflowing so popover does not get pushed outside the left edge
524
+ translateX = isWidthOverFlow ? 0 : -1;
519
525
  translateY = -0.5;
520
526
  break;
521
527
  case 'leftTop':
522
528
  // left = triggerRect.left - SPACING;
523
529
  // top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
524
- left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
530
+ // When width overflows, pin popover left to container left so it stays inside the container
531
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
525
532
  top = isHeightOverFlow ? containerRect.top : (pointAtCenter ? middleY - offsetYWithArrow + ANO_SPACING : triggerRect.top + ANO_SPACING);
526
- translateX = -1;
533
+ translateX = isWidthOverFlow ? 0 : -1;
527
534
  break;
528
535
  case 'leftBottom':
529
536
  // left = triggerRect.left - SPACING;
530
537
  // top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
531
- left = isWidthOverFlow ? containerRect.right + offsetWidth - SPACING + offsetXWithArrow : triggerRect.left - SPACING;
532
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : (pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING);
533
- translateX = -1;
538
+ // When width overflows, pin popover left to container left so it stays inside the container
539
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
540
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 keeps it stuck to bottom edge)
541
+ top = isHeightOverFlow ? containerRect.bottom : (pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING);
542
+ translateX = isWidthOverFlow ? 0 : -1;
534
543
  translateY = -1;
535
544
  break;
536
545
  case 'bottom':
537
546
  // left = middleX;
538
547
  // top = triggerRect.top + triggerRect.height + SPACING;
539
548
  left = isWidthOverFlow ? (isTriggerNearLeft ? containerRect.left + wrapperRect.width / 2 : containerRect.right - wrapperRect.width / 2 + offsetWidth) : middleX + ANO_SPACING;
540
- top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
549
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
550
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.top + triggerRect.height + SPACING;
541
551
  translateX = -0.5;
552
+ translateY = isHeightOverFlow ? -1 : 0;
542
553
  break;
543
554
  case 'bottomLeft':
544
555
  // left = pointAtCenter ? middleX - offsetXWithArrow : triggerRect.left;
545
556
  // top = triggerRect.bottom + SPACING;
546
557
  left = isWidthOverFlow ? (isWrapperWidthOverflow ? containerRect.left : containerRect.right - wrapperRect.width ) : (pointAtCenter ? middleX - offsetXWithArrow + ANO_SPACING : triggerRect.left + ANO_SPACING);
547
- top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
558
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
559
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.top + triggerRect.height + SPACING;
560
+ translateY = isHeightOverFlow ? -1 : 0;
548
561
  break;
549
562
  case 'bottomRight':
550
563
  // left = pointAtCenter ? middleX + offsetXWithArrow : triggerRect.right;
551
564
  // top = triggerRect.bottom + SPACING;
552
565
  left = isWidthOverFlow ? containerRect.right + offsetWidth : (pointAtCenter ? middleX + offsetXWithArrow + ANO_SPACING : triggerRect.right + ANO_SPACING);
553
- top = isHeightOverFlow ? containerRect.top + offsetYWithArrow - SPACING : triggerRect.top + triggerRect.height + SPACING;
566
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
567
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.top + triggerRect.height + SPACING;
554
568
  translateX = -1;
569
+ translateY = isHeightOverFlow ? -1 : 0;
555
570
  break;
556
571
  case 'right':
557
572
  // left = triggerRect.right + SPACING;
558
573
  // top = middleY;
559
- left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
574
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
575
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
560
576
  top = isHeightOverFlow ? (isTriggerNearTop ? containerRect.top + wrapperRect.height / 2 : containerRect.bottom - wrapperRect.height / 2 + offsetHeight) : middleY + ANO_SPACING;
577
+ translateX = isWidthOverFlow ? -1 : 0;
561
578
  translateY = -0.5;
562
579
  break;
563
580
  case 'rightTop':
564
581
  // left = triggerRect.right + SPACING;
565
582
  // top = pointAtCenter ? middleY - offsetYWithArrow : triggerRect.top;
566
- left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
583
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
584
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
567
585
  top = isHeightOverFlow ? containerRect.top : (pointAtCenter ? middleY - offsetYWithArrow + ANO_SPACING : triggerRect.top + ANO_SPACING);
586
+ translateX = isWidthOverFlow ? -1 : 0;
568
587
  break;
569
588
  case 'rightBottom':
570
589
  // left = triggerRect.right + SPACING;
571
590
  // top = pointAtCenter ? middleY + offsetYWithArrow : triggerRect.bottom;
572
- left = isWidthOverFlow ? containerRect.left - SPACING + offsetXWithArrow : triggerRect.right + SPACING;
573
- top = isHeightOverFlow ? containerRect.bottom + offsetHeight : (pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING);
591
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
592
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
593
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 keeps it stuck to bottom edge)
594
+ top = isHeightOverFlow ? containerRect.bottom : (pointAtCenter ? middleY + offsetYWithArrow + ANO_SPACING : triggerRect.bottom + ANO_SPACING);
595
+ translateX = isWidthOverFlow ? -1 : 0;
574
596
  translateY = -1;
575
597
  break;
576
598
  case 'leftTopOver':
577
- left = triggerRect.left - SPACING;
578
- top = triggerRect.top - SPACING;
599
+ // When width overflows, pin popover left to container left (translateX=0 keeps default)
600
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
601
+ // When height overflows, pin popover top to container top (translateY=0 keeps default)
602
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
579
603
  break;
580
604
  case 'rightTopOver':
581
- left = triggerRect.right + SPACING;
582
- top = triggerRect.top - SPACING;
605
+ // When width overflows, pin popover right to container right (translateX=-1 stretches it leftward inside the container)
606
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
607
+ top = isHeightOverFlow ? containerRect.top : triggerRect.top - SPACING;
583
608
  translateX = -1;
584
609
  break;
585
610
  case 'leftBottomOver':
586
- left = triggerRect.left - SPACING;
587
- top = triggerRect.bottom + SPACING;
611
+ left = isWidthOverFlow ? containerRect.left : triggerRect.left - SPACING;
612
+ // When height overflows, pin popover bottom to container bottom (translateY=-1 stretches it upward inside the container)
613
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.bottom + SPACING;
588
614
  translateY = -1;
589
615
  break;
590
616
  case 'rightBottomOver':
591
- left = triggerRect.right + SPACING;
592
- top = triggerRect.bottom + SPACING;
617
+ left = isWidthOverFlow ? containerRect.right : triggerRect.right + SPACING;
618
+ top = isHeightOverFlow ? containerRect.bottom : triggerRect.bottom + SPACING;
593
619
  translateX = -1;
594
620
  translateY = -1;
595
621
  break;
@@ -325,6 +325,14 @@ export default class VideoPlayerFoundation<P = Record<string, any>, S = Record<s
325
325
  }
326
326
 
327
327
  handleBodyKeyDown(e: KeyboardEvent) {
328
+ const videoWrapper = this._adapter.getVideoWrapper();
329
+
330
+ // Only respond to keyboard events when focus is within the video player
331
+ // This prevents interference with other interactive elements on the page
332
+ if (videoWrapper && !videoWrapper.contains(document.activeElement)) {
333
+ return;
334
+ }
335
+
328
336
  const { currentTime, volume } = this.getStates();
329
337
  const { seekTime } = this.getProps();
330
338
  if (e.key === ' ') {