@lexical/react 0.1.9 → 0.1.12

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.
Files changed (95) hide show
  1. package/DEPRECATED_useLexical.dev.js +5 -44
  2. package/DEPRECATED_useLexical.prod.js +1 -2
  3. package/DEPRECATED_useLexicalAutoFormatter.dev.js +87 -41
  4. package/DEPRECATED_useLexicalAutoFormatter.prod.js +20 -18
  5. package/DEPRECATED_useLexicalCharacterLimit.dev.js +22 -19
  6. package/DEPRECATED_useLexicalCharacterLimit.prod.js +8 -8
  7. package/DEPRECATED_useLexicalEditor.dev.js +1 -25
  8. package/DEPRECATED_useLexicalEditor.prod.js +1 -1
  9. package/DEPRECATED_useLexicalHistory.dev.js +1 -1
  10. package/DEPRECATED_useLexicalHistory.prod.js +2 -2
  11. package/DEPRECATED_useLexicalList.dev.js +6 -0
  12. package/DEPRECATED_useLexicalList.prod.js +1 -1
  13. package/DEPRECATED_useLexicalPlainText.dev.js +81 -89
  14. package/DEPRECATED_useLexicalPlainText.prod.js +15 -16
  15. package/DEPRECATED_useLexicalRichText.dev.js +98 -592
  16. package/DEPRECATED_useLexicalRichText.prod.js +17 -29
  17. package/LexicalAutoFormatterPlugin.d.ts +9 -0
  18. package/LexicalAutoFormatterPlugin.dev.js +87 -41
  19. package/LexicalAutoFormatterPlugin.js.flow +10 -0
  20. package/LexicalAutoFormatterPlugin.prod.js +21 -19
  21. package/LexicalAutoLinkPlugin.d.ts +20 -0
  22. package/LexicalAutoLinkPlugin.js.flow +23 -0
  23. package/LexicalCharacterLimitPlugin.d.ts +11 -0
  24. package/LexicalCharacterLimitPlugin.dev.js +22 -19
  25. package/LexicalCharacterLimitPlugin.js.flow +12 -0
  26. package/LexicalCharacterLimitPlugin.prod.js +9 -8
  27. package/LexicalClearEditorPlugin.d.ts +14 -0
  28. package/LexicalClearEditorPlugin.dev.js +73 -0
  29. package/LexicalClearEditorPlugin.js +9 -0
  30. package/LexicalClearEditorPlugin.js.flow +14 -0
  31. package/LexicalClearEditorPlugin.prod.js +8 -0
  32. package/LexicalCollaborationPlugin.d.ts +49 -0
  33. package/LexicalCollaborationPlugin.dev.js +21 -11
  34. package/LexicalCollaborationPlugin.js.flow +55 -0
  35. package/LexicalCollaborationPlugin.prod.js +7 -7
  36. package/LexicalComposer.d.ts +22 -0
  37. package/LexicalComposer.dev.js +29 -5
  38. package/LexicalComposer.js.flow +24 -0
  39. package/LexicalComposer.prod.js +3 -3
  40. package/LexicalComposerContext.d.ts +24 -0
  41. package/LexicalComposerContext.js.flow +27 -0
  42. package/LexicalContentEditable.d.ts +32 -0
  43. package/LexicalContentEditable.dev.js +35 -8
  44. package/LexicalContentEditable.js.flow +35 -0
  45. package/LexicalContentEditable.prod.js +3 -3
  46. package/LexicalHashtagPlugin.d.ts +9 -0
  47. package/LexicalHashtagPlugin.js.flow +10 -0
  48. package/LexicalHistoryPlugin.d.ts +29 -0
  49. package/LexicalHistoryPlugin.dev.js +1 -1
  50. package/LexicalHistoryPlugin.js.flow +34 -0
  51. package/LexicalHistoryPlugin.prod.js +2 -2
  52. package/LexicalHorizontalRuleNode.d.ts +23 -0
  53. package/LexicalHorizontalRuleNode.js.flow +25 -0
  54. package/LexicalLinkPlugin.d.ts +9 -0
  55. package/LexicalLinkPlugin.js.flow +10 -0
  56. package/LexicalListPlugin.d.ts +9 -0
  57. package/LexicalListPlugin.dev.js +6 -0
  58. package/LexicalListPlugin.js.flow +10 -0
  59. package/LexicalListPlugin.prod.js +2 -2
  60. package/LexicalNestedComposer.d.ts +20 -0
  61. package/LexicalNestedComposer.js.flow +21 -0
  62. package/LexicalOnChangePlugin.d.ts +12 -0
  63. package/LexicalOnChangePlugin.js.flow +14 -0
  64. package/LexicalPlainTextPlugin.d.ts +15 -0
  65. package/LexicalPlainTextPlugin.dev.js +77 -84
  66. package/LexicalPlainTextPlugin.js.flow +18 -0
  67. package/LexicalPlainTextPlugin.prod.js +12 -12
  68. package/LexicalRichTextPlugin.d.ts +15 -0
  69. package/LexicalRichTextPlugin.dev.js +93 -586
  70. package/LexicalRichTextPlugin.js.flow +18 -0
  71. package/LexicalRichTextPlugin.prod.js +13 -25
  72. package/LexicalTablePlugin.d.ts +9 -0
  73. package/LexicalTablePlugin.dev.js +23 -1
  74. package/LexicalTablePlugin.js.flow +10 -0
  75. package/LexicalTablePlugin.prod.js +4 -3
  76. package/LexicalTreeView.d.ts +17 -0
  77. package/LexicalTreeView.dev.js +10 -2
  78. package/LexicalTreeView.js.flow +19 -0
  79. package/LexicalTreeView.prod.js +9 -8
  80. package/README.md +0 -1
  81. package/package.json +6 -5
  82. package/useLexicalDecoratorMap.d.ts +14 -0
  83. package/useLexicalDecoratorMap.js.flow +16 -0
  84. package/useLexicalIsTextContentEmpty.d.ts +13 -0
  85. package/useLexicalIsTextContentEmpty.js.flow +15 -0
  86. package/useLexicalNodeSelection.d.ts +12 -0
  87. package/useLexicalNodeSelection.dev.js +70 -0
  88. package/useLexicalNodeSelection.js +9 -0
  89. package/useLexicalNodeSelection.js.flow +14 -0
  90. package/useLexicalNodeSelection.prod.js +8 -0
  91. package/withSubscriptions.d.ts +12 -0
  92. package/withSubscriptions.js.flow +13 -0
  93. package/LexicalBootstrapPlugin.dev.js +0 -122
  94. package/LexicalBootstrapPlugin.js +0 -9
  95. package/LexicalBootstrapPlugin.prod.js +0 -8
