diff --git a/packages/lexical/src/LexicalSelection.ts b/packages/lexical/src/LexicalSelection.ts index 8ffe35923c3..efa8b0dcb45 100644 --- a/packages/lexical/src/LexicalSelection.ts +++ b/packages/lexical/src/LexicalSelection.ts @@ -56,6 +56,7 @@ import { getElementByKeyOrThrow, getTextNodeOffset, INTERNAL_$isBlock, + INTERNAL_$isParentLeafElement, isSelectionCapturedInDecoratorInput, isSelectionWithinEditor, removeDOMBlockCursorElement, @@ -1220,7 +1221,10 @@ export class RangeSelection implements BaseSelection { } const firstPoint = this.isBackward() ? this.focus : this.anchor; - const firstBlock = $getAncestor(firstPoint.getNode(), INTERNAL_$isBlock)!; + const firstBlock = $getAncestor( + firstPoint.getNode(), + INTERNAL_$isParentLeafElement, + )!; const last = nodes[nodes.length - 1]!; @@ -2744,7 +2748,7 @@ function $removeTextAndSplitBlock(selection: RangeSelection): number { let node = anchor.getNode(); let offset = anchor.offset; - while (!INTERNAL_$isBlock(node)) { + while (!INTERNAL_$isParentLeafElement(node)) { [node, offset] = $splitNodeAtPoint(node, offset); } diff --git a/packages/lexical/src/LexicalUtils.ts b/packages/lexical/src/LexicalUtils.ts index 229fb3e3f13..0591b9051e6 100644 --- a/packages/lexical/src/LexicalUtils.ts +++ b/packages/lexical/src/LexicalUtils.ts @@ -1695,6 +1695,26 @@ export function INTERNAL_$isBlock( return !node.isInline() && node.canBeEmpty() !== false && isLeafElement; } +export function INTERNAL_$isParentLeafElement( + node: LexicalNode, +): node is ElementNode | DecoratorNode { + if ($isRootNode(node) || ($isDecoratorNode(node) && !node.isInline())) { + return true; + } + if (!$isElementNode(node) || $isRootOrShadowRoot(node)) { + return false; + } + + const firstChild = node.getFirstChild(); + const isLeafElement = + firstChild === null || + $isLineBreakNode(firstChild) || + $isTextNode(firstChild) || + firstChild.isInline(); + + return isLeafElement; +} + export function $getAncestor( node: LexicalNode, predicate: (ancestor: LexicalNode) => ancestor is NodeType,