Skip to content

Commit

Permalink
Fix forward word deletion destructing element nodes (facebook#5625)
Browse files Browse the repository at this point in the history
  • Loading branch information
ivailop7 authored Mar 7, 2024
1 parent 9f84191 commit 4eb91a8
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 18 deletions.
4 changes: 4 additions & 0 deletions packages/lexical-playground/src/nodes/LayoutContainerNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export class LayoutContainerNode extends ElementNode {
return $createLayoutContainerNode(json.templateColumns);
}

isShadowRoot(): boolean {
return true;
}

canBeEmpty(): boolean {
return false;
}
Expand Down
58 changes: 40 additions & 18 deletions packages/lexical/src/LexicalSelection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1537,6 +1537,39 @@ export class RangeSelection implements BaseSelection {
}
}
}
/**
* Helper for handling forward character and word deletion that prevents element nodes
* like a table, columns layout being destroyed
*
* @param anchor the anchor
* @param anchorNode the anchor node in the selection
* @param isBackward whether or not selection is backwards
*/
forwardDeletion(
anchor: PointType,
anchorNode: TextNode | ElementNode,
isBackward: boolean,
): boolean {
if (
!isBackward &&
// Delete forward handle case
((anchor.type === 'element' &&
$isElementNode(anchorNode) &&
anchor.offset === anchorNode.getChildrenSize()) ||
(anchor.type === 'text' &&
anchor.offset === anchorNode.getTextContentSize()))
) {
const parent = anchorNode.getParent();
const nextSibling =
anchorNode.getNextSibling() ||
(parent === null ? null : parent.getNextSibling());

if ($isElementNode(nextSibling) && nextSibling.isShadowRoot()) {
return true;
}
}
return false;
}

/**
* Performs one logical character deletion operation on the EditorState based on the current Selection.
Expand All @@ -1548,27 +1581,13 @@ export class RangeSelection implements BaseSelection {
const wasCollapsed = this.isCollapsed();
if (this.isCollapsed()) {
const anchor = this.anchor;
const focus = this.focus;
let anchorNode: TextNode | ElementNode | null = anchor.getNode();
if (
!isBackward &&
// Delete forward handle case
((anchor.type === 'element' &&
$isElementNode(anchorNode) &&
anchor.offset === anchorNode.getChildrenSize()) ||
(anchor.type === 'text' &&
anchor.offset === anchorNode.getTextContentSize()))
) {
const parent = anchorNode.getParent();
const nextSibling =
anchorNode.getNextSibling() ||
(parent === null ? null : parent.getNextSibling());

if ($isElementNode(nextSibling) && nextSibling.isShadowRoot()) {
return;
}
if (this.forwardDeletion(anchor, anchorNode, isBackward)) {
return;
}

// Handle the deletion around decorators.
const focus = this.focus;
const possibleNode = $getAdjacentNode(focus, isBackward);
if ($isDecoratorNode(possibleNode) && !possibleNode.isIsolated()) {
// Make it possible to move selection from range selection to
Expand Down Expand Up @@ -1689,6 +1708,9 @@ export class RangeSelection implements BaseSelection {
*/
deleteWord(isBackward: boolean): void {
if (this.isCollapsed()) {
const anchor = this.anchor;
const anchorNode: TextNode | ElementNode | null = anchor.getNode();
if (this.forwardDeletion(anchor, anchorNode, isBackward)) return;
this.modify('extend', isBackward, 'word');
}
this.removeText();
Expand Down

0 comments on commit 4eb91a8

Please sign in to comment.