lexical 0.3.2 → 0.3.5

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
@@ -6,6 +6,58 @@
6
6
  */
7
7
  'use strict';
8
8
 
9
+ /**
10
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
11
+ *
12
+ * This source code is licensed under the MIT license found in the
13
+ * LICENSE file in the root directory of this source tree.
14
+ *
15
+ */
16
+ function createCommand() {
17
+ return {};
18
+ }
19
+ const SELECTION_CHANGE_COMMAND = createCommand();
20
+ const CLICK_COMMAND = createCommand();
21
+ const DELETE_CHARACTER_COMMAND = createCommand();
22
+ const INSERT_LINE_BREAK_COMMAND = createCommand();
23
+ const INSERT_PARAGRAPH_COMMAND = createCommand();
24
+ const CONTROLLED_TEXT_INSERTION_COMMAND = createCommand();
25
+ const PASTE_COMMAND = createCommand();
26
+ const REMOVE_TEXT_COMMAND = createCommand();
27
+ const DELETE_WORD_COMMAND = createCommand();
28
+ const DELETE_LINE_COMMAND = createCommand();
29
+ const FORMAT_TEXT_COMMAND = createCommand();
30
+ const UNDO_COMMAND = createCommand();
31
+ const REDO_COMMAND = createCommand();
32
+ const KEY_ARROW_RIGHT_COMMAND = createCommand();
33
+ const MOVE_TO_END = createCommand();
34
+ const KEY_ARROW_LEFT_COMMAND = createCommand();
35
+ const MOVE_TO_START = createCommand();
36
+ const KEY_ARROW_UP_COMMAND = createCommand();
37
+ const KEY_ARROW_DOWN_COMMAND = createCommand();
38
+ const KEY_ENTER_COMMAND = createCommand();
39
+ const KEY_SPACE_COMMAND = createCommand();
40
+ const KEY_BACKSPACE_COMMAND = createCommand();
41
+ const KEY_ESCAPE_COMMAND = createCommand();
42
+ const KEY_DELETE_COMMAND = createCommand();
43
+ const KEY_TAB_COMMAND = createCommand();
44
+ const INDENT_CONTENT_COMMAND = createCommand();
45
+ const OUTDENT_CONTENT_COMMAND = createCommand();
46
+ const DROP_COMMAND = createCommand();
47
+ const FORMAT_ELEMENT_COMMAND = createCommand();
48
+ const DRAGSTART_COMMAND = createCommand();
49
+ const DRAGOVER_COMMAND = createCommand();
50
+ const DRAGEND_COMMAND = createCommand();
51
+ const COPY_COMMAND = createCommand();
52
+ const CUT_COMMAND = createCommand();
53
+ const CLEAR_EDITOR_COMMAND = createCommand();
54
+ const CLEAR_HISTORY_COMMAND = createCommand();
55
+ const CAN_REDO_COMMAND = createCommand();
56
+ const CAN_UNDO_COMMAND = createCommand();
57
+ const FOCUS_COMMAND = createCommand();
58
+ const BLUR_COMMAND = createCommand();
59
+ const KEY_MODIFIER_COMMAND = createCommand();
60
+
9
61
  /**
10
62
  * Copyright (c) Meta Platforms, Inc. and affiliates.
11
63
  *
@@ -173,12 +225,25 @@ function handleTextMutation(target, node, editor) {
173
225
  $updateTextNodeFromDOMContent(node, text, anchorOffset, focusOffset, false);
174
226
  }
175
227
 
228
+ function shouldUpdateTextNodeFromMutation(selection, targetDOM, targetNode) {
229
+ if ($isRangeSelection(selection)) {
230
+ const anchorNode = selection.anchor.getNode();
231
+
232
+ if (anchorNode.is(targetNode) && selection.format !== anchorNode.getFormat()) {
233
+ return false;
234
+ }
235
+ }
236
+
237
+ return targetDOM.nodeType === DOM_TEXT_TYPE && targetNode.isAttached();
238
+ }
239
+
176
240
  function $flushMutations$1(editor, mutations, observer) {
177
241
  isProcessingMutations = true;
178
242
  const shouldFlushTextMutations = performance.now() - lastTextEntryTimeStamp > TEXT_MUTATION_VARIANCE;
179
243
 
180
244
  try {
181
245
  updateEditor(editor, () => {
246
+ const selection = $getSelection() || getLastSelection(editor);
182
247
  const badDOMTargets = new Map();
183
248
  const rootElement = editor.getRootElement(); // We use the current edtior state, as that reflects what is
184
249
  // actually "on screen".
@@ -200,7 +265,7 @@ function $flushMutations$1(editor, mutations, observer) {
200
265
  if (type === 'characterData') {
201
266
  // Text mutations are deferred and passed to mutation listeners to be
202
267
  // processed outside of the Lexical engine.
203
- if (shouldFlushTextMutations && targetDOM.nodeType === DOM_TEXT_TYPE && $isTextNode(targetNode) && targetNode.isAttached()) {
268
+ if (shouldFlushTextMutations && $isTextNode(targetNode) && shouldUpdateTextNodeFromMutation(selection, targetDOM, targetNode)) {
204
269
  handleTextMutation( // nodeType === DOM_TEXT_TYPE is a Text DOM node
205
270
  targetDOM, targetNode);
206
271
  }
@@ -315,8 +380,6 @@ function $flushMutations$1(editor, mutations, observer) {
315
380
  observer.takeRecords();
316
381
  }
317
382
 
318
- const selection = $getSelection() || getLastSelection(editor);
319
-
320
383
  if (selection !== null) {
321
384
  if (shouldRevertSelection) {
322
385
  selection.dirty = true;
@@ -664,7 +727,6 @@ function $setSelection(selection) {
664
727
  const editorState = getActiveEditorState();
665
728
 
666
729
  if (selection !== null) {
667
- // @ts-ignore
668
730
  {
669
731
  if (Object.isFrozen(selection)) {
670
732
  {
@@ -1173,11 +1235,12 @@ function scrollIntoViewIfNeeded(editor, anchor, rootElement, tags) {
1173
1235
  } else if (rect.top < 0) {
1174
1236
  element.scrollIntoView();
1175
1237
  } else {
1176
- const rootRect = rootElement.getBoundingClientRect();
1238
+ const rootRect = rootElement.getBoundingClientRect(); // Rects can returning decimal numbers that differ due to rounding
1239
+ // differences. So let's normalize the values.
1177
1240
 
1178
- if (rect.bottom > rootRect.bottom) {
1241
+ if (Math.floor(rect.bottom) > Math.floor(rootRect.bottom)) {
1179
1242
  element.scrollIntoView(false);
1180
- } else if (rect.top < rootRect.top) {
1243
+ } else if (Math.floor(rect.top) < Math.floor(rootRect.top)) {
1181
1244
  element.scrollIntoView();
1182
1245
  }
1183
1246
  }
@@ -1473,7 +1536,7 @@ function createNode(key, parentDOM, insertDOM) {
1473
1536
  const text = node.getTextContent();
1474
1537
 
1475
1538
  if ($isDecoratorNode(node)) {
1476
- const decorator = node.decorate(activeEditor$1);
1539
+ const decorator = node.decorate(activeEditor$1, activeEditorConfig);
1477
1540
 
1478
1541
  if (decorator !== null) {
1479
1542
  reconcileDecorator(key, decorator);
@@ -1513,8 +1576,7 @@ function createNode(key, parentDOM, insertDOM) {
1513
1576
  parentDOM.appendChild(dom);
1514
1577
  }
1515
1578
  }
1516
- } // @ts-ignore
1517
-
1579
+ }
1518
1580
 
1519
1581
  {
1520
1582
  // Freeze the node in DEV to prevent accidental mutations
@@ -1789,7 +1851,7 @@ function reconcileNode(key, parentDOM) {
1789
1851
  const text = nextNode.getTextContent();
1790
1852
 
1791
1853
  if ($isDecoratorNode(nextNode)) {
1792
- const decorator = nextNode.decorate(activeEditor$1);
1854
+ const decorator = nextNode.decorate(activeEditor$1, activeEditorConfig);
1793
1855
 
1794
1856
  if (decorator !== null) {
1795
1857
  reconcileDecorator(key, decorator);
@@ -1810,8 +1872,7 @@ function reconcileNode(key, parentDOM) {
1810
1872
  // Cache the latest text content.
1811
1873
  nextNode = nextNode.getWritable();
1812
1874
  nextNode.__cachedText = editorTextContent;
1813
- } // @ts-ignore
1814
-
1875
+ }
1815
1876
 
1816
1877
  {
1817
1878
  // Freeze the node in DEV to prevent accidental mutations
@@ -1970,58 +2031,6 @@ function getPrevElementByKeyOrThrow(key) {
1970
2031
  return element;
1971
2032
  }
1972
2033
 
1973
- /**
1974
- * Copyright (c) Meta Platforms, Inc. and affiliates.
1975
- *
1976
- * This source code is licensed under the MIT license found in the
1977
- * LICENSE file in the root directory of this source tree.
1978
- *
1979
- */
1980
- function createCommand() {
1981
- return {};
1982
- }
1983
- const SELECTION_CHANGE_COMMAND = createCommand();
1984
- const CLICK_COMMAND = createCommand();
1985
- const DELETE_CHARACTER_COMMAND = createCommand();
1986
- const INSERT_LINE_BREAK_COMMAND = createCommand();
1987
- const INSERT_PARAGRAPH_COMMAND = createCommand();
1988
- const CONTROLLED_TEXT_INSERTION_COMMAND = createCommand();
1989
- const PASTE_COMMAND = createCommand();
1990
- const REMOVE_TEXT_COMMAND = createCommand();
1991
- const DELETE_WORD_COMMAND = createCommand();
1992
- const DELETE_LINE_COMMAND = createCommand();
1993
- const FORMAT_TEXT_COMMAND = createCommand();
1994
- const UNDO_COMMAND = createCommand();
1995
- const REDO_COMMAND = createCommand();
1996
- const KEY_ARROW_RIGHT_COMMAND = createCommand();
1997
- const MOVE_TO_END = createCommand();
1998
- const KEY_ARROW_LEFT_COMMAND = createCommand();
1999
- const MOVE_TO_START = createCommand();
2000
- const KEY_ARROW_UP_COMMAND = createCommand();
2001
- const KEY_ARROW_DOWN_COMMAND = createCommand();
2002
- const KEY_ENTER_COMMAND = createCommand();
2003
- const KEY_SPACE_COMMAND = createCommand();
2004
- const KEY_BACKSPACE_COMMAND = createCommand();
2005
- const KEY_ESCAPE_COMMAND = createCommand();
2006
- const KEY_DELETE_COMMAND = createCommand();
2007
- const KEY_TAB_COMMAND = createCommand();
2008
- const INDENT_CONTENT_COMMAND = createCommand();
2009
- const OUTDENT_CONTENT_COMMAND = createCommand();
2010
- const DROP_COMMAND = createCommand();
2011
- const FORMAT_ELEMENT_COMMAND = createCommand();
2012
- const DRAGSTART_COMMAND = createCommand();
2013
- const DRAGOVER_COMMAND = createCommand();
2014
- const DRAGEND_COMMAND = createCommand();
2015
- const COPY_COMMAND = createCommand();
2016
- const CUT_COMMAND = createCommand();
2017
- const CLEAR_EDITOR_COMMAND = createCommand();
2018
- const CLEAR_HISTORY_COMMAND = createCommand();
2019
- const CAN_REDO_COMMAND = createCommand();
2020
- const CAN_UNDO_COMMAND = createCommand();
2021
- const FOCUS_COMMAND = createCommand();
2022
- const BLUR_COMMAND = createCommand();
2023
- const KEY_MODIFIER_COMMAND = createCommand();
2024
-
2025
2034
  /**
2026
2035
  * Copyright (c) Meta Platforms, Inc. and affiliates.
2027
2036
  *
@@ -2038,6 +2047,7 @@ if (CAN_USE_BEFORE_INPUT) {
2038
2047
  }
2039
2048
 
2040
2049
  let lastKeyDownTimeStamp = 0;
2050
+ let lastKeyCode = 0;
2041
2051
  let rootElementsRegistered = 0;
2042
2052
  let isSelectionChangeFromDOMUpdate = false;
2043
2053
  let isInsertLineBreak = false;
@@ -2179,6 +2189,10 @@ function $canRemoveText(anchorNode, focusNode) {
2179
2189
  return anchorNode !== focusNode || $isElementNode(anchorNode) || $isElementNode(focusNode) || !$isTokenOrInert(anchorNode) || !$isTokenOrInert(focusNode);
2180
2190
  }
2181
2191
 
2192
+ function isPossiblyAndroidKeyPress(timeStamp) {
2193
+ return lastKeyCode === 229 && timeStamp < lastKeyDownTimeStamp + ANDROID_COMPOSITION_LATENCY;
2194
+ }
2195
+
2182
2196
  function onBeforeInput(event, editor) {
2183
2197
  const inputType = event.inputType; // We let the browser do its own thing for composition.
2184
2198
 
@@ -2195,7 +2209,9 @@ function onBeforeInput(event, editor) {
2195
2209
  // during composition and see if the previous text contains
2196
2210
  // part of the composed text to work out the actual text that
2197
2211
  // we need to insert.
2198
- const composedText = event.data;
2212
+ const composedText = event.data; // TODO: evaluate if this is Android only. It doesn't always seem
2213
+ // to have any real impact, so could probably be refactored or removed
2214
+ // for an alternative approach.
2199
2215
 
2200
2216
  if (composedText) {
2201
2217
  updateEditor(editor, () => {
@@ -2239,20 +2255,32 @@ function onBeforeInput(event, editor) {
2239
2255
  }
2240
2256
 
2241
2257
  $setSelection(prevSelection.clone());
2242
- } // Used for Android
2258
+ }
2243
2259
 
2260
+ if ($isRangeSelection(selection)) {
2261
+ // Used for handling backspace in Android.
2262
+ if (isPossiblyAndroidKeyPress(event.timeStamp) && selection.anchor.key === selection.focus.key) {
2263
+ $setCompositionKey(null);
2264
+ lastKeyDownTimeStamp = 0; // Fixes an Android bug where selection flickers when backspacing
2244
2265
 
2245
- $setCompositionKey(null);
2246
- event.preventDefault();
2247
- lastKeyDownTimeStamp = 0;
2248
- dispatchCommand(editor, DELETE_CHARACTER_COMMAND, true); // Fixes an Android bug where selection flickers when backspacing
2266
+ setTimeout(() => {
2267
+ updateEditor(editor, () => {
2268
+ $setCompositionKey(null);
2269
+ });
2270
+ }, ANDROID_COMPOSITION_LATENCY);
2249
2271
 
2250
- setTimeout(() => {
2251
- updateEditor(editor, () => {
2252
- $setCompositionKey(null);
2253
- });
2254
- }, ANDROID_COMPOSITION_LATENCY);
2255
- return;
2272
+ if ($isRangeSelection(selection)) {
2273
+ const anchorNode = selection.anchor.getNode();
2274
+ anchorNode.markDirty();
2275
+ selection.format = anchorNode.getFormat();
2276
+ }
2277
+ } else {
2278
+ event.preventDefault();
2279
+ dispatchCommand(editor, DELETE_CHARACTER_COMMAND, false);
2280
+ }
2281
+
2282
+ return;
2283
+ }
2256
2284
  }
2257
2285
 
2258
2286
  if (!$isRangeSelection(selection)) {
@@ -2438,9 +2466,8 @@ function onInput(event, editor) {
2438
2466
  updateEditor(editor, () => {
2439
2467
  const selection = $getSelection();
2440
2468
  const data = event.data;
2441
- const possibleTextReplacement = event.inputType === 'insertText' && data != null && data.length > 1 && !doesContainGrapheme(data);
2442
2469
 
2443
- if (data != null && $isRangeSelection(selection) && (possibleTextReplacement || $shouldPreventDefaultAndInsertText(selection, data))) {
2470
+ if (data != null && $isRangeSelection(selection) && $shouldPreventDefaultAndInsertText(selection, data)) {
2444
2471
  // Given we're over-riding the default behavior, we will need
2445
2472
  // to ensure to disable composition before dispatching the
2446
2473
  // insertText command for when changing the sequence for FF.
@@ -2449,24 +2476,7 @@ function onInput(event, editor) {
2449
2476
  isFirefoxEndingComposition = false;
2450
2477
  }
2451
2478
 
2452
- dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, data);
2453
-
2454
- if (possibleTextReplacement) {
2455
- // If the DOM selection offset is higher than the existing
2456
- // offset, then restore the offset as it's likely correct
2457
- // in the case of text replacements.
2458
- const {
2459
- anchorOffset
2460
- } = window.getSelection();
2461
- const anchor = selection.anchor;
2462
- const focus = selection.focus;
2463
-
2464
- if (anchorOffset > anchor.offset) {
2465
- anchor.set(anchor.key, anchorOffset, anchor.type);
2466
- focus.set(anchor.key, anchorOffset, anchor.type);
2467
- }
2468
- } // This ensures consistency on Android.
2469
-
2479
+ dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, data); // This ensures consistency on Android.
2470
2480
 
2471
2481
  if (!IS_SAFARI && !IS_IOS && editor.isComposing()) {
2472
2482
  lastKeyDownTimeStamp = 0;
@@ -2565,6 +2575,7 @@ function onCompositionEnd(event, editor) {
2565
2575
 
2566
2576
  function onKeyDown(event, editor) {
2567
2577
  lastKeyDownTimeStamp = event.timeStamp;
2578
+ lastKeyCode = event.keyCode;
2568
2579
 
2569
2580
  if (editor.isComposing()) {
2570
2581
  return;
@@ -2830,7 +2841,6 @@ function markCollapsedSelectionFormat(format, offset, key, timeStamp) {
2830
2841
  * LICENSE file in the root directory of this source tree.
2831
2842
  *
2832
2843
  */
