@lexical/react 0.1.10 → 0.1.13
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/DEPRECATED_useLexical.dev.js +3 -7
- package/DEPRECATED_useLexical.prod.js +1 -1
- package/DEPRECATED_useLexicalAutoFormatter.dev.js +83 -37
- package/DEPRECATED_useLexicalAutoFormatter.prod.js +20 -19
- package/DEPRECATED_useLexicalCharacterLimit.dev.js +20 -17
- package/DEPRECATED_useLexicalCharacterLimit.prod.js +8 -8
- package/DEPRECATED_useLexicalList.dev.js +6 -0
- package/DEPRECATED_useLexicalList.prod.js +1 -1
- package/DEPRECATED_useLexicalPlainText.dev.js +84 -75
- package/DEPRECATED_useLexicalPlainText.prod.js +15 -15
- package/DEPRECATED_useLexicalRichText.dev.js +96 -438
- package/DEPRECATED_useLexicalRichText.prod.js +17 -26
- package/LexicalAutoFormatterPlugin.d.ts +9 -0
- package/LexicalAutoFormatterPlugin.dev.js +83 -37
- package/LexicalAutoFormatterPlugin.js.flow +10 -0
- package/LexicalAutoFormatterPlugin.prod.js +21 -20
- package/LexicalAutoLinkPlugin.d.ts +20 -0
- package/LexicalAutoLinkPlugin.js.flow +23 -0
- package/LexicalCharacterLimitPlugin.d.ts +11 -0
- package/LexicalCharacterLimitPlugin.dev.js +20 -17
- package/LexicalCharacterLimitPlugin.js.flow +12 -0
- package/LexicalCharacterLimitPlugin.prod.js +9 -8
- package/LexicalClearEditorPlugin.d.ts +14 -0
- package/LexicalClearEditorPlugin.dev.js +73 -0
- package/LexicalClearEditorPlugin.js +9 -0
- package/LexicalClearEditorPlugin.js.flow +14 -0
- package/LexicalClearEditorPlugin.prod.js +8 -0
- package/LexicalCollaborationPlugin.d.ts +49 -0
- package/LexicalCollaborationPlugin.dev.js +21 -13
- package/LexicalCollaborationPlugin.js.flow +55 -0
- package/LexicalCollaborationPlugin.prod.js +7 -7
- package/LexicalComposer.d.ts +22 -0
- package/LexicalComposer.dev.js +32 -3
- package/LexicalComposer.js.flow +24 -0
- package/LexicalComposer.prod.js +3 -2
- package/LexicalComposerContext.d.ts +24 -0
- package/LexicalComposerContext.js.flow +27 -0
- package/LexicalContentEditable.d.ts +32 -0
- package/LexicalContentEditable.dev.js +35 -8
- package/LexicalContentEditable.js.flow +35 -0
- package/LexicalContentEditable.prod.js +3 -3
- package/LexicalHashtagPlugin.d.ts +9 -0
- package/LexicalHashtagPlugin.js.flow +10 -0
- package/LexicalHistoryPlugin.d.ts +29 -0
- package/LexicalHistoryPlugin.js.flow +34 -0
- package/LexicalHorizontalRuleNode.d.ts +23 -0
- package/LexicalHorizontalRuleNode.js.flow +25 -0
- package/LexicalLinkPlugin.d.ts +9 -0
- package/LexicalLinkPlugin.js.flow +10 -0
- package/LexicalListPlugin.d.ts +9 -0
- package/LexicalListPlugin.dev.js +6 -0
- package/LexicalListPlugin.js.flow +10 -0
- package/LexicalListPlugin.prod.js +2 -2
- package/LexicalNestedComposer.d.ts +17 -0
- package/LexicalNestedComposer.dev.js +21 -11
- package/LexicalNestedComposer.js.flow +18 -0
- package/LexicalNestedComposer.prod.js +3 -2
- package/LexicalOnChangePlugin.d.ts +12 -0
- package/LexicalOnChangePlugin.js.flow +14 -0
- package/LexicalPlainTextPlugin.d.ts +15 -0
- package/LexicalPlainTextPlugin.dev.js +73 -84
- package/LexicalPlainTextPlugin.js.flow +18 -0
- package/LexicalPlainTextPlugin.prod.js +12 -12
- package/LexicalRichTextPlugin.d.ts +15 -0
- package/LexicalRichTextPlugin.dev.js +85 -447
- package/LexicalRichTextPlugin.js.flow +18 -0
- package/LexicalRichTextPlugin.prod.js +13 -22
- package/LexicalTablePlugin.d.ts +9 -0
- package/LexicalTablePlugin.dev.js +22 -0
- package/LexicalTablePlugin.js.flow +10 -0
- package/LexicalTablePlugin.prod.js +4 -3
- package/LexicalTreeView.d.ts +17 -0
- package/LexicalTreeView.js.flow +19 -0
- package/README.md +0 -1
- package/package.json +9 -5
- package/useLexicalDecoratorMap.d.ts +14 -0
- package/useLexicalDecoratorMap.js.flow +16 -0
- package/useLexicalIsTextContentEmpty.d.ts +13 -0
- package/useLexicalIsTextContentEmpty.js.flow +15 -0
- package/useLexicalNodeSelection.d.ts +12 -0
- package/useLexicalNodeSelection.js.flow +14 -0
- package/withSubscriptions.d.ts +12 -0
- package/withSubscriptions.js.flow +13 -0
- package/LexicalBootstrapPlugin.dev.js +0 -122
- package/LexicalBootstrapPlugin.js +0 -9
- package/LexicalBootstrapPlugin.prod.js +0 -8
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
var withSubscriptions = require('@lexical/react/withSubscriptions');
|
|
10
10
|
var lexical = require('lexical');
|
|
11
11
|
var react = require('react');
|
|
12
|
+
var clipboard = require('@lexical/clipboard');
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -347,188 +348,6 @@ function useLexicalHistory(editor, externalHistoryState, delay = 1000) {
|
|
|
347
348
|
*
|
|
348
349
|
*/
|
|
349
350
|
|
|
350
|
-
function $cloneWithProperties(node) {
|
|
351
|
-
const latest = node.getLatest();
|
|
352
|
-
const constructor = latest.constructor;
|
|
353
|
-
const clone = constructor.clone(latest);
|
|
354
|
-
clone.__parent = latest.__parent;
|
|
355
|
-
|
|
356
|
-
if (lexical.$isElementNode(latest) && lexical.$isElementNode(clone)) {
|
|
357
|
-
clone.__children = Array.from(latest.__children);
|
|
358
|
-
clone.__format = latest.__format;
|
|
359
|
-
clone.__indent = latest.__indent;
|
|
360
|
-
clone.__dir = latest.__dir;
|
|
361
|
-
} else if (lexical.$isTextNode(latest) && lexical.$isTextNode(clone)) {
|
|
362
|
-
clone.__format = latest.__format;
|
|
363
|
-
clone.__style = latest.__style;
|
|
364
|
-
clone.__mode = latest.__mode;
|
|
365
|
-
clone.__detail = latest.__detail;
|
|
366
|
-
} else if (lexical.$isDecoratorNode(latest) && lexical.$isDecoratorNode(clone)) {
|
|
367
|
-
clone.__state = latest.__state;
|
|
368
|
-
} // $FlowFixMe
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
return clone;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
function $getIndexFromPossibleClone(node, parent, nodeMap) {
|
|
375
|
-
const parentClone = nodeMap.get(parent.getKey());
|
|
376
|
-
|
|
377
|
-
if (lexical.$isElementNode(parentClone)) {
|
|
378
|
-
return parentClone.__children.indexOf(node.getKey());
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
return node.getIndexWithinParent();
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
function $getParentAvoidingExcludedElements(node) {
|
|
385
|
-
let parent = node.getParent();
|
|
386
|
-
|
|
387
|
-
while (parent !== null && parent.excludeFromCopy()) {
|
|
388
|
-
parent = parent.getParent();
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
return parent;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
function $copyLeafNodeBranchToRoot(leaf, startingOffset, isLeftSide, range, nodeMap) {
|
|
395
|
-
let node = leaf;
|
|
396
|
-
let offset = startingOffset;
|
|
397
|
-
|
|
398
|
-
while (node !== null) {
|
|
399
|
-
const parent = $getParentAvoidingExcludedElements(node);
|
|
400
|
-
|
|
401
|
-
if (parent === null) {
|
|
402
|
-
break;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
if (!lexical.$isElementNode(node) || !node.excludeFromCopy()) {
|
|
406
|
-
const key = node.getKey();
|
|
407
|
-
let clone = nodeMap.get(key);
|
|
408
|
-
const needsClone = clone === undefined;
|
|
409
|
-
|
|
410
|
-
if (needsClone) {
|
|
411
|
-
clone = $cloneWithProperties(node);
|
|
412
|
-
nodeMap.set(key, clone);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
if (lexical.$isTextNode(clone) && !clone.isSegmented() && !clone.isToken()) {
|
|
416
|
-
clone.__text = clone.__text.slice(isLeftSide ? offset : 0, isLeftSide ? undefined : offset);
|
|
417
|
-
} else if (lexical.$isElementNode(clone)) {
|
|
418
|
-
clone.__children = clone.__children.slice(isLeftSide ? offset : 0, isLeftSide ? undefined : offset + 1);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
if (lexical.$isRootNode(parent)) {
|
|
422
|
-
if (needsClone) {
|
|
423
|
-
// We only want to collect a range of top level nodes.
|
|
424
|
-
// So if the parent is the root, we know this is a top level.
|
|
425
|
-
range.push(key);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
break;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
offset = $getIndexFromPossibleClone(node, parent, nodeMap);
|
|
433
|
-
node = parent;
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
function $cloneContents(selection) {
|
|
438
|
-
if (!lexical.$isRangeSelection(selection)) {
|
|
439
|
-
{
|
|
440
|
-
throw Error(`TODO`);
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
const anchor = selection.anchor;
|
|
445
|
-
const focus = selection.focus;
|
|
446
|
-
const anchorOffset = anchor.getCharacterOffset();
|
|
447
|
-
const focusOffset = focus.getCharacterOffset();
|
|
448
|
-
const anchorNode = anchor.getNode();
|
|
449
|
-
const focusNode = focus.getNode();
|
|
450
|
-
const anchorNodeParent = anchorNode.getParentOrThrow(); // Handle a single text node extraction
|
|
451
|
-
|
|
452
|
-
if (anchorNode === focusNode && lexical.$isTextNode(anchorNode) && (anchorNodeParent.canBeEmpty() || anchorNodeParent.getChildrenSize() > 1)) {
|
|
453
|
-
const clonedFirstNode = $cloneWithProperties(anchorNode);
|
|
454
|
-
const isBefore = focusOffset > anchorOffset;
|
|
455
|
-
const startOffset = isBefore ? anchorOffset : focusOffset;
|
|
456
|
-
const endOffset = isBefore ? focusOffset : anchorOffset;
|
|
457
|
-
clonedFirstNode.__text = clonedFirstNode.__text.slice(startOffset, endOffset);
|
|
458
|
-
const key = clonedFirstNode.getKey();
|
|
459
|
-
return {
|
|
460
|
-
nodeMap: [[key, clonedFirstNode]],
|
|
461
|
-
range: [key]
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const nodes = selection.getNodes();
|
|
466
|
-
|
|
467
|
-
if (nodes.length === 0) {
|
|
468
|
-
return {
|
|
469
|
-
nodeMap: [],
|
|
470
|
-
range: []
|
|
471
|
-
};
|
|
472
|
-
} // Check if we can use the parent of the nodes, if the
|
|
473
|
-
// parent can't be empty, then it's important that we
|
|
474
|
-
// also copy that element node along with its children.
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
let nodesLength = nodes.length;
|
|
478
|
-
const firstNode = nodes[0];
|
|
479
|
-
const firstNodeParent = firstNode.getParent();
|
|
480
|
-
|
|
481
|
-
if (firstNodeParent !== null && (!firstNodeParent.canBeEmpty() || lexical.$isRootNode(firstNodeParent))) {
|
|
482
|
-
const parentChildren = firstNodeParent.__children;
|
|
483
|
-
const parentChildrenLength = parentChildren.length;
|
|
484
|
-
|
|
485
|
-
if (parentChildrenLength === nodesLength) {
|
|
486
|
-
let areTheSame = true;
|
|
487
|
-
|
|
488
|
-
for (let i = 0; i < parentChildren.length; i++) {
|
|
489
|
-
if (parentChildren[i] !== nodes[i].__key) {
|
|
490
|
-
areTheSame = false;
|
|
491
|
-
break;
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
if (areTheSame) {
|
|
496
|
-
nodesLength++;
|
|
497
|
-
nodes.push(firstNodeParent);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
const lastNode = nodes[nodesLength - 1];
|
|
503
|
-
const isBefore = anchor.isBefore(focus);
|
|
504
|
-
const nodeMap = new Map();
|
|
505
|
-
const range = []; // Do first node to root
|
|
506
|
-
|
|
507
|
-
$copyLeafNodeBranchToRoot(firstNode, isBefore ? anchorOffset : focusOffset, true, range, nodeMap); // Copy all nodes between
|
|
508
|
-
|
|
509
|
-
for (let i = 0; i < nodesLength; i++) {
|
|
510
|
-
const node = nodes[i];
|
|
511
|
-
const key = node.getKey();
|
|
512
|
-
|
|
513
|
-
if (!nodeMap.has(key) && (!lexical.$isElementNode(node) || !node.excludeFromCopy())) {
|
|
514
|
-
const clone = $cloneWithProperties(node);
|
|
515
|
-
|
|
516
|
-
if (lexical.$isRootNode(node.getParent())) {
|
|
517
|
-
range.push(node.getKey());
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
nodeMap.set(key, clone);
|
|
521
|
-
}
|
|
522
|
-
} // Do last node to root
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
$copyLeafNodeBranchToRoot(lastNode, isBefore ? focusOffset : anchorOffset, false, range, nodeMap);
|
|
526
|
-
return {
|
|
527
|
-
nodeMap: Array.from(nodeMap.entries()),
|
|
528
|
-
range
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
|
|
532
351
|
function $moveCaretSelection(selection, isHoldingShift, isBackward, granularity) {
|
|
533
352
|
selection.modify(isHoldingShift ? 'extend' : 'move', isBackward, granularity);
|
|
534
353
|
}
|
|
@@ -541,6 +360,10 @@ function $moveCharacter(selection, isHoldingShift, isBackward) {
|
|
|
541
360
|
const isRTL = $isParentElementRTL(selection);
|
|
542
361
|
$moveCaretSelection(selection, isHoldingShift, isBackward ? !isRTL : isRTL, 'character');
|
|
543
362
|
}
|
|
363
|
+
function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
|
|
364
|
+
const possibleNode = lexical.$getDecoratorNode(selection.focus, isBackward);
|
|
365
|
+
return lexical.$isDecoratorNode(possibleNode) && !possibleNode.isIsolated();
|
|
366
|
+
}
|
|
544
367
|
|
|
545
368
|
/**
|
|
546
369
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -550,46 +373,7 @@ function $moveCharacter(selection, isHoldingShift, isBackward) {
|
|
|
550
373
|
*
|
|
551
374
|
*
|
|
552
375
|
*/
|
|
553
|
-
|
|
554
|
-
const parent = element.getParent();
|
|
555
|
-
let offset = focusOffset;
|
|
556
|
-
let block = element;
|
|
557
|
-
|
|
558
|
-
if (parent !== null) {
|
|
559
|
-
if (isBackward && focusOffset === 0) {
|
|
560
|
-
offset = block.getIndexWithinParent();
|
|
561
|
-
block = parent;
|
|
562
|
-
} else if (!isBackward && focusOffset === block.getChildrenSize()) {
|
|
563
|
-
offset = block.getIndexWithinParent() + 1;
|
|
564
|
-
block = parent;
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
return block.getChildAtIndex(isBackward ? offset - 1 : offset);
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
function getPossibleDecoratorNode(focus, isBackward) {
|
|
572
|
-
const focusOffset = focus.offset;
|
|
573
|
-
|
|
574
|
-
if (focus.type === 'element') {
|
|
575
|
-
const block = focus.getNode();
|
|
576
|
-
return resolveElement(block, isBackward, focusOffset);
|
|
577
|
-
} else {
|
|
578
|
-
const focusNode = focus.getNode();
|
|
579
|
-
|
|
580
|
-
if (isBackward && focusOffset === 0 || !isBackward && focusOffset === focusNode.getTextContentSize()) {
|
|
581
|
-
const possibleNode = isBackward ? focusNode.getPreviousSibling() : focusNode.getNextSibling();
|
|
582
|
-
|
|
583
|
-
if (possibleNode === null) {
|
|
584
|
-
return resolveElement(focusNode.getParentOrThrow(), isBackward, focusNode.getIndexWithinParent() + (isBackward ? 0 : 1));
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
return possibleNode;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
return null;
|
|
592
|
-
}
|
|
376
|
+
const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
|
|
593
377
|
|
|
594
378
|
/**
|
|
595
379
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -599,185 +383,50 @@ function getPossibleDecoratorNode(focus, isBackward) {
|
|
|
599
383
|
*
|
|
600
384
|
*
|
|
601
385
|
*/
|
|
386
|
+
const useLayoutEffectImpl = CAN_USE_DOM ? react.useLayoutEffect : react.useEffect;
|
|
387
|
+
var useLayoutEffect = useLayoutEffectImpl;
|
|
602
388
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
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
|
+
*/
|
|
397
|
+
function onCutForRichText(event, editor) {
|
|
398
|
+
onCopyForRichText(event, editor);
|
|
399
|
+
editor.update(() => {
|
|
400
|
+
const selection = lexical.$getSelection();
|
|
614
401
|
|
|
615
|
-
if (
|
|
616
|
-
|
|
617
|
-
nodes.push(node);
|
|
402
|
+
if (lexical.$isRangeSelection(selection)) {
|
|
403
|
+
selection.removeText();
|
|
618
404
|
}
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
return nodes;
|
|
405
|
+
});
|
|
622
406
|
}
|
|
407
|
+
function onCopyForRichText(event, editor) {
|
|
408
|
+
event.preventDefault();
|
|
409
|
+
editor.update(() => {
|
|
410
|
+
const clipboardData = event.clipboardData;
|
|
411
|
+
const selection = lexical.$getSelection();
|
|
623
412
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
const cachedConversions = editor._htmlConversions.get(nodeName.toLowerCase());
|
|
630
|
-
|
|
631
|
-
let currentConversion = null;
|
|
632
|
-
|
|
633
|
-
if (cachedConversions !== undefined) {
|
|
634
|
-
cachedConversions.forEach(cachedConversion => {
|
|
635
|
-
const domConversion = cachedConversion(domNode);
|
|
413
|
+
if (selection !== null) {
|
|
414
|
+
if (clipboardData != null) {
|
|
415
|
+
const htmlString = clipboard.getHtmlContent(editor);
|
|
416
|
+
const lexicalString = clipboard.$getLexicalContent(editor);
|
|
636
417
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
currentConversion = domConversion;
|
|
418
|
+
if (htmlString !== null) {
|
|
419
|
+
clipboardData.setData('text/html', htmlString);
|
|
640
420
|
}
|
|
641
|
-
}
|
|
642
|
-
});
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
return currentConversion !== null ? currentConversion.conversion : null;
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
function $createNodesFromDOM(node, editor, forChildMap = new Map()) {
|
|
649
|
-
let lexicalNodes = [];
|
|
650
|
-
let currentLexicalNode = null;
|
|
651
|
-
const transformFunction = getConversionFunction(node, editor);
|
|
652
|
-
const transformOutput = transformFunction ? transformFunction(node) : null;
|
|
653
|
-
let postTransform = null;
|
|
654
|
-
|
|
655
|
-
if (transformOutput !== null) {
|
|
656
|
-
postTransform = transformOutput.after;
|
|
657
|
-
currentLexicalNode = transformOutput.node;
|
|
658
|
-
|
|
659
|
-
if (currentLexicalNode !== null) {
|
|
660
|
-
lexicalNodes.push(currentLexicalNode);
|
|
661
|
-
const forChildFunctions = Array.from(forChildMap.values());
|
|
662
|
-
|
|
663
|
-
for (let i = 0; i < forChildFunctions.length; i++) {
|
|
664
|
-
forChildFunctions[i](currentLexicalNode);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
if (transformOutput.forChild != null) {
|
|
669
|
-
forChildMap.set(node.nodeName, transformOutput.forChild);
|
|
670
|
-
}
|
|
671
|
-
} // If the DOM node doesn't have a transformer, we don't know what
|
|
672
|
-
// to do with it but we still need to process any childNodes.
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
const children = node.childNodes;
|
|
676
|
-
let childLexicalNodes = [];
|
|
677
|
-
|
|
678
|
-
for (let i = 0; i < children.length; i++) {
|
|
679
|
-
childLexicalNodes.push(...$createNodesFromDOM(children[i], editor, forChildMap));
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
if (postTransform != null) {
|
|
683
|
-
childLexicalNodes = postTransform(childLexicalNodes);
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
if (currentLexicalNode == null) {
|
|
687
|
-
// If it hasn't been converted to a LexicalNode, we hoist its children
|
|
688
|
-
// up to the same level as it.
|
|
689
|
-
lexicalNodes = lexicalNodes.concat(childLexicalNodes);
|
|
690
|
-
} else {
|
|
691
|
-
if (lexical.$isElementNode(currentLexicalNode)) {
|
|
692
|
-
// If the current node is a ElementNode after conversion,
|
|
693
|
-
// we can append all the children to it.
|
|
694
|
-
currentLexicalNode.append(...childLexicalNodes);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
return lexicalNodes;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
function $generateNodesFromDOM(dom, editor) {
|
|
702
|
-
let lexicalNodes = [];
|
|
703
|
-
const elements = dom.body ? Array.from(dom.body.childNodes) : [];
|
|
704
|
-
const elementsLength = elements.length;
|
|
705
|
-
|
|
706
|
-
for (let i = 0; i < elementsLength; i++) {
|
|
707
|
-
const lexicalNode = $createNodesFromDOM(elements[i], editor);
|
|
708
|
-
|
|
709
|
-
if (lexicalNode !== null) {
|
|
710
|
-
lexicalNodes = lexicalNodes.concat(lexicalNode);
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
return lexicalNodes;
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
function $insertDataTransferForRichText(dataTransfer, selection, editor) {
|
|
718
|
-
const lexicalNodesString = dataTransfer.getData('application/x-lexical-editor');
|
|
719
|
-
|
|
720
|
-
if (lexicalNodesString) {
|
|
721
|
-
const namespace = editor._config.namespace;
|
|
722
|
-
|
|
723
|
-
try {
|
|
724
|
-
const lexicalClipboardData = JSON.parse(lexicalNodesString);
|
|
725
421
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
const nodes = $generateNodes(nodeRange);
|
|
729
|
-
selection.insertNodes(nodes);
|
|
730
|
-
return;
|
|
731
|
-
}
|
|
732
|
-
} catch (e) {// Malformed, missing nodes..
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
const textHtmlMimeType = 'text/html';
|
|
737
|
-
const htmlString = dataTransfer.getData(textHtmlMimeType);
|
|
738
|
-
|
|
739
|
-
if (htmlString) {
|
|
740
|
-
const parser = new DOMParser();
|
|
741
|
-
const dom = parser.parseFromString(htmlString, textHtmlMimeType);
|
|
742
|
-
const nodes = $generateNodesFromDOM(dom, editor); // Wrap text and inline nodes in paragraph nodes so we have all blocks at the top-level
|
|
743
|
-
|
|
744
|
-
const topLevelBlocks = [];
|
|
745
|
-
let currentBlock = null;
|
|
746
|
-
|
|
747
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
748
|
-
const node = nodes[i];
|
|
749
|
-
|
|
750
|
-
if (!lexical.$isElementNode(node) || node.isInline()) {
|
|
751
|
-
if (currentBlock === null) {
|
|
752
|
-
currentBlock = lexical.$createParagraphNode();
|
|
753
|
-
topLevelBlocks.push(currentBlock);
|
|
422
|
+
if (lexicalString !== null) {
|
|
423
|
+
clipboardData.setData('application/x-lexical-editor', lexicalString);
|
|
754
424
|
}
|
|
755
425
|
|
|
756
|
-
|
|
757
|
-
currentBlock.append(node);
|
|
758
|
-
}
|
|
759
|
-
} else {
|
|
760
|
-
topLevelBlocks.push(node);
|
|
761
|
-
currentBlock = null;
|
|
426
|
+
clipboardData.setData('text/plain', selection.getTextContent());
|
|
762
427
|
}
|
|
763
428
|
}
|
|
764
|
-
|
|
765
|
-
selection.insertNodes(topLevelBlocks);
|
|
766
|
-
return;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
$insertDataTransferForPlainText(dataTransfer, selection);
|
|
770
|
-
}
|
|
771
|
-
function $insertDataTransferForPlainText(dataTransfer, selection) {
|
|
772
|
-
const text = dataTransfer.getData('text/plain');
|
|
773
|
-
|
|
774
|
-
if (text != null) {
|
|
775
|
-
selection.insertRawText(text);
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
|
|
779
|
-
const possibleNode = getPossibleDecoratorNode(selection.focus, isBackward);
|
|
780
|
-
return lexical.$isDecoratorNode(possibleNode) && !possibleNode.isIsolated();
|
|
429
|
+
});
|
|
781
430
|
}
|
|
782
431
|
function onPasteForRichText(event, editor) {
|
|
783
432
|
event.preventDefault();
|
|
@@ -786,52 +435,65 @@ function onPasteForRichText(event, editor) {
|
|
|
786
435
|
const clipboardData = event.clipboardData;
|
|
787
436
|
|
|
788
437
|
if (clipboardData != null && lexical.$isRangeSelection(selection)) {
|
|
789
|
-
|
|
790
|
-
}
|
|
791
|
-
});
|
|
792
|
-
}
|
|
793
|
-
function onCutForRichText(event, editor) {
|
|
794
|
-
onCopyForRichText(event, editor);
|
|
795
|
-
editor.update(() => {
|
|
796
|
-
const selection = lexical.$getSelection();
|
|
797
|
-
|
|
798
|
-
if (lexical.$isRangeSelection(selection)) {
|
|
799
|
-
selection.removeText();
|
|
438
|
+
clipboard.$insertDataTransferForRichText(clipboardData, selection, editor);
|
|
800
439
|
}
|
|
801
440
|
});
|
|
802
441
|
}
|
|
803
|
-
function onCopyForRichText(event, editor) {
|
|
804
|
-
event.preventDefault();
|
|
805
|
-
editor.update(() => {
|
|
806
|
-
const clipboardData = event.clipboardData;
|
|
807
|
-
const selection = lexical.$getSelection();
|
|
808
|
-
|
|
809
|
-
if (selection !== null) {
|
|
810
|
-
if (clipboardData != null) {
|
|
811
|
-
const domSelection = window.getSelection(); // If we haven't selected a range, then don't copy anything
|
|
812
442
|
|
|
813
|
-
|
|
814
|
-
|
|
443
|
+
/**
|
|
444
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
445
|
+
*
|
|
446
|
+
* This source code is licensed under the MIT license found in the
|
|
447
|
+
* LICENSE file in the root directory of this source tree.
|
|
448
|
+
*
|
|
449
|
+
*
|
|
450
|
+
*/
|
|
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;
|
|
815
482
|
}
|
|
816
483
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
const frag = range.cloneContents();
|
|
822
|
-
container.appendChild(frag);
|
|
823
|
-
clipboardData.setData('text/html', container.innerHTML);
|
|
484
|
+
case 'object':
|
|
485
|
+
{
|
|
486
|
+
editor.setEditorState(initialEditorState, setEditorOptions);
|
|
487
|
+
break;
|
|
824
488
|
}
|
|
825
489
|
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
}));
|
|
832
|
-
}
|
|
490
|
+
case 'function':
|
|
491
|
+
{
|
|
492
|
+
editor.update(initialEditorState, updateOptions);
|
|
493
|
+
break;
|
|
494
|
+
}
|
|
833
495
|
}
|
|
834
|
-
}
|
|
496
|
+
}
|
|
835
497
|
}
|
|
836
498
|
|
|
837
499
|
/**
|
|
@@ -930,8 +592,8 @@ function useLexicalDragonSupport(editor) {
|
|
|
930
592
|
*
|
|
931
593
|
*
|
|
932
594
|
*/
|
|
933
|
-
function useRichTextSetup(editor) {
|
|
934
|
-
|
|
595
|
+
function useRichTextSetup(editor, initialEditorState) {
|
|
596
|
+
useLayoutEffect(() => {
|
|
935
597
|
const removeListener = editor.addListener('command', (type, payload) => {
|
|
936
598
|
const selection = lexical.$getSelection();
|
|
937
599
|
|
|
@@ -976,7 +638,7 @@ function useRichTextSetup(editor) {
|
|
|
976
638
|
const dataTransfer = eventOrText.dataTransfer;
|
|
977
639
|
|
|
978
640
|
if (dataTransfer != null) {
|
|
979
|
-
|
|
641
|
+
clipboard.$insertDataTransferForRichText(dataTransfer, selection, editor);
|
|
980
642
|
} else {
|
|
981
643
|
const data = eventOrText.data;
|
|
982
644
|
|
|
@@ -1170,13 +832,9 @@ function useRichTextSetup(editor) {
|
|
|
1170
832
|
|
|
1171
833
|
return false;
|
|
1172
834
|
}, 0);
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
console.warn('bootstrapEditor command was not handled. Did you forget to add <BootstrapPlugin />?');
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
return removeListener;
|
|
835
|
+
initializeEditor(editor, initialEditorState);
|
|
836
|
+
return removeListener; // We only do this for init
|
|
837
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1180
838
|
}, [editor]);
|
|
1181
839
|
useLexicalDragonSupport(editor);
|
|
1182
840
|
}
|
|
@@ -1189,8 +847,8 @@ function useRichTextSetup(editor) {
|
|
|
1189
847
|
*
|
|
1190
848
|
*
|
|
1191
849
|
*/
|
|
1192
|
-
function useLexicalRichText(editor, externalHistoryState) {
|
|
1193
|
-
useRichTextSetup(editor);
|
|
850
|
+
function useLexicalRichText(editor, externalHistoryState, initialEditorState) {
|
|
851
|
+
useRichTextSetup(editor, initialEditorState);
|
|
1194
852
|
useLexicalHistory(editor, externalHistoryState);
|
|
1195
853
|
}
|
|
1196
854
|
|