lexical 0.27.3-nightly.20250314.0 → 0.27.3-nightly.20250318.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Lexical.dev.js CHANGED
@@ -1538,7 +1538,7 @@ function $reconcileNode(key, parentDOM) {
1538
1538
  return dom;
1539
1539
  }
1540
1540
  // If the node key doesn't point to the same instance in both maps,
1541
- // it means it were cloned. If they're also dirty, we mark them as mutated.
1541
+ // it was cloned. If it's also dirty, we mark it as mutated.
1542
1542
  if (prevNode !== nextNode && isDirty) {
1543
1543
  setMutatedNode(mutatedNodes, activeEditorNodes, activeMutationListeners, nextNode, 'updated');
1544
1544
  }
@@ -5336,6 +5336,22 @@ class NodeSelection {
5336
5336
  }
5337
5337
  return textContent;
5338
5338
  }
5339
+
5340
+ /**
5341
+ * Remove all nodes in the NodeSelection. If there were any nodes,
5342
+ * replace the selection with a new RangeSelection at the previous
5343
+ * location of the first node.
5344
+ */
5345
+ deleteNodes() {
5346
+ const nodes = this.getNodes();
5347
+ if (($getSelection() || $getPreviousSelection()) === this && nodes[0]) {
5348
+ const firstCaret = $getSiblingCaret(nodes[0], 'next');
5349
+ $setSelectionFromCaretRange($getCaretRange(firstCaret, firstCaret));
5350
+ }
5351
+ for (const node of nodes) {
5352
+ node.remove();
5353
+ }
5354
+ }
5339
5355
  }
