diff --git a/packages/lexical-playground/src/plugins/LayoutPlugin/LayoutPlugin.tsx b/packages/lexical-playground/src/plugins/LayoutPlugin/LayoutPlugin.tsx index 3f2328da82e..dd226849e62 100644 --- a/packages/lexical-playground/src/plugins/LayoutPlugin/LayoutPlugin.tsx +++ b/packages/lexical-playground/src/plugins/LayoutPlugin/LayoutPlugin.tsx @@ -6,13 +6,7 @@ * */ -import type { - ElementNode, - LexicalCommand, - LexicalNode, - NodeKey, - NodeMutation, -} from 'lexical'; +import type {ElementNode, LexicalCommand, LexicalNode, NodeKey} from 'lexical'; import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext'; import { @@ -103,23 +97,26 @@ export function LayoutPlugin(): null { return false; }; - const $fillLayoutItemIfEmpty = (nodes: Map) => { - editor.update(() => { - nodes.forEach((_, key) => { - const layoutItem = $getNodeByKey(key) as LayoutItemNode; - if (layoutItem) { - if (layoutItem.isEmpty()) { - layoutItem.append($createParagraphNode()); - } - } - }); - }); + const $fillLayoutItemIfEmpty = (node: LayoutItemNode) => { + if (node.isEmpty()) { + node.append($createParagraphNode()); + } + }; + + const $removeIsolatedLayoutItem = (node: LayoutItemNode): boolean => { + const parent = node.getParent(); + if (!$isLayoutContainerNode(parent)) { + const children = node.getChildren(); + for (const child of children) { + node.insertBefore(child); + } + node.remove(); + return true; + } + return false; }; return mergeRegister( - // Layout item should always have a child. this function will listen - // for any empty layout item and fill it with a paragraph node - editor.registerMutationListener(LayoutItemNode, $fillLayoutItemIfEmpty), // When layout is the last child pressing down/right arrow will insert paragraph // below it to allow adding more content. It's similar what $insertBlockNode // (mainly for decorators), except it'll always be possible to continue adding @@ -208,17 +205,17 @@ export function LayoutPlugin(): null { }, COMMAND_PRIORITY_EDITOR, ), - // Structure enforcing transformers for each node type. In case nesting structure is not - // "Container > Item" it'll unwrap nodes and convert it back - // to regular content. + editor.registerNodeTransform(LayoutItemNode, (node) => { - const parent = node.getParent(); - if (!$isLayoutContainerNode(parent)) { - const children = node.getChildren(); - for (const child of children) { - node.insertBefore(child); - } - node.remove(); + // Structure enforcing transformers for each node type. In case nesting structure is not + // "Container > Item" it'll unwrap nodes and convert it back + // to regular content. + const isRemoved = $removeIsolatedLayoutItem(node); + + if (!isRemoved) { + // Layout item should always have a child. this function will listen + // for any empty layout item and fill it with a paragraph node + $fillLayoutItemIfEmpty(node); } }), editor.registerNodeTransform(LayoutContainerNode, (node) => {