@@ -10,10 +10,7 @@ var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
10
10
  var React = require('react');
11
11
  var lexical = require('lexical');
12
12
  var reactDom = require('react-dom');
13
- var list = require('@lexical/list');
14
- var CodeNode = require('lexical/CodeNode');
15
- var HeadingNode = require('lexical/HeadingNode');
16
- var LinkNode = require('lexical/LinkNode');
13
+ var clipboard = require('@lexical/clipboard');
17
14
 
18
15
  /**
19
16
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -173,182 +170,6 @@ function useDecorators(editor) {
173
170
  *
174
171
  */
175
172
 
176
- function $cloneWithProperties(node) {
177
- const latest = node.getLatest();
178
- const constructor = latest.constructor;
179
- const clone = constructor.clone(latest);
180
- clone.__parent = latest.__parent;
181
-
182
- if (lexical.$isElementNode(latest) && lexical.$isElementNode(clone)) {
183
- clone.__children = Array.from(latest.__children);
184
- clone.__format = latest.__format;
185
- clone.__indent = latest.__indent;
186
- clone.__dir = latest.__dir;
187
- } else if (lexical.$isTextNode(latest) && lexical.$isTextNode(clone)) {
188
- clone.__format = latest.__format;
189
- clone.__style = latest.__style;
190
- clone.__mode = latest.__mode;
191
- clone.__detail = latest.__detail;
192
- } else if (lexical.$isDecoratorNode(latest) && lexical.$isDecoratorNode(clone)) {
193
- clone.__state = latest.__state;
194
- } // $FlowFixMe
195
-
196
-
197
- return clone;
198
- }
199
-
200
- function $getIndexFromPossibleClone(node, parent, nodeMap) {
201
- const parentClone = nodeMap.get(parent.getKey());
202
-
203
- if (lexical.$isElementNode(parentClone)) {
204
- return parentClone.__children.indexOf(node.getKey());
205
- }
206
-
207
- return node.getIndexWithinParent();
208
- }
209
-
210
- function $getParentAvoidingExcludedElements(node) {
211
- let parent = node.getParent();
212
-
213
- while (parent !== null && parent.excludeFromCopy()) {
214
- parent = parent.getParent();
215
- }
216
-
217
- return parent;
218
- }
219
-
220
- function $copyLeafNodeBranchToRoot(leaf, startingOffset, isLeftSide, range, nodeMap) {
221
- let node = leaf;
222
- let offset = startingOffset;
223
-
224
- while (node !== null) {
225
- const parent = $getParentAvoidingExcludedElements(node);
226
-
227
- if (parent === null) {
228
- break;
229
- }
230
-
231
- if (!lexical.$isElementNode(node) || !node.excludeFromCopy()) {
232
- const key = node.getKey();
233
- let clone = nodeMap.get(key);
234
- const needsClone = clone === undefined;
235
-
236
- if (needsClone) {
237
- clone = $cloneWithProperties(node);
238
- nodeMap.set(key, clone);
239
- }
240
-
241
- if (lexical.$isTextNode(clone) && !clone.isSegmented() && !clone.isToken()) {
242
- clone.__text = clone.__text.slice(isLeftSide ? offset : 0, isLeftSide ? undefined : offset);
243
- } else if (lexical.$isElementNode(clone)) {
244
- clone.__children = clone.__children.slice(isLeftSide ? offset : 0, isLeftSide ? undefined : offset + 1);
245
- }
246
-
247
- if (lexical.$isRootNode(parent)) {
248
- if (needsClone) {
249
- // We only want to collect a range of top level nodes.
250
- // So if the parent is the root, we know this is a top level.
251
- range.push(key);
252
- }
253
-
254
- break;
255
- }
256
- }
257
-
258
- offset = $getIndexFromPossibleClone(node, parent, nodeMap);
259
- node = parent;
260
- }
261
- }
262
-
263
- function $cloneContents(selection) {
264
- const anchor = selection.anchor;
265
- const focus = selection.focus;
266
- const anchorOffset = anchor.getCharacterOffset();
267
- const focusOffset = focus.getCharacterOffset();
268
- const anchorNode = anchor.getNode();
269
- const focusNode = focus.getNode();
270
- const anchorNodeParent = anchorNode.getParentOrThrow(); // Handle a single text node extraction
271
-
272
- if (anchorNode === focusNode && lexical.$isTextNode(anchorNode) && (anchorNodeParent.canBeEmpty() || anchorNodeParent.getChildrenSize() > 1)) {
273
- const clonedFirstNode = $cloneWithProperties(anchorNode);
274
- const isBefore = focusOffset > anchorOffset;
275
- const startOffset = isBefore ? anchorOffset : focusOffset;
276
- const endOffset = isBefore ? focusOffset : anchorOffset;
277
- clonedFirstNode.__text = clonedFirstNode.__text.slice(startOffset, endOffset);
278
- const key = clonedFirstNode.getKey();
279
- return {
280
- nodeMap: [[key, clonedFirstNode]],
281
- range: [key]
282
- };
283
- }
284
-
285
- const nodes = selection.getNodes();
286
-
287
- if (nodes.length === 0) {
288
- return {
289
- nodeMap: [],
290
- range: []
291
- };
292
- } // Check if we can use the parent of the nodes, if the
293
- // parent can't be empty, then it's important that we
294
- // also copy that element node along with its children.
295
-
296
-
297
- let nodesLength = nodes.length;
298
- const firstNode = nodes[0];
299
- const firstNodeParent = firstNode.getParent();
300
-
301
- if (firstNodeParent !== null && (!firstNodeParent.canBeEmpty() || lexical.$isRootNode(firstNodeParent))) {
302
- const parentChildren = firstNodeParent.__children;
303
- const parentChildrenLength = parentChildren.length;
304
-
305
- if (parentChildrenLength === nodesLength) {
306
- let areTheSame = true;
307
-
308
- for (let i = 0; i < parentChildren.length; i++) {
309
- if (parentChildren[i] !== nodes[i].__key) {
310
- areTheSame = false;
311
- break;
312
- }
313
- }
314
-
315
- if (areTheSame) {
316
- nodesLength++;
317
- nodes.push(firstNodeParent);
318
- }
319
- }
320
- }
321
-
322
- const lastNode = nodes[nodesLength - 1];
323
- const isBefore = anchor.isBefore(focus);
324
- const nodeMap = new Map();
325
- const range = []; // Do first node to root
326
-
327
- $copyLeafNodeBranchToRoot(firstNode, isBefore ? anchorOffset : focusOffset, true, range, nodeMap); // Copy all nodes between
328
-
329
- for (let i = 0; i < nodesLength; i++) {
330
- const node = nodes[i];
331
- const key = node.getKey();
332
-
333
- if (!nodeMap.has(key) && (!lexical.$isElementNode(node) || !node.excludeFromCopy())) {
334
- const clone = $cloneWithProperties(node);
335
-
336
- if (lexical.$isRootNode(node.getParent())) {
337
- range.push(node.getKey());
338
- }
339
-
340
- nodeMap.set(key, clone);
341
- }
342
- } // Do last node to root
343
-
344
-
345
- $copyLeafNodeBranchToRoot(lastNode, isBefore ? focusOffset : anchorOffset, false, range, nodeMap);
346
- return {
347
- nodeMap: Array.from(nodeMap.entries()),
348
- range
349
- };
350
- }
351
-
352
173
  function $moveCaretSelection(selection, isHoldingShift, isBackward, granularity) {
353
174
  selection.modify(isHoldingShift ? 'extend' : 'move', isBackward, granularity);
354
175
  }