2833
-
2834
2844
  class Point {
2835
2845
  constructor(key, offset, type) {
2836
2846
  this._selection = null;
@@ -3467,6 +3477,7 @@ class RangeSelection {
3467
3477
 
3468
3478
  if (!$isTextNode(nextSibling) || $isTokenOrInertOrSegmented(nextSibling)) {
3469
3479
  nextSibling = $createTextNode();
3480
+ nextSibling.setFormat(format);
3470
3481
 
3471
3482
  if (!firstNodeParent.canInsertTextAfter()) {
3472
3483
  firstNodeParent.insertAfter(nextSibling);
@@ -3487,6 +3498,7 @@ class RangeSelection {
3487
3498
 
3488
3499
  if (!$isTextNode(prevSibling) || $isTokenOrInertOrSegmented(prevSibling)) {
3489
3500
  prevSibling = $createTextNode();
3501
+ prevSibling.setFormat(format);
3490
3502
 
3491
3503
  if (!firstNodeParent.canInsertTextBefore()) {
3492
3504
  firstNodeParent.insertBefore(prevSibling);
@@ -3504,6 +3516,7 @@ class RangeSelection {
3504
3516
  }
3505
3517
  } else if (firstNode.isSegmented() && startOffset !== firstNodeTextLength) {
3506
3518
  const textNode = $createTextNode(firstNode.getTextContent());
3519
+ textNode.setFormat(format);
3507
3520
  firstNode.replace(textNode);
3508
3521
  firstNode = textNode;
3509
3522
  } else if (!this.isCollapsed() && text !== '') {
@@ -3561,10 +3574,14 @@ class RangeSelection {
3561
3574
 
3562
3575
  if (firstNode.getTextContent() === '') {
3563
3576
  firstNode.remove();
3564
- } else if (firstNode.isComposing() && this.anchor.type === 'text') {
3565
- // When composing, we need to adjust the anchor offset so that
3566
- // we correctly replace that right range.
3567
- this.anchor.offset -= text.length;
3577
+ } else if (this.anchor.type === 'text') {
3578
+ if (firstNode.isComposing()) {
3579
+ // When composing, we need to adjust the anchor offset so that
3580
+ // we correctly replace that right range.
3581
+ this.anchor.offset -= text.length;
3582
+ } else {
3583
+ this.format = firstNodeFormat;
3584
+ }
3568
3585
  }
3569
3586
  } else {
3570
3587
  const markedNodeKeysForKeep = new Set([...firstNode.getParentKeys(), ...lastNode.getParentKeys()]); // We have to get the parent elements before the next section,
@@ -4763,15 +4780,15 @@ function internalMakeRangeSelection(anchorKey, anchorOffset, focusKey, focusOffs
4763
4780
  editorState._selection = selection;
4764
4781
  return selection;
4765
4782
  }
4766
- function $createEmptyRangeSelection() {
4783
+ function $createRangeSelection() {
4767
4784
  const anchor = $createPoint('root', 0, 'element');
4768
4785
  const focus = $createPoint('root', 0, 'element');
4769
4786
  return new RangeSelection(anchor, focus, 0);
4770
4787
  }
4771
- function $createEmptyObjectSelection() {
4788
+ function $createNodeSelection() {
4772
4789
  return new NodeSelection(new Set());
4773
4790
  }
4774
- function $createEmptyGridSelection() {
4791
+ function $createGridSelection() {
4775
4792
  const anchor = $createPoint('root', 0, 'element');
4776
4793
  const focus = $createPoint('root', 0, 'element');
4777
4794
  return new GridSelection('root', anchor, focus);
@@ -5365,7 +5382,7 @@ function parseEditorState(serializedEditorState, editor, updateFn) {
5365
5382
  } // Make the editorState immutable
5366
5383
 
5367
5384
 
5368
- editorState._readOnly = true; // @ts-ignore
5385
+ editorState._readOnly = true;
5369
5386
 
5370
5387
  {
5371
5388
  handleDEVOnlyPendingUpdateGuarantees(editorState);
@@ -5470,6 +5487,9 @@ function commitPendingUpdates(editor) {
5470
5487
  isAttemptingToRecoverFromReconcilerError = true;
5471
5488
  commitPendingUpdates(editor);
5472
5489
  isAttemptingToRecoverFromReconcilerError = false;
5490
+ } else {
5491
+ // To avoid a possible situation of infinite loops, lets throw
5492
+ throw error;
5473
5493
  }
5474
5494
 
5475
5495
  return;
@@ -5486,7 +5506,7 @@ function commitPendingUpdates(editor) {
5486
5506
  }
5487
5507
  }
5488
5508
 
5489
- pendingEditorState._readOnly = true; // @ts-ignore
5509
+ pendingEditorState._readOnly = true;
5490
5510
 
5491
5511
  {
5492
5512
  handleDEVOnlyPendingUpdateGuarantees(pendingEditorState);
@@ -5827,8 +5847,17 @@ function updateEditor(editor, updateFn, options) {
5827
5847
  beginUpdate(editor, updateFn, options);
5828
5848
  }
5829
5849
  }
5850
+ function internalGetActiveEditor() {
5851
+ return activeEditor;
5852
+ }
5830
5853
 
5831
- /* eslint-disable no-constant-condition */
5854
+ /**
5855
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
5856
+ *
5857
+ * This source code is licensed under the MIT license found in the
5858
+ * LICENSE file in the root directory of this source tree.
5859
+ *
5860
+ */
5832
5861
  function removeNode(nodeToRemove, restoreSelection, preserveEmptyParent) {
5833
5862
  errorOnReadOnly();
5834
5863
  const key = nodeToRemove.__key;
@@ -5895,6 +5924,7 @@ function $getNodeByKeyOrThrow(key) {
5895
5924
  return node;
5896
5925
  }
5897
5926
  class LexicalNode {
5927
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5898
5928
  // Flow doesn't support abstract classes unfortunately, so we can't _force_
5899
5929
  // subclasses of Node to implement statics. All subclasses of Node should have
5900
5930
  // a static getType and clone method though. We define getType and clone here so we can call it
@@ -5916,7 +5946,7 @@ class LexicalNode {
5916
5946
  // @ts-expect-error
5917
5947
  this.__type = this.constructor.getType();
5918
5948
  this.__parent = null;
5919
- $setNodeKey(this, key); // @ts-ignore
5949
+ $setNodeKey(this, key);
5920
5950
 
5921
5951
  {
5922
5952
  if (this.__type !== 'root') {
@@ -6385,52 +6415,11 @@ class LexicalNode {
6385
6415
 
6386
6416
  exportDOM(editor) {
6387
6417
  const element = this.createDOM(editor._config, editor);
6388
- const serializedNode = this.exportJSON();
6389
- element.setAttribute('data-lexical-node-type', this.__type);
6390
- element.setAttribute('data-lexical-node-json', JSON.stringify(serializedNode));
6391
- element.setAttribute('data-lexical-editor-key', editor._key);
6392
6418
  return {
6393
6419
  element
6394
6420
  };
6395
6421
  }
6396
6422
 
6397
- static importDOM() {
6398
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6399
- const proto = this.prototype.constructor;
6400
- return {
6401
- // Catch-all key because we don't know the nodeName of the element returned by exportDOM.
6402
- '*': domNode => {
6403
- if (!(domNode instanceof HTMLElement)) return null;
6404
- const editorKey = domNode.getAttribute('data-lexical-editor-key');
6405
- const nodeType = domNode.getAttribute('data-lexical-node-type');
6406
- if (editorKey == null || nodeType == null) return null;
6407
- const editor = getActiveEditor();
6408
-
6409
- if (editorKey === editor.getKey() && nodeType === proto.getType()) {
6410
- try {
6411
- const json = domNode.getAttribute('data-lexical-node-json');
6412
-
6413
- if (json != null) {
6414
- const serializedNode = JSON.parse(json);
6415
- const node = proto.importJSON(serializedNode);
6416
- return {
6417
- conversion: () => ({
6418
- node
6419
- }),
6420
- // Max priority because of the 'data-lexical-node-type' attribute
6421
- // matching the one on node klass guarantees a match.
6422
- priority: 4
6423
- }; // eslint-disable-next-line no-empty
6424
- } // eslint-disable-next-line no-empty
6425
-
6426
- } catch {}
6427
- }
6428
-
6429
- return null;
6430
- }
6431
- };
6432
- }
6433
-
6434
6423
  exportJSON() {
6435
6424
  {
6436
6425
  throw Error(`exportJSON: base method not extended`);
@@ -6649,7 +6638,7 @@ class DecoratorNode extends LexicalNode {
6649
6638
  super(key);
6650
6639
  }
6651
6640
 
6652
- decorate(editor) {
6641
+ decorate(editor, config) {
6653
6642
  {
6654
6643
  throw Error(`decorate: base method not extended`);
6655
6644
  }
@@ -7118,7 +7107,7 @@ class ElementNode extends LexicalNode {
7118
7107
  return false;
7119
7108
  }
7120
7109
 
7121
- excludeFromCopy() {
7110
+ excludeFromCopy(destination) {
7122
7111
  return false;
7123
7112
  }
7124
7113
 
@@ -7561,7 +7550,9 @@ function setTextContent(nextText, dom, node) {
7561
7550
  dom.textContent = text;
7562
7551
  } else {
7563
7552
  const nodeValue = firstChild.nodeValue;
7564
- if (nodeValue !== text) if (isComposing) {
7553
+ if (nodeValue !== text) if (isComposing || IS_FIREFOX) {
7554
+ // We also use the diff composed text for general text in FF to avoid
7555
+ // the spellcheck red line from flickering.
7565
7556
  const [index, remove, insert] = diffComposedText(nodeValue, text);
7566
7557
 
7567
7558
  if (remove !== 0) {
@@ -8170,8 +8161,21 @@ function convertBringAttentionToElement(domNode) {
8170
8161
  }
8171
8162
 
8172
8163
  function convertTextDOMNode(domNode) {
8164
+ const {
8165
+ parentElement,
8166
+ textContent
8167
+ } = domNode;
8168
+ const textContentTrim = textContent.trim();
8169
+ const isPre = parentElement != null && parentElement.tagName.toLowerCase() === 'pre';
8170
+
8171
+ if (!isPre && textContentTrim.length === 0 && textContent.includes('\n')) {
8172
+ return {
8173
+ node: null
8174
+ };
8175
+ }
8176
+
8173
8177
  return {
8174
- node: $createTextNode(domNode.textContent)
8178
+ node: $createTextNode(textContent)
8175
8179
  };
8176
8180
  }
8177
8181
 
@@ -8384,10 +8388,11 @@ function initializeConversionCache(nodes) {
8384
8388
  const conversionCache = new Map();
8385
8389
  const handledConversions = new Set();
8386
8390
  nodes.forEach(node => {
8387
- // @ts-expect-error TODO Replace Class utility type with InstanceType
8388
- const importDOM = node.klass.importDOM.bind(node.klass); // debugger;
8391
+ const importDOM = // @ts-expect-error TODO Replace Class utility type with InstanceType
8392
+ node.klass.importDOM != null ? // @ts-expect-error TODO Replace Class utility type with InstanceType
8393
+ node.klass.importDOM.bind(node.klass) : null;
8389
8394
 
8390
- if (handledConversions.has(importDOM)) {
8395
+ if (importDOM == null || handledConversions.has(importDOM)) {
8391
8396
  return;
8392
8397
  }
8393
8398
 
@@ -8410,69 +8415,77 @@ function initializeConversionCache(nodes) {
8410
8415
  return conversionCache;
8411
8416
  }
8412
8417
 
8413
- function createEditor(editorConfig = {}) {
8414
- const config = editorConfig;
8418
+ function createEditor(editorConfig) {
8419
+ const config = editorConfig || {};
8420
+ const activeEditor = internalGetActiveEditor();
8415
8421
  const theme = config.theme || {};
8416
- const parentEditor = config.parentEditor || null;
8422
+ const parentEditor = editorConfig === undefined ? activeEditor : config.parentEditor || null;
8417
8423
  const disableEvents = config.disableEvents || false;
8418
8424
  const editorState = createEmptyEditorState();
8425
+ const namespace = config.namespace || (parentEditor !== null ? parentEditor._config.namespace : createUID());
8419
8426
  const initialEditorState = config.editorState;
8420
8427
  const nodes = [RootNode, TextNode, LineBreakNode, ParagraphNode, ...(config.nodes || [])];
8421
8428
  const onError = config.onError;
8422
8429
  const isReadOnly = config.readOnly || false;
8423
- const registeredNodes = new Map();
8430
+ let registeredNodes;
8424
8431
 
8425
- for (let i = 0; i < nodes.length; i++) {
8426
- const klass = nodes[i]; // Ensure custom nodes implement required methods.
8427
- // @ts-ignore
8432
+ if (editorConfig === undefined && activeEditor !== null) {
8433
+ registeredNodes = activeEditor._nodes;
8434
+ } else {
8435
+ registeredNodes = new Map();
8428
8436
 
8429
- {
8430
- const name = klass.name;
8431
-
8432
- if (name !== 'RootNode') {
8433
- const proto = klass.prototype;
8434
- ['getType', 'clone'].forEach(method => {
8435
- // eslint-disable-next-line no-prototype-builtins
8436
- if (!klass.hasOwnProperty(method)) {
8437
- console.warn(`${name} must implement static "${method}" method`);
8438
- }
8439
- });
8437
+ for (let i = 0; i < nodes.length; i++) {
8438
+ const klass = nodes[i]; // Ensure custom nodes implement required methods.
8440
8439
 
8441
- if ( // eslint-disable-next-line no-prototype-builtins
8442
- !klass.hasOwnProperty('importDOM') && // eslint-disable-next-line no-prototype-builtins
8443
- klass.hasOwnProperty('exportDOM')) {
8444
- console.warn(`${name} should implement "importDOM" if using a custom "exportDOM" method to ensure HTML serialization (important for copy & paste) works as expected`);
8445
- }
8440
+ {
8441
+ const name = klass.name;
8442
+
8443
+ if (name !== 'RootNode') {
8444
+ const proto = klass.prototype;
8445
+ ['getType', 'clone'].forEach(method => {
8446
+ // eslint-disable-next-line no-prototype-builtins
8447
+ if (!klass.hasOwnProperty(method)) {
8448
+ console.warn(`${name} must implement static "${method}" method`);
8449
+ }
8450
+ });
8446
8451
 
8447
- if (proto instanceof DecoratorNode) {
8448
- // eslint-disable-next-line no-prototype-builtins
8449
- if (!proto.hasOwnProperty('decorate')) {
8450
- console.warn(`${this.constructor.name} must implement "decorate" method`);
8452
+ if ( // eslint-disable-next-line no-prototype-builtins
8453
+ !klass.hasOwnProperty('importDOM') && // eslint-disable-next-line no-prototype-builtins
8454
+ klass.hasOwnProperty('exportDOM')) {
8455
+ console.warn(`${name} should implement "importDOM" if using a custom "exportDOM" method to ensure HTML serialization (important for copy & paste) works as expected`);
8451
8456
  }
8452
- }
8453
8457
 
8454
- if ( // eslint-disable-next-line no-prototype-builtins
8455
- !klass.hasOwnProperty('importJSON')) {
8456
- console.warn(`${name} should implement "importJSON" method to ensure JSON and default HTML serialization works as expected`);
8457
- }
8458
+ if (proto instanceof DecoratorNode) {
8459
+ // eslint-disable-next-line no-prototype-builtins
8460
+ if (!proto.hasOwnProperty('decorate')) {
8461
+ console.warn(`${this.constructor.name} must implement "decorate" method`);
8462
+ }
8463
+ }
8458
8464
 
8459
- if ( // eslint-disable-next-line no-prototype-builtins
8460
- !proto.hasOwnProperty('exportJSON')) {
8461
- console.warn(`${name} should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected`);
8465
+ if ( // eslint-disable-next-line no-prototype-builtins
8466
+ !klass.hasOwnProperty('importJSON')) {
8467
+ console.warn(`${name} should implement "importJSON" method to ensure JSON and default HTML serialization works as expected`);
8468
+ }
8469
+
8470
+ if ( // eslint-disable-next-line no-prototype-builtins
8471
+ !proto.hasOwnProperty('exportJSON')) {
8472
+ console.warn(`${name} should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected`);
8473
+ }
8462
8474
  }
8463
- }
8464
- } // @ts-expect-error TODO Replace Class utility type with InstanceType
8475
+ } // @ts-expect-error TODO Replace Class utility type with InstanceType
8465
8476
 
8466
8477
 
8467
- const type = klass.getType();
8468
- registeredNodes.set(type, {
8469
- klass,
8470
- transforms: new Set()
8471
- });
8478
+ const type = klass.getType();
8479
+ registeredNodes.set(type, {
8480
+ klass,
8481
+ transforms: new Set()
8482
+ });
8483
+ }
8472
8484
  }
8473
8485
 
8474
8486
  const editor = new LexicalEditor(editorState, parentEditor, registeredNodes, {
8475
8487
  disableEvents,
8488
+ namespace,
8476
8489
  theme
8477
8490
  }, onError, initializeConversionCache(registeredNodes), isReadOnly);
8478
8491
 
@@ -8629,9 +8642,7 @@ class LexicalEditor {
8629
8642
  };
8630
8643
  }
8631
8644
 
8632
- registerNodeTransform( // There's no Flow-safe way to preserve the T in Transform<T>, but <T = LexicalNode> in the
8633
- // declaration below guarantees these are LexicalNodes.
8634
- klass, listener) {
8645
+ registerNodeTransform(klass, listener) {
8635
8646
  // @ts-expect-error TODO Replace Class utility type with InstanceType
8636
8647
  const type = klass.getType();
8637
8648
 
@@ -8653,7 +8664,7 @@ class LexicalEditor {
8653
8664
 
8654
8665
  hasNodes(nodes) {
8655
8666
  for (let i = 0; i < nodes.length; i++) {
8656
- const klass = nodes[i]; // @ts-expect-error TODO Replace Class utility type with InstanceType
8667
+ const klass = nodes[i]; // @ts-expect-error
8657
8668
 
8658
8669
  const type = klass.getType();
8659
8670
 
@@ -8822,7 +8833,7 @@ class LexicalEditor {
8822
8833
 
8823
8834
  toJSON() {
8824
8835
  return {
8825
- editorState: this._editorState
8836
+ editorState: this._editorState.toJSON()
8826
8837
  };
8827
8838
  }
8828
8839
 
@@ -8835,7 +8846,7 @@ class LexicalEditor {
8835
8846
  * LICENSE file in the root directory of this source tree.
8836
8847
  *
8837
8848
  */
8838
- const VERSION = '0.3.2';
8849
+ const VERSION = '0.3.5';
8839
8850
 
8840
8851
  /**
8841
8852
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -8885,11 +8896,11 @@ function $isGridRowNode(node) {
8885
8896
  return node instanceof GridRowNode;
8886
8897
  }
8887
8898
 
8888
- exports.$createGridSelection = $createEmptyGridSelection;
8899
+ exports.$createGridSelection = $createGridSelection;
8889
8900
  exports.$createLineBreakNode = $createLineBreakNode;
8890
- exports.$createNodeSelection = $createEmptyObjectSelection;
8901
+ exports.$createNodeSelection = $createNodeSelection;
8891
8902
  exports.$createParagraphNode = $createParagraphNode;
8892
- exports.$createRangeSelection = $createEmptyRangeSelection;
8903
+ exports.$createRangeSelection = $createRangeSelection;
8893
8904
  exports.$createTextNode = $createTextNode;
8894
8905
  exports.$getDecoratorNode = $getDecoratorNode;
8895
8906
  exports.$getNearestNodeFromDOMNode = $getNearestNodeFromDOMNode;