@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
@@ -9,10 +9,7 @@
9
9
  var withSubscriptions = require('@lexical/react/withSubscriptions');
10
10
  var lexical = require('lexical');
11
11
  var react = require('react');
12
- var list = require('@lexical/list');
13
- var CodeNode = require('lexical/CodeNode');
14
- var HeadingNode = require('lexical/HeadingNode');
15
- var LinkNode = require('lexical/LinkNode');
12
+ var clipboard = require('@lexical/clipboard');
16
13
 
17
14
  /**
18
15
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -30,7 +27,7 @@ const COMPOSING_CHARACTER = 1;
30
27
  const INSERT_CHARACTER_AFTER_SELECTION = 2;
31
28
  const DELETE_CHARACTER_BEFORE_SELECTION = 3;
32
29
  const DELETE_CHARACTER_AFTER_SELECTION = 4;
33
- const EditorPriority$1 = 0;
30
+ const EditorPriority = 0;
34
31
 
35
32
  function getDirtyNodes(editorState, dirtyLeavesSet, dirtyElementsSet) {
36
33
  const dirtyLeaves = Array.from(dirtyLeavesSet);
@@ -77,7 +74,7 @@ function getChangeType(prevEditorState, nextEditorState, dirtyLeavesSet, dirtyEl
77
74
  return COMPOSING_CHARACTER;
78
75
  }
79
76
 
80
- if (nextSelection === null || prevSelection === null || !prevSelection.isCollapsed() || !nextSelection.isCollapsed()) {
77
+ if (!lexical.$isRangeSelection(nextSelection) || !lexical.$isRangeSelection(prevSelection) || !prevSelection.isCollapsed() || !nextSelection.isCollapsed()) {
81
78
  return OTHER;
82
79
  }
83
80
 
@@ -319,7 +316,7 @@ function useHistory(editor, externalHistoryState, delay = 1000) {
319
316
  }
320
317
  };
321
318
 
322
- return withSubscriptions(editor.addListener('command', applyCommand, EditorPriority$1), editor.addListener('update', applyChange));
319
+ return withSubscriptions(editor.addListener('command', applyCommand, EditorPriority), editor.addListener('update', applyChange));
323
320
  }, [clearHistory, delay, editor, historyState]);
324
321
  }
325
322
  function createEmptyHistoryState() {
@@ -351,182 +348,6 @@ function useLexicalHistory(editor, externalHistoryState, delay = 1000) {
351
348
  *
352
349
  */
353
350
 
