lexical 0.27.3-nightly.20250314.0 → 0.27.3-nightly.20250318.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Lexical.dev.js +122 -14
- package/Lexical.dev.mjs +121 -15
- package/Lexical.js.flow +24 -9
- package/Lexical.mjs +2 -0
- package/Lexical.node.mjs +2 -0
- package/Lexical.prod.js +1 -1
- package/Lexical.prod.mjs +1 -1
- package/LexicalEditor.d.ts +52 -6
- package/LexicalSelection.d.ts +6 -0
- package/LexicalUpdates.d.ts +2 -2
- package/caret/LexicalCaret.d.ts +5 -1
- package/caret/LexicalCaretUtils.d.ts +37 -0
- package/index.d.ts +3 -3
- package/nodes/LexicalElementNode.d.ts +9 -9
- package/nodes/LexicalRootNode.d.ts +1 -1
- package/package.json +1 -1
package/Lexical.dev.js
CHANGED
|
@@ -1538,7 +1538,7 @@ function $reconcileNode(key, parentDOM) {
|
|
|
1538
1538
|
return dom;
|
|
1539
1539
|
}
|
|
1540
1540
|
// If the node key doesn't point to the same instance in both maps,
|
|
1541
|
-
// it
|
|
1541
|
+
// it was cloned. If it's also dirty, we mark it as mutated.
|
|
1542
1542
|
if (prevNode !== nextNode && isDirty) {
|
|
1543
1543
|
setMutatedNode(mutatedNodes, activeEditorNodes, activeMutationListeners, nextNode, 'updated');
|
|
1544
1544
|
}
|
|
@@ -5336,6 +5336,22 @@ class NodeSelection {
|
|
|
5336
5336
|
}
|
|
5337
5337
|
return textContent;
|
|
5338
5338
|
}
|
|
5339
|
+
|
|
5340
|
+
/**
|
|
5341
|
+
* Remove all nodes in the NodeSelection. If there were any nodes,
|
|
5342
|
+
* replace the selection with a new RangeSelection at the previous
|
|
5343
|
+
* location of the first node.
|
|
5344
|
+
*/
|
|
5345
|
+
deleteNodes() {
|
|
5346
|
+
const nodes = this.getNodes();
|
|
5347
|
+
if (($getSelection() || $getPreviousSelection()) === this && nodes[0]) {
|
|
5348
|
+
const firstCaret = $getSiblingCaret(nodes[0], 'next');
|
|
5349
|
+
$setSelectionFromCaretRange($getCaretRange(firstCaret, firstCaret));
|
|
5350
|
+
}
|
|
5351
|
+
for (const node of nodes) {
|
|
5352
|
+
node.remove();
|
|
5353
|
+
}
|
|
5354
|
+
}
|
|
5339
5355
|
}
|
|
5340
5356
|
function $isRangeSelection(x) {
|
|
5341
5357
|
return x instanceof RangeSelection;
|
|
@@ -7688,6 +7704,7 @@ function $applyAllTransforms(editorState, editor) {
|
|
|
7688
7704
|
for (const currentUntransformedDirtyElement of untransformedDirtyElements) {
|
|
7689
7705
|
const nodeKey = currentUntransformedDirtyElement[0];
|
|
7690
7706
|
const intentionallyMarkedAsDirty = currentUntransformedDirtyElement[1];
|
|
7707
|
+
dirtyElements.set(nodeKey, intentionallyMarkedAsDirty);
|
|
7691
7708
|
if (nodeKey !== 'root' && !intentionallyMarkedAsDirty) {
|
|
7692
7709
|
continue;
|
|
7693
7710
|
}
|
|
@@ -7695,7 +7712,6 @@ function $applyAllTransforms(editorState, editor) {
|
|
|
7695
7712
|
if (node !== undefined && $isNodeValidForTransform(node, compositionKey)) {
|
|
7696
7713
|
$applyTransforms(editor, node, transformsCache);
|
|
7697
7714
|
}
|
|
7698
|
-
dirtyElements.set(nodeKey, intentionallyMarkedAsDirty);
|
|
7699
7715
|
}
|
|
7700
7716
|
untransformedDirtyLeaves = editor._dirtyLeaves;
|
|
7701
7717
|
untransformedDirtyLeavesLength = untransformedDirtyLeaves.size;
|
|
@@ -7961,6 +7977,7 @@ function $commitPendingUpdates(editor, recoveryEditorState) {
|
|
|
7961
7977
|
dirtyElements,
|
|
7962
7978
|
dirtyLeaves,
|
|
7963
7979
|
editorState: pendingEditorState,
|
|
7980
|
+
mutatedNodes,
|
|
7964
7981
|
normalizedNodes,
|
|
7965
7982
|
prevEditorState: recoveryEditorState || currentEditorState,
|
|
7966
7983
|
tags
|
|
@@ -7996,7 +8013,6 @@ function triggerListeners(type, editor, isCurrentlyEnqueuingUpdates, ...payload)
|
|
|
7996
8013
|
try {
|
|
7997
8014
|
const listeners = Array.from(editor._listeners[type]);
|
|
7998
8015
|
for (let i = 0; i < listeners.length; i++) {
|
|
7999
|
-
// @ts-ignore
|
|
8000
8016
|
listeners[i].apply(null, payload);
|
|
8001
8017
|
}
|
|
8002
8018
|
} finally {
|
|
@@ -8258,6 +8274,9 @@ class ElementDOMSlot {
|
|
|
8258
8274
|
* Return a new ElementDOMSlot with an updated root element
|
|
8259
8275
|
*/
|
|
8260
8276
|
withElement(element) {
|
|
8277
|
+
if (this.element === element) {
|
|
8278
|
+
return this;
|
|
8279
|
+
}
|
|
8261
8280
|
return new ElementDOMSlot(element, this.before, this.after);
|
|
8262
8281
|
}
|
|
8263
8282
|
/**
|
|
@@ -9126,17 +9145,13 @@ class RootNode extends ElementNode {
|
|
|
9126
9145
|
}
|
|
9127
9146
|
|
|
9128
9147
|
// Mutate
|
|
9129
|
-
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
if (!$isElementNode(node) && !$isDecoratorNode(node)) {
|
|
9134
|
-
{
|
|
9135
|
-
formatDevErrorMessage(`rootNode.append: Only element or decorator nodes can be appended to the root node`);
|
|
9136
|
-
}
|
|
9148
|
+
splice(start, deleteCount, nodesToInsert) {
|
|
9149
|
+
for (const node of nodesToInsert) {
|
|
9150
|
+
if (!($isElementNode(node) || $isDecoratorNode(node))) {
|
|
9151
|
+
formatDevErrorMessage(`rootNode.splice: Only element or decorator nodes can be inserted to the root node`);
|
|
9137
9152
|
}
|
|
9138
9153
|
}
|
|
9139
|
-
return super.
|
|
9154
|
+
return super.splice(start, deleteCount, nodesToInsert);
|
|
9140
9155
|
}
|
|
9141
9156
|
static importJSON(serializedNode) {
|
|
9142
9157
|
// We don't create a root, and instead use the existing root.
|
|
@@ -9368,6 +9383,15 @@ function $isParagraphNode(node) {
|
|
|
9368
9383
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9369
9384
|
|
|
9370
9385
|
const DEFAULT_SKIP_INITIALIZATION = false;
|
|
9386
|
+
|
|
9387
|
+
/**
|
|
9388
|
+
* The payload passed to an UpdateListener
|
|
9389
|
+
*/
|
|
9390
|
+
|
|
9391
|
+
/**
|
|
9392
|
+
* A listener that gets called after the editor is updated
|
|
9393
|
+
*/
|
|
9394
|
+
|
|
9371
9395
|
const COMMAND_PRIORITY_EDITOR = 0;
|
|
9372
9396
|
const COMMAND_PRIORITY_LOW = 1;
|
|
9373
9397
|
const COMMAND_PRIORITY_NORMAL = 2;
|
|
@@ -10223,7 +10247,7 @@ class LexicalEditor {
|
|
|
10223
10247
|
};
|
|
10224
10248
|
}
|
|
10225
10249
|
}
|
|
10226
|
-
LexicalEditor.version = "0.27.3-nightly.
|
|
10250
|
+
LexicalEditor.version = "0.27.3-nightly.20250318.0+dev.cjs";
|
|
10227
10251
|
|
|
10228
10252
|
let keyCounter = 1;
|
|
10229
10253
|
function resetRandomKey() {
|
|
@@ -12197,6 +12221,13 @@ function $extendCaretToRange(anchor) {
|
|
|
12197
12221
|
return $getCaretRange(anchor, $getSiblingCaret($getRoot(), anchor.direction));
|
|
12198
12222
|
}
|
|
12199
12223
|
|
|
12224
|
+
/**
|
|
12225
|
+
* Construct a collapsed CaretRange that starts and ends at anchor.
|
|
12226
|
+
*/
|
|
12227
|
+
function $getCollapsedCaretRange(anchor) {
|
|
12228
|
+
return $getCaretRange(anchor, anchor);
|
|
12229
|
+
}
|
|
12230
|
+
|
|
12200
12231
|
/**
|
|
12201
12232
|
* Construct a CaretRange from anchor and focus carets pointing in the
|
|
12202
12233
|
* same direction. In order to get the expected behavior,
|
|
@@ -12659,7 +12690,7 @@ function $removeTextFromCaretRange(initialRange, sliceMode = 'removeEmptySlices'
|
|
|
12659
12690
|
const bestCandidate = [anchorCandidate, focusCandidate, ...anchorCandidates, ...focusCandidates].find($isCaretAttached);
|
|
12660
12691
|
if (bestCandidate) {
|
|
12661
12692
|
const anchor = $getCaretInDirection($normalizeCaret(bestCandidate), initialRange.direction);
|
|
12662
|
-
return $
|
|
12693
|
+
return $getCollapsedCaretRange(anchor);
|
|
12663
12694
|
}
|
|
12664
12695
|
{
|
|
12665
12696
|
formatDevErrorMessage(`$removeTextFromCaretRange: selection was lost, could not find a new anchor given candidates with keys: ${JSON.stringify(anchorCandidates.map(n => n.origin.__key))}`);
|
|
@@ -12847,6 +12878,81 @@ function $getAdjacentSiblingOrParentSiblingCaret(startCaret, rootMode = 'root')
|
|
|
12847
12878
|
return nextCaret && [nextCaret, depthDiff];
|
|
12848
12879
|
}
|
|
12849
12880
|
|
|
12881
|
+
/**
|
|
12882
|
+
* Get the adjacent nodes to initialCaret in the given direction.
|
|
12883
|
+
*
|
|
12884
|
+
* @example
|
|
12885
|
+
* ```ts
|
|
12886
|
+
* expect($getAdjacentNodes($getChildCaret(parent, 'next'))).toEqual(parent.getChildren());
|
|
12887
|
+
* expect($getAdjacentNodes($getChildCaret(parent, 'previous'))).toEqual(parent.getChildren().reverse());
|
|
12888
|
+
* expect($getAdjacentNodes($getSiblingCaret(node, 'next'))).toEqual(node.getNextSiblings());
|
|
12889
|
+
* expect($getAdjacentNodes($getSiblingCaret(node, 'previous'))).toEqual(node.getPreviousSiblings().reverse());
|
|
12890
|
+
* ```
|
|
12891
|
+
*
|
|
12892
|
+
* @param initialCaret The caret to start at (the origin will not be included)
|
|
12893
|
+
* @returns An array of siblings.
|
|
12894
|
+
*/
|
|
12895
|
+
function $getAdjacentNodes(initialCaret) {
|
|
12896
|
+
const siblings = [];
|
|
12897
|
+
for (let caret = initialCaret.getAdjacentCaret(); caret; caret = caret.getAdjacentCaret()) {
|
|
12898
|
+
siblings.push(caret.origin);
|
|
12899
|
+
}
|
|
12900
|
+
return siblings;
|
|
12901
|
+
}
|
|
12902
|
+
function $splitTextPointCaret(textPointCaret) {
|
|
12903
|
+
const {
|
|
12904
|
+
origin,
|
|
12905
|
+
offset,
|
|
12906
|
+
direction
|
|
12907
|
+
} = textPointCaret;
|
|
12908
|
+
if (offset === $getTextNodeOffset(origin, direction)) {
|
|
12909
|
+
return textPointCaret.getSiblingCaret();
|
|
12910
|
+
} else if (offset === $getTextNodeOffset(origin, flipDirection(direction))) {
|
|
12911
|
+
return $rewindSiblingCaret(textPointCaret.getSiblingCaret());
|
|
12912
|
+
}
|
|
12913
|
+
const [textNode] = origin.splitText(offset);
|
|
12914
|
+
if (!$isTextNode(textNode)) {
|
|
12915
|
+
formatDevErrorMessage(`$splitTextPointCaret: splitText must return at least one TextNode`);
|
|
12916
|
+
}
|
|
12917
|
+
return $getCaretInDirection($getSiblingCaret(textNode, 'next'), direction);
|
|
12918
|
+
}
|
|
12919
|
+
function $alwaysSplit(_node, _edge) {
|
|
12920
|
+
return true;
|
|
12921
|
+
}
|
|
12922
|
+
|
|
12923
|
+
/**
|
|
12924
|
+
* Split a node at a PointCaret and return a NodeCaret at that point, or null if the
|
|
12925
|
+
* node can't be split. This is non-recursive and will only perform at most one split.
|
|
12926
|
+
*
|
|
12927
|
+
* @returns The NodeCaret pointing to the location of the split (or null if a split is not possible)
|
|
12928
|
+
*/
|
|
12929
|
+
function $splitAtPointCaretNext(pointCaret, {
|
|
12930
|
+
$copyElementNode = $copyNode,
|
|
12931
|
+
$splitTextPointCaretNext = $splitTextPointCaret,
|
|
12932
|
+
rootMode = 'shadowRoot',
|
|
12933
|
+
$shouldSplit = $alwaysSplit
|
|
12934
|
+
} = {}) {
|
|
12935
|
+
if ($isTextPointCaret(pointCaret)) {
|
|
12936
|
+
return $splitTextPointCaretNext(pointCaret);
|
|
12937
|
+
}
|
|
12938
|
+
const parentCaret = pointCaret.getParentCaret(rootMode);
|
|
12939
|
+
if (parentCaret) {
|
|
12940
|
+
const {
|
|
12941
|
+
origin
|
|
12942
|
+
} = parentCaret;
|
|
12943
|
+
if ($isChildCaret(pointCaret) && !(origin.canBeEmpty() && $shouldSplit(origin, 'first'))) {
|
|
12944
|
+
// No split necessary, the left side would be empty
|
|
12945
|
+
return $rewindSiblingCaret(parentCaret);
|
|
12946
|
+
}
|
|
12947
|
+
const siblings = $getAdjacentNodes(pointCaret);
|
|
12948
|
+
if (siblings.length > 0 || origin.canBeEmpty() && $shouldSplit(origin, 'last')) {
|
|
12949
|
+
// Split and insert the siblings into the new tree
|
|
12950
|
+
parentCaret.insert($copyElementNode(origin).splice(0, 0, siblings));
|
|
12951
|
+
}
|
|
12952
|
+
}
|
|
12953
|
+
return parentCaret;
|
|
12954
|
+
}
|
|
12955
|
+
|
|
12850
12956
|
exports.$addUpdateTag = $addUpdateTag;
|
|
12851
12957
|
exports.$applyNodeReplacement = $applyNodeReplacement;
|
|
12852
12958
|
exports.$caretFromPoint = $caretFromPoint;
|
|
@@ -12873,6 +12979,7 @@ exports.$getCharacterOffsets = $getCharacterOffsets;
|
|
|
12873
12979
|
exports.$getChildCaret = $getChildCaret;
|
|
12874
12980
|
exports.$getChildCaretAtIndex = $getChildCaretAtIndex;
|
|
12875
12981
|
exports.$getChildCaretOrSelf = $getChildCaretOrSelf;
|
|
12982
|
+
exports.$getCollapsedCaretRange = $getCollapsedCaretRange;
|
|
12876
12983
|
exports.$getCommonAncestor = $getCommonAncestor;
|
|
12877
12984
|
exports.$getCommonAncestorResultBranchOrder = $getCommonAncestorResultBranchOrder;
|
|
12878
12985
|
exports.$getEditor = $getEditor;
|
|
@@ -12927,6 +13034,7 @@ exports.$setPointFromCaret = $setPointFromCaret;
|
|
|
12927
13034
|
exports.$setSelection = $setSelection;
|
|
12928
13035
|
exports.$setSelectionFromCaretRange = $setSelectionFromCaretRange;
|
|
12929
13036
|
exports.$setState = $setState;
|
|
13037
|
+
exports.$splitAtPointCaretNext = $splitAtPointCaretNext;
|
|
12930
13038
|
exports.$splitNode = $splitNode;
|
|
12931
13039
|
exports.$updateRangeSelectionFromCaretRange = $updateRangeSelectionFromCaretRange;
|
|
12932
13040
|
exports.ArtificialNode__DO_NOT_USE = ArtificialNode__DO_NOT_USE;
|
package/Lexical.dev.mjs
CHANGED
|
@@ -1536,7 +1536,7 @@ function $reconcileNode(key, parentDOM) {
|
|
|
1536
1536
|
return dom;
|
|
1537
1537
|
}
|
|
1538
1538
|
// If the node key doesn't point to the same instance in both maps,
|
|
1539
|
-
// it
|
|
1539
|
+
// it was cloned. If it's also dirty, we mark it as mutated.
|
|
1540
1540
|
if (prevNode !== nextNode && isDirty) {
|
|
1541
1541
|
setMutatedNode(mutatedNodes, activeEditorNodes, activeMutationListeners, nextNode, 'updated');
|
|
1542
1542
|
}
|
|
@@ -5334,6 +5334,22 @@ class NodeSelection {
|
|
|
5334
5334
|
}
|
|
5335
5335
|
return textContent;
|
|
5336
5336
|
}
|
|
5337
|
+
|
|
5338
|
+
/**
|
|
5339
|
+
* Remove all nodes in the NodeSelection. If there were any nodes,
|
|
5340
|
+
* replace the selection with a new RangeSelection at the previous
|
|
5341
|
+
* location of the first node.
|
|
5342
|
+
*/
|
|
5343
|
+
deleteNodes() {
|
|
5344
|
+
const nodes = this.getNodes();
|
|
5345
|
+
if (($getSelection() || $getPreviousSelection()) === this && nodes[0]) {
|
|
5346
|
+
const firstCaret = $getSiblingCaret(nodes[0], 'next');
|
|
5347
|
+
$setSelectionFromCaretRange($getCaretRange(firstCaret, firstCaret));
|
|
5348
|
+
}
|
|
5349
|
+
for (const node of nodes) {
|
|
5350
|
+
node.remove();
|
|
5351
|
+
}
|
|
5352
|
+
}
|
|
5337
5353
|
}
|
|
5338
5354
|
function $isRangeSelection(x) {
|
|
5339
5355
|
return x instanceof RangeSelection;
|
|
@@ -7686,6 +7702,7 @@ function $applyAllTransforms(editorState, editor) {
|
|
|
7686
7702
|
for (const currentUntransformedDirtyElement of untransformedDirtyElements) {
|
|
7687
7703
|
const nodeKey = currentUntransformedDirtyElement[0];
|
|
7688
7704
|
const intentionallyMarkedAsDirty = currentUntransformedDirtyElement[1];
|
|
7705
|
+
dirtyElements.set(nodeKey, intentionallyMarkedAsDirty);
|
|
7689
7706
|
if (nodeKey !== 'root' && !intentionallyMarkedAsDirty) {
|
|
7690
7707
|
continue;
|
|
7691
7708
|
}
|
|
@@ -7693,7 +7710,6 @@ function $applyAllTransforms(editorState, editor) {
|
|
|
7693
7710
|
if (node !== undefined && $isNodeValidForTransform(node, compositionKey)) {
|
|
7694
7711
|
$applyTransforms(editor, node, transformsCache);
|
|
7695
7712
|
}
|
|
7696
|
-
dirtyElements.set(nodeKey, intentionallyMarkedAsDirty);
|
|
7697
7713
|
}
|
|
7698
7714
|
untransformedDirtyLeaves = editor._dirtyLeaves;
|
|
7699
7715
|
untransformedDirtyLeavesLength = untransformedDirtyLeaves.size;
|
|
@@ -7959,6 +7975,7 @@ function $commitPendingUpdates(editor, recoveryEditorState) {
|
|
|
7959
7975
|
dirtyElements,
|
|
7960
7976
|
dirtyLeaves,
|
|
7961
7977
|
editorState: pendingEditorState,
|
|
7978
|
+
mutatedNodes,
|
|
7962
7979
|
normalizedNodes,
|
|
7963
7980
|
prevEditorState: recoveryEditorState || currentEditorState,
|
|
7964
7981
|
tags
|
|
@@ -7994,7 +8011,6 @@ function triggerListeners(type, editor, isCurrentlyEnqueuingUpdates, ...payload)
|
|
|
7994
8011
|
try {
|
|
7995
8012
|
const listeners = Array.from(editor._listeners[type]);
|
|
7996
8013
|
for (let i = 0; i < listeners.length; i++) {
|
|
7997
|
-
// @ts-ignore
|
|
7998
8014
|
listeners[i].apply(null, payload);
|
|
7999
8015
|
}
|
|
8000
8016
|
} finally {
|
|
@@ -8256,6 +8272,9 @@ class ElementDOMSlot {
|
|
|
8256
8272
|
* Return a new ElementDOMSlot with an updated root element
|
|
8257
8273
|
*/
|
|
8258
8274
|
withElement(element) {
|
|
8275
|
+
if (this.element === element) {
|
|
8276
|
+
return this;
|
|
8277
|
+
}
|
|
8259
8278
|
return new ElementDOMSlot(element, this.before, this.after);
|
|
8260
8279
|
}
|
|
8261
8280
|
/**
|
|
@@ -9124,17 +9143,13 @@ class RootNode extends ElementNode {
|
|
|
9124
9143
|
}
|
|
9125
9144
|
|
|
9126
9145
|
// Mutate
|
|
9127
|
-
|
|
9128
|
-
|
|
9129
|
-
|
|
9130
|
-
|
|
9131
|
-
if (!$isElementNode(node) && !$isDecoratorNode(node)) {
|
|
9132
|
-
{
|
|
9133
|
-
formatDevErrorMessage(`rootNode.append: Only element or decorator nodes can be appended to the root node`);
|
|
9134
|
-
}
|
|
9146
|
+
splice(start, deleteCount, nodesToInsert) {
|
|
9147
|
+
for (const node of nodesToInsert) {
|
|
9148
|
+
if (!($isElementNode(node) || $isDecoratorNode(node))) {
|
|
9149
|
+
formatDevErrorMessage(`rootNode.splice: Only element or decorator nodes can be inserted to the root node`);
|
|
9135
9150
|
}
|
|
9136
9151
|
}
|
|
9137
|
-
return super.
|
|
9152
|
+
return super.splice(start, deleteCount, nodesToInsert);
|
|
9138
9153
|
}
|
|
9139
9154
|
static importJSON(serializedNode) {
|
|
9140
9155
|
// We don't create a root, and instead use the existing root.
|
|
@@ -9366,6 +9381,15 @@ function $isParagraphNode(node) {
|
|
|
9366
9381
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9367
9382
|
|
|
9368
9383
|
const DEFAULT_SKIP_INITIALIZATION = false;
|
|
9384
|
+
|
|
9385
|
+
/**
|
|
9386
|
+
* The payload passed to an UpdateListener
|
|
9387
|
+
*/
|
|
9388
|
+
|
|
9389
|
+
/**
|
|
9390
|
+
* A listener that gets called after the editor is updated
|
|
9391
|
+
*/
|
|
9392
|
+
|
|
9369
9393
|
const COMMAND_PRIORITY_EDITOR = 0;
|
|
9370
9394
|
const COMMAND_PRIORITY_LOW = 1;
|
|
9371
9395
|
const COMMAND_PRIORITY_NORMAL = 2;
|
|
@@ -10221,7 +10245,7 @@ class LexicalEditor {
|
|
|
10221
10245
|
};
|
|
10222
10246
|
}
|
|
10223
10247
|
}
|
|
10224
|
-
LexicalEditor.version = "0.27.3-nightly.
|
|
10248
|
+
LexicalEditor.version = "0.27.3-nightly.20250318.0+dev.esm";
|
|
10225
10249
|
|
|
10226
10250
|
let keyCounter = 1;
|
|
10227
10251
|
function resetRandomKey() {
|
|
@@ -12195,6 +12219,13 @@ function $extendCaretToRange(anchor) {
|
|
|
12195
12219
|
return $getCaretRange(anchor, $getSiblingCaret($getRoot(), anchor.direction));
|
|
12196
12220
|
}
|
|
12197
12221
|
|
|
12222
|
+
/**
|
|
12223
|
+
* Construct a collapsed CaretRange that starts and ends at anchor.
|
|
12224
|
+
*/
|
|
12225
|
+
function $getCollapsedCaretRange(anchor) {
|
|
12226
|
+
return $getCaretRange(anchor, anchor);
|
|
12227
|
+
}
|
|
12228
|
+
|
|
12198
12229
|
/**
|
|
12199
12230
|
* Construct a CaretRange from anchor and focus carets pointing in the
|
|
12200
12231
|
* same direction. In order to get the expected behavior,
|
|
@@ -12657,7 +12688,7 @@ function $removeTextFromCaretRange(initialRange, sliceMode = 'removeEmptySlices'
|
|
|
12657
12688
|
const bestCandidate = [anchorCandidate, focusCandidate, ...anchorCandidates, ...focusCandidates].find($isCaretAttached);
|
|
12658
12689
|
if (bestCandidate) {
|
|
12659
12690
|
const anchor = $getCaretInDirection($normalizeCaret(bestCandidate), initialRange.direction);
|
|
12660
|
-
return $
|
|
12691
|
+
return $getCollapsedCaretRange(anchor);
|
|
12661
12692
|
}
|
|
12662
12693
|
{
|
|
12663
12694
|
formatDevErrorMessage(`$removeTextFromCaretRange: selection was lost, could not find a new anchor given candidates with keys: ${JSON.stringify(anchorCandidates.map(n => n.origin.__key))}`);
|
|
@@ -12845,4 +12876,79 @@ function $getAdjacentSiblingOrParentSiblingCaret(startCaret, rootMode = 'root')
|
|
|
12845
12876
|
return nextCaret && [nextCaret, depthDiff];
|
|
12846
12877
|
}
|
|
12847
12878
|
|
|
12848
|
-
|
|
12879
|
+
/**
|
|
12880
|
+
* Get the adjacent nodes to initialCaret in the given direction.
|
|
12881
|
+
*
|
|
12882
|
+
* @example
|
|
12883
|
+
* ```ts
|
|
12884
|
+
* expect($getAdjacentNodes($getChildCaret(parent, 'next'))).toEqual(parent.getChildren());
|
|
12885
|
+
* expect($getAdjacentNodes($getChildCaret(parent, 'previous'))).toEqual(parent.getChildren().reverse());
|
|
12886
|
+
* expect($getAdjacentNodes($getSiblingCaret(node, 'next'))).toEqual(node.getNextSiblings());
|
|
12887
|
+
* expect($getAdjacentNodes($getSiblingCaret(node, 'previous'))).toEqual(node.getPreviousSiblings().reverse());
|
|
12888
|
+
* ```
|
|
12889
|
+
*
|
|
12890
|
+
* @param initialCaret The caret to start at (the origin will not be included)
|
|
12891
|
+
* @returns An array of siblings.
|
|
12892
|
+
*/
|
|
12893
|
+
function $getAdjacentNodes(initialCaret) {
|
|
12894
|
+
const siblings = [];
|
|
12895
|
+
for (let caret = initialCaret.getAdjacentCaret(); caret; caret = caret.getAdjacentCaret()) {
|
|
12896
|
+
siblings.push(caret.origin);
|
|
12897
|
+
}
|
|
12898
|
+
return siblings;
|
|
12899
|
+
}
|
|
12900
|
+
function $splitTextPointCaret(textPointCaret) {
|
|
12901
|
+
const {
|
|
12902
|
+
origin,
|
|
12903
|
+
offset,
|
|
12904
|
+
direction
|
|
12905
|
+
} = textPointCaret;
|
|
12906
|
+
if (offset === $getTextNodeOffset(origin, direction)) {
|
|
12907
|
+
return textPointCaret.getSiblingCaret();
|
|
12908
|
+
} else if (offset === $getTextNodeOffset(origin, flipDirection(direction))) {
|
|
12909
|
+
return $rewindSiblingCaret(textPointCaret.getSiblingCaret());
|
|
12910
|
+
}
|
|
12911
|
+
const [textNode] = origin.splitText(offset);
|
|
12912
|
+
if (!$isTextNode(textNode)) {
|
|
12913
|
+
formatDevErrorMessage(`$splitTextPointCaret: splitText must return at least one TextNode`);
|
|
12914
|
+
}
|
|
12915
|
+
return $getCaretInDirection($getSiblingCaret(textNode, 'next'), direction);
|
|
12916
|
+
}
|
|
12917
|
+
function $alwaysSplit(_node, _edge) {
|
|
12918
|
+
return true;
|
|
12919
|
+
}
|
|
12920
|
+
|
|
12921
|
+
/**
|
|
12922
|
+
* Split a node at a PointCaret and return a NodeCaret at that point, or null if the
|
|
12923
|
+
* node can't be split. This is non-recursive and will only perform at most one split.
|
|
12924
|
+
*
|
|
12925
|
+
* @returns The NodeCaret pointing to the location of the split (or null if a split is not possible)
|
|
12926
|
+
*/
|
|
12927
|
+
function $splitAtPointCaretNext(pointCaret, {
|
|
12928
|
+
$copyElementNode = $copyNode,
|
|
12929
|
+
$splitTextPointCaretNext = $splitTextPointCaret,
|
|
12930
|
+
rootMode = 'shadowRoot',
|
|
12931
|
+
$shouldSplit = $alwaysSplit
|
|
12932
|
+
} = {}) {
|
|
12933
|
+
if ($isTextPointCaret(pointCaret)) {
|
|
12934
|
+
return $splitTextPointCaretNext(pointCaret);
|
|
12935
|
+
}
|
|
12936
|
+
const parentCaret = pointCaret.getParentCaret(rootMode);
|
|
12937
|
+
if (parentCaret) {
|
|
12938
|
+
const {
|
|
12939
|
+
origin
|
|
12940
|
+
} = parentCaret;
|
|
12941
|
+
if ($isChildCaret(pointCaret) && !(origin.canBeEmpty() && $shouldSplit(origin, 'first'))) {
|
|
12942
|
+
// No split necessary, the left side would be empty
|
|
12943
|
+
return $rewindSiblingCaret(parentCaret);
|
|
12944
|
+
}
|
|
12945
|
+
const siblings = $getAdjacentNodes(pointCaret);
|
|
12946
|
+
if (siblings.length > 0 || origin.canBeEmpty() && $shouldSplit(origin, 'last')) {
|
|
12947
|
+
// Split and insert the siblings into the new tree
|
|
12948
|
+
parentCaret.insert($copyElementNode(origin).splice(0, 0, siblings));
|
|
12949
|
+
}
|
|
12950
|
+
}
|
|
12951
|
+
return parentCaret;
|
|
12952
|
+
}
|
|
12953
|
+
|
|
12954
|
+
export { $addUpdateTag, $applyNodeReplacement, $caretFromPoint, $caretRangeFromSelection, $cloneWithProperties, $comparePointCaretNext, $copyNode, $createLineBreakNode, $createNodeSelection, $createParagraphNode, $createPoint, $createRangeSelection, $createRangeSelectionFromDom, $createTabNode, $createTextNode, $extendCaretToRange, $getAdjacentChildCaret, $getAdjacentNode, $getAdjacentSiblingOrParentSiblingCaret, $getCaretInDirection, $getCaretRange, $getCaretRangeInDirection, $getCharacterOffsets, $getChildCaret, $getChildCaretAtIndex, $getChildCaretOrSelf, $getCollapsedCaretRange, $getCommonAncestor, $getCommonAncestorResultBranchOrder, $getEditor, $getNearestNodeFromDOMNode, $getNearestRootOrShadowRoot, $getNodeByKey, $getNodeByKeyOrThrow, $getPreviousSelection, $getRoot, $getSelection, $getSiblingCaret, $getState, $getStateChange, $getTextContent, $getTextNodeOffset, $getTextPointCaret, $getTextPointCaretSlice, $getWritableNodeState, $hasAncestor, $hasUpdateTag, $insertNodes, $isBlockElementNode, $isChildCaret, $isDecoratorNode, $isElementNode, $isExtendableTextPointCaret, $isInlineElementOrDecoratorNode, $isLeafNode, $isLineBreakNode, $isNodeCaret, $isNodeSelection, $isParagraphNode, $isRangeSelection, $isRootNode, $isRootOrShadowRoot, $isSiblingCaret, $isTabNode, $isTextNode, $isTextPointCaret, $isTextPointCaretSlice, $isTokenOrSegmented, $nodesOfType, $normalizeCaret, $normalizeSelection as $normalizeSelection__EXPERIMENTAL, $onUpdate, $parseSerializedNode, $removeTextFromCaretRange, $rewindSiblingCaret, $selectAll, $setCompositionKey, $setPointFromCaret, $setSelection, $setSelectionFromCaretRange, $setState, $splitAtPointCaretNext, $splitNode, $updateRangeSelectionFromCaretRange, ArtificialNode__DO_NOT_USE, BLUR_COMMAND, CAN_REDO_COMMAND, CAN_UNDO_COMMAND, CLEAR_EDITOR_COMMAND, CLEAR_HISTORY_COMMAND, CLICK_COMMAND, COMMAND_PRIORITY_CRITICAL, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_LOW, COMMAND_PRIORITY_NORMAL, CONTROLLED_TEXT_INSERTION_COMMAND, COPY_COMMAND, CUT_COMMAND, DELETE_CHARACTER_COMMAND, DELETE_LINE_COMMAND, DELETE_WORD_COMMAND, DRAGEND_COMMAND, DRAGOVER_COMMAND, DRAGSTART_COMMAND, DROP_COMMAND, DecoratorNode, ElementNode, FOCUS_COMMAND, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, INDENT_CONTENT_COMMAND, INSERT_LINE_BREAK_COMMAND, INSERT_PARAGRAPH_COMMAND, INSERT_TAB_COMMAND, INTERNAL_$isBlock, IS_ALL_FORMATTING, IS_BOLD, IS_CODE, IS_HIGHLIGHT, IS_ITALIC, IS_STRIKETHROUGH, IS_SUBSCRIPT, IS_SUPERSCRIPT, IS_UNDERLINE, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_LEFT_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_DOWN_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, KEY_MODIFIER_COMMAND, KEY_SPACE_COMMAND, KEY_TAB_COMMAND, LineBreakNode, MOVE_TO_END, MOVE_TO_START, NODE_STATE_KEY, OUTDENT_CONTENT_COMMAND, PASTE_COMMAND, ParagraphNode, REDO_COMMAND, REMOVE_TEXT_COMMAND, RootNode, SELECTION_CHANGE_COMMAND, SELECTION_INSERT_CLIPBOARD_NODES_COMMAND, SELECT_ALL_COMMAND, TEXT_TYPE_TO_FORMAT, TabNode, TextNode, UNDO_COMMAND, createCommand, createEditor, createState, flipDirection, getDOMOwnerDocument, getDOMSelection, getDOMSelectionFromTarget, getDOMTextNode, getEditorPropertyFromDOMNode, getNearestEditorFromDOMNode, isBlockDomNode, isCurrentlyReadOnlyMode, isDOMDocumentNode, isDOMNode, isDOMTextNode, isDOMUnmanaged, isDocumentFragment, isHTMLAnchorElement, isHTMLElement, isInlineDomNode, isLexicalEditor, isSelectionCapturedInDecoratorInput, isSelectionWithinEditor, makeStepwiseIterator, resetRandomKey, setDOMUnmanaged, setNodeIndentFromDOM };
|
package/Lexical.js.flow
CHANGED
|
@@ -809,7 +809,7 @@ declare export class ElementNode extends LexicalNode {
|
|
|
809
809
|
nodesToInsert: Array<LexicalNode>,
|
|
810
810
|
): this;
|
|
811
811
|
exportJSON(): SerializedElementNode;
|
|
812
|
-
getDOMSlot(dom: HTMLElement): ElementDOMSlot
|
|
812
|
+
getDOMSlot(dom: HTMLElement): ElementDOMSlot<HTMLElement>;
|
|
813
813
|
}
|
|
814
814
|
declare export function $isElementNode(
|
|
815
815
|
node: ?LexicalNode,
|
|
@@ -818,14 +818,14 @@ declare export function $isElementNode(
|
|
|
818
818
|
/**
|
|
819
819
|
* ElementDOMSlot
|
|
820
820
|
*/
|
|
821
|
-
declare export class ElementDOMSlot {
|
|
822
|
-
element: HTMLElement;
|
|
823
|
-
before: Node | null;
|
|
824
|
-
after: Node | null;
|
|
821
|
+
declare export class ElementDOMSlot<+T: HTMLElement> {
|
|
822
|
+
+element: HTMLElement;
|
|
823
|
+
+before: Node | null;
|
|
824
|
+
+after: Node | null;
|
|
825
825
|
constructor(element: HTMLElement, before?: Node | null | void, after?: Node | null | void): void;
|
|
826
|
-
withBefore(before: Node | null | void): ElementDOMSlot
|
|
827
|
-
withAfter(after: Node | null | void): ElementDOMSlot
|
|
828
|
-
withElement(element:
|
|
826
|
+
withBefore(before: Node | null | void): ElementDOMSlot<T>;
|
|
827
|
+
withAfter(after: Node | null | void): ElementDOMSlot<T>;
|
|
828
|
+
withElement<ElementType: HTMLElement>(element: ElementType): ElementDOMSlot<ElementType>;
|
|
829
829
|
insertChild(dom: Node): this;
|
|
830
830
|
removeChild(dom: Node): this;
|
|
831
831
|
replaceChild(dom: Node, prevDom: Node): this;
|
|
@@ -1227,7 +1227,22 @@ declare export function $getCommonAncestor<
|
|
|
1227
1227
|
declare export function $extendCaretToRange<D: CaretDirection>(
|
|
1228
1228
|
anchor: PointCaret<D>,
|
|
1229
1229
|
): CaretRange<D>;
|
|
1230
|
-
|
|
1230
|
+
declare export function $getCollapsedCaretRange<D: CaretDirection>(
|
|
1231
|
+
anchor: PointCaret<D>,
|
|
1232
|
+
): CaretRange<D>;
|
|
1231
1233
|
declare export function $isExtendableTextPointCaret<D: CaretDirection>(
|
|
1232
1234
|
caret: PointCaret<D>
|
|
1233
1235
|
): implies caret is TextPointCaret<TextNode, D>;
|
|
1236
|
+
|
|
1237
|
+
export interface SplitAtPointCaretNextOptions {
|
|
1238
|
+
$copyElementNode?: (node: ElementNode) => ElementNode;
|
|
1239
|
+
$splitTextPointCaretNext?: (
|
|
1240
|
+
caret: TextPointCaret<TextNode, 'next'>,
|
|
1241
|
+
) => NodeCaret<'next'>;
|
|
1242
|
+
rootMode?: RootMode;
|
|
1243
|
+
$shouldSplit?: (node: ElementNode, edge: 'first' | 'last') => boolean;
|
|
1244
|
+
}
|
|
1245
|
+
declare export function $splitAtPointCaretNext(
|
|
1246
|
+
pointCaret: PointCaret<'next'>,
|
|
1247
|
+
options?: SplitAtPointCaretNextOptions,
|
|
1248
|
+
): null | NodeCaret<'next'>;
|
package/Lexical.mjs
CHANGED
|
@@ -35,6 +35,7 @@ export const $getCharacterOffsets = mod.$getCharacterOffsets;
|
|
|
35
35
|
export const $getChildCaret = mod.$getChildCaret;
|
|
36
36
|
export const $getChildCaretAtIndex = mod.$getChildCaretAtIndex;
|
|
37
37
|
export const $getChildCaretOrSelf = mod.$getChildCaretOrSelf;
|
|
38
|
+
export const $getCollapsedCaretRange = mod.$getCollapsedCaretRange;
|
|
38
39
|
export const $getCommonAncestor = mod.$getCommonAncestor;
|
|
39
40
|
export const $getCommonAncestorResultBranchOrder = mod.$getCommonAncestorResultBranchOrder;
|
|
40
41
|
export const $getEditor = mod.$getEditor;
|
|
@@ -89,6 +90,7 @@ export const $setPointFromCaret = mod.$setPointFromCaret;
|
|
|
89
90
|
export const $setSelection = mod.$setSelection;
|
|
90
91
|
export const $setSelectionFromCaretRange = mod.$setSelectionFromCaretRange;
|
|
91
92
|
export const $setState = mod.$setState;
|
|
93
|
+
export const $splitAtPointCaretNext = mod.$splitAtPointCaretNext;
|
|
92
94
|
export const $splitNode = mod.$splitNode;
|
|
93
95
|
export const $updateRangeSelectionFromCaretRange = mod.$updateRangeSelectionFromCaretRange;
|
|
94
96
|
export const ArtificialNode__DO_NOT_USE = mod.ArtificialNode__DO_NOT_USE;
|
package/Lexical.node.mjs
CHANGED
|
@@ -33,6 +33,7 @@ export const $getCharacterOffsets = mod.$getCharacterOffsets;
|
|
|
33
33
|
export const $getChildCaret = mod.$getChildCaret;
|
|
34
34
|
export const $getChildCaretAtIndex = mod.$getChildCaretAtIndex;
|
|
35
35
|
export const $getChildCaretOrSelf = mod.$getChildCaretOrSelf;
|
|
36
|
+
export const $getCollapsedCaretRange = mod.$getCollapsedCaretRange;
|
|
36
37
|
export const $getCommonAncestor = mod.$getCommonAncestor;
|
|
37
38
|
export const $getCommonAncestorResultBranchOrder = mod.$getCommonAncestorResultBranchOrder;
|
|
38
39
|
export const $getEditor = mod.$getEditor;
|
|
@@ -87,6 +88,7 @@ export const $setPointFromCaret = mod.$setPointFromCaret;
|
|
|
87
88
|
export const $setSelection = mod.$setSelection;
|
|
88
89
|
export const $setSelectionFromCaretRange = mod.$setSelectionFromCaretRange;
|
|
89
90
|
export const $setState = mod.$setState;
|
|
91
|
+
export const $splitAtPointCaretNext = mod.$splitAtPointCaretNext;
|
|
90
92
|
export const $splitNode = mod.$splitNode;
|
|
91
93
|
export const $updateRangeSelectionFromCaretRange = mod.$updateRangeSelectionFromCaretRange;
|
|
92
94
|
export const ArtificialNode__DO_NOT_USE = mod.ArtificialNode__DO_NOT_USE;
|