lexical 0.4.0 → 0.5.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
@@ -104,8 +104,8 @@ const FULL_RECONCILE = 2; // Text node modes
104
104
 
105
105
  const IS_NORMAL = 0;
106
106
  const IS_TOKEN = 1;
107
- const IS_SEGMENTED = 2;
108
- const IS_INERT = 3; // Text node formatting
107
+ const IS_SEGMENTED = 2; // IS_INERT = 3
108
+ // Text node formatting
109
109
 
110
110
  const IS_BOLD = 1;
111
111
  const IS_ITALIC = 1 << 1;
@@ -165,13 +165,11 @@ const ELEMENT_FORMAT_TO_TYPE = {
165
165
  [IS_ALIGN_RIGHT]: 'right'
166
166
  };
167
167
  const TEXT_MODE_TO_TYPE = {
168
- inert: IS_INERT,
169
168
  normal: IS_NORMAL,
170
169
  segmented: IS_SEGMENTED,
171
170
  token: IS_TOKEN
172
171
  };
173
172
  const TEXT_TYPE_TO_MODE = {
174
- [IS_INERT]: 'inert',
175
173
  [IS_NORMAL]: 'normal',
176
174
  [IS_SEGMENTED]: 'segmented',
177
175
  [IS_TOKEN]: 'token'
@@ -490,11 +488,8 @@ function getTextDirection(text) {
490
488
 
491
489
  return null;
492
490
  }
493
- function $isTokenOrInertOrSegmented(node) {
494
- return $isTokenOrInert(node) || node.isSegmented();
495
- }
496
- function $isTokenOrInert(node) {
497
- return node.isToken() || node.isInert();
491
+ function $isTokenOrSegmented(node) {
492
+ return node.isToken() || node.isSegmented();
498
493
  }
499
494
 
500
495
  function isDOMNodeLexicalTextNode(node) {
@@ -660,6 +655,10 @@ function $setCompositionKey(compositionKey) {
660
655
  }
661
656
  }
662
657
  function $getCompositionKey() {
658
+ if (isCurrentlyReadOnlyMode()) {
659
+ return null;
660
+ }
661
+
663
662
  const editor = getActiveEditor();
664
663
  return editor._compositionKey;
665
664
  }
@@ -886,7 +885,7 @@ function $updateTextNodeFromDOMContent(textNode, textContent, anchorOffset, focu
886
885
  const parent = node.getParent();
887
886
  const prevSelection = $getPreviousSelection();
888
887
 
889
- if ($isTokenOrInert(node) || $getCompositionKey() !== null && !isComposing || // Check if character was added at the start, and we need
888
+ if (node.isToken() || $getCompositionKey() !== null && !isComposing || // Check if character was added at the start, and we need
890
889
  // to clear this input from occurring as that action wasn't
891
890
  // permitted.
892
891
  parent !== null && $isRangeSelection(prevSelection) && !parent.canInsertTextBefore() && prevSelection.anchor.offset === 0) {
@@ -918,7 +917,10 @@ function $updateTextNodeFromDOMContent(textNode, textContent, anchorOffset, focu
918
917
  function $previousSiblingDoesNotAcceptText(node) {
919
918
  const previousSibling = node.getPreviousSibling();
920
919
  return ($isTextNode(previousSibling) || $isElementNode(previousSibling) && previousSibling.isInline()) && !previousSibling.canInsertTextAfter();
921
- }
920
+ } // This function is connected to $shouldPreventDefaultAndInsertText and determines whether the
921
+ // TextNode boundaries are writable or we should use the previous/next sibling instead. For example,
922
+ // in the case of a LinkNode, boundaries are not writable.
923
+
922
924
 
923
925
  function $shouldInsertTextAfterOrBeforeTextNode(selection, node) {
924
926
  if (node.isSegmented()) {
@@ -932,9 +934,14 @@ function $shouldInsertTextAfterOrBeforeTextNode(selection, node) {
932
934
  const offset = selection.anchor.offset;
933
935
  const parent = node.getParentOrThrow();
934
936
  const isToken = node.isToken();
935
- const shouldInsertTextBefore = offset === 0 && (!node.canInsertTextBefore() || !parent.canInsertTextBefore() || isToken || $previousSiblingDoesNotAcceptText(node));
936
- const shouldInsertTextAfter = node.getTextContentSize() === offset && (!node.canInsertTextBefore() || !parent.canInsertTextBefore() || isToken);
937
- return shouldInsertTextBefore || shouldInsertTextAfter;
937
+
938
+ if (offset === 0) {
939
+ return !node.canInsertTextBefore() || !parent.canInsertTextBefore() || isToken || $previousSiblingDoesNotAcceptText(node);
940
+ } else if (offset === node.getTextContentSize()) {
941
+ return !node.canInsertTextAfter() || !parent.canInsertTextAfter() || isToken;
942
+ } else {
943
+ return false;
944
+ }
938
945
  } // This function is used to determine if Lexical should attempt to override
939
946
  // the default browser behavior for insertion of text and use its own internal
940
947
  // heuristics. This is an extremely important function, and makes much of Lexical
@@ -955,7 +962,7 @@ function $shouldPreventDefaultAndInsertText(selection, text) {
955
962
  return anchorKey !== focus.key || // If we're working with a non-text node.
956
963
  !$isTextNode(anchorNode) || // If we are replacing a range with a single character or grapheme, and not composing.
957
964
  (textLength < 2 || doesContainGrapheme(text)) && anchor.offset !== focus.offset && !anchorNode.isComposing() || // Any non standard text node.
958
- $isTokenOrInertOrSegmented(anchorNode) || // If the text length is more than a single character and we're either
965
+ $isTokenOrSegmented(anchorNode) || // If the text length is more than a single character and we're either
959
966
  // dealing with this in "beforeinput" or where the node has already recently
960
967
  // been changed (thus is dirty).
961
968
  anchorNode.isDirty() && textLength > 1 || // If the DOM selection element is not the same as the backing node
@@ -1274,6 +1281,12 @@ function scrollIntoViewIfNeeded(editor, anchor, rootElement, tags) {
1274
1281
  tags.add('scroll-into-view');
1275
1282
  }
1276
1283
  }
1284
+ function $addUpdateTag(tag) {
1285
+ errorOnReadOnly();
1286
+ const editor = getActiveEditor();
1287
+
1288
+ editor._updateTags.add(tag);
1289
+ }
1277
1290
  function $maybeMoveChildrenSelectionToParent(parentNode, offset = 0) {
1278
1291
  if (offset !== 0) {
1279
1292
  {
@@ -1304,7 +1317,6 @@ function $maybeMoveChildrenSelectionToParent(parentNode, offset = 0) {
1304
1317
 
1305
1318
  return selection;
1306
1319
  }
1307
-
1308
1320
  function $hasAncestor(child, targetNode) {
1309
1321
  let parent = child.getParent();
1310
1322
 
@@ -1318,7 +1330,6 @@ function $hasAncestor(child, targetNode) {
1318
1330
 
1319
1331
  return false;
1320
1332
  }
1321
-
1322
1333
  function getDefaultView(domElem) {
1323
1334
  const ownerDoc = domElem.ownerDocument;
1324
1335
  return ownerDoc && ownerDoc.defaultView || null;
@@ -1334,6 +1345,12 @@ function getWindow(editor) {
1334
1345
 
1335
1346
  return windowObj;
1336
1347
  }
1348
+ function $isInlineElementOrDecoratorNode(node) {
1349
+ return $isElementNode(node) && node.isInline() || $isDecoratorNode(node) && node.isInline();
1350
+ }
1351
+ function $isRootOrShadowRoot(node) {
1352
+ return $isRootNode(node) || $isElementNode(node) && node.isShadowRoot();
1353
+ }
1337
1354
 
1338
1355
  /**
1339
1356
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -1486,6 +1503,37 @@ function $normalizeTextNode(textNode) {
1486
1503
  }
1487
1504
  }
1488
1505
  }
1506
+ function $normalizeSelection(selection) {
1507
+ $normalizePoint(selection.anchor);
1508
+ $normalizePoint(selection.focus);
1509
+ return selection;
1510
+ }
1511
+
1512
+ function $normalizePoint(point) {
1513
+ while (point.type === 'element') {
1514
+ const node = point.getNode();
1515
+ const offset = point.offset;
1516
+ let nextNode;
1517
+ let nextOffsetAtEnd;
1518
+
1519
+ if (offset === node.getChildrenSize()) {
1520
+ nextNode = node.getChildAtIndex(offset - 1);
1521
+ nextOffsetAtEnd = true;
1522
+ } else {
1523
+ nextNode = node.getChildAtIndex(offset);
1524
+ nextOffsetAtEnd = false;
1525
+ }
1526
+
1527
+ if ($isTextNode(nextNode)) {
1528
+ point.set(nextNode.__key, nextOffsetAtEnd ? nextNode.getTextContentSize() : 0, 'text');
1529
+ break;
1530
+ } else if (!$isElementNode(nextNode)) {
1531
+ break;
1532
+ }
1533
+
1534
+ point.set(nextNode.__key, nextOffsetAtEnd ? nextNode.getChildrenSize() : 0, 'element');
1535
+ }
1536
+ }
1489
1537
 
1490
1538
  /**
1491
1539
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -1634,15 +1682,6 @@ function createNode(key, parentDOM, insertDOM) {
1634
1682
  if (!node.isDirectionless()) {
1635
1683
  subTreeDirectionedTextContent += text;
1636
1684
  }
1637
-
1638
- if (node.isInert()) {
1639
- const domStyle = dom.style;
1640
- domStyle.pointerEvents = 'none';
1641
- domStyle.userSelect = 'none';
1642
- dom.contentEditable = 'false'; // To support Safari
1643
-
1644
- domStyle.setProperty('-webkit-user-select', 'none');
1645
- }
1646
1685
  }
1647
1686
 
1648
1687
  subTreeTextContent += text;
@@ -1699,7 +1738,7 @@ function isLastChildLineBreakOrDecorator(children, nodeMap) {
1699
1738
  const childKey = children[children.length - 1];
1700
1739
  const node = nodeMap.get(childKey);
1701
1740
  return $isLineBreakNode(node) || $isDecoratorNode(node);
1702
- } // If we end an element with a LinkBreakNode, then we need to add an additional <br>
1741
+ } // If we end an element with a LineBreakNode, then we need to add an additional <br>
1703
1742
 
1704
1743
 
1705
1744
  function reconcileElementTerminatingLineBreak(prevChildren, nextChildren, dom) {
@@ -2196,7 +2235,7 @@ function onSelectionChange(domSelection, editor, isActive) {
2196
2235
 
2197
2236
  if (selection.isCollapsed()) {
2198
2237
  // Badly interpreted range selection when collapsed - #1482
2199
- if (domSelection.type === 'Range') {
2238
+ if (domSelection.type === 'Range' && domSelection.anchorNode === domSelection.focusNode) {
2200
2239
  selection.dirty = true;
2201
2240
  } // If we have marked a collapsed selection format, and we're
2202
2241
  // within the given time range – then attempt to use that format
@@ -2294,7 +2333,7 @@ function $applyTargetRange(selection, event) {
2294
2333
  }
2295
2334
 
2296
2335
  function $canRemoveText(anchorNode, focusNode) {
2297
- return anchorNode !== focusNode || $isElementNode(anchorNode) || $isElementNode(focusNode) || !$isTokenOrInert(anchorNode) || !$isTokenOrInert(focusNode);
2336
+ return anchorNode !== focusNode || $isElementNode(anchorNode) || $isElementNode(focusNode) || !anchorNode.isToken() || !focusNode.isToken();
2298
2337
  }
2299
2338
 
2300
2339
  function isPossiblyAndroidKeyPress(timeStamp) {
@@ -2332,7 +2371,7 @@ function onBeforeInput(event, editor) {
2332
2371
 
2333
2372
  if ($isRangeSelection(selection)) {
2334
2373
  // Used for handling backspace in Android.
2335
- if (isPossiblyAndroidKeyPress(event.timeStamp) && selection.anchor.key === selection.focus.key) {
2374
+ if (isPossiblyAndroidKeyPress(event.timeStamp) && editor.isComposing() && selection.anchor.key === selection.focus.key) {
2336
2375
  $setCompositionKey(null);
2337
2376
  lastKeyDownTimeStamp = 0; // Fixes an Android bug where selection flickers when backspacing
2338
2377
 
@@ -3173,6 +3212,28 @@ class NodeSelection {
3173
3212
  insertText() {// Do nothing?
3174
3213
  }
3175
3214
 
3215
+ insertNodes(nodes, selectStart) {
3216
+ const selectedNodes = this.getNodes();
3217
+ const selectedNodesLength = selectedNodes.length;
3218
+ const lastSelectedNode = selectedNodes[selectedNodesLength - 1];
3219
+ let selectionAtEnd; // Insert nodes
3220
+
3221
+ if ($isTextNode(lastSelectedNode)) {
3222
+ selectionAtEnd = lastSelectedNode.select();
3223
+ } else {
3224
+ const index = lastSelectedNode.getIndexWithinParent() + 1;
3225
+ selectionAtEnd = lastSelectedNode.getParentOrThrow().select(index, index);
3226
+ }
3227
+
3228
+ selectionAtEnd.insertNodes(nodes, selectStart); // Remove selected nodes
3229
+
3230
+ for (let i = 0; i < selectedNodesLength; i++) {
3231
+ selectedNodes[i].remove();
3232
+ }
3233
+
3234
+ return true;
3235
+ }
3236
+
3176
3237
  getNodes() {
3177
3238
  const cachedNodes = this._cachedNodes;
3178
3239
 
@@ -3225,7 +3286,7 @@ class GridSelection {
3225
3286
  }
3226
3287
 
3227
3288
  is(selection) {
3228
- if (!$isGridSelection(selection)) {
3289
+ if (!DEPRECATED_$isGridSelection(selection)) {
3229
3290
  return false;
3230
3291
  }
3231
3292
 
@@ -3266,6 +3327,12 @@ class GridSelection {
3266
3327
  insertText() {// Do nothing?
3267
3328
  }
3268
3329
 
3330
+ insertNodes(nodes, selectStart) {
3331
+ const focusNode = this.focus.getNode();
3332
+ const selection = $normalizeSelection(focusNode.select(0, focusNode.getChildrenSize()));
3333
+ return selection.insertNodes(nodes, selectStart);
3334
+ }
3335
+
3269
3336
  getShape() {
3270
3337
  const anchorCellNode = $getNodeByKey(this.anchor.key);
3271
3338
 
@@ -3311,7 +3378,7 @@ class GridSelection {
3311
3378
  } = this.getShape();
3312
3379
  const gridNode = $getNodeByKey(this.gridKey);
3313
3380
 
3314
- if (!$isGridNode(gridNode)) {
3381
+ if (!DEPRECATED_$isGridNode(gridNode)) {
3315
3382
  {
3316
3383
  throw Error(`getNodes: expected to find GridNode`);
3317
3384
  }
@@ -3324,7 +3391,7 @@ class GridSelection {
3324
3391
  const gridRowNode = gridRowNodes[r];
3325
3392
  nodesSet.add(gridRowNode);
3326
3393
 
3327
- if (!$isGridRowNode(gridRowNode)) {
3394
+ if (!DEPRECATED_$isGridRowNode(gridRowNode)) {
3328
3395
  {
3329
3396
  throw Error(`getNodes: expected to find GridRowNode`);
3330
3397
  }
@@ -3335,7 +3402,7 @@ class GridSelection {
3335
3402
  for (let c = fromX; c <= toX; c++) {
3336
3403
  const gridCellNode = gridCellNodes[c];
3337
3404
 
3338
- if (!$isGridCellNode(gridCellNode)) {
3405
+ if (!DEPRECATED_$isGridCellNode(gridCellNode)) {
3339
3406
  {
3340
3407
  throw Error(`getNodes: expected to find GridCellNode`);
3341
3408
  }
@@ -3376,7 +3443,7 @@ class GridSelection {
3376
3443
  }
3377
3444
 
3378
3445
  }
3379
- function $isGridSelection(x) {
3446
+ function DEPRECATED_$isGridSelection(x) {
3380
3447
  return x instanceof GridSelection;
3381
3448
  }
3382
3449
  class RangeSelection {
@@ -3602,7 +3669,7 @@ class RangeSelection {
3602
3669
  if (this.isCollapsed() && startOffset === firstNodeTextLength && (firstNode.isSegmented() || firstNode.isToken() || !firstNode.canInsertTextAfter() || !firstNodeParent.canInsertTextAfter() && firstNode.getNextSibling() === null)) {
3603
3670
  let nextSibling = firstNode.getNextSibling();
3604
3671
 
3605
- if (!$isTextNode(nextSibling) || $isTokenOrInertOrSegmented(nextSibling)) {
3672
+ if (!$isTextNode(nextSibling) || $isTokenOrSegmented(nextSibling)) {
3606
3673
  nextSibling = $createTextNode();
3607
3674
  nextSibling.setFormat(format);
3608
3675
 
@@ -3623,7 +3690,7 @@ class RangeSelection {
3623
3690
  } else if (this.isCollapsed() && startOffset === 0 && (firstNode.isSegmented() || firstNode.isToken() || !firstNode.canInsertTextBefore() || !firstNodeParent.canInsertTextBefore() && firstNode.getPreviousSibling() === null)) {
3624
3691
  let prevSibling = firstNode.getPreviousSibling();
3625
3692
 
3626
- if (!$isTextNode(prevSibling) || $isTokenOrInertOrSegmented(prevSibling)) {
3693
+ if (!$isTextNode(prevSibling) || $isTokenOrSegmented(prevSibling)) {
3627
3694
  prevSibling = $createTextNode();
3628
3695
  prevSibling.setFormat(format);
3629
3696
 
@@ -3662,7 +3729,7 @@ class RangeSelection {
3662
3729
  }
3663
3730
 
3664
3731
  if (selectedNodesLength === 1) {
3665
- if ($isTokenOrInert(firstNode)) {
3732
+ if (firstNode.isToken()) {
3666
3733
  const textNode = $createTextNode(text);
3667
3734
  textNode.select();
3668
3735
  firstNode.replace(textNode);
@@ -3731,7 +3798,7 @@ class RangeSelection {
3731
3798
 
3732
3799
 
3733
3800
  if (endPoint.type === 'text' && (endOffset !== 0 || lastNode.getTextContent() === '') || endPoint.type === 'element' && lastNode.getIndexWithinParent() < endOffset) {
3734
- if ($isTextNode(lastNode) && !$isTokenOrInert(lastNode) && endOffset !== lastNode.getTextContentSize()) {
3801
+ if ($isTextNode(lastNode) && !lastNode.isToken() && endOffset !== lastNode.getTextContentSize()) {
3735
3802
  if (lastNode.isSegmented()) {
3736
3803
  const textNode = $createTextNode(lastNode.getTextContent());
3737
3804
  lastNode.replace(textNode);
@@ -3807,7 +3874,7 @@ class RangeSelection {
3807
3874
  // can have side-effects (in the case of hashtags).
3808
3875
 
3809
3876
 
3810
- if (!$isTokenOrInert(firstNode)) {
3877
+ if (!firstNode.isToken()) {
3811
3878
  firstNode = firstNode.spliceText(startOffset, firstNodeTextLength - startOffset, text, true);
3812
3879
 
3813
3880
  if (firstNode.getTextContent() === '') {
@@ -3987,7 +4054,7 @@ class RangeSelection {
3987
4054
  // append them after the last node we're inserting.
3988
4055
 
3989
4056
  const nextSiblings = anchorNode.getNextSiblings();
3990
- const topLevelElement = $isRootNode(anchorNode) ? null : anchorNode.getTopLevelElementOrThrow();
4057
+ const topLevelElement = $isRootOrShadowRoot(anchorNode) ? null : anchorNode.getTopLevelElementOrThrow();
3991
4058
 
3992
4059
  if ($isTextNode(anchorNode)) {
3993
4060
  const textContent = anchorNode.getTextContent();
@@ -4005,8 +4072,8 @@ class RangeSelection {
4005
4072
  siblings.push(anchorNode);
4006
4073
  } else if (anchorOffset === textContentLength) {
4007
4074
  target = anchorNode;
4008
- } else if ($isTokenOrInert(anchorNode)) {
4009
- // Do nothing if we're inside a token/inert node
4075
+ } else if (anchorNode.isToken()) {
4076
+ // Do nothing if we're inside a token node
4010
4077
  return false;
4011
4078
  } else {
4012
4079
  // If we started with a range selected grab the danglingText after the
@@ -4114,7 +4181,7 @@ class RangeSelection {
4114
4181
 
4115
4182
  target = topLevelElement;
4116
4183
  }
4117
- } else if (didReplaceOrMerge && !$isDecoratorNode(node) && $isRootNode(target.getParent())) {
4184
+ } else if (didReplaceOrMerge && !$isDecoratorNode(node) && $isRootOrShadowRoot(target.getParent())) {
4118
4185
  {
4119
4186
  throw Error(`insertNodes: cannot insert a non-element into a root node`);
4120
4187
  }
@@ -4125,7 +4192,7 @@ class RangeSelection {
4125
4192
  if ($isElementNode(target) && !target.isInline()) {
4126
4193
  lastNode = node;
4127
4194
 
4128
- if ($isDecoratorNode(node) && node.isTopLevel()) {
4195
+ if ($isDecoratorNode(node) && !node.isInline()) {
4129
4196
  target = target.insertAfter(node);
4130
4197
  } else if (!$isElementNode(node)) {
4131
4198
  const firstChild = target.getFirstChild();
@@ -4142,7 +4209,7 @@ class RangeSelection {
4142
4209
  continue;
4143
4210
  }
4144
4211
 
4145
- if ($isRootNode(target)) {
4212
+ if ($isRootOrShadowRoot(target)) {
4146
4213
  const placementNode = target.getChildAtIndex(anchorOffset);
4147
4214
 
4148
4215
  if (placementNode !== null) {
@@ -4156,7 +4223,7 @@ class RangeSelection {
4156
4223
  target = target.insertAfter(node);
4157
4224
  }
4158
4225
  }
4159
- } else if (!$isElementNode(node) || $isElementNode(node) && node.isInline() || $isDecoratorNode(target) && target.isTopLevel()) {
4226
+ } else if (!$isElementNode(node) || $isElementNode(node) && node.isInline() || $isDecoratorNode(target) && !target.isInline()) {
4160
4227
  lastNode = node;
4161
4228
  target = target.insertAfter(node);
4162
4229
  } else {
@@ -4213,7 +4280,7 @@ class RangeSelection {
4213
4280
  const sibling = siblings[i];
4214
4281
  const prevParent = sibling.getParentOrThrow();
4215
4282
 
4216
- if ($isElementNode(target) && !$isBlockElementNode(sibling) && !($isDecoratorNode(sibling) && sibling.isTopLevel())) {
4283
+ if ($isElementNode(target) && !$isBlockElementNode(sibling) && !($isDecoratorNode(sibling) && !sibling.isInline())) {
4217
4284
  if (originalTarget === target) {
4218
4285
  target.append(sibling);
4219
4286
  } else {
@@ -4301,7 +4368,7 @@ class RangeSelection {
4301
4368
  } else {
4302
4369
  currentElement = anchor.getNode();
4303
4370
 
4304
- if ($isRootNode(currentElement)) {
4371
+ if ($isRootOrShadowRoot(currentElement)) {
4305
4372
  const paragraph = $createParagraphNode();
4306
4373
  const child = currentElement.getChildAtIndex(anchorOffset);
4307
4374
  paragraph.select();
@@ -4837,7 +4904,7 @@ function resolveSelectionPointOnBoundary(point, isBackward, isCollapsed) {
4837
4904
  point.offset = prevSibling.getChildrenSize(); // @ts-expect-error: intentional
4838
4905
 
4839
4906
  point.type = 'element';
4840
- } else if ($isTextNode(prevSibling) && !prevSibling.isInert()) {
4907
+ } else if ($isTextNode(prevSibling)) {
4841
4908
  point.key = prevSibling.__key;
4842
4909
  point.offset = prevSibling.getTextContent().length;
4843
4910
  }
@@ -4950,7 +5017,7 @@ function $createRangeSelection() {
4950
5017
  function $createNodeSelection() {
4951
5018
  return new NodeSelection(new Set());
4952
5019
  }
4953
- function $createGridSelection() {
5020
+ function DEPRECATED_$createGridSelection() {
4954
5021
  const anchor = $createPoint('root', 0, 'element');
4955
5022
  const focus = $createPoint('root', 0, 'element');
4956
5023
  return new GridSelection('root', anchor, focus);
@@ -4960,7 +5027,7 @@ function internalCreateSelection(editor) {
4960
5027
  const lastSelection = currentEditorState._selection;
4961
5028
  const domSelection = getDOMSelection();
4962
5029
 
4963
- if ($isNodeSelection(lastSelection) || $isGridSelection(lastSelection)) {
5030
+ if ($isNodeSelection(lastSelection) || DEPRECATED_$isGridSelection(lastSelection)) {
4964
5031
  return lastSelection.clone();
4965
5032
  }
4966
5033
 
@@ -5313,6 +5380,15 @@ function updateDOMSelection(prevSelection, nextSelection, editor, domSelection,
5313
5380
  // should happen.
5314
5381
  }
5315
5382
  }
5383
+ function $insertNodes(nodes, selectStart) {
5384
+ let selection = $getSelection();
5385
+
5386
+ if (selection === null) {
5387
+ selection = $getRoot().selectEnd();
5388
+ }
5389
+
5390
+ return selection.insertNodes(nodes, selectStart);
5391
+ }
5316
5392
 
5317
5393
  /**
5318
5394
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -5693,7 +5769,6 @@ function commitPendingUpdates(editor) {
5693
5769
  const dirtyElements = editor._dirtyElements;
5694
5770
  const normalizedNodes = editor._normalizedNodes;
5695
5771
  const tags = editor._updateTags;
5696
- const pendingDecorators = editor._pendingDecorators;
5697
5772
  const deferred = editor._deferred;
5698
5773
 
5699
5774
  if (needsUpdate) {
@@ -5730,6 +5805,12 @@ function commitPendingUpdates(editor) {
5730
5805
  if (mutatedNodes !== null) {
5731
5806
  triggerMutationListeners(editor, currentEditorState, pendingEditorState, mutatedNodes, tags, dirtyLeaves);
5732
5807
  }
5808
+ /**
5809
+ * Capture pendingDecorators after garbage collecting detached decorators
5810
+ */
5811
+
5812
+
5813
+ const pendingDecorators = editor._pendingDecorators;
5733
5814
 
5734
5815
  if (pendingDecorators !== null) {
5735
5816
  editor._decorators = pendingDecorators;
@@ -6092,11 +6173,11 @@ function removeNode(nodeToRemove, restoreSelection, preserveEmptyParent) {
6092
6173
  $updateElementSelectionOnCreateDeleteNode(selection, parent, index, -1);
6093
6174
  }
6094
6175
 
6095
- if (!preserveEmptyParent && parent !== null && !$isRootNode(parent) && !parent.canBeEmpty() && parent.isEmpty()) {
6176
+ if (!preserveEmptyParent && !$isRootOrShadowRoot(parent) && !parent.canBeEmpty() && parent.isEmpty()) {
6096
6177
  removeNode(parent, restoreSelection);
6097
6178
  }
6098
6179
 
6099
- if (parent !== null && $isRootNode(parent) && parent.isEmpty()) {
6180
+ if ($isRootNode(parent) && parent.isEmpty()) {
6100
6181
  parent.selectEnd();
6101
6182
  }
6102
6183
  }
@@ -6236,7 +6317,7 @@ class LexicalNode {
6236
6317
  while (node !== null) {
6237
6318
  const parent = node.getParent();
6238
6319
 
6239
- if ($isRootNode(parent) && ($isElementNode(node) || $isDecoratorNode(node) && node.isTopLevel())) {
6320
+ if ($isRootOrShadowRoot(parent)) {
6240
6321
  return node;
6241
6322
  }
6242
6323
 
@@ -6579,12 +6660,12 @@ class LexicalNode {
6579
6660
  return mutableNode;
6580
6661
  }
6581
6662
 
6582
- getTextContent(_includeInert, _includeDirectionless) {
6663
+ getTextContent() {
6583
6664
  return '';
6584
6665
  }
6585
6666
 
6586
- getTextContentSize(includeInert, includeDirectionless) {
6587
- return this.getTextContent(includeInert, includeDirectionless).length;
6667
+ getTextContentSize() {
6668
+ return this.getTextContent().length;
6588
6669
  } // View
6589
6670
 
6590
6671
 
@@ -6798,7 +6879,7 @@ function errorOnTypeKlassMismatch(type, klass) {
6798
6879
 
6799
6880
  if (registeredNode === undefined) {
6800
6881
  {
6801
- throw Error(`Create node: Attempted to create node ${klass.name} that was not previously registered on the editor. You can use register your custom nodes.`);
6882
+ throw Error(`Create node: Attempted to create node ${klass.name} that was not configured to be used on the editor.`);
6802
6883
  }
6803
6884
  }
6804
6885
 
@@ -6835,8 +6916,8 @@ class DecoratorNode extends LexicalNode {
6835
6916
  return false;
6836
6917
  }
6837
6918
 
6838
- isTopLevel() {
6839
- return false;
6919
+ isInline() {
6920
+ return true;
6840
6921
  }
6841
6922
 
6842
6923
  }
@@ -6925,7 +7006,7 @@ class ElementNode extends LexicalNode {
6925
7006
  return parent.getLastChild() === self;
6926
7007
  }
6927
7008
 
6928
- getAllTextNodes(includeInert) {
7009
+ getAllTextNodes() {
6929
7010
  const textNodes = [];
6930
7011
  const self = this.getLatest();
6931
7012
  const children = self.__children;
@@ -6933,10 +7014,10 @@ class ElementNode extends LexicalNode {
6933
7014
  for (let i = 0; i < children.length; i++) {
6934
7015
  const childNode = $getNodeByKey(children[i]);
6935
7016
 
6936
- if ($isTextNode(childNode) && (includeInert || !childNode.isInert())) {
7017
+ if ($isTextNode(childNode)) {
6937
7018
  textNodes.push(childNode);
6938
7019
  } else if ($isElementNode(childNode)) {
6939
- const subChildrenNodes = childNode.getAllTextNodes(includeInert);
7020
+ const subChildrenNodes = childNode.getAllTextNodes();
6940
7021
  textNodes.push(...subChildrenNodes);
6941
7022
  }
6942
7023
  }
@@ -7032,6 +7113,18 @@ class ElementNode extends LexicalNode {
7032
7113
  return $getNodeByKey(children[childrenLength - 1]);
7033
7114
  }
7034
7115
 
7116
+ getLastChildOrThrow() {
7117
+ const lastChild = this.getLastChild();
7118
+
7119
+ if (lastChild === null) {
7120
+ {
7121
+ throw Error(`Expected node ${this.__key} to have a last child.`);
7122
+ }
7123
+ }
7124
+
7125
+ return lastChild;
7126
+ }
7127
+
7035
7128
  getChildAtIndex(index) {
7036
7129
  const self = this.getLatest();
7037
7130
  const children = self.__children;
@@ -7044,14 +7137,14 @@ class ElementNode extends LexicalNode {
7044
7137
  return $getNodeByKey(key);
7045
7138
  }
7046
7139
 
7047
- getTextContent(includeInert, includeDirectionless) {
7140
+ getTextContent() {
7048
7141
  let textContent = '';
7049
7142
  const children = this.getChildren();
7050
7143
  const childrenLength = children.length;
7051
7144
 
7052
7145
  for (let i = 0; i < childrenLength; i++) {
7053
7146
  const child = children[i];
7054
- textContent += child.getTextContent(includeInert, includeDirectionless);
7147
+ textContent += child.getTextContent();
7055
7148
 
7056
7149
  if ($isElementNode(child) && i !== childrenLength - 1 && !child.isInline()) {
7057
7150
  textContent += DOUBLE_LINE_BREAK;
@@ -7263,7 +7356,7 @@ class ElementNode extends LexicalNode {
7263
7356
  } // Cleanup if node can't be empty
7264
7357
 
7265
7358
 
7266
- if (writableSelfChildren.length === 0 && !this.canBeEmpty() && !$isRootNode(this)) {
7359
+ if (writableSelfChildren.length === 0 && !this.canBeEmpty() && !$isRootOrShadowRoot(this)) {
7267
7360
  this.remove();
7268
7361
  }
7269
7362
  }
@@ -7331,6 +7424,14 @@ class ElementNode extends LexicalNode {
7331
7424
 
7332
7425
  isInline() {
7333
7426
  return false;
7427
+ } // A shadow root is a Node that behaves like RootNode. The shadow root (and RootNode) mark the
7428
+ // end of the hiercharchy, most implementations should treat it as there's nothing (upwards)
7429
+ // beyond this point. For example, node.getTopElement(), when performed inside a TableCellNode
7430
+ // will return the immediate first child underneath TableCellNode instead of RootNode.
7431
+
7432
+
7433
+ isShadowRoot() {
7434
+ return false;
7334
7435
  }
7335
7436
 
7336
7437
  canMergeWith(node) {
@@ -7376,16 +7477,16 @@ class RootNode extends ElementNode {
7376
7477
  }
7377
7478
  }
7378
7479
 
7379
- getTextContent(includeInert, includeDirectionless) {
7480
+ getTextContent() {
7380
7481
  const cachedText = this.__cachedText;
7381
7482
 
7382
7483
  if (isCurrentlyReadOnlyMode() || getActiveEditor()._dirtyType === NO_DIRTY_NODES) {
7383
- if (cachedText !== null && (!includeInert || includeDirectionless !== false)) {
7484
+ if (cachedText !== null) {
7384
7485
  return cachedText;
7385
7486
  }
7386
7487
  }
7387
7488
 
7388
- return super.getTextContent(includeInert, includeDirectionless);
7489
+ return super.getTextContent();
7389
7490
  }
7390
7491
 
7391
7492
  remove() {
@@ -7836,11 +7937,6 @@ class TextNode extends LexicalNode {
7836
7937
  return self.__mode === IS_SEGMENTED;
7837
7938
  }
7838
7939
 
7839
- isInert() {
7840
- const self = this.getLatest();
7841
- return self.__mode === IS_INERT;
7842
- }
7843
-
7844
7940
  isDirectionless() {
7845
7941
  const self = this.getLatest();
7846
7942
  return (self.__detail & IS_DIRECTIONLESS) !== 0;
@@ -7860,11 +7956,7 @@ class TextNode extends LexicalNode {
7860
7956
  return this.__type === 'text' && this.__mode === 0;
7861
7957
  }
7862
7958
 
7863
- getTextContent(includeInert, includeDirectionless) {
7864
- if (!includeInert && this.isInert() || includeDirectionless === false && this.isDirectionless()) {
7865
- return '';
7866
- }
7867
-
7959
+ getTextContent() {
7868
7960
  const self = this.getLatest();
7869
7961
  return self.__text;
7870
7962
  }
@@ -8383,18 +8475,17 @@ function convertBringAttentionToElement(domNode) {
8383
8475
  };
8384
8476
  }
8385
8477
 
8386
- function convertTextDOMNode(domNode) {
8387
- const {
8388
- parentElement
8389
- } = domNode;
8390
- const textContent = domNode.textContent || '';
8391
- const textContentTrim = textContent.trim();
8392
- const isPre = parentElement != null && parentElement.tagName.toLowerCase() === 'pre';
8478
+ function convertTextDOMNode(domNode, _parent, preformatted) {
8479
+ let textContent = domNode.textContent || '';
8393
8480
 
8394
- if (!isPre && textContentTrim.length === 0 && textContent.includes('\n')) {
8395
- return {
8396
- node: null
8397
- };
8481
+ if (!preformatted && /\n/.test(textContent)) {
8482
+ textContent = textContent.replace(/\r?\n/gm, ' ');
8483
+
8484
+ if (textContent.trim().length === 0) {
8485
+ return {
8486
+ node: null
8487
+ };
8488
+ }
8398
8489
  }
8399
8490
 
8400
8491
  return {
@@ -8491,6 +8582,24 @@ class ParagraphNode extends ElementNode {
8491
8582
  element.append(document.createElement('br'));
8492
8583
  }
8493
8584
 
8585
+ if (element) {
8586
+ const formatType = this.getFormatType();
8587
+ element.style.textAlign = formatType;
8588
+ const direction = this.getDirection();
8589
+
8590
+ if (direction) {
8591
+ element.dir = direction;
8592
+ }
8593
+
8594
+ const indent = this.getIndent();
8595
+
8596
+ if (indent > 0) {
8597
+ // padding-inline-start is not widely supported in email HTML, but
8598
+ // Lexical Reconciler uses padding-inline-start. Using text-indent instead.
8599
+ element.style.textIndent = `${indent * 20}px`;
8600
+ }
8601
+ }
8602
+
8494
8603
  return {
8495
8604
  element
8496
8605
  };
@@ -8648,7 +8757,7 @@ function createEditor(editorConfig) {
8648
8757
  const initialEditorState = config.editorState;
8649
8758
  const nodes = [RootNode, TextNode, LineBreakNode, ParagraphNode, ...(config.nodes || [])];
8650
8759
  const onError = config.onError;
8651
- const isEditable = config.editable || true;
8760
+ const isEditable = config.editable !== undefined ? config.editable : true;
8652
8761
  let registeredNodes;
8653
8762
 
8654
8763
  if (editorConfig === undefined && activeEditor !== null) {
@@ -8763,7 +8872,9 @@ class LexicalEditor {
8763
8872
 
8764
8873
  this._key = createUID();
8765
8874
  this._onError = onError;
8766
- this._htmlConversions = htmlConversions;
8875
+ this._htmlConversions = htmlConversions; // We don't actually make use of the `editable` argument above.
8876
+ // Doing so, causes e2e tests around the lock to fail.
8877
+
8767
8878
  this._editable = true;
8768
8879
  this._headless = false;
8769
8880
  this._window = null;
@@ -9080,7 +9191,7 @@ class LexicalEditor {
9080
9191
  * LICENSE file in the root directory of this source tree.
9081
9192
  *
9082
9193
  */
9083
- const VERSION = '0.4.0';
9194
+ const VERSION = '0.4.1';
9084
9195
 
9085
9196
  /**
9086
9197
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -9091,7 +9202,7 @@ const VERSION = '0.4.0';
9091
9202
  */
9092
9203
 
9093
9204
  /** @noInheritDoc */
9094
- class GridCellNode extends ElementNode {
9205
+ class DEPRECATED_GridCellNode extends ElementNode {
9095
9206
  /** @internal */
9096
9207
  constructor(colSpan, key) {
9097
9208
  super(key);
@@ -9105,8 +9216,8 @@ class GridCellNode extends ElementNode {
9105
9216
  }
9106
9217
 
9107
9218
  }
9108
- function $isGridCellNode(node) {
9109
- return node instanceof GridCellNode;
9219
+ function DEPRECATED_$isGridCellNode(node) {
9220
+ return node instanceof DEPRECATED_GridCellNode;
9110
9221
  }
9111
9222
 
9112
9223
  /**
@@ -9116,9 +9227,9 @@ function $isGridCellNode(node) {
9116
9227
  * LICENSE file in the root directory of this source tree.
9117
9228
  *
9118
9229
  */
9119
- class GridNode extends ElementNode {}
9120
- function $isGridNode(node) {
9121
- return node instanceof GridNode;
9230
+ class DEPRECATED_GridNode extends ElementNode {}
9231
+ function DEPRECATED_$isGridNode(node) {
9232
+ return node instanceof DEPRECATED_GridNode;
9122
9233
  }
9123
9234
 
9124
9235
  /**
@@ -9128,12 +9239,12 @@ function $isGridNode(node) {
9128
9239
  * LICENSE file in the root directory of this source tree.
9129
9240
  *
9130
9241
  */
9131
- class GridRowNode extends ElementNode {}
9132
- function $isGridRowNode(node) {
9133
- return node instanceof GridRowNode;
9242
+ class DEPRECATED_GridRowNode extends ElementNode {}
9243
+ function DEPRECATED_$isGridRowNode(node) {
9244
+ return node instanceof DEPRECATED_GridRowNode;
9134
9245
  }
9135
9246
 
9136
- exports.$createGridSelection = $createGridSelection;
9247
+ exports.$addUpdateTag = $addUpdateTag;
9137
9248
  exports.$createLineBreakNode = $createLineBreakNode;
9138
9249
  exports.$createNodeSelection = $createNodeSelection;
9139
9250
  exports.$createParagraphNode = $createParagraphNode;
@@ -9145,18 +9256,18 @@ exports.$getNodeByKey = $getNodeByKey;
9145
9256
  exports.$getPreviousSelection = $getPreviousSelection;
9146
9257
  exports.$getRoot = $getRoot;
9147
9258
  exports.$getSelection = $getSelection;
9259
+ exports.$hasAncestor = $hasAncestor;
9260
+ exports.$insertNodes = $insertNodes;
9148
9261
  exports.$isDecoratorNode = $isDecoratorNode;
9149
9262
  exports.$isElementNode = $isElementNode;
9150
- exports.$isGridCellNode = $isGridCellNode;
9151
- exports.$isGridNode = $isGridNode;
9152
- exports.$isGridRowNode = $isGridRowNode;
9153
- exports.$isGridSelection = $isGridSelection;
9263
+ exports.$isInlineElementOrDecoratorNode = $isInlineElementOrDecoratorNode;
9154
9264
  exports.$isLeafNode = $isLeafNode;
9155
9265
  exports.$isLineBreakNode = $isLineBreakNode;
9156
9266
  exports.$isNodeSelection = $isNodeSelection;
9157
9267
  exports.$isParagraphNode = $isParagraphNode;
9158
9268
  exports.$isRangeSelection = $isRangeSelection;
9159
9269
  exports.$isRootNode = $isRootNode;
9270
+ exports.$isRootOrShadowRoot = $isRootOrShadowRoot;
9160
9271
  exports.$isTextNode = $isTextNode;
9161
9272
  exports.$nodesOfType = $nodesOfType;
9162
9273
  exports.$parseSerializedNode = $parseSerializedNode;
@@ -9179,6 +9290,14 @@ exports.CUT_COMMAND = CUT_COMMAND;
9179
9290
  exports.DELETE_CHARACTER_COMMAND = DELETE_CHARACTER_COMMAND;
9180
9291
  exports.DELETE_LINE_COMMAND = DELETE_LINE_COMMAND;
9181
9292
  exports.DELETE_WORD_COMMAND = DELETE_WORD_COMMAND;
9293
+ exports.DEPRECATED_$createGridSelection = DEPRECATED_$createGridSelection;
9294
+ exports.DEPRECATED_$isGridCellNode = DEPRECATED_$isGridCellNode;
9295
+ exports.DEPRECATED_$isGridNode = DEPRECATED_$isGridNode;
9296
+ exports.DEPRECATED_$isGridRowNode = DEPRECATED_$isGridRowNode;
9297
+ exports.DEPRECATED_$isGridSelection = DEPRECATED_$isGridSelection;
9298
+ exports.DEPRECATED_GridCellNode = DEPRECATED_GridCellNode;
9299
+ exports.DEPRECATED_GridNode = DEPRECATED_GridNode;
9300
+ exports.DEPRECATED_GridRowNode = DEPRECATED_GridRowNode;
9182
9301
  exports.DRAGEND_COMMAND = DRAGEND_COMMAND;
9183
9302
  exports.DRAGOVER_COMMAND = DRAGOVER_COMMAND;
9184
9303
  exports.DRAGSTART_COMMAND = DRAGSTART_COMMAND;
@@ -9188,9 +9307,6 @@ exports.ElementNode = ElementNode;
9188
9307
  exports.FOCUS_COMMAND = FOCUS_COMMAND;
9189
9308
  exports.FORMAT_ELEMENT_COMMAND = FORMAT_ELEMENT_COMMAND;
9190
9309
  exports.FORMAT_TEXT_COMMAND = FORMAT_TEXT_COMMAND;
9191
- exports.GridCellNode = GridCellNode;
9192
- exports.GridNode = GridNode;
9193
- exports.GridRowNode = GridRowNode;
9194
9310
  exports.INDENT_CONTENT_COMMAND = INDENT_CONTENT_COMMAND;
9195
9311
  exports.INSERT_LINE_BREAK_COMMAND = INSERT_LINE_BREAK_COMMAND;
9196
9312
  exports.INSERT_PARAGRAPH_COMMAND = INSERT_PARAGRAPH_COMMAND;