internalMarkNodeAsDirty,
removeFromParent,
} from './LexicalUtils';
+import {$insertAndSelectNewEmptyAdjacentNode} from "../../utils/nodes";
export type NodeMap = Map<NodeKey, 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();
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);
import {
$createLineBreakNode,
$createParagraphNode,
- $createTextNode,
+ $createTextNode, $getNearestNodeFromDOMNode,
$isDecoratorNode,
$isElementNode,
$isLineBreakNode,
toggleTextFormatType,
} from './LexicalUtils';
import {$createTabNode, $isTabNode} from './nodes/LexicalTabNode';
+import {$selectSingleNode} from "../../utils/selection";
export type TextPointType = {
_selection: BaseSelection;
}
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
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 = {
* 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();
});
});
}
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;
}, 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);
if (selectionChange) {
editor.update(() => {
const selection = $getSelection();
+ // console.log('manager::selection', selection);
this.triggerStateUpdate({
editor, selection,
});
$isTextNode,
ElementNode,
LexicalEditor,
- LexicalNode
+ LexicalNode, RangeSelection
} from "lexical";
import {LexicalNodeMatcher} from "../nodes";
import {$generateNodesFromDOM} from "@lexical/html";
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;
}