fix(editor): auto focus between tab switch (#12572)

Closes: BS-2290

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **Bug Fixes**
  - Improved focus behavior when switching between tabs to prevent unwanted automatic focusing of the content-editable area.
  - Enhanced selection clearing to avoid unnecessary blurring when the main editable element is already focused.
  - Refined focus checks in tests to specifically target contenteditable elements, ensuring more accurate validation of focus behavior.
  - Adjusted test assertions for block selection to be less strict and removed redundant blur operations for smoother test execution.
  - Updated toolbar dropdown closing method to use keyboard interaction for better reliability.
- **New Features**
  - Added a recoverable property to selection types, improving selection state management and recovery.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Saul-Mirone
2025-05-27 13:38:02 +00:00
parent dc7cd0487b
commit 7eb6b268a6
9 changed files with 39 additions and 12 deletions

View File

@@ -279,6 +279,21 @@ export class RangeBinding {
selection.is(TextSelection)
) ?? null;
if (!text && selections.length > 0) {
const hasRecoverable = selections.find(selection => {
const selectionConstructor =
selection.constructor as typeof BaseSelection;
return selectionConstructor.recoverable;
});
if (!hasRecoverable) {
// prevent focus to top-level content-editable element
// if the browser focus to the top-level content-editable element,
// when switching between tabs,
// the browser will focus to the top-level content-editable element
this.host.focus({ preventScroll: true });
}
}
if (text === this._prevTextSelection) {
return;
}

View File

@@ -33,10 +33,17 @@ export class RangeManager extends LifeCycleWatcher {
if (!selection) return;
selection.removeAllRanges();
if (document.activeElement === this.std.host) {
return;
}
const topContenteditableElement = this.std.host.querySelector(
'[contenteditable="true"]'
);
if (topContenteditableElement instanceof HTMLElement) {
if (
topContenteditableElement instanceof HTMLElement &&
topContenteditableElement.contains(document.activeElement)
) {
topContenteditableElement.blur();
}
if (document.activeElement instanceof HTMLElement) {

View File

@@ -13,6 +13,8 @@ export class SurfaceSelection extends BaseSelection {
static override type = 'surface';
static override recoverable = true;
readonly editing: boolean;
readonly elements: string[];

View File

@@ -36,6 +36,8 @@ export class TextSelection extends BaseSelection {
static override type = 'text';
static override recoverable = true;
from: TextRangePoint;
reverse: boolean;