5340
5356
  function $isRangeSelection(x) {
5341
5357
  return x instanceof RangeSelection;
@@ -7688,6 +7704,7 @@ function $applyAllTransforms(editorState, editor) {
7688
7704
  for (const currentUntransformedDirtyElement of untransformedDirtyElements) {
7689
7705
  const nodeKey = currentUntransformedDirtyElement[0];
7690
7706
  const intentionallyMarkedAsDirty = currentUntransformedDirtyElement[1];
7707
+ dirtyElements.set(nodeKey, intentionallyMarkedAsDirty);
7691
7708
  if (nodeKey !== 'root' && !intentionallyMarkedAsDirty) {
7692
7709
  continue;
7693
7710
  }
@@ -7695,7 +7712,6 @@ function $applyAllTransforms(editorState, editor) {
7695
7712
  if (node !== undefined && $isNodeValidForTransform(node, compositionKey)) {
7696
7713
  $applyTransforms(editor, node, transformsCache);
7697
7714
  }
7698
- dirtyElements.set(nodeKey, intentionallyMarkedAsDirty);
7699
7715
  }
7700
7716
  untransformedDirtyLeaves = editor._dirtyLeaves;
7701
7717
  untransformedDirtyLeavesLength = untransformedDirtyLeaves.size;
@@ -7961,6 +7977,7 @@ function $commitPendingUpdates(editor, recoveryEditorState) {
7961
7977
  dirtyElements,
7962
7978
  dirtyLeaves,
7963
7979
  editorState: pendingEditorState,
7980
+ mutatedNodes,
7964
7981
  normalizedNodes,
7965
7982
  prevEditorState: recoveryEditorState || currentEditorState,
7966
7983
  tags
@@ -7996,7 +8013,6 @@ function triggerListeners(type, editor, isCurrentlyEnqueuingUpdates, ...payload)
7996
8013
  try {
7997
8014
  const listeners = Array.from(editor._listeners[type]);
7998
8015
  for (let i = 0; i < listeners.length; i++) {
7999
- // @ts-ignore
8000
8016
  listeners[i].apply(null, payload);
8001
8017
  }
8002
8018
  } finally {
@@ -8258,6 +8274,9 @@ class ElementDOMSlot {
8258
8274
  * Return a new ElementDOMSlot with an updated root element
8259
8275
  */
8260
8276
  withElement(element) {
8277
+ if (this.element === element) {
8278
+ return this;
8279
+ }
8261
8280
  return new ElementDOMSlot(element, this.before, this.after);
8262
8281
  }
8263
8282
  /**
@@ -9126,17 +9145,13 @@ class RootNode extends ElementNode {
9126
9145
  }
9127
9146
 
9128
9147
  // Mutate
9129
-
9130
- append(...nodesToAppend) {
9131
- for (let i = 0; i < nodesToAppend.length; i++) {
9132
- const node = nodesToAppend[i];
9133
- if (!$isElementNode(node) && !$isDecoratorNode(node)) {
9134
- {
9135
- formatDevErrorMessage(`rootNode.append: Only element or decorator nodes can be appended to the root node`);
9136
- }
9148
+ splice(start, deleteCount, nodesToInsert) {
9149
+ for (const node of nodesToInsert) {
9150
+ if (!($isElementNode(node) || $isDecoratorNode(node))) {
9151
+ formatDevErrorMessage(`rootNode.splice: Only element or decorator nodes can be inserted to the root node`);
9137
9152
  }
9138
9153
  }
9139
- return super.append(...nodesToAppend);
9154
+ return super.splice(start, deleteCount, nodesToInsert);
9140
9155
  }
9141
9156
  static importJSON(serializedNode) {
9142
9157
  // We don't create a root, and instead use the existing root.
@@ -9368,6 +9383,15 @@ function $isParagraphNode(node) {
9368
9383
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
9369
9384
 
9370
9385
  const DEFAULT_SKIP_INITIALIZATION = false;
9386
+
9387
+ /**
9388
+ * The payload passed to an UpdateListener
9389
+ */
9390
+
9391
+ /**
9392
+ * A listener that gets called after the editor is updated
9393
+ */
9394
+
9371
9395
  const COMMAND_PRIORITY_EDITOR = 0;
9372
9396
  const COMMAND_PRIORITY_LOW = 1;
9373
9397
  const COMMAND_PRIORITY_NORMAL = 2;
@@ -10223,7 +10247,7 @@ class LexicalEditor {
10223
10247
  };
10224
10248
  }
10225
10249
  }
10226
- LexicalEditor.version = "0.27.3-nightly.20250314.0+dev.cjs";
10250
+ LexicalEditor.version = "0.27.3-nightly.20250318.0+dev.cjs";
10227
10251
 
10228
10252
  let keyCounter = 1;
10229
10253
  function resetRandomKey() {
@@ -12197,6 +12221,13 @@ function $extendCaretToRange(anchor) {
12197
12221
  return $getCaretRange(anchor, $getSiblingCaret($getRoot(), anchor.direction));
12198
12222
  }
12199
12223
 
12224
+ /**
12225
+ * Construct a collapsed CaretRange that starts and ends at anchor.
12226
+ */
12227
+ function $getCollapsedCaretRange(anchor) {
12228
+ return $getCaretRange(anchor, anchor);
12229
+ }
12230
+
12200
12231
  /**
12201
12232
  * Construct a CaretRange from anchor and focus carets pointing in the
12202
12233
  * same direction. In order to get the expected behavior,
@@ -12659,7 +12690,7 @@ function $removeTextFromCaretRange(initialRange, sliceMode = 'removeEmptySlices'
12659
12690
  const bestCandidate = [anchorCandidate, focusCandidate, ...anchorCandidates, ...focusCandidates].find($isCaretAttached);
12660
12691
  if (bestCandidate) {
12661
12692
  const anchor = $getCaretInDirection($normalizeCaret(bestCandidate), initialRange.direction);
12662
- return $getCaretRange(anchor, anchor);
12693
+ return $getCollapsedCaretRange(anchor);
12663
12694
  }
12664
12695
  {
12665
12696
  formatDevErrorMessage(`$removeTextFromCaretRange: selection was lost, could not find a new anchor given candidates with keys: ${JSON.stringify(anchorCandidates.map(n => n.origin.__key))}`);
@@ -12847,6 +12878,81 @@ function $getAdjacentSiblingOrParentSiblingCaret(startCaret, rootMode = 'root')
12847
12878
  return nextCaret && [nextCaret, depthDiff];
12848
12879
  }
12849
12880
 
12881
+ /**
12882
+ * Get the adjacent nodes to initialCaret in the given direction.
12883
+ *
12884
+ * @example
12885
+ * ```ts
12886
+ * expect($getAdjacentNodes($getChildCaret(parent, 'next'))).toEqual(parent.getChildren());
12887
+ * expect($getAdjacentNodes($getChildCaret(parent, 'previous'))).toEqual(parent.getChildren().reverse());
12888
+ * expect($getAdjacentNodes($getSiblingCaret(node, 'next'))).toEqual(node.getNextSiblings());
12889
+ * expect($getAdjacentNodes($getSiblingCaret(node, 'previous'))).toEqual(node.getPreviousSiblings().reverse());
12890
+ * ```
12891
+ *
12892
+ * @param initialCaret The caret to start at (the origin will not be included)
12893
+ * @returns An array of siblings.
12894
+ */
12895
+ function $getAdjacentNodes(initialCaret) {
12896
+ const siblings = [];
12897
+ for (let caret = initialCaret.getAdjacentCaret(); caret; caret = caret.getAdjacentCaret()) {
12898
+ siblings.push(caret.origin);
12899
+ }
12900
+ return siblings;
12901
+ }
12902
+ function $splitTextPointCaret(textPointCaret) {
12903
+ const {
12904
+ origin,
12905
+ offset,
12906
+ direction
12907
+ } = textPointCaret;
12908
+ if (offset === $getTextNodeOffset(origin, direction)) {
12909
+ return textPointCaret.getSiblingCaret();
12910
+ } else if (offset === $getTextNodeOffset(origin, flipDirection(direction))) {
12911
+ return $rewindSiblingCaret(textPointCaret.getSiblingCaret());
12912
+ }
12913
+ const [textNode] = origin.splitText(offset);
12914
+ if (!$isTextNode(textNode)) {
12915
+ formatDevErrorMessage(`$splitTextPointCaret: splitText must return at least one TextNode`);
12916
+ }
12917
+ return $getCaretInDirection($getSiblingCaret(textNode, 'next'), direction);
12918
+ }
12919
+ function $alwaysSplit(_node, _edge) {
12920
+ return true;
12921
+ }
12922
+
12923
+ /**
12924
+ * Split a node at a PointCaret and return a NodeCaret at that point, or null if the
12925
+ * node can't be split. This is non-recursive and will only perform at most one split.
12926
+ *
12927
+ * @returns The NodeCaret pointing to the location of the split (or null if a split is not possible)
12928
+ */
12929
+ function $splitAtPointCaretNext(pointCaret, {
12930
+ $copyElementNode = $copyNode,
12931
+ $splitTextPointCaretNext = $splitTextPointCaret,
12932
+ rootMode = 'shadowRoot',
12933
+ $shouldSplit = $alwaysSplit
12934
+ } = {}) {
12935
+ if ($isTextPointCaret(pointCaret)) {
12936
+ return $splitTextPointCaretNext(pointCaret);
12937
+ }
12938
+ const parentCaret = pointCaret.getParentCaret(rootMode);
12939
+ if (parentCaret) {
12940
+ const {
12941
+ origin
12942
+ } = parentCaret;
12943
+ if ($isChildCaret(pointCaret) && !(origin.canBeEmpty() && $shouldSplit(origin, 'first'))) {
12944
+ // No split necessary, the left side would be empty
12945
+ return $rewindSiblingCaret(parentCaret);
12946
+ }
12947
+ const siblings = $getAdjacentNodes(pointCaret);
12948
+ if (siblings.length > 0 || origin.canBeEmpty() && $shouldSplit(origin, 'last')) {
12949
+ // Split and insert the siblings into the new tree
12950
+ parentCaret.insert($copyElementNode(origin).splice(0, 0, siblings));
12951
+ }
12952
+ }
12953
+ return parentCaret;
12954
+ }
12955
+
12850
12956
  exports.$addUpdateTag = $addUpdateTag;
12851
12957
  exports.$applyNodeReplacement = $applyNodeReplacement;
12852
12958
  exports.$caretFromPoint = $caretFromPoint;
@@ -12873,6 +12979,7 @@ exports.$getCharacterOffsets = $getCharacterOffsets;
12873
12979
  exports.$getChildCaret = $getChildCaret;
12874
12980
  exports.$getChildCaretAtIndex = $getChildCaretAtIndex;
12875
12981
  exports.$getChildCaretOrSelf = $getChildCaretOrSelf;
12982
+ exports.$getCollapsedCaretRange = $getCollapsedCaretRange;
12876
12983
  exports.$getCommonAncestor = $getCommonAncestor;
12877
12984
  exports.$getCommonAncestorResultBranchOrder = $getCommonAncestorResultBranchOrder;
12878
12985
  exports.$getEditor = $getEditor;
@@ -12927,6 +13034,7 @@ exports.$setPointFromCaret = $setPointFromCaret;
12927
13034
  exports.$setSelection = $setSelection;
12928
13035
  exports.$setSelectionFromCaretRange = $setSelectionFromCaretRange;
12929
13036
  exports.$setState = $setState;
13037
+ exports.$splitAtPointCaretNext = $splitAtPointCaretNext;
12930
13038
  exports.$splitNode = $splitNode;
12931
13039
  exports.$updateRangeSelectionFromCaretRange = $updateRangeSelectionFromCaretRange;
12932
13040
  exports.ArtificialNode__DO_NOT_USE = ArtificialNode__DO_NOT_USE;
package/Lexical.dev.mjs CHANGED
@@ -1536,7 +1536,7 @@ function $reconcileNode(key, parentDOM) {
1536
1536
  return dom;
1537
1537
  }
1538
1538
  // If the node key doesn't point to the same instance in both maps,
1539
- // it means it were cloned. If they're also dirty, we mark them as mutated.
1539
+ // it was cloned. If it's also dirty, we mark it as mutated.
1540
1540
  if (prevNode !== nextNode && isDirty) {
1541
1541
  setMutatedNode(mutatedNodes, activeEditorNodes, activeMutationListeners, nextNode, 'updated');
1542
1542
  }
@@ -5334,6 +5334,22 @@ class NodeSelection {
5334
5334
  }
5335
5335
  return textContent;
5336
5336
  }
5337
+
5338
+ /**
5339
+ * Remove all nodes in the NodeSelection. If there were any nodes,
5340
+ * replace the selection with a new RangeSelection at the previous
5341
+ * location of the first node.
5342
+ */
5343
+ deleteNodes() {
5344
+ const nodes = this.getNodes();
5345
+ if (($getSelection() || $getPreviousSelection()) === this && nodes[0]) {
5346
+ const firstCaret = $getSiblingCaret(nodes[0], 'next');
5347
+ $setSelectionFromCaretRange($getCaretRange(firstCaret, firstCaret));
5348
+ }
5349
+ for (const node of nodes) {
5350
+ node.remove();
5351
+ }
5352
+ }
5337
5353
  }
5338
5354
  function $isRangeSelection(x) {
5339
5355
  return x instanceof RangeSelection;
@@ -7686,6 +7702,7 @@ function $applyAllTransforms(editorState, editor) {
7686
7702
  for (const currentUntransformedDirtyElement of untransformedDirtyElements) {
7687
7703
  const nodeKey = currentUntransformedDirtyElement[0];
7688
7704
  const intentionallyMarkedAsDirty = currentUntransformedDirtyElement[1];
7705
+ dirtyElements.set(nodeKey, intentionallyMarkedAsDirty);
7689
7706
  if (nodeKey !== 'root' && !intentionallyMarkedAsDirty) {
7690
7707
  continue;
7691
7708
  }
@@ -7693,7 +7710,6 @@ function $applyAllTransforms(editorState, editor) {
7693
7710
  if (node !== undefined && $isNodeValidForTransform(node, compositionKey)) {
7694
7711
  $applyTransforms(editor, node, transformsCache);
7695
7712
  }
7696
- dirtyElements.set(nodeKey, intentionallyMarkedAsDirty);
7697
7713
  }
7698
7714
  untransformedDirtyLeaves = editor._dirtyLeaves;
7699
7715
  untransformedDirtyLeavesLength = untransformedDirtyLeaves.size;
@@ -7959,6 +7975,7 @@ function $commitPendingUpdates(editor, recoveryEditorState) {
7959
7975
  dirtyElements,
7960
7976
  dirtyLeaves,
7961
7977
  editorState: pendingEditorState,
7978
+ mutatedNodes,
7962
7979
  normalizedNodes,
7963
7980
  prevEditorState: recoveryEditorState || currentEditorState,
7964
7981
  tags
@@ -7994,7 +8011,6 @@ function triggerListeners(type, editor, isCurrentlyEnqueuingUpdates, ...payload)
7994
8011
  try {
7995
8012
  const listeners = Array.from(editor._listeners[type]);
7996
8013
  for (let i = 0; i < listeners.length; i++) {
7997
- // @ts-ignore
7998
8014
  listeners[i].apply(null, payload);
7999
8015
  }
8000
8016
  } finally {
@@ -8256,6 +8272,9 @@ class ElementDOMSlot {
8256
8272
  * Return a new ElementDOMSlot with an updated root element
8257
8273
  */
8258
8274
  withElement(element) {
8275
+ if (this.element === element) {
8276
+ return this;
8277
+ }
8259
8278
  return new ElementDOMSlot(element, this.before, this.after);
8260
8279
  }
8261
8280
  /**
@@ -9124,17 +9143,13 @@ class RootNode extends ElementNode {
9124
9143
  }
9125
9144
 
9126
9145
  // Mutate
9127
-
9128
- append(...nodesToAppend) {
9129
- for (let i = 0; i < nodesToAppend.length; i++) {
9130
- const node = nodesToAppend[i];
9131
- if (!$isElementNode(node) && !$isDecoratorNode(node)) {
9132
- {
9133
- formatDevErrorMessage(`rootNode.append: Only element or decorator nodes can be appended to the root node`);
9134
- }
9146
+ splice(start, deleteCount, nodesToInsert) {
9147
+ for (const node of nodesToInsert) {
9148
+ if (!($isElementNode(node) || $isDecoratorNode(node))) {
9149
+ formatDevErrorMessage(`rootNode.splice: Only element or decorator nodes can be inserted to the root node`);
9135
9150
  }
9136
9151
  }
9137
- return super.append(...nodesToAppend);
9152
+ return super.splice(start, deleteCount, nodesToInsert);
9138
9153
  }
9139
9154
  static importJSON(serializedNode) {
9140
9155
  // We don't create a root, and instead use the existing root.
@@ -9366,6 +9381,15 @@ function $isParagraphNode(node) {
9366
9381
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
9367
9382
 
9368
9383
  const DEFAULT_SKIP_INITIALIZATION = false;
9384
+
9385
+ /**
9386
+ * The payload passed to an UpdateListener
9387
+ */
9388
+
9389
+ /**
9390
+ * A listener that gets called after the editor is updated
9391
+ */
9392
+
9369
9393
  const COMMAND_PRIORITY_EDITOR = 0;
9370
9394
  const COMMAND_PRIORITY_LOW = 1;
9371
9395
  const COMMAND_PRIORITY_NORMAL = 2;
@@ -10221,7 +10245,7 @@ class LexicalEditor {
10221
10245
  };
10222
10246
  }
10223
10247
  }
10224
- LexicalEditor.version = "0.27.3-nightly.20250314.0+dev.esm";
10248
+ LexicalEditor.version = "0.27.3-nightly.20250318.0+dev.esm";
10225
10249
 
10226
10250
  let keyCounter = 1;
10227
10251
  function resetRandomKey() {
@@ -12195,6 +12219,13 @@ function $extendCaretToRange(anchor) {
12195
12219
  return $getCaretRange(anchor, $getSiblingCaret($getRoot(), anchor.direction));
12196
12220
  }
12197
12221
 
12222
+ /**
12223
+ * Construct a collapsed CaretRange that starts and ends at anchor.
12224
+ */
12225
+ function $getCollapsedCaretRange(anchor) {
12226
+ return $getCaretRange(anchor, anchor);
12227
+ }
12228
+
12198
12229
  /**
12199
12230
  * Construct a CaretRange from anchor and focus carets pointing in the
12200
12231
  * same direction. In order to get the expected behavior,
@@ -12657,7 +12688,7 @@ function $removeTextFromCaretRange(initialRange, sliceMode = 'removeEmptySlices'
12657
12688
  const bestCandidate = [anchorCandidate, focusCandidate, ...anchorCandidates, ...focusCandidates].find($isCaretAttached);
12658
12689
  if (bestCandidate) {
12659
12690
  const anchor = $getCaretInDirection($normalizeCaret(bestCandidate), initialRange.direction);
12660
- return $getCaretRange(anchor, anchor);
12691
+ return $getCollapsedCaretRange(anchor);
12661
12692
  }
12662
12693
  {
12663
12694
  formatDevErrorMessage(`$removeTextFromCaretRange: selection was lost, could not find a new anchor given candidates with keys: ${JSON.stringify(anchorCandidates.map(n => n.origin.__key))}`);
@@ -12845,4 +12876,79 @@ function $getAdjacentSiblingOrParentSiblingCaret(startCaret, rootMode = 'root')
12845
12876
  return nextCaret && [nextCaret, depthDiff];
12846
12877
  }
12847
12878
 
12848
- export { $addUpdateTag, $applyNodeReplacement, $caretFromPoint, $caretRangeFromSelection, $cloneWithProperties, $comparePointCaretNext, $copyNode, $createLineBreakNode, $createNodeSelection, $createParagraphNode, $createPoint, $createRangeSelection, $createRangeSelectionFromDom, $createTabNode, $createTextNode, $extendCaretToRange, $getAdjacentChildCaret, $getAdjacentNode, $getAdjacentSiblingOrParentSiblingCaret, $getCaretInDirection, $getCaretRange, $getCaretRangeInDirection, $getCharacterOffsets, $getChildCaret, $getChildCaretAtIndex, $getChildCaretOrSelf, $getCommonAncestor, $getCommonAncestorResultBranchOrder, $getEditor, $getNearestNodeFromDOMNode, $getNearestRootOrShadowRoot, $getNodeByKey, $getNodeByKeyOrThrow, $getPreviousSelection, $getRoot, $getSelection, $getSiblingCaret, $getState, $getStateChange, $getTextContent, $getTextNodeOffset, $getTextPointCaret, $getTextPointCaretSlice, $getWritableNodeState, $hasAncestor, $hasUpdateTag, $insertNodes, $isBlockElementNode, $isChildCaret, $isDecoratorNode, $isElementNode, $isExtendableTextPointCaret, $isInlineElementOrDecoratorNode, $isLeafNode, $isLineBreakNode, $isNodeCaret, $isNodeSelection, $isParagraphNode, $isRangeSelection, $isRootNode, $isRootOrShadowRoot, $isSiblingCaret, $isTabNode, $isTextNode, $isTextPointCaret, $isTextPointCaretSlice, $isTokenOrSegmented, $nodesOfType, $normalizeCaret, $normalizeSelection as $normalizeSelection__EXPERIMENTAL, $onUpdate, $parseSerializedNode, $removeTextFromCaretRange, $rewindSiblingCaret, $selectAll, $setCompositionKey, $setPointFromCaret, $setSelection, $setSelectionFromCaretRange, $setState, $splitNode, $updateRangeSelectionFromCaretRange, ArtificialNode__DO_NOT_USE, BLUR_COMMAND, CAN_REDO_COMMAND, CAN_UNDO_COMMAND, CLEAR_EDITOR_COMMAND, CLEAR_HISTORY_COMMAND, CLICK_COMMAND, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, CONTROLLED_TEXT_INSERTION_COMMAND, COPY_COMMAND, CUT_COMMAND, DELETE_CHARACTER_COMMAND, DELETE_LINE_COMMAND, DELETE_WORD_COMMAND, DRAGEND_COMMAND, DRAGOVER_COMMAND, DRAGSTART_COMMAND, DROP_COMMAND, DecoratorNode, ElementNode, FOCUS_COMMAND, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, INDENT_CONTENT_COMMAND, INSERT_LINE_BREAK_COMMAND, INSERT_PARAGRAPH_COMMAND, INSERT_TAB_COMMAND, INTERNAL_$isBlock, IS_ALL_FORMATTING, IS_BOLD, IS_CODE, IS_HIGHLIGHT, IS_ITALIC, IS_STRIKETHROUGH, IS_SUBSCRIPT, IS_SUPERSCRIPT, IS_UNDERLINE, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_DOWN_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, KEY_MODIFIER_COMMAND, KEY_SPACE_COMMAND, KEY_TAB_COMMAND, LineBreakNode, MOVE_TO_END, MOVE_TO_START, NODE_STATE_KEY, OUTDENT_CONTENT_COMMAND, PASTE_COMMAND, ParagraphNode, REDO_COMMAND, REMOVE_TEXT_COMMAND, RootNode, SELECTION_CHANGE_COMMAND, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, SELECT_ALL_COMMAND, TEXT_TYPE_TO_FORMAT, TabNode, TextNode, UNDO_COMMAND, createCommand, createEditor, createState, flipDirection, getDOMOwnerDocument, getDOMSelection, getDOMSelectionFromTarget, getDOMTextNode, getEditorPropertyFromDOMNode, getNearestEditorFromDOMNode, isBlockDomNode, isCurrentlyReadOnlyMode, isDOMDocumentNode, isDOMNode, isDOMTextNode, isDOMUnmanaged, isDocumentFragment, isHTMLAnchorElement, isHTMLElement, isInlineDomNode, isLexicalEditor, isSelectionCapturedInDecoratorInput, isSelectionWithinEditor, makeStepwiseIterator, resetRandomKey, setDOMUnmanaged, setNodeIndentFromDOM };
12879
+ /**
12880
+ * Get the adjacent nodes to initialCaret in the given direction.
12881
+ *
12882
+ * @example
12883
+ * ```ts
12884
+ * expect($getAdjacentNodes($getChildCaret(parent, 'next'))).toEqual(parent.getChildren());
12885
+ * expect($getAdjacentNodes($getChildCaret(parent, 'previous'))).toEqual(parent.getChildren().reverse());
12886
+ * expect($getAdjacentNodes($getSiblingCaret(node, 'next'))).toEqual(node.getNextSiblings());
12887
+ * expect($getAdjacentNodes($getSiblingCaret(node, 'previous'))).toEqual(node.getPreviousSiblings().reverse());
12888
+ * ```
12889
+ *
12890
+ * @param initialCaret The caret to start at (the origin will not be included)
12891
+ * @returns An array of siblings.
12892
+ */
12893
+ function $getAdjacentNodes(initialCaret) {
12894
+ const siblings = [];
12895
+ for (let caret = initialCaret.getAdjacentCaret(); caret; caret = caret.getAdjacentCaret()) {
12896
+ siblings.push(caret.origin);
12897
+ }
12898
+ return siblings;
12899
+ }
12900
+ function $splitTextPointCaret(textPointCaret) {
12901
+ const {
12902
+ origin,
12903
+ offset,
12904
+ direction
12905
+ } = textPointCaret;
12906
+ if (offset === $getTextNodeOffset(origin, direction)) {
12907
+ return textPointCaret.getSiblingCaret();
12908
+ } else if (offset === $getTextNodeOffset(origin, flipDirection(direction))) {
12909
+ return $rewindSiblingCaret(textPointCaret.getSiblingCaret());
12910
+ }
12911
+ const [textNode] = origin.splitText(offset);
12912
+ if (!$isTextNode(textNode)) {
12913
+ formatDevErrorMessage(`$splitTextPointCaret: splitText must return at least one TextNode`);
12914
+ }
12915
+ return $getCaretInDirection($getSiblingCaret(textNode, 'next'), direction);
12916
+ }
12917
+ function $alwaysSplit(_node, _edge) {
12918
+ return true;
12919
+ }
12920
+
12921
+ /**
12922
+ * Split a node at a PointCaret and return a NodeCaret at that point, or null if the
12923
+ * node can't be split. This is non-recursive and will only perform at most one split.
12924
+ *
12925
+ * @returns The NodeCaret pointing to the location of the split (or null if a split is not possible)
12926
+ */
12927
+ function $splitAtPointCaretNext(pointCaret, {
12928
+ $copyElementNode = $copyNode,
12929
+ $splitTextPointCaretNext = $splitTextPointCaret,
12930
+ rootMode = 'shadowRoot',
12931
+ $shouldSplit = $alwaysSplit
12932
+ } = {}) {
12933
+ if ($isTextPointCaret(pointCaret)) {
12934
+ return $splitTextPointCaretNext(pointCaret);
12935
+ }
12936
+ const parentCaret = pointCaret.getParentCaret(rootMode);
12937
+ if (parentCaret) {
12938
+ const {
12939
+ origin
12940
+ } = parentCaret;
12941
+ if ($isChildCaret(pointCaret) && !(origin.canBeEmpty() && $shouldSplit(origin, 'first'))) {
12942
+ // No split necessary, the left side would be empty
12943
+ return $rewindSiblingCaret(parentCaret);
12944
+ }
12945
+ const siblings = $getAdjacentNodes(pointCaret);
12946
+ if (siblings.length > 0 || origin.canBeEmpty() && $shouldSplit(origin, 'last')) {
12947
+ // Split and insert the siblings into the new tree
12948
+ parentCaret.insert($copyElementNode(origin).splice(0, 0, siblings));
12949
+ }
12950
+ }
12951
+ return parentCaret;
12952
+ }
12953
+
12954
+ export { $addUpdateTag, $applyNodeReplacement, $caretFromPoint, $caretRangeFromSelection, $cloneWithProperties, $comparePointCaretNext, $copyNode, $createLineBreakNode, $createNodeSelection, $createParagraphNode, $createPoint, $createRangeSelection, $createRangeSelectionFromDom, $createTabNode, $createTextNode, $extendCaretToRange, $getAdjacentChildCaret, $getAdjacentNode, $getAdjacentSiblingOrParentSiblingCaret, $getCaretInDirection, $getCaretRange, $getCaretRangeInDirection, $getCharacterOffsets, $getChildCaret, $getChildCaretAtIndex, $getChildCaretOrSelf, $getCollapsedCaretRange, $getCommonAncestor, $getCommonAncestorResultBranchOrder, $getEditor, $getNearestNodeFromDOMNode, $getNearestRootOrShadowRoot, $getNodeByKey, $getNodeByKeyOrThrow, $getPreviousSelection, $getRoot, $getSelection, $getSiblingCaret, $getState, $getStateChange, $getTextContent, $getTextNodeOffset, $getTextPointCaret, $getTextPointCaretSlice, $getWritableNodeState, $hasAncestor, $hasUpdateTag, $insertNodes, $isBlockElementNode, $isChildCaret, $isDecoratorNode, $isElementNode, $isExtendableTextPointCaret, $isInlineElementOrDecoratorNode, $isLeafNode, $isLineBreakNode, $isNodeCaret, $isNodeSelection, $isParagraphNode, $isRangeSelection, $isRootNode, $isRootOrShadowRoot, $isSiblingCaret, $isTabNode, $isTextNode, $isTextPointCaret, $isTextPointCaretSlice, $isTokenOrSegmented, $nodesOfType, $normalizeCaret, $normalizeSelection as $normalizeSelection__EXPERIMENTAL, $onUpdate, $parseSerializedNode, $removeTextFromCaretRange, $rewindSiblingCaret, $selectAll, $setCompositionKey, $setPointFromCaret, $setSelection, $setSelectionFromCaretRange, $setState, $splitAtPointCaretNext, $splitNode, $updateRangeSelectionFromCaretRange, ArtificialNode__DO_NOT_USE, BLUR_COMMAND, CAN_REDO_COMMAND, CAN_UNDO_COMMAND, CLEAR_EDITOR_COMMAND, CLEAR_HISTORY_COMMAND, CLICK_COMMAND, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, CONTROLLED_TEXT_INSERTION_COMMAND, COPY_COMMAND, CUT_COMMAND, DELETE_CHARACTER_COMMAND, DELETE_LINE_COMMAND, DELETE_WORD_COMMAND, DRAGEND_COMMAND, DRAGOVER_COMMAND, DRAGSTART_COMMAND, DROP_COMMAND, DecoratorNode, ElementNode, FOCUS_COMMAND, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, INDENT_CONTENT_COMMAND, INSERT_LINE_BREAK_COMMAND, INSERT_PARAGRAPH_COMMAND, INSERT_TAB_COMMAND, INTERNAL_$isBlock, IS_ALL_FORMATTING, IS_BOLD, IS_CODE, IS_HIGHLIGHT, IS_ITALIC, IS_STRIKETHROUGH, IS_SUBSCRIPT, IS_SUPERSCRIPT, IS_UNDERLINE, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_DOWN_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, KEY_MODIFIER_COMMAND, KEY_SPACE_COMMAND, KEY_TAB_COMMAND, LineBreakNode, MOVE_TO_END, MOVE_TO_START, NODE_STATE_KEY, OUTDENT_CONTENT_COMMAND, PASTE_COMMAND, ParagraphNode, REDO_COMMAND, REMOVE_TEXT_COMMAND, RootNode, SELECTION_CHANGE_COMMAND, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, SELECT_ALL_COMMAND, TEXT_TYPE_TO_FORMAT, TabNode, TextNode, UNDO_COMMAND, createCommand, createEditor, createState, flipDirection, getDOMOwnerDocument, getDOMSelection, getDOMSelectionFromTarget, getDOMTextNode, getEditorPropertyFromDOMNode, getNearestEditorFromDOMNode, isBlockDomNode, isCurrentlyReadOnlyMode, isDOMDocumentNode, isDOMNode, isDOMTextNode, isDOMUnmanaged, isDocumentFragment, isHTMLAnchorElement, isHTMLElement, isInlineDomNode, isLexicalEditor, isSelectionCapturedInDecoratorInput, isSelectionWithinEditor, makeStepwiseIterator, resetRandomKey, setDOMUnmanaged, setNodeIndentFromDOM };
package/Lexical.js.flow CHANGED
@@ -809,7 +809,7 @@ declare export class ElementNode extends LexicalNode {
809
809
  nodesToInsert: Array<LexicalNode>,
810
810
  ): this;
811
811
  exportJSON(): SerializedElementNode;
812
- getDOMSlot(dom: HTMLElement): ElementDOMSlot;
812
+ getDOMSlot(dom: HTMLElement): ElementDOMSlot<HTMLElement>;
813
813
  }
814
814
  declare export function $isElementNode(
815
815
  node: ?LexicalNode,
@@ -818,14 +818,14 @@ declare export function $isElementNode(
818
818
  /**
819
819
  * ElementDOMSlot
820
820
  */
821
- declare export class ElementDOMSlot {
822
- element: HTMLElement;
823
- before: Node | null;
824
- after: Node | null;
821
+ declare export class ElementDOMSlot<+T: HTMLElement> {
822
+ +element: HTMLElement;
823
+ +before: Node | null;
824
+ +after: Node | null;
825
825
  constructor(element: HTMLElement, before?: Node | null | void, after?: Node | null | void): void;
826
- withBefore(before: Node | null | void): ElementDOMSlot;
827
- withAfter(after: Node | null | void): ElementDOMSlot;
828
- withElement(element: HTMLElement): ElementDOMSlot;
826
+ withBefore(before: Node | null | void): ElementDOMSlot<T>;
827
+ withAfter(after: Node | null | void): ElementDOMSlot<T>;
828
+ withElement<ElementType: HTMLElement>(element: ElementType): ElementDOMSlot<ElementType>;
829
829
  insertChild(dom: Node): this;
830
830
  removeChild(dom: Node): this;
831
831
  replaceChild(dom: Node, prevDom: Node): this;
@@ -1227,7 +1227,22 @@ declare export function $getCommonAncestor<
1227
1227
  declare export function $extendCaretToRange<D: CaretDirection>(
1228
1228
  anchor: PointCaret<D>,
1229
1229
  ): CaretRange<D>;
1230
-
1230
+ declare export function $getCollapsedCaretRange<D: CaretDirection>(
1231
+ anchor: PointCaret<D>,
1232
+ ): CaretRange<D>;
1231
1233
  declare export function $isExtendableTextPointCaret<D: CaretDirection>(
1232
1234
  caret: PointCaret<D>
1233
1235
  ): implies caret is TextPointCaret<TextNode, D>;
1236
+
1237
+ export interface SplitAtPointCaretNextOptions {
1238
+ $copyElementNode?: (node: ElementNode) => ElementNode;
1239
+ $splitTextPointCaretNext?: (
1240
+ caret: TextPointCaret<TextNode, 'next'>,
1241
+ ) => NodeCaret<'next'>;
1242
+ rootMode?: RootMode;
1243
+ $shouldSplit?: (node: ElementNode, edge: 'first' | 'last') => boolean;
1244
+ }
1245
+ declare export function $splitAtPointCaretNext(
1246
+ pointCaret: PointCaret<'next'>,
1247
+ options?: SplitAtPointCaretNextOptions,
1248
+ ): null | NodeCaret<'next'>;
package/Lexical.mjs CHANGED
@@ -35,6 +35,7 @@ export const $getCharacterOffsets = mod.$getCharacterOffsets;
35
35
  export const $getChildCaret = mod.$getChildCaret;
36
36
  export const $getChildCaretAtIndex = mod.$getChildCaretAtIndex;
37
37
  export const $getChildCaretOrSelf = mod.$getChildCaretOrSelf;
38
+ export const $getCollapsedCaretRange = mod.$getCollapsedCaretRange;
38
39
  export const $getCommonAncestor = mod.$getCommonAncestor;
39
40
  export const $getCommonAncestorResultBranchOrder = mod.$getCommonAncestorResultBranchOrder;
40
41
  export const $getEditor = mod.$getEditor;
@@ -89,6 +90,7 @@ export const $setPointFromCaret = mod.$setPointFromCaret;
89
90
  export const $setSelection = mod.$setSelection;
90
91
  export const $setSelectionFromCaretRange = mod.$setSelectionFromCaretRange;
91
92
  export const $setState = mod.$setState;
93
+ export const $splitAtPointCaretNext = mod.$splitAtPointCaretNext;
92
94
  export const $splitNode = mod.$splitNode;
93
95
  export const $updateRangeSelectionFromCaretRange = mod.$updateRangeSelectionFromCaretRange;
94
96
  export const ArtificialNode__DO_NOT_USE = mod.ArtificialNode__DO_NOT_USE;
package/Lexical.node.mjs CHANGED
@@ -33,6 +33,7 @@ export const $getCharacterOffsets = mod.$getCharacterOffsets;
33
33
  export const $getChildCaret = mod.$getChildCaret;
34
34
  export const $getChildCaretAtIndex = mod.$getChildCaretAtIndex;
35
35
  export const $getChildCaretOrSelf = mod.$getChildCaretOrSelf;
36
+ export const $getCollapsedCaretRange = mod.$getCollapsedCaretRange;
36
37
  export const $getCommonAncestor = mod.$getCommonAncestor;
37
38
  export const $getCommonAncestorResultBranchOrder = mod.$getCommonAncestorResultBranchOrder;
38
39
  export const $getEditor = mod.$getEditor;
@@ -87,6 +88,7 @@ export const $setPointFromCaret = mod.$setPointFromCaret;
87
88
  export const $setSelection = mod.$setSelection;
88
89
  export const $setSelectionFromCaretRange = mod.$setSelectionFromCaretRange;
89
90
  export const $setState = mod.$setState;
91
+ export const $splitAtPointCaretNext = mod.$splitAtPointCaretNext;
90
92
  export const $splitNode = mod.$splitNode;
91
93
  export const $updateRangeSelectionFromCaretRange = mod.$updateRangeSelectionFromCaretRange;
92
94
  export const ArtificialNode__DO_NOT_USE = mod.ArtificialNode__DO_NOT_USE;