354
- function $cloneWithProperties(node) {
355
- const latest = node.getLatest();
356
- const constructor = latest.constructor;
357
- const clone = constructor.clone(latest);
358
- clone.__parent = latest.__parent;
359
-
360
- if (lexical.$isElementNode(latest) && lexical.$isElementNode(clone)) {
361
- clone.__children = Array.from(latest.__children);
362
- clone.__format = latest.__format;
363
- clone.__indent = latest.__indent;
364
- clone.__dir = latest.__dir;
365
- } else if (lexical.$isTextNode(latest) && lexical.$isTextNode(clone)) {
366
- clone.__format = latest.__format;
367
- clone.__style = latest.__style;
368
- clone.__mode = latest.__mode;
369
- clone.__detail = latest.__detail;
370
- } else if (lexical.$isDecoratorNode(latest) && lexical.$isDecoratorNode(clone)) {
371
- clone.__state = latest.__state;
372
- } // $FlowFixMe
373
-
374
-
375
- return clone;
376
- }
377
-
378
- function $getIndexFromPossibleClone(node, parent, nodeMap) {
379
- const parentClone = nodeMap.get(parent.getKey());
380
-
381
- if (lexical.$isElementNode(parentClone)) {
382
- return parentClone.__children.indexOf(node.getKey());
383
- }
384
-
385
- return node.getIndexWithinParent();
386
- }
387
-
388
- function $getParentAvoidingExcludedElements(node) {
389
- let parent = node.getParent();
390
-
391
- while (parent !== null && parent.excludeFromCopy()) {
392
- parent = parent.getParent();
393
- }
394
-
395
- return parent;
396
- }
397
-
398
- function $copyLeafNodeBranchToRoot(leaf, startingOffset, isLeftSide, range, nodeMap) {
399
- let node = leaf;
400
- let offset = startingOffset;
401
-
402
- while (node !== null) {
403
- const parent = $getParentAvoidingExcludedElements(node);
404
-
405
- if (parent === null) {
406
- break;
407
- }
408
-
409
- if (!lexical.$isElementNode(node) || !node.excludeFromCopy()) {
410
- const key = node.getKey();
411
- let clone = nodeMap.get(key);
412
- const needsClone = clone === undefined;
413
-
414
- if (needsClone) {
415
- clone = $cloneWithProperties(node);
416
- nodeMap.set(key, clone);
417
- }
418
-
419
- if (lexical.$isTextNode(clone) && !clone.isSegmented() && !clone.isToken()) {
420
- clone.__text = clone.__text.slice(isLeftSide ? offset : 0, isLeftSide ? undefined : offset);
421
- } else if (lexical.$isElementNode(clone)) {
422
- clone.__children = clone.__children.slice(isLeftSide ? offset : 0, isLeftSide ? undefined : offset + 1);
423
- }
424
-
425
- if (lexical.$isRootNode(parent)) {
426
- if (needsClone) {
427
- // We only want to collect a range of top level nodes.
428
- // So if the parent is the root, we know this is a top level.
429
- range.push(key);
430
- }
431
-
432
- break;
433
- }
434
- }
435
-
436
- offset = $getIndexFromPossibleClone(node, parent, nodeMap);
437
- node = parent;
438
- }
439
- }
440
-
441
- function $cloneContents(selection) {
442
- const anchor = selection.anchor;
443
- const focus = selection.focus;
444
- const anchorOffset = anchor.getCharacterOffset();
445
- const focusOffset = focus.getCharacterOffset();
446
- const anchorNode = anchor.getNode();
447
- const focusNode = focus.getNode();
448
- const anchorNodeParent = anchorNode.getParentOrThrow(); // Handle a single text node extraction
449
-
450
- if (anchorNode === focusNode && lexical.$isTextNode(anchorNode) && (anchorNodeParent.canBeEmpty() || anchorNodeParent.getChildrenSize() > 1)) {
451
- const clonedFirstNode = $cloneWithProperties(anchorNode);
452
- const isBefore = focusOffset > anchorOffset;
453
- const startOffset = isBefore ? anchorOffset : focusOffset;
454
- const endOffset = isBefore ? focusOffset : anchorOffset;
455
- clonedFirstNode.__text = clonedFirstNode.__text.slice(startOffset, endOffset);
456
- const key = clonedFirstNode.getKey();
457
- return {
458
- nodeMap: [[key, clonedFirstNode]],
459
- range: [key]
460
- };
461
- }
462
-
463
- const nodes = selection.getNodes();
464
-
465
- if (nodes.length === 0) {
466
- return {
467
- nodeMap: [],
468
- range: []
469
- };
470
- } // Check if we can use the parent of the nodes, if the
471
- // parent can't be empty, then it's important that we
472
- // also copy that element node along with its children.
473
-
474
-
475
- let nodesLength = nodes.length;
476
- const firstNode = nodes[0];
477
- const firstNodeParent = firstNode.getParent();
478
-
479
- if (firstNodeParent !== null && (!firstNodeParent.canBeEmpty() || lexical.$isRootNode(firstNodeParent))) {
480
- const parentChildren = firstNodeParent.__children;
481
- const parentChildrenLength = parentChildren.length;
482
-
483
- if (parentChildrenLength === nodesLength) {
484
- let areTheSame = true;
485
-
486
- for (let i = 0; i < parentChildren.length; i++) {
487
- if (parentChildren[i] !== nodes[i].__key) {
488
- areTheSame = false;
489
- break;
490
- }
491
- }
492
-
493
- if (areTheSame) {
494
- nodesLength++;
495
- nodes.push(firstNodeParent);
496
- }
497
- }
498
- }
499
-
500
- const lastNode = nodes[nodesLength - 1];
501
- const isBefore = anchor.isBefore(focus);
502
- const nodeMap = new Map();
503
- const range = []; // Do first node to root
504
-
505
- $copyLeafNodeBranchToRoot(firstNode, isBefore ? anchorOffset : focusOffset, true, range, nodeMap); // Copy all nodes between
506
-
507
- for (let i = 0; i < nodesLength; i++) {
508
- const node = nodes[i];
509
- const key = node.getKey();
510
-
511
- if (!nodeMap.has(key) && (!lexical.$isElementNode(node) || !node.excludeFromCopy())) {
512
- const clone = $cloneWithProperties(node);
513
-
514
- if (lexical.$isRootNode(node.getParent())) {
515
- range.push(node.getKey());
516
- }
517
-
518
- nodeMap.set(key, clone);
519
- }
520
- } // Do last node to root
521
-
522
-
523
- $copyLeafNodeBranchToRoot(lastNode, isBefore ? focusOffset : anchorOffset, false, range, nodeMap);
524
- return {
525
- nodeMap: Array.from(nodeMap.entries()),
526
- range
527
- };
528
- }
529
-
530
351
  function $moveCaretSelection(selection, isHoldingShift, isBackward, granularity) {
531
352
  selection.modify(isHoldingShift ? 'extend' : 'move', isBackward, granularity);
532
353
  }
