diff --git a/resources/js/wysiwyg/lexical/core/LexicalNode.ts b/resources/js/wysiwyg/lexical/core/LexicalNode.ts index 7306e6bca..e54cd1066 100644 --- a/resources/js/wysiwyg/lexical/core/LexicalNode.ts +++ b/resources/js/wysiwyg/lexical/core/LexicalNode.ts @@ -48,6 +48,7 @@ import { internalMarkNodeAsDirty, removeFromParent, } from './LexicalUtils'; +import {$insertAndSelectNewEmptyAdjacentNode} from "../../utils/nodes"; export type NodeMap = Map; @@ -1130,7 +1131,7 @@ export class LexicalNode { const prevSibling = this.getPreviousSibling(); const parent = this.getParentOrThrow(); if (prevSibling === null) { - return parent.select(0, 0); + return $insertAndSelectNewEmptyAdjacentNode(this, false); } if ($isElementNode(prevSibling)) { return prevSibling.select(); @@ -1152,7 +1153,7 @@ export class LexicalNode { const nextSibling = this.getNextSibling(); const parent = this.getParentOrThrow(); if (nextSibling === null) { - return parent.select(); + return $insertAndSelectNewEmptyAdjacentNode(this, true); } if ($isElementNode(nextSibling)) { return nextSibling.select(0, 0); diff --git a/resources/js/wysiwyg/lexical/core/LexicalSelection.ts b/resources/js/wysiwyg/lexical/core/LexicalSelection.ts index db18cfc4a..297286a4b 100644 --- a/resources/js/wysiwyg/lexical/core/LexicalSelection.ts +++ b/resources/js/wysiwyg/lexical/core/LexicalSelection.ts @@ -17,7 +17,7 @@ import invariant from 'lexical/shared/invariant'; import { $createLineBreakNode, $createParagraphNode, - $createTextNode, + $createTextNode, $getNearestNodeFromDOMNode, $isDecoratorNode, $isElementNode, $isLineBreakNode, @@ -63,6 +63,7 @@ import { toggleTextFormatType, } from './LexicalUtils'; import {$createTabNode, $isTabNode} from './nodes/LexicalTabNode'; +import {$selectSingleNode} from "../../utils/selection"; export type TextPointType = { _selection: BaseSelection; @@ -2568,6 +2569,17 @@ export function updateDOMSelection( } if (!$isRangeSelection(nextSelection)) { + + // If the DOM selection enters a decorator node update the selection to a single node selection + if (activeElement !== null && domSelection.isCollapsed && focusDOMNode instanceof Node) { + const node = $getNearestNodeFromDOMNode(focusDOMNode); + if ($isDecoratorNode(node)) { + domSelection.removeAllRanges(); + $selectSingleNode(node); + return; + } + } + // We don't remove selection if the prevSelection is null because // of editor.setRootElement(). If this occurs on init when the // editor is already focused, then this can cause the editor to diff --git a/resources/js/wysiwyg/lexical/table/LexicalTableSelectionHelpers.ts b/resources/js/wysiwyg/lexical/table/LexicalTableSelectionHelpers.ts index e098a21e4..d9164a778 100644 --- a/resources/js/wysiwyg/lexical/table/LexicalTableSelectionHelpers.ts +++ b/resources/js/wysiwyg/lexical/table/LexicalTableSelectionHelpers.ts @@ -917,6 +917,11 @@ export function getTable(tableElement: HTMLElement): TableDOMTable { while (currentNode != null) { const nodeMame = currentNode.nodeName; + if (nodeMame === 'COLGROUP') { + currentNode = currentNode.nextSibling; + continue; + } + if (nodeMame === 'TD' || nodeMame === 'TH') { const elem = currentNode as HTMLElement; const cell = { diff --git a/resources/js/wysiwyg/services/keyboard-handling.ts b/resources/js/wysiwyg/services/keyboard-handling.ts index 41a917ecb..39818acb0 100644 --- a/resources/js/wysiwyg/services/keyboard-handling.ts +++ b/resources/js/wysiwyg/services/keyboard-handling.ts @@ -47,16 +47,21 @@ function deleteSingleSelectedNode(editor: LexicalEditor) { * Insert a new empty node before/after the selection if the selection contains a single * selected node (like image, media etc...). */ -function insertAfterSingleSelectedNode(editor: LexicalEditor, event: KeyboardEvent|null): boolean { +function insertAdjacentToSingleSelectedNode(editor: LexicalEditor, event: KeyboardEvent|null): boolean { const selectionNodes = getLastSelection(editor)?.getNodes() || []; if (isSingleSelectedNode(selectionNodes)) { const node = selectionNodes[0]; const nearestBlock = $getNearestNodeBlockParent(node) || node; + const insertBefore = event?.shiftKey === true; if (nearestBlock) { requestAnimationFrame(() => { editor.update(() => { const newParagraph = $createParagraphNode(); - nearestBlock.insertAfter(newParagraph); + if (insertBefore) { + nearestBlock.insertBefore(newParagraph); + } else { + nearestBlock.insertAfter(newParagraph); + } newParagraph.select(); }); }); @@ -75,22 +80,14 @@ function focusAdjacentOrInsertForSingleSelectNode(editor: LexicalEditor, event: } event?.preventDefault(); - const node = selectionNodes[0]; - const nearestBlock = $getNearestNodeBlockParent(node) || node; - let target = after ? nearestBlock.getNextSibling() : nearestBlock.getPreviousSibling(); editor.update(() => { - if (!target) { - target = $createParagraphNode(); - if (after) { - nearestBlock.insertAfter(target) - } else { - nearestBlock.insertBefore(target); - } + if (after) { + node.selectNext(); + } else { + node.selectPrevious(); } - - target.selectStart(); }); return true; @@ -220,7 +217,7 @@ export function registerKeyboardHandling(context: EditorUiContext): () => void { }, COMMAND_PRIORITY_LOW); const unregisterEnter = context.editor.registerCommand(KEY_ENTER_COMMAND, (event): boolean => { - return insertAfterSingleSelectedNode(context.editor, event) + return insertAdjacentToSingleSelectedNode(context.editor, event) || moveAfterDetailsOnEmptyLine(context.editor, event); }, COMMAND_PRIORITY_LOW); diff --git a/resources/js/wysiwyg/ui/framework/manager.ts b/resources/js/wysiwyg/ui/framework/manager.ts index c80291fb7..2d15b341b 100644 --- a/resources/js/wysiwyg/ui/framework/manager.ts +++ b/resources/js/wysiwyg/ui/framework/manager.ts @@ -244,6 +244,7 @@ export class EditorUIManager { if (selectionChange) { editor.update(() => { const selection = $getSelection(); + // console.log('manager::selection', selection); this.triggerStateUpdate({ editor, selection, }); diff --git a/resources/js/wysiwyg/utils/nodes.ts b/resources/js/wysiwyg/utils/nodes.ts index 591232ea3..ebf01e39d 100644 --- a/resources/js/wysiwyg/utils/nodes.ts +++ b/resources/js/wysiwyg/utils/nodes.ts @@ -6,7 +6,7 @@ import { $isTextNode, ElementNode, LexicalEditor, - LexicalNode + LexicalNode, RangeSelection } from "lexical"; import {LexicalNodeMatcher} from "../nodes"; import {$generateNodesFromDOM} from "@lexical/html"; @@ -118,6 +118,17 @@ export function $sortNodes(nodes: LexicalNode[]): LexicalNode[] { return sorted; } +export function $insertAndSelectNewEmptyAdjacentNode(node: LexicalNode, after: boolean): RangeSelection { + const target = $createParagraphNode(); + if (after) { + node.insertAfter(target) + } else { + node.insertBefore(target); + } + + return target.select(); +} + export function nodeHasAlignment(node: object): node is NodeHasAlignment { return '__alignment' in node; }