@@ -361,6 +182,10 @@ function $moveCharacter(selection, isHoldingShift, isBackward) {
361
182
  const isRTL = $isParentElementRTL(selection);
362
183
  $moveCaretSelection(selection, isHoldingShift, isBackward ? !isRTL : isRTL, 'character');
363
184
  }
185
+ function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
186
+ const possibleNode = lexical.$getDecoratorNode(selection.focus, isBackward);
187
+ return lexical.$isDecoratorNode(possibleNode) && !possibleNode.isIsolated();
188
+ }
364
189
 
365
190
  /**
366
191
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -370,45 +195,50 @@ function $moveCharacter(selection, isHoldingShift, isBackward) {
370
195
  *
371
196
  *
372
197
  */
373
- function resolveElement(element, isBackward, focusOffset) {
374
- const parent = element.getParent();
375
- let offset = focusOffset;
376
- let block = element;
377
-
378
- if (parent !== null) {
379
- if (isBackward && focusOffset === 0) {
380
- offset = block.getIndexWithinParent();
381
- block = parent;
382
- } else if (!isBackward && focusOffset === block.getChildrenSize()) {
383
- offset = block.getIndexWithinParent() + 1;
384
- block = parent;
385
- }
386
- }
198
+ function onCutForRichText(event, editor) {
199
+ onCopyForRichText(event, editor);
200
+ editor.update(() => {
201
+ const selection = lexical.$getSelection();
387
202
 
388
- return block.getChildAtIndex(isBackward ? offset - 1 : offset);
203
+ if (lexical.$isRangeSelection(selection)) {
204
+ selection.removeText();
205
+ }
206
+ });
389
207
  }
208
+ function onCopyForRichText(event, editor) {
209
+ event.preventDefault();
210
+ editor.update(() => {
211
+ const clipboardData = event.clipboardData;
212
+ const selection = lexical.$getSelection();
390
213
 
391
- function getPossibleDecoratorNode(focus, isBackward) {
392
- const focusOffset = focus.offset;
214
+ if (selection !== null) {
215
+ if (clipboardData != null) {
216
+ const htmlString = clipboard.getHtmlContent(editor);
217
+ const lexicalString = clipboard.$getLexicalContent(editor);
393
218
 
394
- if (focus.type === 'element') {
395
- const block = focus.getNode();
396
- return resolveElement(block, isBackward, focusOffset);
397
- } else {
398
- const focusNode = focus.getNode();
219
+ if (htmlString !== null) {
220
+ clipboardData.setData('text/html', htmlString);
221
+ }
399
222
 
400
- if (isBackward && focusOffset === 0 || !isBackward && focusOffset === focusNode.getTextContentSize()) {
401
- const possibleNode = isBackward ? focusNode.getPreviousSibling() : focusNode.getNextSibling();
223
+ if (lexicalString !== null) {
224
+ clipboardData.setData('application/x-lexical-editor', lexicalString);
225
+ }
402
226
 
403
- if (possibleNode === null) {
404
- return resolveElement(focusNode.getParentOrThrow(), isBackward, focusNode.getIndexWithinParent() + (isBackward ? 0 : 1));
227
+ clipboardData.setData('text/plain', selection.getTextContent());
405
228
  }
406
-
407
- return possibleNode;
408
229
  }
409
- }
230
+ });
231
+ }
232
+ function onPasteForRichText(event, editor) {
233
+ event.preventDefault();
234
+ editor.update(() => {
235
+ const selection = lexical.$getSelection();
236
+ const clipboardData = event.clipboardData;
410
237
 
411
- return null;
238
+ if (clipboardData != null && lexical.$isRangeSelection(selection)) {
239
+ clipboard.$insertDataTransferForRichText(clipboardData, selection, editor);
240
+ }
241
+ });
412
242
  }
413
243
 
414
244
  /**
@@ -419,381 +249,52 @@ function getPossibleDecoratorNode(focus, isBackward) {
419
249
  *
420
250
  *
421
251
  */
422
-
423
- const isCodeElement = div => {
424
- return div.style.fontFamily.match('monospace') !== null;
252
+ // Convoluted logic to make this work with Flow. Order matters.
253
+ const options = {
254
+ tag: 'history-merge'
425
255
  };
426
-
427
- const DOM_NODE_NAME_TO_LEXICAL_NODE = {
428
- '#text': domNode => ({
429
- node: lexical.$createTextNode(domNode.textContent)
430
- }),
431
- a: domNode => {
432
- let node;
433
-
434
- if (domNode instanceof HTMLAnchorElement) {
435
- node = LinkNode.$createLinkNode(domNode.href);
436
- } else {
437
- node = lexical.$createTextNode(domNode.textContent);
438
- }
439
-
440
- return {
441
- node
442
- };
443
- },
444
- b: domNode => {
445
- // $FlowFixMe[incompatible-type] domNode is a <b> since we matched it by nodeName
446
- const b = domNode; // Google Docs wraps all copied HTML in a <b> with font-weight normal
447
-
448
- const hasNormalFontWeight = b.style.fontWeight === 'normal';
449
- return {
450
- forChild: lexicalNode => {
451
- if (lexical.$isTextNode(lexicalNode) && !hasNormalFontWeight) {
452
- lexicalNode.toggleFormat('bold');
453
- }
454
- },
455
- node: null
456
- };
457
- },
458
- br: () => ({
459
- node: lexical.$createLineBreakNode()
460
- }),
461
- div: domNode => {
462
- // $FlowFixMe[incompatible-type] domNode is a <div> since we matched it by nodeName
463
- const div = domNode;
464
- return {
465
- after: childLexicalNodes => {
466
- const domParent = domNode.parentNode;
467
-
468
- if (domParent != null && domNode !== domParent.lastChild) {
469
- childLexicalNodes.push(lexical.$createLineBreakNode());
470
- }
471
-
472
- return childLexicalNodes;
473
- },
474
- node: isCodeElement(div) ? CodeNode.$createCodeNode() : null
475
- };
476
- },
477
- em: domNode => {
478
- return {
479
- forChild: lexicalNode => {
480
- if (lexical.$isTextNode(lexicalNode)) {
481
- lexicalNode.toggleFormat('italic');
482
- }
483
- },
484
- node: null
485
- };
486
- },
487
- h1: () => ({
488
- node: HeadingNode.$createHeadingNode('h1')
489
- }),
490
- h2: () => ({
491
- node: HeadingNode.$createHeadingNode('h2')
492
- }),
493
- h3: () => ({
494
- node: HeadingNode.$createHeadingNode('h3')
495
- }),
496
- h4: () => ({
497
- node: HeadingNode.$createHeadingNode('h4')
498
- }),
499
- h5: () => ({
500
- node: HeadingNode.$createHeadingNode('h5')
501
- }),
502
- i: domNode => {
503
- return {
504
- forChild: lexicalNode => {
505
- if (lexical.$isTextNode(lexicalNode)) {
506
- lexicalNode.toggleFormat('italic');
507
- }
508
- },
509
- node: null
510
- };
511
- },
512
- li: () => ({
513
- node: list.$createListItemNode()
514
- }),
515
- ol: () => ({
516
- node: list.$createListNode('ol')
517
- }),
518
- p: () => ({
519
- node: lexical.$createParagraphNode()
520
- }),
521
- pre: domNode => ({
522
- node: CodeNode.$createCodeNode()
523
- }),
524
- span: domNode => {
525
- // $FlowFixMe[incompatible-type] domNode is a <span> since we matched it by nodeName
526
- const span = domNode; // Google Docs uses span tags + font-weight for bold text
527
-
528
- const hasBoldFontWeight = span.style.fontWeight === '700';
529
- return {
530
- forChild: lexicalNode => {
531
- if (lexical.$isTextNode(lexicalNode) && hasBoldFontWeight) {
532
- lexicalNode.toggleFormat('bold');
533
- }
534
- },
535
- node: null
536
- };
537
- },
538
- strong: domNode => {
539
- return {
540
- forChild: lexicalNode => {
541
- if (lexical.$isTextNode(lexicalNode)) {
542
- lexicalNode.toggleFormat('bold');
543
- }
544
- },
545
- node: null
546
- };
547
- },
548
- table: domNode => {
549
- // $FlowFixMe[incompatible-type] domNode is a <table> since we matched it by nodeName
550
- const table = domNode;
551
- const isGitHubCodeTable = table.classList.contains('js-file-line-container');
552
- return {
553
- node: isGitHubCodeTable ? CodeNode.$createCodeNode() : null
554
- };
555
- },
556
- td: domNode => {
557
- // $FlowFixMe[incompatible-type] domNode is a <table> since we matched it by nodeName
558
- const cell = domNode;
559
- const isGitHubCodeCell = cell.classList.contains('js-file-line');
560
- return {
561
- after: childLexicalNodes => {
562
- if (isGitHubCodeCell && cell.parentNode && cell.parentNode.nextSibling) {
563
- // Append newline between code lines
564
- childLexicalNodes.push(lexical.$createLineBreakNode());
565
- }
566
-
567
- return childLexicalNodes;
568
- },
569
- node: null
570
- };
571
- },
572
- u: domNode => {
573
- return {
574
- forChild: lexicalNode => {
575
- if (lexical.$isTextNode(lexicalNode)) {
576
- lexicalNode.toggleFormat('underline');
256
+ const setEditorOptions = options;
257
+ const updateOptions = options;
258
+ function initializeEditor(editor, initialEditorState) {
259
+ if (initialEditorState === null) {
260
+ return;
261
+ } else if (initialEditorState === undefined) {
262
+ editor.update(() => {
263
+ const root = lexical.$getRoot();
264
+ const firstChild = root.getFirstChild();
265
+
266
+ if (firstChild === null) {
267
+ const paragraph = lexical.$createParagraphNode();
268
+ root.append(paragraph);
269
+ const activeElement = document.activeElement;
270
+
271
+ if (lexical.$getSelection() !== null || activeElement !== null && activeElement === editor.getRootElement()) {
272
+ paragraph.select();
577
273
  }
578
- },
579
- node: null
580
- };
581
- },
582
- ul: () => ({
583
- node: list.$createListNode('ul')
584
- })
585
- };
586
-
587
- function $generateNodes(nodeRange) {
588
- const {
589
- range,
590
- nodeMap
591
- } = nodeRange;
592
- const parsedNodeMap = new Map(nodeMap);
593
- const nodes = [];
594
-
595
- for (let i = 0; i < range.length; i++) {
596
- const key = range[i];
597
- const parsedNode = parsedNodeMap.get(key);
598
-
599
- if (parsedNode !== undefined) {
600
- const node = lexical.$createNodeFromParse(parsedNode, parsedNodeMap);
601
- nodes.push(node);
602
- }
603
- }
604
-
605
- return nodes;
606
- }
607
-
608
- function $createNodesFromDOM(node, conversionMap, editor, forChildMap = new Map()) {
609
- let lexicalNodes = [];
610
- let currentLexicalNode = null;
611
- const nodeName = node.nodeName.toLowerCase();
612
- const customHtmlTransforms = editor._config.htmlTransforms || {};
613
- const transformFunction = customHtmlTransforms[nodeName] || conversionMap[nodeName];
614
- const transformOutput = transformFunction ? transformFunction(node) : null;
615
- let postTransform = null;
616
-
617
- if (transformOutput !== null) {
618
- postTransform = transformOutput.after;
619
- currentLexicalNode = transformOutput.node;
620
-
621
- if (currentLexicalNode !== null) {
622
- lexicalNodes.push(currentLexicalNode);
623
- const forChildFunctions = Array.from(forChildMap.values());
624
-
625
- for (let i = 0; i < forChildFunctions.length; i++) {
626
- forChildFunctions[i](currentLexicalNode);
627
274
  }
628
- }
629
-
630
- if (transformOutput.forChild != null) {
631
- forChildMap.set(nodeName, transformOutput.forChild);
632
- }
633
- } // If the DOM node doesn't have a transformer, we don't know what
634
- // to do with it but we still need to process any childNodes.
635
-
636
-
637
- const children = node.childNodes;
638
- let childLexicalNodes = [];
639
-
640
- for (let i = 0; i < children.length; i++) {
641
- childLexicalNodes.push(...$createNodesFromDOM(children[i], conversionMap, editor, forChildMap));
642
- }
643
-
644
- if (postTransform != null) {
645
- childLexicalNodes = postTransform(childLexicalNodes);
646
- }
647
-
648
- if (currentLexicalNode == null) {
649
- // If it hasn't been converted to a LexicalNode, we hoist its children
650
- // up to the same level as it.
651
- lexicalNodes = lexicalNodes.concat(childLexicalNodes);
652
- } else {
653
- if (lexical.$isElementNode(currentLexicalNode)) {
654
- // If the current node is a ElementNode after conversion,
655
- // we can append all the children to it.
656
- currentLexicalNode.append(...childLexicalNodes);
657
- }
658
- }
659
-
660
- return lexicalNodes;
661
- }
662
-
663
- function $generateNodesFromDOM(dom, conversionMap, editor) {
664
- let lexicalNodes = [];
665
- const elements = dom.body ? Array.from(dom.body.childNodes) : [];
666
- const elementsLength = elements.length;
667
-
668
- for (let i = 0; i < elementsLength; i++) {
669
- const lexicalNode = $createNodesFromDOM(elements[i], conversionMap, editor);
670
-
671
- if (lexicalNode !== null) {
672
- lexicalNodes = lexicalNodes.concat(lexicalNode);
673
- }
674
- }
675
-
676
- return lexicalNodes;
677
- }
678
-
679
- function $insertDataTransferForRichText(dataTransfer, selection, editor) {
680
- const lexicalNodesString = dataTransfer.getData('application/x-lexical-editor');
681
-
682
- if (lexicalNodesString) {
683
- const namespace = editor._config.namespace;
684
-
685
- try {
686
- const lexicalClipboardData = JSON.parse(lexicalNodesString);
687
-
688
- if (lexicalClipboardData.namespace === namespace) {
689
- const nodeRange = lexicalClipboardData.state;
690
- const nodes = $generateNodes(nodeRange);
691
- selection.insertNodes(nodes);
692
- return;
693
- }
694
- } catch (e) {// Malformed, missing nodes..
695
- }
696
- }
697
-
698
- const textHtmlMimeType = 'text/html';
699
- const htmlString = dataTransfer.getData(textHtmlMimeType);
700
-
701
- if (htmlString) {
702
- const parser = new DOMParser();
703
- const dom = parser.parseFromString(htmlString, textHtmlMimeType);
704
- const nodes = $generateNodesFromDOM(dom, DOM_NODE_NAME_TO_LEXICAL_NODE, editor); // Wrap text and inline nodes in paragraph nodes so we have all blocks at the top-level
705
-
706
- const topLevelBlocks = [];
707
- let currentBlock = null;
708
-
709
- for (let i = 0; i < nodes.length; i++) {
710
- const node = nodes[i];
711
-
712
- if (!lexical.$isElementNode(node) || node.isInline()) {
713
- if (currentBlock === null) {
714
- currentBlock = lexical.$createParagraphNode();
715
- topLevelBlocks.push(currentBlock);
716
- }
717
-
718
- if (currentBlock !== null) {
719
- currentBlock.append(node);
275
+ }, updateOptions);
276
+ } else if (initialEditorState !== null) {
277
+ switch (typeof initialEditorState) {
278
+ case 'string':
279
+ {
280
+ const parsedEditorState = editor.parseEditorState(initialEditorState);
281
+ editor.setEditorState(parsedEditorState, setEditorOptions);
282
+ break;
720
283
  }
721
- } else {
722
- topLevelBlocks.push(node);
723
- currentBlock = null;
724
- }
725
- }
726
-
727
- selection.insertNodes(topLevelBlocks);
728
- return;
729
- }
730
-
731
- $insertDataTransferForPlainText(dataTransfer, selection);
732
- }
733
- function $insertDataTransferForPlainText(dataTransfer, selection) {
734
- const text = dataTransfer.getData('text/plain');
735
-
736
- if (text != null) {
737
- selection.insertRawText(text);
738
- }
739
- }
740
- function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
741
- const possibleNode = getPossibleDecoratorNode(selection.focus, isBackward);
742
- return lexical.$isDecoratorNode(possibleNode) && !possibleNode.isIsolated();
743
- }
744
- function onPasteForRichText(event, editor) {
745
- event.preventDefault();
746
- editor.update(() => {
747
- const selection = lexical.$getSelection();
748
- const clipboardData = event.clipboardData;
749
-
750
- if (clipboardData != null && selection !== null) {
751
- $insertDataTransferForRichText(clipboardData, selection, editor);
752
- }
753
- });
754
- }
755
- function onCutForRichText(event, editor) {
756
- onCopyForRichText(event, editor);
757
- editor.update(() => {
758
- const selection = lexical.$getSelection();
759
-
760
- if (selection !== null) {
761
- selection.removeText();
762
- }
763
- });
764
- }
765
- function onCopyForRichText(event, editor) {
766
- event.preventDefault();
767
- editor.update(() => {
768
- const clipboardData = event.clipboardData;
769
- const selection = lexical.$getSelection();
770
-
771
- if (selection !== null) {
772
- if (clipboardData != null) {
773
- const domSelection = window.getSelection(); // If we haven't selected a range, then don't copy anything
774
284
 
775
- if (domSelection.isCollapsed) {
776
- return;
285
+ case 'object':
286
+ {
287
+ editor.setEditorState(initialEditorState, setEditorOptions);
288
+ break;
777
289
  }
778
290
 
779
- const range = domSelection.getRangeAt(0);
780
-
781
- if (range) {
782
- const container = document.createElement('div');
783
- const frag = range.cloneContents();
784
- container.appendChild(frag);
785
- clipboardData.setData('text/html', container.innerHTML);
291
+ case 'function':
292
+ {
293
+ editor.update(initialEditorState, updateOptions);
294
+ break;
786
295
  }
787
-
788
- clipboardData.setData('text/plain', selection.getTextContent());
789
- const namespace = editor._config.namespace;
790
- clipboardData.setData('application/x-lexical-editor', JSON.stringify({
791
- namespace,
792
- state: $cloneContents(selection)
793
- }));
794
- }
795
296
  }
796
- });
297
+ }
797
298
  }
798
299
 
799
300
  /**
@@ -835,7 +336,7 @@ function useLexicalDragonSupport(editor) {
835
336
  editor.update(() => {
836
337
  const selection = lexical.$getSelection();
837
338
 
838
- if (selection !== null) {
339
+ if (lexical.$isRangeSelection(selection)) {
839
340
  const anchor = selection.anchor;
840
341
  let anchorNode = anchor.getNode();
841
342
  let setSelStart = 0;
@@ -892,13 +393,17 @@ function useLexicalDragonSupport(editor) {
892
393
  *
893
394
  *
894
395
  */
895
- const EditorPriority = 0;
896
- function useRichTextSetup(editor) {
396
+ function useRichTextSetup(editor, initialEditorState) {
897
397
  useLayoutEffect(() => {
898
398
  const removeListener = editor.addListener('command', (type, payload) => {
899
399
  const selection = lexical.$getSelection();
900
400
 
901
- if (selection === null) {
401
+ if (type === 'click' && lexical.$isNodeSelection(selection)) {
402
+ selection.clear();
403
+ return true;
404
+ }
405
+
406
+ if (!lexical.$isRangeSelection(selection)) {
902
407
  return false;
903
408
  }
904
409
 
@@ -934,7 +439,7 @@ function useRichTextSetup(editor) {
934
439
  const dataTransfer = eventOrText.dataTransfer;
935
440
 
936
441
  if (dataTransfer != null) {
937
- $insertDataTransferForRichText(dataTransfer, selection, editor);
442
+ clipboard.$insertDataTransferForRichText(dataTransfer, selection, editor);
938
443
  } else {
939
444
  const data = eventOrText.data;
940
445
 
@@ -1127,9 +632,10 @@ function useRichTextSetup(editor) {
1127
632
  }
1128
633
 
1129
634
  return false;
1130
- }, EditorPriority);
1131
- editor.execCommand('bootstrapEditor');
1132
- return removeListener;
635
+ }, 0);
636
+ initializeEditor(editor, initialEditorState);
637
+ return removeListener; // We only do this for init
638
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1133
639
  }, [editor]);
1134
640
  useLexicalDragonSupport(editor);
1135
641
  }
@@ -1144,11 +650,12 @@ function useRichTextSetup(editor) {
1144
650
  */
1145
651
  function RichTextPlugin({
1146
652
  contentEditable,
1147
- placeholder
653
+ placeholder,
654
+ initialEditorState
1148
655
  }) {
1149
656
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
1150
657
  const showPlaceholder = useLexicalCanShowPlaceholder(editor);
1151
- useRichTextSetup(editor);
658
+ useRichTextSetup(editor, initialEditorState);
1152
659
  const decorators = useDecorators(editor);
1153
660
  return /*#__PURE__*/React.createElement(React.Fragment, null, contentEditable, showPlaceholder && placeholder, decorators);
1154
661
  }