@@ -539,6 +360,10 @@ function $moveCharacter(selection, isHoldingShift, isBackward) {
539
360
  const isRTL = $isParentElementRTL(selection);
540
361
  $moveCaretSelection(selection, isHoldingShift, isBackward ? !isRTL : isRTL, 'character');
541
362
  }
363
+ function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
364
+ const possibleNode = lexical.$getDecoratorNode(selection.focus, isBackward);
365
+ return lexical.$isDecoratorNode(possibleNode) && !possibleNode.isIsolated();
366
+ }
542
367
 
543
368
  /**
544
369
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -548,46 +373,7 @@ function $moveCharacter(selection, isHoldingShift, isBackward) {
548
373
  *
549
374
  *
550
375
  */
551
- function resolveElement(element, isBackward, focusOffset) {
552
- const parent = element.getParent();
553
- let offset = focusOffset;
554
- let block = element;
555
-
556
- if (parent !== null) {
557
- if (isBackward && focusOffset === 0) {
558
- offset = block.getIndexWithinParent();
559
- block = parent;
560
- } else if (!isBackward && focusOffset === block.getChildrenSize()) {
561
- offset = block.getIndexWithinParent() + 1;
562
- block = parent;
563
- }
564
- }
565
-
566
- return block.getChildAtIndex(isBackward ? offset - 1 : offset);
567
- }
568
-
569
- function getPossibleDecoratorNode(focus, isBackward) {
570
- const focusOffset = focus.offset;
571
-
572
- if (focus.type === 'element') {
573
- const block = focus.getNode();
574
- return resolveElement(block, isBackward, focusOffset);
575
- } else {
576
- const focusNode = focus.getNode();
577
-
578
- if (isBackward && focusOffset === 0 || !isBackward && focusOffset === focusNode.getTextContentSize()) {
579
- const possibleNode = isBackward ? focusNode.getPreviousSibling() : focusNode.getNextSibling();
580
-
581
- if (possibleNode === null) {
582
- return resolveElement(focusNode.getParentOrThrow(), isBackward, focusNode.getIndexWithinParent() + (isBackward ? 0 : 1));
583
- }
584
-
585
- return possibleNode;
586
- }
587
- }
588
-
589
- return null;
590
- }
376
+ const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
591
377
 
592
378
  /**
593
379
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -597,345 +383,23 @@ function getPossibleDecoratorNode(focus, isBackward) {
597
383
  *
598
384
  *
599
385
  */
386
+ const useLayoutEffectImpl = CAN_USE_DOM ? react.useLayoutEffect : react.useEffect;
387
+ var useLayoutEffect = useLayoutEffectImpl;
600
388
 
601
- const isCodeElement = div => {
602
- return div.style.fontFamily.match('monospace') !== null;
603
- };
604
-
605
- const DOM_NODE_NAME_TO_LEXICAL_NODE = {
606
- '#text': domNode => ({
607
- node: lexical.$createTextNode(domNode.textContent)
608
- }),
609
- a: domNode => {
610
- let node;
611
-
612
- if (domNode instanceof HTMLAnchorElement) {
613
- node = LinkNode.$createLinkNode(domNode.href);
614
- } else {
615
- node = lexical.$createTextNode(domNode.textContent);
616
- }
617
-
618
- return {
619
- node
620
- };
621
- },
622
- b: domNode => {
623
- // $FlowFixMe[incompatible-type] domNode is a <b> since we matched it by nodeName
624
- const b = domNode; // Google Docs wraps all copied HTML in a <b> with font-weight normal
625
-
626
- const hasNormalFontWeight = b.style.fontWeight === 'normal';
627
- return {
628
- forChild: lexicalNode => {
629
- if (lexical.$isTextNode(lexicalNode) && !hasNormalFontWeight) {
630
- lexicalNode.toggleFormat('bold');
631
- }
632
- },
633
- node: null
634
- };
635
- },
636
- br: () => ({
637
- node: lexical.$createLineBreakNode()
638
- }),
639
- div: domNode => {
640
- // $FlowFixMe[incompatible-type] domNode is a <div> since we matched it by nodeName
641
- const div = domNode;
642
- return {
643
- after: childLexicalNodes => {
644
- const domParent = domNode.parentNode;
645
-
646
- if (domParent != null && domNode !== domParent.lastChild) {
647
- childLexicalNodes.push(lexical.$createLineBreakNode());
648
- }
649
-
650
- return childLexicalNodes;
651
- },
652
- node: isCodeElement(div) ? CodeNode.$createCodeNode() : null
653
- };
654
- },
655
- em: domNode => {
656
- return {
657
- forChild: lexicalNode => {
658
- if (lexical.$isTextNode(lexicalNode)) {
659
- lexicalNode.toggleFormat('italic');
660
- }
661
- },
662
- node: null
663
- };
664
- },
665
- h1: () => ({
666
- node: HeadingNode.$createHeadingNode('h1')
667
- }),
668
- h2: () => ({
669
- node: HeadingNode.$createHeadingNode('h2')
670
- }),
671
- h3: () => ({
672
- node: HeadingNode.$createHeadingNode('h3')
673
- }),
674
- h4: () => ({
675
- node: HeadingNode.$createHeadingNode('h4')
676
- }),
677
- h5: () => ({
678
- node: HeadingNode.$createHeadingNode('h5')
679
- }),
680
- i: domNode => {
681
- return {
682
- forChild: lexicalNode => {
683
- if (lexical.$isTextNode(lexicalNode)) {
684
- lexicalNode.toggleFormat('italic');
685
- }
686
- },
687
- node: null
688
- };
689
- },
690
- li: () => ({
691
- node: list.$createListItemNode()
692
- }),
693
- ol: () => ({
694
- node: list.$createListNode('ol')
695
- }),
696
- p: () => ({
697
- node: lexical.$createParagraphNode()
698
- }),
699
- pre: domNode => ({
700
- node: CodeNode.$createCodeNode()
701
- }),
702
- span: domNode => {
703
- // $FlowFixMe[incompatible-type] domNode is a <span> since we matched it by nodeName
704
- const span = domNode; // Google Docs uses span tags + font-weight for bold text
705
-
706
- const hasBoldFontWeight = span.style.fontWeight === '700';
707
- return {
708
- forChild: lexicalNode => {
709
- if (lexical.$isTextNode(lexicalNode) && hasBoldFontWeight) {
710
- lexicalNode.toggleFormat('bold');
711
- }
712
- },
713
- node: null
714
- };
715
- },
716
- strong: domNode => {
717
- return {
718
- forChild: lexicalNode => {
719
- if (lexical.$isTextNode(lexicalNode)) {
720
- lexicalNode.toggleFormat('bold');
721
- }
722
- },
723
- node: null
724
- };
725
- },
726
- table: domNode => {
727
- // $FlowFixMe[incompatible-type] domNode is a <table> since we matched it by nodeName
728
- const table = domNode;
729
- const isGitHubCodeTable = table.classList.contains('js-file-line-container');
730
- return {
731
- node: isGitHubCodeTable ? CodeNode.$createCodeNode() : null
732
- };
733
- },
734
- td: domNode => {
735
- // $FlowFixMe[incompatible-type] domNode is a <table> since we matched it by nodeName
736
- const cell = domNode;
737
- const isGitHubCodeCell = cell.classList.contains('js-file-line');
738
- return {
739
- after: childLexicalNodes => {
740
- if (isGitHubCodeCell && cell.parentNode && cell.parentNode.nextSibling) {
741
- // Append newline between code lines
742
- childLexicalNodes.push(lexical.$createLineBreakNode());
743
- }
744
-
745
- return childLexicalNodes;
746
- },
747
- node: null
748
- };
749
- },
750
- u: domNode => {
751
- return {
752
- forChild: lexicalNode => {
753
- if (lexical.$isTextNode(lexicalNode)) {
754
- lexicalNode.toggleFormat('underline');
755
- }
756
- },
757
- node: null
758
- };
759
- },
760
- ul: () => ({
761
- node: list.$createListNode('ul')
762
- })
763
- };
764
-
765
- function $generateNodes(nodeRange) {
766
- const {
767
- range,
768
- nodeMap
769
- } = nodeRange;
770
- const parsedNodeMap = new Map(nodeMap);
771
- const nodes = [];
772
-
773
- for (let i = 0; i < range.length; i++) {
774
- const key = range[i];
775
- const parsedNode = parsedNodeMap.get(key);
776
-
777
- if (parsedNode !== undefined) {
778
- const node = lexical.$createNodeFromParse(parsedNode, parsedNodeMap);
779
- nodes.push(node);
780
- }
781
- }
782
-
783
- return nodes;
784
- }
785
-
786
- function $createNodesFromDOM(node, conversionMap, editor, forChildMap = new Map()) {
787
- let lexicalNodes = [];
788
- let currentLexicalNode = null;
789
- const nodeName = node.nodeName.toLowerCase();
790
- const customHtmlTransforms = editor._config.htmlTransforms || {};
791
- const transformFunction = customHtmlTransforms[nodeName] || conversionMap[nodeName];
792
- const transformOutput = transformFunction ? transformFunction(node) : null;
793
- let postTransform = null;
794
-
795
- if (transformOutput !== null) {
796
- postTransform = transformOutput.after;
797
- currentLexicalNode = transformOutput.node;
798
-
799
- if (currentLexicalNode !== null) {
800
- lexicalNodes.push(currentLexicalNode);
801
- const forChildFunctions = Array.from(forChildMap.values());
802
-
803
- for (let i = 0; i < forChildFunctions.length; i++) {
804
- forChildFunctions[i](currentLexicalNode);
805
- }
806
- }
807
-
808
- if (transformOutput.forChild != null) {
809
- forChildMap.set(nodeName, transformOutput.forChild);
810
- }
811
- } // If the DOM node doesn't have a transformer, we don't know what
812
- // to do with it but we still need to process any childNodes.
813
-
814
-
815
- const children = node.childNodes;
816
- let childLexicalNodes = [];
817
-
818
- for (let i = 0; i < children.length; i++) {
819
- childLexicalNodes.push(...$createNodesFromDOM(children[i], conversionMap, editor, forChildMap));
820
- }
821
-
822
- if (postTransform != null) {
823
- childLexicalNodes = postTransform(childLexicalNodes);
824
- }
825
-
826
- if (currentLexicalNode == null) {
827
- // If it hasn't been converted to a LexicalNode, we hoist its children
828
- // up to the same level as it.
829
- lexicalNodes = lexicalNodes.concat(childLexicalNodes);
830
- } else {
831
- if (lexical.$isElementNode(currentLexicalNode)) {
832
- // If the current node is a ElementNode after conversion,
833
- // we can append all the children to it.
834
- currentLexicalNode.append(...childLexicalNodes);
835
- }
836
- }
837
-
838
- return lexicalNodes;
839
- }
840
-
841
- function $generateNodesFromDOM(dom, conversionMap, editor) {
842
- let lexicalNodes = [];
843
- const elements = dom.body ? Array.from(dom.body.childNodes) : [];
844
- const elementsLength = elements.length;
845
-
846
- for (let i = 0; i < elementsLength; i++) {
847
- const lexicalNode = $createNodesFromDOM(elements[i], conversionMap, editor);
848
-
849
- if (lexicalNode !== null) {
850
- lexicalNodes = lexicalNodes.concat(lexicalNode);
851
- }
852
- }
853
-
854
- return lexicalNodes;
855
- }
856
-
857
- function $insertDataTransferForRichText(dataTransfer, selection, editor) {
858
- const lexicalNodesString = dataTransfer.getData('application/x-lexical-editor');
859
-
860
- if (lexicalNodesString) {
861
- const namespace = editor._config.namespace;
862
-
863
- try {
864
- const lexicalClipboardData = JSON.parse(lexicalNodesString);
865
-
866
- if (lexicalClipboardData.namespace === namespace) {
867
- const nodeRange = lexicalClipboardData.state;
868
- const nodes = $generateNodes(nodeRange);
869
- selection.insertNodes(nodes);
870
- return;
871
- }
872
- } catch (e) {// Malformed, missing nodes..
873
- }
874
- }
875
-
876
- const textHtmlMimeType = 'text/html';
877
- const htmlString = dataTransfer.getData(textHtmlMimeType);
878
-
879
- if (htmlString) {
880
- const parser = new DOMParser();
881
- const dom = parser.parseFromString(htmlString, textHtmlMimeType);
882
- 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
883
-
884
- const topLevelBlocks = [];
885
- let currentBlock = null;
886
-
887
- for (let i = 0; i < nodes.length; i++) {
888
- const node = nodes[i];
889
-
890
- if (!lexical.$isElementNode(node) || node.isInline()) {
891
- if (currentBlock === null) {
892
- currentBlock = lexical.$createParagraphNode();
893
- topLevelBlocks.push(currentBlock);
894
- }
895
-
896
- if (currentBlock !== null) {
897
- currentBlock.append(node);
898
- }
899
- } else {
900
- topLevelBlocks.push(node);
901
- currentBlock = null;
902
- }
903
- }
904
-
905
- selection.insertNodes(topLevelBlocks);
906
- return;
907
- }
908
-
909
- $insertDataTransferForPlainText(dataTransfer, selection);
910
- }
911
- function $insertDataTransferForPlainText(dataTransfer, selection) {
912
- const text = dataTransfer.getData('text/plain');
913
-
914
- if (text != null) {
915
- selection.insertRawText(text);
916
- }
917
- }
918
- function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
919
- const possibleNode = getPossibleDecoratorNode(selection.focus, isBackward);
920
- return lexical.$isDecoratorNode(possibleNode) && !possibleNode.isIsolated();
921
- }
922
- function onPasteForRichText(event, editor) {
923
- event.preventDefault();
924
- editor.update(() => {
925
- const selection = lexical.$getSelection();
926
- const clipboardData = event.clipboardData;
927
-
928
- if (clipboardData != null && selection !== null) {
929
- $insertDataTransferForRichText(clipboardData, selection, editor);
930
- }
931
- });
932
- }
389
+ /**
390
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
391
+ *
392
+ * This source code is licensed under the MIT license found in the
393
+ * LICENSE file in the root directory of this source tree.
394
+ *
395
+ *
396
+ */
933
397
  function onCutForRichText(event, editor) {
934
398
  onCopyForRichText(event, editor);
935
399
  editor.update(() => {
936
400
  const selection = lexical.$getSelection();
937
401
 
938
- if (selection !== null) {
402
+ if (lexical.$isRangeSelection(selection)) {
939
403
  selection.removeText();
940
404
  }
941
405
  });
@@ -948,41 +412,33 @@ function onCopyForRichText(event, editor) {
948
412
 
949
413
  if (selection !== null) {
950
414
  if (clipboardData != null) {
951
- const domSelection = window.getSelection(); // If we haven't selected a range, then don't copy anything
415
+ const htmlString = clipboard.getHtmlContent(editor);
416
+ const lexicalString = clipboard.$getLexicalContent(editor);
952
417
 
953
- if (domSelection.isCollapsed) {
954
- return;
418
+ if (htmlString !== null) {
419
+ clipboardData.setData('text/html', htmlString);
955
420
  }
956
421
 
957
- const range = domSelection.getRangeAt(0);
958
-
959
- if (range) {
960
- const container = document.createElement('div');
961
- const frag = range.cloneContents();
962
- container.appendChild(frag);
963
- clipboardData.setData('text/html', container.innerHTML);
422
+ if (lexicalString !== null) {
423
+ clipboardData.setData('application/x-lexical-editor', lexicalString);
964
424
  }
965
425
 
966
426
  clipboardData.setData('text/plain', selection.getTextContent());
967
- const namespace = editor._config.namespace;
968
- clipboardData.setData('application/x-lexical-editor', JSON.stringify({
969
- namespace,
970
- state: $cloneContents(selection)
971
- }));
972
427
  }
973
428
  }
974
429
  });
975
430
  }
431
+ function onPasteForRichText(event, editor) {
432
+ event.preventDefault();
433
+ editor.update(() => {
434
+ const selection = lexical.$getSelection();
435
+ const clipboardData = event.clipboardData;
976
436
 
977
- /**
978
- * Copyright (c) Meta Platforms, Inc. and affiliates.
979
- *
980
- * This source code is licensed under the MIT license found in the
981
- * LICENSE file in the root directory of this source tree.
982
- *
983
- *
984
- */
985
- const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
437
+ if (clipboardData != null && lexical.$isRangeSelection(selection)) {
438
+ clipboard.$insertDataTransferForRichText(clipboardData, selection, editor);
439
+ }
440
+ });
441
+ }
986
442
 
987
443
  /**
988
444
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -992,8 +448,53 @@ const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !==
992
448
  *
993
449
  *
994
450
  */
995
- const useLayoutEffectImpl = CAN_USE_DOM ? react.useLayoutEffect : react.useEffect;
996
- var useLayoutEffect = useLayoutEffectImpl;
451
+ // Convoluted logic to make this work with Flow. Order matters.
452
+ const options = {
453
+ tag: 'history-merge'
454
+ };
455
+ const setEditorOptions = options;
456
+ const updateOptions = options;
457
+ function initializeEditor(editor, initialEditorState) {
458
+ if (initialEditorState === null) {
459
+ return;
460
+ } else if (initialEditorState === undefined) {
461
+ editor.update(() => {
462
+ const root = lexical.$getRoot();
463
+ const firstChild = root.getFirstChild();
464
+
465
+ if (firstChild === null) {
466
+ const paragraph = lexical.$createParagraphNode();
467
+ root.append(paragraph);
468
+ const activeElement = document.activeElement;
469
+
470
+ if (lexical.$getSelection() !== null || activeElement !== null && activeElement === editor.getRootElement()) {
471
+ paragraph.select();
472
+ }
473
+ }
474
+ }, updateOptions);
475
+ } else if (initialEditorState !== null) {
476
+ switch (typeof initialEditorState) {
477
+ case 'string':
478
+ {
479
+ const parsedEditorState = editor.parseEditorState(initialEditorState);
480
+ editor.setEditorState(parsedEditorState, setEditorOptions);
481
+ break;
482
+ }
483
+
484
+ case 'object':
485
+ {
486
+ editor.setEditorState(initialEditorState, setEditorOptions);
487
+ break;
488
+ }
489
+
490
+ case 'function':
491
+ {
492
+ editor.update(initialEditorState, updateOptions);
493
+ break;
494
+ }
495
+ }
496
+ }
497
+ }
997
498
 
998
499
  /**
999
500
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -1034,7 +535,7 @@ function useLexicalDragonSupport(editor) {
1034
535
  editor.update(() => {
1035
536
  const selection = lexical.$getSelection();
1036
537
 
1037
- if (selection !== null) {
538
+ if (lexical.$isRangeSelection(selection)) {
1038
539
  const anchor = selection.anchor;
1039
540
  let anchorNode = anchor.getNode();
1040
541
  let setSelStart = 0;
@@ -1091,13 +592,17 @@ function useLexicalDragonSupport(editor) {
1091
592
  *
1092
593
  *
1093
594
  */
1094
- const EditorPriority = 0;
1095
- function useRichTextSetup(editor) {
595
+ function useRichTextSetup(editor, initialEditorState) {
1096
596
  useLayoutEffect(() => {
1097
597
  const removeListener = editor.addListener('command', (type, payload) => {
1098
598
  const selection = lexical.$getSelection();
1099
599
 
1100
- if (selection === null) {
600
+ if (type === 'click' && lexical.$isNodeSelection(selection)) {
601
+ selection.clear();
602
+ return true;
603
+ }
604
+
605
+ if (!lexical.$isRangeSelection(selection)) {
1101
606
  return false;
1102
607
  }
1103
608
 
@@ -1133,7 +638,7 @@ function useRichTextSetup(editor) {
1133
638
  const dataTransfer = eventOrText.dataTransfer;
1134
639
 
1135
640
  if (dataTransfer != null) {
1136
- $insertDataTransferForRichText(dataTransfer, selection, editor);
641
+ clipboard.$insertDataTransferForRichText(dataTransfer, selection, editor);
1137
642
  } else {
1138
643
  const data = eventOrText.data;
1139
644
 
@@ -1326,9 +831,10 @@ function useRichTextSetup(editor) {
1326
831
  }
1327
832
 
1328
833
  return false;
1329
- }, EditorPriority);
1330
- editor.execCommand('bootstrapEditor');
1331
- return removeListener;
834
+ }, 0);
835
+ initializeEditor(editor, initialEditorState);
836
+ return removeListener; // We only do this for init
837
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1332
838
  }, [editor]);
1333
839
  useLexicalDragonSupport(editor);
1334
840
  }
@@ -1341,8 +847,8 @@ function useRichTextSetup(editor) {
1341
847
  *
1342
848
  *
1343
849
  */
1344
- function useLexicalRichText(editor, externalHistoryState) {
1345
- useRichTextSetup(editor);
850
+ function useLexicalRichText(editor, externalHistoryState, initialEditorState) {
851
+ useRichTextSetup(editor, initialEditorState);
1346
852
  useLexicalHistory(editor, externalHistoryState);
1347
853
  }
1348
854