@lexical/selection 0.8.1 → 0.9.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.
@@ -24,23 +24,31 @@ const CSS_TO_STYLES = new Map();
24
24
  * LICENSE file in the root directory of this source tree.
25
25
  *
26
26
  */
27
+
27
28
  function getDOMTextNode(element) {
28
29
  let node = element;
30
+
29
31
  while (node != null) {
30
32
  if (node.nodeType === Node.TEXT_NODE) {
31
33
  return node;
32
34
  }
35
+
33
36
  node = node.firstChild;
34
37
  }
38
+
35
39
  return null;
36
40
  }
41
+
37
42
  function getDOMIndexWithinParent(node) {
38
43
  const parent = node.parentNode;
44
+
39
45
  if (parent == null) {
40
46
  throw new Error('Should never happen');
41
47
  }
48
+
42
49
  return [parent, Array.from(parent.childNodes).indexOf(node)];
43
50
  }
51
+
44
52
  function createDOMRange(editor, anchorNode, _anchorOffset, focusNode, _focusOffset) {
45
53
  const anchorKey = anchorNode.getKey();
46
54
  const focusKey = focusNode.getKey();
@@ -49,94 +57,116 @@ function createDOMRange(editor, anchorNode, _anchorOffset, focusNode, _focusOffs
49
57
  let focusDOM = editor.getElementByKey(focusKey);
50
58
  let anchorOffset = _anchorOffset;
51
59
  let focusOffset = _focusOffset;
60
+
52
61
  if (lexical.$isTextNode(anchorNode)) {
53
62
  anchorDOM = getDOMTextNode(anchorDOM);
54
63
  }
64
+
55
65
  if (lexical.$isTextNode(focusNode)) {
56
66
  focusDOM = getDOMTextNode(focusDOM);
57
67
  }
68
+
58
69
  if (anchorNode === undefined || focusNode === undefined || anchorDOM === null || focusDOM === null) {
59
70
  return null;
60
71
  }
72
+
61
73
  if (anchorDOM.nodeName === 'BR') {
62
74
  [anchorDOM, anchorOffset] = getDOMIndexWithinParent(anchorDOM);
63
75
  }
76
+
64
77
  if (focusDOM.nodeName === 'BR') {
65
78
  [focusDOM, focusOffset] = getDOMIndexWithinParent(focusDOM);
66
79
  }
80
+
67
81
  const firstChild = anchorDOM.firstChild;
82
+
68
83
  if (anchorDOM === focusDOM && firstChild != null && firstChild.nodeName === 'BR' && anchorOffset === 0 && focusOffset === 0) {
69
84
  focusOffset = 1;
70
85
  }
86
+
71
87
  try {
72
88
  range.setStart(anchorDOM, anchorOffset);
73
89
  range.setEnd(focusDOM, focusOffset);
74
90
  } catch (e) {
75
91
  return null;
76
92
  }
93
+
77
94
  if (range.collapsed && (anchorOffset !== focusOffset || anchorKey !== focusKey)) {
78
95
  // Range is backwards, we need to reverse it
79
96
  range.setStart(focusDOM, focusOffset);
80
97
  range.setEnd(anchorDOM, anchorOffset);
81
98
  }
99
+
82
100
  return range;
83
101
  }
84
102
  function createRectsFromDOMRange(editor, range) {
85
103
  const rootElement = editor.getRootElement();
104
+
86
105
  if (rootElement === null) {
87
106
  return [];
88
107
  }
108
+
89
109
  const rootRect = rootElement.getBoundingClientRect();
90
110
  const computedStyle = getComputedStyle(rootElement);
91
111
  const rootPadding = parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight);
92
112
  const selectionRects = Array.from(range.getClientRects());
93
113
  let selectionRectsLength = selectionRects.length;
94
114
  let prevRect;
115
+
95
116
  for (let i = 0; i < selectionRectsLength; i++) {
96
- const selectionRect = selectionRects[i];
97
- // Exclude a rect that is the exact same as the last rect. getClientRects() can return
117
+ const selectionRect = selectionRects[i]; // Exclude a rect that is the exact same as the last rect. getClientRects() can return
98
118
  // the same rect twice for some elements. A more sophisticated thing to do here is to
99
119
  // merge all the rects together into a set of rects that don't overlap, so we don't
100
120
  // generate backgrounds that are too dark.
101
- const isDuplicateRect = prevRect && prevRect.top === selectionRect.top && prevRect.left === selectionRect.left && prevRect.width === selectionRect.width && prevRect.height === selectionRect.height;
102
121
 
103
- // Exclude selections that span the entire element
122
+ const isDuplicateRect = prevRect && prevRect.top === selectionRect.top && prevRect.left === selectionRect.left && prevRect.width === selectionRect.width && prevRect.height === selectionRect.height; // Exclude selections that span the entire element
123
+
104
124
  const selectionSpansElement = selectionRect.width + rootPadding === rootRect.width;
125
+
105
126
  if (isDuplicateRect || selectionSpansElement) {
106
127
  selectionRects.splice(i--, 1);
107
128
  selectionRectsLength--;
108
129
  continue;
109
130
  }
131
+
110
132
  prevRect = selectionRect;
111
133
  }
134
+
112
135
  return selectionRects;
113
136
  }
114
137
  function getStyleObjectFromRawCSS(css) {
115
138
  const styleObject = {};
116
139
  const styles = css.split(';');
140
+
117
141
  for (const style of styles) {
118
142
  if (style !== '') {
119
143
  const [key, value] = style.split(/:([^]+)/); // split on first colon
144
+
120
145
  styleObject[key.trim()] = value.trim();
121
146
  }
122
147
  }
148
+
123
149
  return styleObject;
124
150
  }
125
151
  function getStyleObjectFromCSS(css) {
126
152
  let value = CSS_TO_STYLES.get(css);
153
+
127
154
  if (value === undefined) {
128
155
  value = getStyleObjectFromRawCSS(css);
129
156
  CSS_TO_STYLES.set(css, value);
130
157
  }
158
+
131
159
  return value;
132
160
  }
133
161
  function getCSSFromStyleObject(styles) {
134
162
  let css = '';
163
+
135
164
  for (const style in styles) {
136
165
  if (style) {
137
166
  css += `${style}: ${styles[style]};`;
138
167
  }
139
168
  }
169
+
140
170
  return css;
141
171
  }
142
172
 
@@ -147,6 +177,7 @@ function getCSSFromStyleObject(styles) {
147
177
  * LICENSE file in the root directory of this source tree.
148
178
  *
149
179
  */
180
+
150
181
  function $updateElementNodeProperties(target, source) {
151
182
  target.__first = source.__first;
152
183
  target.__last = source.__last;
@@ -156,6 +187,7 @@ function $updateElementNodeProperties(target, source) {
156
187
  target.__dir = source.__dir;
157
188
  return target;
158
189
  }
190
+
159
191
  function $updateTextNodeProperties(target, source) {
160
192
  target.__format = source.__format;
161
193
  target.__style = source.__style;
@@ -163,20 +195,24 @@ function $updateTextNodeProperties(target, source) {
163
195
  target.__detail = source.__detail;
164
196
  return target;
165
197
  }
198
+
166
199
  function $cloneWithProperties(node) {
167
200
  const latest = node.getLatest();
168
- const constructor = latest.constructor;
169
- // @ts-expect-error
201
+ const constructor = latest.constructor; // @ts-expect-error
202
+
170
203
  const clone = constructor.clone(latest);
171
204
  clone.__parent = latest.__parent;
172
205
  clone.__next = latest.__next;
173
206
  clone.__prev = latest.__prev;
207
+
174
208
  if (lexical.$isElementNode(latest) && lexical.$isElementNode(clone)) {
175
209
  return $updateElementNodeProperties(clone, latest);
176
210
  }
211
+
177
212
  if (lexical.$isTextNode(latest) && lexical.$isTextNode(clone)) {
178
213
  return $updateTextNodeProperties(clone, latest);
179
214
  }
215
+
180
216
  return clone;
181
217
  }
182
218
  function $sliceSelectedTextNodeContent(selection, textNode) {
@@ -185,6 +221,7 @@ function $sliceSelectedTextNodeContent(selection, textNode) {
185
221
  const focusNode = selection.focus.getNode();
186
222
  const isAnchor = textNode.is(anchorNode);
187
223
  const isFocus = textNode.is(focusNode);
224
+
188
225
  if (isAnchor || isFocus) {
189
226
  const isBackward = selection.isBackward();
190
227
  const [anchorOffset, focusOffset] = selection.getCharacterOffsets();
@@ -193,6 +230,7 @@ function $sliceSelectedTextNodeContent(selection, textNode) {
193
230
  const isLast = textNode.is(isBackward ? anchorNode : focusNode);
194
231
  let startOffset = 0;
195
232
  let endOffset = undefined;
233
+
196
234
  if (isSame) {
197
235
  startOffset = anchorOffset > focusOffset ? focusOffset : anchorOffset;
198
236
  endOffset = anchorOffset > focusOffset ? anchorOffset : focusOffset;
@@ -205,44 +243,56 @@ function $sliceSelectedTextNodeContent(selection, textNode) {
205
243
  startOffset = 0;
206
244
  endOffset = offset;
207
245
  }
246
+
208
247
  textNode.__text = textNode.__text.slice(startOffset, endOffset);
209
248
  return textNode;
210
249
  }
211
250
  }
251
+
212
252
  return textNode;
213
253
  }
214
254
  function $isAtNodeEnd(point) {
215
255
  if (point.type === 'text') {
216
256
  return point.offset === point.getNode().getTextContentSize();
217
257
  }
258
+
218
259
  return point.offset === point.getNode().getChildrenSize();
219
260
  }
220
261
  function trimTextContentFromAnchor(editor, anchor, delCount) {
221
262
  // Work from the current selection anchor point
222
263
  let currentNode = anchor.getNode();
223
264
  let remaining = delCount;
265
+
224
266
  if (lexical.$isElementNode(currentNode)) {
225
267
  const descendantNode = currentNode.getDescendantByIndex(anchor.offset);
268
+
226
269
  if (descendantNode !== null) {
227
270
  currentNode = descendantNode;
228
271
  }
229
272
  }
273
+
230
274
  while (remaining > 0 && currentNode !== null) {
231
275
  let nextNode = currentNode.getPreviousSibling();
232
276
  let additionalElementWhitespace = 0;
277
+
233
278
  if (nextNode === null) {
234
279
  let parent = currentNode.getParentOrThrow();
235
280
  let parentSibling = parent.getPreviousSibling();
281
+
236
282
  while (parentSibling === null) {
237
283
  parent = parent.getParent();
284
+
238
285
  if (parent === null) {
239
286
  nextNode = null;
240
287
  break;
241
288
  }
289
+
242
290
  parentSibling = parent.getPreviousSibling();
243
291
  }
292
+
244
293
  if (parent !== null) {
245
294
  additionalElementWhitespace = parent.isInline() ? 0 : 2;
295
+
246
296
  if (lexical.$isElementNode(parentSibling)) {
247
297
  nextNode = parentSibling.getLastDescendant();
248
298
  } else {
@@ -250,37 +300,46 @@ function trimTextContentFromAnchor(editor, anchor, delCount) {
250
300
  }
251
301
  }
252
302
  }
253
- let text = currentNode.getTextContent();
254
- // If the text is empty, we need to consider adding in two line breaks to match
303
+
304
+ let text = currentNode.getTextContent(); // If the text is empty, we need to consider adding in two line breaks to match
255
305
  // the content if we were to get it from its parent.
306
+
256
307
  if (text === '' && lexical.$isElementNode(currentNode) && !currentNode.isInline()) {
257
308
  // TODO: should this be handled in core?
258
309
  text = '\n\n';
259
310
  }
260
- const textNodeSize = text.length;
261
- const offset = textNodeSize - remaining;
262
- const slicedText = text.slice(0, offset);
263
- if (!lexical.$isTextNode(currentNode) || remaining >= textNodeSize) {
311
+
312
+ const currentNodeSize = currentNode.getTextContentSize();
313
+
314
+ if (!lexical.$isTextNode(currentNode) || remaining >= currentNodeSize) {
264
315
  const parent = currentNode.getParent();
265
316
  currentNode.remove();
266
- if (parent != null && parent.getChildrenSize() === 0) {
317
+
318
+ if (parent != null && parent.getChildrenSize() === 0 && !lexical.$isRootNode(parent)) {
267
319
  parent.remove();
268
320
  }
269
- remaining -= textNodeSize + additionalElementWhitespace;
321
+
322
+ remaining -= currentNodeSize + additionalElementWhitespace;
270
323
  currentNode = nextNode;
271
324
  } else {
272
- const key = currentNode.getKey();
273
- // See if we can just revert it to what was in the last editor state
325
+ const key = currentNode.getKey(); // See if we can just revert it to what was in the last editor state
326
+
274
327
  const prevTextContent = editor.getEditorState().read(() => {
275
328
  const prevNode = lexical.$getNodeByKey(key);
329
+
276
330
  if (lexical.$isTextNode(prevNode) && prevNode.isSimpleText()) {
277
331
  return prevNode.getTextContent();
278
332
  }
333
+
279
334
  return null;
280
335
  });
336
+ const offset = currentNodeSize - remaining;
337
+ const slicedText = text.slice(0, offset);
338
+
281
339
  if (prevTextContent !== null && prevTextContent !== text) {
282
340
  const prevSelection = lexical.$getPreviousSelection();
283
341
  let target = currentNode;
342
+
284
343
  if (!currentNode.isSimpleText()) {
285
344
  const textNode = lexical.$createTextNode(prevTextContent);
286
345
  currentNode.replace(textNode);
@@ -288,6 +347,7 @@ function trimTextContentFromAnchor(editor, anchor, delCount) {
288
347
  } else {
289
348
  currentNode.setTextContent(prevTextContent);
290
349
  }
350
+
291
351
  if (lexical.$isRangeSelection(prevSelection) && prevSelection.isCollapsed()) {
292
352
  const prevOffset = prevSelection.anchor.offset;
293
353
  target.select(prevOffset, prevOffset);
@@ -295,14 +355,16 @@ function trimTextContentFromAnchor(editor, anchor, delCount) {
295
355
  } else if (currentNode.isSimpleText()) {
296
356
  // Split text
297
357
  const isSelected = anchor.key === key;
298
- let anchorOffset = anchor.offset;
299
- // Move offset to end if it's less than the remaniing number, otherwise
358
+ let anchorOffset = anchor.offset; // Move offset to end if it's less than the remaining number, otherwise
300
359
  // we'll have a negative splitStart.
360
+
301
361
  if (anchorOffset < remaining) {
302
- anchorOffset = textNodeSize;
362
+ anchorOffset = currentNodeSize;
303
363
  }
364
+
304
365
  const splitStart = isSelected ? anchorOffset - remaining : 0;
305
366
  const splitEnd = isSelected ? anchorOffset : offset;
367
+
306
368
  if (isSelected && splitStart === 0) {
307
369
  const [excessNode] = currentNode.splitText(splitStart, splitEnd);
308
370
  excessNode.remove();
@@ -314,6 +376,7 @@ function trimTextContentFromAnchor(editor, anchor, delCount) {
314
376
  const textNode = lexical.$createTextNode(slicedText);
315
377
  currentNode.replace(textNode);
316
378
  }
379
+
317
380
  remaining = 0;
318
381
  }
319
382
  }
@@ -323,6 +386,7 @@ function $addNodeStyle(node) {
323
386
  const styles = getStyleObjectFromRawCSS(CSSText);
324
387
  CSS_TO_STYLES.set(CSSText, styles);
325
388
  }
389
+
326
390
  function $patchStyle(target, patch) {
327
391
  const prevStyles = getStyleObjectFromCSS('getStyle' in target ? target.getStyle() : target.style);
328
392
  const newStyles = Object.entries(patch).reduce((styles, [key, value]) => {
@@ -331,24 +395,27 @@ function $patchStyle(target, patch) {
331
395
  } else {
332
396
  styles[key] = value;
333
397
  }
398
+
334
399
  return styles;
335
- }, {
336
- ...prevStyles
400
+ }, { ...prevStyles
337
401
  } || {});
338
402
  const newCSSText = getCSSFromStyleObject(newStyles);
339
403
  target.setStyle(newCSSText);
340
404
  CSS_TO_STYLES.set(newCSSText, newStyles);
341
405
  }
406
+
342
407
  function $patchStyleText(selection, patch) {
343
408
  const selectedNodes = selection.getNodes();
344
409
  const selectedNodesLength = selectedNodes.length;
345
410
  const lastIndex = selectedNodesLength - 1;
346
411
  let firstNode = selectedNodes[0];
347
412
  let lastNode = selectedNodes[lastIndex];
413
+
348
414
  if (selection.isCollapsed()) {
349
415
  $patchStyle(selection, patch);
350
416
  return;
351
417
  }
418
+
352
419
  const anchor = selection.anchor;
353
420
  const focus = selection.focus;
354
421
  const firstNodeText = firstNode.getTextContent();
@@ -360,32 +427,31 @@ function $patchStyleText(selection, patch) {
360
427
  let endOffset = isBefore ? focusOffset : anchorOffset;
361
428
  const startType = isBefore ? anchor.type : focus.type;
362
429
  const endType = isBefore ? focus.type : anchor.type;
363
- const endKey = isBefore ? focus.key : anchor.key;
364
-
365
- // This is the case where the user only selected the very end of the
430
+ const endKey = isBefore ? focus.key : anchor.key; // This is the case where the user only selected the very end of the
366
431
  // first node so we don't want to include it in the formatting change.
432
+
367
433
  if (lexical.$isTextNode(firstNode) && startOffset === firstNodeTextLength) {
368
434
  const nextSibling = firstNode.getNextSibling();
435
+
369
436
  if (lexical.$isTextNode(nextSibling)) {
370
437
  // we basically make the second node the firstNode, changing offsets accordingly
371
438
  anchorOffset = 0;
372
439
  startOffset = 0;
373
440
  firstNode = nextSibling;
374
441
  }
375
- }
442
+ } // This is the case where we only selected a single node
376
443
 
377
- // This is the case where we only selected a single node
378
- if (firstNode.is(lastNode)) {
444
+
445
+ if (selectedNodes.length === 1) {
379
446
  if (lexical.$isTextNode(firstNode)) {
380
447
  startOffset = startType === 'element' ? 0 : anchorOffset > focusOffset ? focusOffset : anchorOffset;
381
- endOffset = endType === 'element' ? firstNodeTextLength : anchorOffset > focusOffset ? anchorOffset : focusOffset;
448
+ endOffset = endType === 'element' ? firstNodeTextLength : anchorOffset > focusOffset ? anchorOffset : focusOffset; // No actual text is selected, so do nothing.
382
449
 
383
- // No actual text is selected, so do nothing.
384
450
  if (startOffset === endOffset) {
385
451
  return;
386
- }
452
+ } // The entire node is selected, so just format it
453
+
387
454
 
388
- // The entire node is selected, so just format it
389
455
  if (startOffset === 0 && endOffset === firstNodeTextLength) {
390
456
  $patchStyle(firstNode, patch);
391
457
  firstNode.select(startOffset, endOffset);
@@ -398,6 +464,7 @@ function $patchStyleText(selection, patch) {
398
464
  replacement.select(0, endOffset - startOffset);
399
465
  }
400
466
  } // multiple nodes selected.
467
+
401
468
  } else {
402
469
  if (lexical.$isTextNode(firstNode) && startOffset < firstNode.getTextContentSize()) {
403
470
  if (startOffset !== 0) {
@@ -405,33 +472,36 @@ function $patchStyleText(selection, patch) {
405
472
  firstNode = firstNode.splitText(startOffset)[1];
406
473
  startOffset = 0;
407
474
  }
475
+
408
476
  $patchStyle(firstNode, patch);
409
477
  }
478
+
410
479
  if (lexical.$isTextNode(lastNode)) {
411
480
  const lastNodeText = lastNode.getTextContent();
412
- const lastNodeTextLength = lastNodeText.length;
413
-
414
- // The last node might not actually be the end node
481
+ const lastNodeTextLength = lastNodeText.length; // The last node might not actually be the end node
415
482
  //
416
483
  // If not, assume the last node is fully-selected unless the end offset is
417
484
  // zero.
485
+
418
486
  if (lastNode.__key !== endKey && endOffset !== 0) {
419
487
  endOffset = lastNodeTextLength;
420
- }
488
+ } // if the entire last node isn't selected, split it
489
+
421
490
 
422
- // if the entire last node isn't selected, split it
423
491
  if (endOffset !== lastNodeTextLength) {
424
492
  [lastNode] = lastNode.splitText(endOffset);
425
493
  }
494
+
426
495
  if (endOffset !== 0) {
427
496
  $patchStyle(lastNode, patch);
428
497
  }
429
- }
498
+ } // style all the text nodes in between
499
+
430
500
 
431
- // style all the text nodes in between
432
501
  for (let i = 1; i < lastIndex; i++) {
433
502
  const selectedNode = selectedNodes[i];
434
503
  const selectedNodeKey = selectedNode.getKey();
504
+
435
505
  if (lexical.$isTextNode(selectedNode) && selectedNodeKey !== firstNode.getKey() && selectedNodeKey !== lastNode.getKey() && !selectedNode.isToken()) {
436
506
  $patchStyle(selectedNode, patch);
437
507
  }
@@ -446,7 +516,6 @@ function $patchStyleText(selection, patch) {
446
516
  * LICENSE file in the root directory of this source tree.
447
517
  *
448
518
  */
449
-
450
519
  /**
451
520
  * Converts all nodes in the selection that are of one block type to another specified by parameter
452
521
  *
@@ -454,50 +523,87 @@ function $patchStyleText(selection, patch) {
454
523
  * @param createElement
455
524
  * @returns
456
525
  */
457
- function $setBlocksType_experimental(selection, createElement) {
526
+
527
+ function $setBlocksType(selection, createElement) {
458
528
  if (selection.anchor.key === 'root') {
459
529
  const element = createElement();
460
530
  const root = lexical.$getRoot();
461
531
  const firstChild = root.getFirstChild();
462
- if (firstChild) firstChild.replace(element, true);else root.append(element);
532
+
533
+ if (firstChild) {
534
+ firstChild.replace(element, true);
535
+ } else {
536
+ root.append(element);
537
+ }
538
+
463
539
  return;
464
540
  }
541
+
465
542
  const nodes = selection.getNodes();
466
- if (selection.anchor.type === 'text') {
467
- let firstBlock = selection.anchor.getNode().getParent();
468
- firstBlock = firstBlock.isInline() ? firstBlock.getParent() : firstBlock;
469
- if (nodes.indexOf(firstBlock) === -1) nodes.push(firstBlock);
543
+ let maybeBlock = selection.anchor.getNode().getParentOrThrow();
544
+
545
+ if (nodes.indexOf(maybeBlock) === -1) {
546
+ nodes.push(maybeBlock);
547
+ }
548
+
549
+ if (maybeBlock.isInline()) {
550
+ maybeBlock = maybeBlock.getParentOrThrow();
551
+
552
+ if (nodes.indexOf(maybeBlock) === -1) {
553
+ nodes.push(maybeBlock);
554
+ }
470
555
  }
556
+
471
557
  for (let i = 0; i < nodes.length; i++) {
472
558
  const node = nodes[i];
473
- if (!isBlock(node)) continue;
559
+
560
+ if (!isBlock(node)) {
561
+ continue;
562
+ }
563
+
474
564
  const targetElement = createElement();
475
565
  targetElement.setFormat(node.getFormatType());
476
566
  targetElement.setIndent(node.getIndent());
477
567
  node.replace(targetElement, true);
478
568
  }
479
569
  }
570
+
480
571
  function isBlock(node) {
481
- return lexical.$isElementNode(node) && !lexical.$isRootOrShadowRoot(node) && !node.isInline();
572
+ if (!lexical.$isElementNode(node) || lexical.$isRootOrShadowRoot(node)) {
573
+ return false;
574
+ }
575
+
576
+ const firstChild = node.getFirstChild();
577
+ const isLeafElement = firstChild === null || lexical.$isTextNode(firstChild) || firstChild.isInline();
578
+ return !node.isInline() && node.canBeEmpty() !== false && isLeafElement;
482
579
  }
580
+
483
581
  function isPointAttached(point) {
484
582
  return point.getNode().isAttached();
485
583
  }
584
+
486
585
  function $removeParentEmptyElements(startingNode) {
487
586
  let node = startingNode;
587
+
488
588
  while (node !== null && !lexical.$isRootOrShadowRoot(node)) {
489
589
  const latest = node.getLatest();
490
590
  const parentNode = node.getParent();
591
+
491
592
  if (latest.getChildrenSize() === 0) {
492
593
  node.remove(true);
493
594
  }
595
+
494
596
  node = parentNode;
495
597
  }
496
598
  }
599
+ /** @deprecated */
600
+
601
+
497
602
  function $wrapNodes(selection, createElement, wrappingElement = null) {
498
603
  const nodes = selection.getNodes();
499
604
  const nodesLength = nodes.length;
500
605
  const anchor = selection.anchor;
606
+
501
607
  if (nodesLength === 0 || nodesLength === 1 && anchor.type === 'element' && anchor.getNode().getChildrenSize() === 0) {
502
608
  const target = anchor.type === 'text' ? anchor.getNode().getParentOrThrow() : anchor.getNode();
503
609
  const children = target.getChildren();
@@ -505,20 +611,24 @@ function $wrapNodes(selection, createElement, wrappingElement = null) {
505
611
  element.setFormat(target.getFormatType());
506
612
  element.setIndent(target.getIndent());
507
613
  children.forEach(child => element.append(child));
614
+
508
615
  if (wrappingElement) {
509
616
  element = wrappingElement.append(element);
510
617
  }
618
+
511
619
  target.replace(element);
512
620
  return;
513
621
  }
622
+
514
623
  let topLevelNode = null;
515
624
  let descendants = [];
625
+
516
626
  for (let i = 0; i < nodesLength; i++) {
517
- const node = nodes[i];
518
- // Determine whether wrapping has to be broken down into multiple chunks. This can happen if the
627
+ const node = nodes[i]; // Determine whether wrapping has to be broken down into multiple chunks. This can happen if the
519
628
  // user selected multiple Root-like nodes that have to be treated separately as if they are
520
629
  // their own branch. I.e. you don't want to wrap a whole table, but rather the contents of each
521
630
  // of each of the cell nodes.
631
+
522
632
  if (lexical.$isRootOrShadowRoot(node)) {
523
633
  $wrapNodesImpl(selection, descendants, descendants.length, createElement, wrappingElement);
524
634
  descendants = [];
@@ -530,69 +640,82 @@ function $wrapNodes(selection, createElement, wrappingElement = null) {
530
640
  descendants = [node];
531
641
  }
532
642
  }
643
+
533
644
  $wrapNodesImpl(selection, descendants, descendants.length, createElement, wrappingElement);
534
645
  }
535
646
  function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingElement = null) {
536
647
  if (nodes.length === 0) {
537
648
  return;
538
649
  }
650
+
539
651
  const firstNode = nodes[0];
540
652
  const elementMapping = new Map();
541
- const elements = [];
542
- // The below logic is to find the right target for us to
653
+ const elements = []; // The below logic is to find the right target for us to
543
654
  // either insertAfter/insertBefore/append the corresponding
544
655
  // elements to. This is made more complicated due to nested
545
656
  // structures.
657
+
546
658
  let target = lexical.$isElementNode(firstNode) ? firstNode : firstNode.getParentOrThrow();
659
+
547
660
  if (target.isInline()) {
548
661
  target = target.getParentOrThrow();
549
662
  }
663
+
550
664
  let targetIsPrevSibling = false;
665
+
551
666
  while (target !== null) {
552
667
  const prevSibling = target.getPreviousSibling();
668
+
553
669
  if (prevSibling !== null) {
554
670
  target = prevSibling;
555
671
  targetIsPrevSibling = true;
556
672
  break;
557
673
  }
674
+
558
675
  target = target.getParentOrThrow();
676
+
559
677
  if (lexical.$isRootOrShadowRoot(target)) {
560
678
  break;
561
679
  }
562
680
  }
563
- const emptyElements = new Set();
564
681
 
565
- // Find any top level empty elements
682
+ const emptyElements = new Set(); // Find any top level empty elements
683
+
566
684
  for (let i = 0; i < nodesLength; i++) {
567
685
  const node = nodes[i];
686
+
568
687
  if (lexical.$isElementNode(node) && node.getChildrenSize() === 0) {
569
688
  emptyElements.add(node.getKey());
570
689
  }
571
690
  }
572
- const movedNodes = new Set();
573
691
 
574
- // Move out all leaf nodes into our elements array.
692
+ const movedNodes = new Set(); // Move out all leaf nodes into our elements array.
575
693
  // If we find a top level empty element, also move make
576
694
  // an element for that.
695
+
577
696
  for (let i = 0; i < nodesLength; i++) {
578
697
  const node = nodes[i];
579
698
  let parent = node.getParent();
699
+
580
700
  if (parent !== null && parent.isInline()) {
581
701
  parent = parent.getParent();
582
702
  }
703
+
583
704
  if (parent !== null && lexical.$isLeafNode(node) && !movedNodes.has(node.getKey())) {
584
705
  const parentKey = parent.getKey();
706
+
585
707
  if (elementMapping.get(parentKey) === undefined) {
586
708
  const targetElement = createElement();
587
709
  targetElement.setFormat(parent.getFormatType());
588
710
  targetElement.setIndent(parent.getIndent());
589
711
  elements.push(targetElement);
590
- elementMapping.set(parentKey, targetElement);
591
- // Move node and its siblings to the new
712
+ elementMapping.set(parentKey, targetElement); // Move node and its siblings to the new
592
713
  // element.
714
+
593
715
  parent.getChildren().forEach(child => {
594
716
  targetElement.append(child);
595
717
  movedNodes.add(child.getKey());
718
+
596
719
  if (lexical.$isElementNode(child)) {
597
720
  // Skip nested leaf nodes if the parent has already been moved
598
721
  child.getChildrenKeys().forEach(key => movedNodes.add(key));
@@ -608,16 +731,17 @@ function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingEl
608
731
  node.remove(true);
609
732
  }
610
733
  }
734
+
611
735
  if (wrappingElement !== null) {
612
736
  for (let i = 0; i < elements.length; i++) {
613
737
  const element = elements[i];
614
738
  wrappingElement.append(element);
615
739
  }
616
740
  }
617
- let lastElement = null;
618
741
 
619
- // If our target is Root-like, let's see if we can re-adjust
742
+ let lastElement = null; // If our target is Root-like, let's see if we can re-adjust
620
743
  // so that the target is the first child instead.
744
+
621
745
  if (lexical.$isRootOrShadowRoot(target)) {
622
746
  if (targetIsPrevSibling) {
623
747
  if (wrappingElement !== null) {
@@ -630,9 +754,11 @@ function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingEl
630
754
  }
631
755
  } else {
632
756
  const firstChild = target.getFirstChild();
757
+
633
758
  if (lexical.$isElementNode(firstChild)) {
634
759
  target = firstChild;
635
760
  }
761
+
636
762
  if (firstChild === null) {
637
763
  if (wrappingElement) {
638
764
  target.append(wrappingElement);
@@ -666,7 +792,9 @@ function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingEl
666
792
  }
667
793
  }
668
794
  }
795
+
669
796
  const prevSelection = lexical.$getPreviousSelection();
797
+
670
798
  if (lexical.$isRangeSelection(prevSelection) && isPointAttached(prevSelection.anchor) && isPointAttached(prevSelection.focus)) {
671
799
  lexical.$setSelection(prevSelection.clone());
672
800
  } else if (lastElement !== null) {
@@ -702,30 +830,37 @@ function $selectAll(selection) {
702
830
  let firstType = 'element';
703
831
  let lastType = 'element';
704
832
  let lastOffset = 0;
833
+
705
834
  if (lexical.$isTextNode(firstNode)) {
706
835
  firstType = 'text';
707
836
  } else if (!lexical.$isElementNode(firstNode) && firstNode !== null) {
708
837
  firstNode = firstNode.getParentOrThrow();
709
838
  }
839
+
710
840
  if (lexical.$isTextNode(lastNode)) {
711
841
  lastType = 'text';
712
842
  lastOffset = lastNode.getTextContentSize();
713
843
  } else if (!lexical.$isElementNode(lastNode) && lastNode !== null) {
714
844
  lastNode = lastNode.getParentOrThrow();
715
845
  }
846
+
716
847
  if (firstNode && lastNode) {
717
848
  anchor.set(firstNode.getKey(), 0, firstType);
718
849
  focus.set(lastNode.getKey(), lastOffset, lastType);
719
850
  }
720
851
  }
852
+
721
853
  function $getNodeStyleValueForProperty(node, styleProperty, defaultValue) {
722
854
  const css = node.getStyle();
723
855
  const styleObject = getStyleObjectFromCSS(css);
856
+
724
857
  if (styleObject !== null) {
725
858
  return styleObject[styleProperty] || defaultValue;
726
859
  }
860
+
727
861
  return defaultValue;
728
862
  }
863
+
729
864
  function $getSelectionStyleValueForProperty(selection, styleProperty, defaultValue = '') {
730
865
  let styleValue = null;
731
866
  const nodes = selection.getNodes();
@@ -734,24 +869,28 @@ function $getSelectionStyleValueForProperty(selection, styleProperty, defaultVal
734
869
  const isBackward = selection.isBackward();
735
870
  const endOffset = isBackward ? focus.offset : anchor.offset;
736
871
  const endNode = isBackward ? focus.getNode() : anchor.getNode();
872
+
737
873
  if (selection.style !== '') {
738
874
  const css = selection.style;
739
875
  const styleObject = getStyleObjectFromCSS(css);
876
+
740
877
  if (styleObject !== null && styleProperty in styleObject) {
741
878
  return styleObject[styleProperty];
742
879
  }
743
880
  }
744
- for (let i = 0; i < nodes.length; i++) {
745
- const node = nodes[i];
746
881
 
747
- // if no actual characters in the end node are selected, we don't
882
+ for (let i = 0; i < nodes.length; i++) {
883
+ const node = nodes[i]; // if no actual characters in the end node are selected, we don't
748
884
  // include it in the selection for purposes of determining style
749
885
  // value
886
+
750
887
  if (i !== 0 && endOffset === 0 && node.is(endNode)) {
751
888
  continue;
752
889
  }
890
+
753
891
  if (lexical.$isTextNode(node)) {
754
892
  const nodeStyleValue = $getNodeStyleValueForProperty(node, styleProperty, defaultValue);
893
+
755
894
  if (styleValue === null) {
756
895
  styleValue = nodeStyleValue;
757
896
  } else if (styleValue !== nodeStyleValue) {
@@ -762,6 +901,7 @@ function $getSelectionStyleValueForProperty(selection, styleProperty, defaultVal
762
901
  }
763
902
  }
764
903
  }
904
+
765
905
  return styleValue === null ? defaultValue : styleValue;
766
906
  }
767
907
 
@@ -774,7 +914,7 @@ exports.$moveCaretSelection = $moveCaretSelection;
774
914
  exports.$moveCharacter = $moveCharacter;
775
915
  exports.$patchStyleText = $patchStyleText;
776
916
  exports.$selectAll = $selectAll;
777
- exports.$setBlocksType_experimental = $setBlocksType_experimental;
917
+ exports.$setBlocksType = $setBlocksType;
778
918
  exports.$shouldOverrideDefaultCharacterSelection = $shouldOverrideDefaultCharacterSelection;
779
919
  exports.$sliceSelectedTextNodeContent = $sliceSelectedTextNodeContent;
780
920
  exports.$wrapNodes = $wrapNodes;
@@ -49,7 +49,7 @@ declare export function $wrapNodes(
49
49
  createElement: () => ElementNode,
50
50
  wrappingElement?: ElementNode,
51
51
  ): void;
52
- declare export function $setBlocksType_experimental(
52
+ declare export function $setBlocksType(
53
53
  selection: RangeSelection,
54
54
  createElement: () => ElementNode,
55
55
  ): void;
@@ -4,25 +4,25 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- 'use strict';var l=require("lexical");let u=new Map;function v(a){for(;null!=a;){if(a.nodeType===Node.TEXT_NODE)return a;a=a.firstChild}return null}function w(a){let b=a.parentNode;if(null==b)throw Error("Should never happen");return[b,Array.from(b.childNodes).indexOf(a)]}function y(a){let b={};a=a.split(";");for(let c of a)if(""!==c){let [f,d]=c.split(/:([^]+)/);b[f.trim()]=d.trim()}return b}function z(a){let b=u.get(a);void 0===b&&(b=y(a),u.set(a,b));return b}
8
- function A(a){let b="";for(let c in a)c&&(b+=`${c}: ${a[c]};`);return b}function B(a,b){var c=z("getStyle"in a?a.getStyle():a.style);b=Object.entries(b).reduce((f,[d,e])=>{null===e?delete f[d]:f[d]=e;return f},{...c});c=A(b);a.setStyle(c);u.set(c,b)}function C(a){for(;null!==a&&!l.$isRootOrShadowRoot(a);){let b=a.getLatest(),c=a.getParent();0===b.getChildrenSize()&&a.remove(!0);a=c}}
9
- function D(a,b,c,f,d=null){if(0!==b.length){var e=b[0],h=new Map,g=[];e=l.$isElementNode(e)?e:e.getParentOrThrow();e.isInline()&&(e=e.getParentOrThrow());for(var k=!1;null!==e;){var m=e.getPreviousSibling();if(null!==m){e=m;k=!0;break}e=e.getParentOrThrow();if(l.$isRootOrShadowRoot(e))break}m=new Set;for(var q=0;q<c;q++){var n=b[q];l.$isElementNode(n)&&0===n.getChildrenSize()&&m.add(n.getKey())}var p=new Set;for(q=0;q<c;q++){n=b[q];var r=n.getParent();null!==r&&r.isInline()&&(r=r.getParent());if(null!==
10
- r&&l.$isLeafNode(n)&&!p.has(n.getKey())){if(n=r.getKey(),void 0===h.get(n)){let t=f();t.setFormat(r.getFormatType());t.setIndent(r.getIndent());g.push(t);h.set(n,t);r.getChildren().forEach(x=>{t.append(x);p.add(x.getKey());l.$isElementNode(x)&&x.getChildrenKeys().forEach(G=>p.add(G))});C(r)}}else m.has(n.getKey())&&(r=f(),r.setFormat(n.getFormatType()),r.setIndent(n.getIndent()),g.push(r),n.remove(!0))}if(null!==d)for(b=0;b<g.length;b++)d.append(g[b]);b=null;if(l.$isRootOrShadowRoot(e))if(k)if(null!==
11
- d)e.insertAfter(d);else for(d=g.length-1;0<=d;d--)e.insertAfter(g[d]);else if(k=e.getFirstChild(),l.$isElementNode(k)&&(e=k),null===k)if(d)e.append(d);else for(d=0;d<g.length;d++)k=g[d],e.append(k),b=k;else if(null!==d)k.insertBefore(d);else for(e=0;e<g.length;e++)d=g[e],k.insertBefore(d),b=d;else if(d)e.insertAfter(d);else for(d=g.length-1;0<=d;d--)k=g[d],e.insertAfter(k),b=k;g=l.$getPreviousSelection();l.$isRangeSelection(g)&&g.anchor.getNode().isAttached()&&g.focus.getNode().isAttached()?l.$setSelection(g.clone()):
12
- null!==b?b.selectEnd():a.dirty=!0}}function E(a,b,c,f){a.modify(b?"extend":"move",c,f)}function F(a){a=a.anchor.getNode();return"rtl"===(l.$isRootNode(a)?a:a.getParentOrThrow()).getDirection()}exports.$addNodeStyle=function(a){a=a.getStyle();let b=y(a);u.set(a,b)};
13
- exports.$cloneWithProperties=function(a){a=a.getLatest();let b=a.constructor.clone(a);b.__parent=a.__parent;b.__next=a.__next;b.__prev=a.__prev;if(l.$isElementNode(a)&&l.$isElementNode(b))return b.__first=a.__first,b.__last=a.__last,b.__size=a.__size,b.__format=a.__format,b.__indent=a.__indent,b.__dir=a.__dir,b;l.$isTextNode(a)&&l.$isTextNode(b)&&(b.__format=a.__format,b.__style=a.__style,b.__mode=a.__mode,b.__detail=a.__detail);return b};
14
- exports.$getSelectionStyleValueForProperty=function(a,b,c=""){let f=null,d=a.getNodes();var e=a.anchor,h=a.focus,g=a.isBackward();let k=g?h.offset:e.offset;e=g?h.getNode():e.getNode();if(""!==a.style&&(a=z(a.style),null!==a&&b in a))return a[b];for(a=0;a<d.length;a++){var m=d[a];if((0===a||0!==k||!m.is(e))&&l.$isTextNode(m))if(h=b,g=c,m=m.getStyle(),m=z(m),h=null!==m?m[h]||g:g,null===f)f=h;else if(f!==h){f="";break}}return null===f?c:f};
15
- exports.$isAtNodeEnd=function(a){return"text"===a.type?a.offset===a.getNode().getTextContentSize():a.offset===a.getNode().getChildrenSize()};exports.$isParentElementRTL=F;exports.$moveCaretSelection=E;exports.$moveCharacter=function(a,b,c){let f=F(a);E(a,b,c?!f:f,"character")};
16
- exports.$patchStyleText=function(a,b){var c=a.getNodes();let f=c.length-1,d=c[0],e=c[f];if(a.isCollapsed())B(a,b);else{var h=a.anchor,g=a.focus,k=d.getTextContent().length,m=g.offset,q=h.offset,n=h.isBefore(g),p=n?q:m;a=n?m:q;var r=n?h.type:g.type,t=n?g.type:h.type;h=n?g.key:h.key;l.$isTextNode(d)&&p===k&&(g=d.getNextSibling(),l.$isTextNode(g)&&(p=q=0,d=g));if(d.is(e))l.$isTextNode(d)&&(p="element"===r?0:q>m?m:q,a="element"===t?k:q>m?q:m,p!==a&&(0===p&&a===k?(B(d,b),d.select(p,a)):(c=d.splitText(p,
17
- a),c=0===p?c[0]:c[1],B(c,b),c.select(0,a-p))));else for(l.$isTextNode(d)&&p<d.getTextContentSize()&&(0!==p&&(d=d.splitText(p)[1]),B(d,b)),l.$isTextNode(e)&&(p=e.getTextContent().length,e.__key!==h&&0!==a&&(a=p),a!==p&&([e]=e.splitText(a)),0!==a&&B(e,b)),a=1;a<f;a++)p=c[a],k=p.getKey(),l.$isTextNode(p)&&k!==d.getKey()&&k!==e.getKey()&&!p.isToken()&&B(p,b)}};
18
- exports.$selectAll=function(a){let b=a.anchor;a=a.focus;var c=b.getNode().getTopLevelElementOrThrow().getParentOrThrow();let f=c.getFirstDescendant();c=c.getLastDescendant();let d="element",e="element",h=0;l.$isTextNode(f)?d="text":l.$isElementNode(f)||null===f||(f=f.getParentOrThrow());l.$isTextNode(c)?(e="text",h=c.getTextContentSize()):l.$isElementNode(c)||null===c||(c=c.getParentOrThrow());f&&c&&(b.set(f.getKey(),0,d),a.set(c.getKey(),h,e))};
19
- exports.$setBlocksType_experimental=function(a,b){if("root"===a.anchor.key){b=b();var c=l.$getRoot();(a=c.getFirstChild())?a.replace(b,!0):c.append(b)}else for(c=a.getNodes(),"text"===a.anchor.type&&(a=a.anchor.getNode().getParent(),a=a.isInline()?a.getParent():a,-1===c.indexOf(a)&&c.push(a)),a=0;a<c.length;a++){let d=c[a];var f=d;!l.$isElementNode(f)||l.$isRootOrShadowRoot(f)||f.isInline()||(f=b(),f.setFormat(d.getFormatType()),f.setIndent(d.getIndent()),d.replace(f,!0))}};
20
- exports.$shouldOverrideDefaultCharacterSelection=function(a,b){a=l.$getAdjacentNode(a.focus,b);return l.$isDecoratorNode(a)&&!a.isIsolated()||l.$isElementNode(a)&&!a.isInline()&&!a.canBeEmpty()};
21
- exports.$sliceSelectedTextNodeContent=function(a,b){if(b.isSelected()&&!b.isSegmented()&&!b.isToken()&&(l.$isRangeSelection(a)||l.DEPRECATED_$isGridSelection(a))){var c=a.anchor.getNode(),f=a.focus.getNode(),d=b.is(c),e=b.is(f);if(d||e){d=a.isBackward();let [h,g]=a.getCharacterOffsets();a=c.is(f);e=b.is(d?f:c);f=b.is(d?c:f);c=0;let k=void 0;a?(c=h>g?g:h,k=h>g?h:g):e?(c=d?g:h,k=void 0):f&&(d=d?h:g,c=0,k=d);b.__text=b.__text.slice(c,k)}}return b};
22
- exports.$wrapNodes=function(a,b,c=null){var f=a.getNodes();let d=f.length;var e=a.anchor;if(0===d||1===d&&"element"===e.type&&0===e.getNode().getChildrenSize()){a="text"===e.type?e.getNode().getParentOrThrow():e.getNode();f=a.getChildren();let g=b();g.setFormat(a.getFormatType());g.setIndent(a.getIndent());f.forEach(k=>g.append(k));c&&(g=c.append(g));a.replace(g)}else{e=null;var h=[];for(let g=0;g<d;g++){let k=f[g];l.$isRootOrShadowRoot(k)?(D(a,h,h.length,b,c),h=[],e=k):null===e||null!==e&&l.$hasAncestor(k,
23
- e)?h.push(k):(D(a,h,h.length,b,c),h=[k])}D(a,h,h.length,b,c)}};
24
- exports.createDOMRange=function(a,b,c,f,d){let e=b.getKey(),h=f.getKey(),g=document.createRange(),k=a.getElementByKey(e);a=a.getElementByKey(h);l.$isTextNode(b)&&(k=v(k));l.$isTextNode(f)&&(a=v(a));if(void 0===b||void 0===f||null===k||null===a)return null;"BR"===k.nodeName&&([k,c]=w(k));"BR"===a.nodeName&&([a,d]=w(a));b=k.firstChild;k===a&&null!=b&&"BR"===b.nodeName&&0===c&&0===d&&(d=1);try{g.setStart(k,c),g.setEnd(a,d)}catch(m){return null}!g.collapsed||c===d&&e===h||(g.setStart(a,d),g.setEnd(k,
25
- c));return g};exports.createRectsFromDOMRange=function(a,b){var c=a.getRootElement();if(null===c)return[];a=c.getBoundingClientRect();c=getComputedStyle(c);c=parseFloat(c.paddingLeft)+parseFloat(c.paddingRight);b=Array.from(b.getClientRects());let f=b.length,d;for(let e=0;e<f;e++){let h=b[e],g=h.width+c===a.width;d&&d.top===h.top&&d.left===h.left&&d.width===h.width&&d.height===h.height||g?(b.splice(e--,1),f--):d=h}return b};exports.getStyleObjectFromCSS=z;
26
- exports.trimTextContentFromAnchor=function(a,b,c){let f=b.getNode();if(l.$isElementNode(f)){var d=f.getDescendantByIndex(b.offset);null!==d&&(f=d)}for(;0<c&&null!==f;){var e=f.getPreviousSibling(),h=0;if(null===e){d=f.getParentOrThrow();for(var g=d.getPreviousSibling();null===g;){d=d.getParent();if(null===d){e=null;break}g=d.getPreviousSibling()}null!==d&&(h=d.isInline()?0:2,e=l.$isElementNode(g)?g.getLastDescendant():g)}let k=f.getTextContent();""===k&&l.$isElementNode(f)&&!f.isInline()&&(k="\n\n");
27
- d=k.length;g=d-c;let m=k.slice(0,g);if(!l.$isTextNode(f)||c>=d)g=f.getParent(),f.remove(),null!=g&&0===g.getChildrenSize()&&g.remove(),c-=d+h,f=e;else{let q=f.getKey();e=a.getEditorState().read(()=>{const n=l.$getNodeByKey(q);return l.$isTextNode(n)&&n.isSimpleText()?n.getTextContent():null});null!==e&&e!==k?(c=l.$getPreviousSelection(),d=f,f.isSimpleText()?f.setTextContent(e):(d=l.$createTextNode(e),f.replace(d)),l.$isRangeSelection(c)&&c.isCollapsed()&&(c=c.anchor.offset,d.select(c,c))):f.isSimpleText()?
28
- (e=b.key===q,h=b.offset,h<c&&(h=d),c=e?h-c:0,d=e?h:g,e&&0===c?([c]=f.splitText(c,d),c.remove()):([,c]=f.splitText(c,d),c.remove())):(c=l.$createTextNode(m),f.replace(c));c=0}}}
7
+ 'use strict';var k=require("lexical");let u=new Map;function v(a){for(;null!=a;){if(a.nodeType===Node.TEXT_NODE)return a;a=a.firstChild}return null}function w(a){let b=a.parentNode;if(null==b)throw Error("Should never happen");return[b,Array.from(b.childNodes).indexOf(a)]}function y(a){let b={};a=a.split(";");for(let c of a)if(""!==c){let [e,d]=c.split(/:([^]+)/);b[e.trim()]=d.trim()}return b}function z(a){let b=u.get(a);void 0===b&&(b=y(a),u.set(a,b));return b}
8
+ function A(a){let b="";for(let c in a)c&&(b+=`${c}: ${a[c]};`);return b}function B(a,b){var c=z("getStyle"in a?a.getStyle():a.style);b=Object.entries(b).reduce((e,[d,f])=>{null===f?delete e[d]:e[d]=f;return e},{...c});c=A(b);a.setStyle(c);u.set(c,b)}function C(a){for(;null!==a&&!k.$isRootOrShadowRoot(a);){let b=a.getLatest(),c=a.getParent();0===b.getChildrenSize()&&a.remove(!0);a=c}}
9
+ function D(a,b,c,e,d=null){if(0!==b.length){var f=b[0],h=new Map,g=[];f=k.$isElementNode(f)?f:f.getParentOrThrow();f.isInline()&&(f=f.getParentOrThrow());for(var l=!1;null!==f;){var m=f.getPreviousSibling();if(null!==m){f=m;l=!0;break}f=f.getParentOrThrow();if(k.$isRootOrShadowRoot(f))break}m=new Set;for(var q=0;q<c;q++){var p=b[q];k.$isElementNode(p)&&0===p.getChildrenSize()&&m.add(p.getKey())}var n=new Set;for(q=0;q<c;q++){p=b[q];var r=p.getParent();null!==r&&r.isInline()&&(r=r.getParent());if(null!==
10
+ r&&k.$isLeafNode(p)&&!n.has(p.getKey())){if(p=r.getKey(),void 0===h.get(p)){let t=e();t.setFormat(r.getFormatType());t.setIndent(r.getIndent());g.push(t);h.set(p,t);r.getChildren().forEach(x=>{t.append(x);n.add(x.getKey());k.$isElementNode(x)&&x.getChildrenKeys().forEach(G=>n.add(G))});C(r)}}else m.has(p.getKey())&&(r=e(),r.setFormat(p.getFormatType()),r.setIndent(p.getIndent()),g.push(r),p.remove(!0))}if(null!==d)for(b=0;b<g.length;b++)d.append(g[b]);b=null;if(k.$isRootOrShadowRoot(f))if(l)if(null!==
11
+ d)f.insertAfter(d);else for(d=g.length-1;0<=d;d--)f.insertAfter(g[d]);else if(l=f.getFirstChild(),k.$isElementNode(l)&&(f=l),null===l)if(d)f.append(d);else for(d=0;d<g.length;d++)l=g[d],f.append(l),b=l;else if(null!==d)l.insertBefore(d);else for(f=0;f<g.length;f++)d=g[f],l.insertBefore(d),b=d;else if(d)f.insertAfter(d);else for(d=g.length-1;0<=d;d--)l=g[d],f.insertAfter(l),b=l;g=k.$getPreviousSelection();k.$isRangeSelection(g)&&g.anchor.getNode().isAttached()&&g.focus.getNode().isAttached()?k.$setSelection(g.clone()):
12
+ null!==b?b.selectEnd():a.dirty=!0}}function E(a,b,c,e){a.modify(b?"extend":"move",c,e)}function F(a){a=a.anchor.getNode();return"rtl"===(k.$isRootNode(a)?a:a.getParentOrThrow()).getDirection()}exports.$addNodeStyle=function(a){a=a.getStyle();let b=y(a);u.set(a,b)};
13
+ exports.$cloneWithProperties=function(a){a=a.getLatest();let b=a.constructor.clone(a);b.__parent=a.__parent;b.__next=a.__next;b.__prev=a.__prev;if(k.$isElementNode(a)&&k.$isElementNode(b))return b.__first=a.__first,b.__last=a.__last,b.__size=a.__size,b.__format=a.__format,b.__indent=a.__indent,b.__dir=a.__dir,b;k.$isTextNode(a)&&k.$isTextNode(b)&&(b.__format=a.__format,b.__style=a.__style,b.__mode=a.__mode,b.__detail=a.__detail);return b};
14
+ exports.$getSelectionStyleValueForProperty=function(a,b,c=""){let e=null,d=a.getNodes();var f=a.anchor,h=a.focus,g=a.isBackward();let l=g?h.offset:f.offset;f=g?h.getNode():f.getNode();if(""!==a.style&&(a=z(a.style),null!==a&&b in a))return a[b];for(a=0;a<d.length;a++){var m=d[a];if((0===a||0!==l||!m.is(f))&&k.$isTextNode(m))if(h=b,g=c,m=m.getStyle(),m=z(m),h=null!==m?m[h]||g:g,null===e)e=h;else if(e!==h){e="";break}}return null===e?c:e};
15
+ exports.$isAtNodeEnd=function(a){return"text"===a.type?a.offset===a.getNode().getTextContentSize():a.offset===a.getNode().getChildrenSize()};exports.$isParentElementRTL=F;exports.$moveCaretSelection=E;exports.$moveCharacter=function(a,b,c){let e=F(a);E(a,b,c?!e:e,"character")};
16
+ exports.$patchStyleText=function(a,b){var c=a.getNodes();let e=c.length-1,d=c[0],f=c[e];if(a.isCollapsed())B(a,b);else{var h=a.anchor,g=a.focus,l=d.getTextContent().length,m=g.offset,q=h.offset,p=h.isBefore(g),n=p?q:m;a=p?m:q;var r=p?h.type:g.type,t=p?g.type:h.type;h=p?g.key:h.key;k.$isTextNode(d)&&n===l&&(g=d.getNextSibling(),k.$isTextNode(g)&&(n=q=0,d=g));if(1===c.length)k.$isTextNode(d)&&(n="element"===r?0:q>m?m:q,a="element"===t?l:q>m?q:m,n!==a&&(0===n&&a===l?(B(d,b),d.select(n,a)):(c=d.splitText(n,
17
+ a),c=0===n?c[0]:c[1],B(c,b),c.select(0,a-n))));else for(k.$isTextNode(d)&&n<d.getTextContentSize()&&(0!==n&&(d=d.splitText(n)[1]),B(d,b)),k.$isTextNode(f)&&(n=f.getTextContent().length,f.__key!==h&&0!==a&&(a=n),a!==n&&([f]=f.splitText(a)),0!==a&&B(f,b)),a=1;a<e;a++)n=c[a],l=n.getKey(),k.$isTextNode(n)&&l!==d.getKey()&&l!==f.getKey()&&!n.isToken()&&B(n,b)}};
18
+ exports.$selectAll=function(a){let b=a.anchor;a=a.focus;var c=b.getNode().getTopLevelElementOrThrow().getParentOrThrow();let e=c.getFirstDescendant();c=c.getLastDescendant();let d="element",f="element",h=0;k.$isTextNode(e)?d="text":k.$isElementNode(e)||null===e||(e=e.getParentOrThrow());k.$isTextNode(c)?(f="text",h=c.getTextContentSize()):k.$isElementNode(c)||null===c||(c=c.getParentOrThrow());e&&c&&(b.set(e.getKey(),0,d),a.set(c.getKey(),h,f))};
19
+ exports.$setBlocksType=function(a,b){if("root"===a.anchor.key){b=b();var c=k.$getRoot();(a=c.getFirstChild())?a.replace(b,!0):c.append(b)}else for(c=a.getNodes(),a=a.anchor.getNode().getParentOrThrow(),-1===c.indexOf(a)&&c.push(a),a.isInline()&&(a=a.getParentOrThrow(),-1===c.indexOf(a)&&c.push(a)),a=0;a<c.length;a++){let f=c[a];var e=f;if(!k.$isElementNode(e)||k.$isRootOrShadowRoot(e))e=!1;else{var d=e.getFirstChild();d=null===d||k.$isTextNode(d)||d.isInline();e=!e.isInline()&&!1!==e.canBeEmpty()&&
20
+ d}e&&(e=b(),e.setFormat(f.getFormatType()),e.setIndent(f.getIndent()),f.replace(e,!0))}};exports.$shouldOverrideDefaultCharacterSelection=function(a,b){a=k.$getAdjacentNode(a.focus,b);return k.$isDecoratorNode(a)&&!a.isIsolated()||k.$isElementNode(a)&&!a.isInline()&&!a.canBeEmpty()};
21
+ exports.$sliceSelectedTextNodeContent=function(a,b){if(b.isSelected()&&!b.isSegmented()&&!b.isToken()&&(k.$isRangeSelection(a)||k.DEPRECATED_$isGridSelection(a))){var c=a.anchor.getNode(),e=a.focus.getNode(),d=b.is(c),f=b.is(e);if(d||f){d=a.isBackward();let [h,g]=a.getCharacterOffsets();a=c.is(e);f=b.is(d?e:c);e=b.is(d?c:e);c=0;let l=void 0;a?(c=h>g?g:h,l=h>g?h:g):f?(c=d?g:h,l=void 0):e&&(d=d?h:g,c=0,l=d);b.__text=b.__text.slice(c,l)}}return b};
22
+ exports.$wrapNodes=function(a,b,c=null){var e=a.getNodes();let d=e.length;var f=a.anchor;if(0===d||1===d&&"element"===f.type&&0===f.getNode().getChildrenSize()){a="text"===f.type?f.getNode().getParentOrThrow():f.getNode();e=a.getChildren();let g=b();g.setFormat(a.getFormatType());g.setIndent(a.getIndent());e.forEach(l=>g.append(l));c&&(g=c.append(g));a.replace(g)}else{f=null;var h=[];for(let g=0;g<d;g++){let l=e[g];k.$isRootOrShadowRoot(l)?(D(a,h,h.length,b,c),h=[],f=l):null===f||null!==f&&k.$hasAncestor(l,
23
+ f)?h.push(l):(D(a,h,h.length,b,c),h=[l])}D(a,h,h.length,b,c)}};
24
+ exports.createDOMRange=function(a,b,c,e,d){let f=b.getKey(),h=e.getKey(),g=document.createRange(),l=a.getElementByKey(f);a=a.getElementByKey(h);k.$isTextNode(b)&&(l=v(l));k.$isTextNode(e)&&(a=v(a));if(void 0===b||void 0===e||null===l||null===a)return null;"BR"===l.nodeName&&([l,c]=w(l));"BR"===a.nodeName&&([a,d]=w(a));b=l.firstChild;l===a&&null!=b&&"BR"===b.nodeName&&0===c&&0===d&&(d=1);try{g.setStart(l,c),g.setEnd(a,d)}catch(m){return null}!g.collapsed||c===d&&f===h||(g.setStart(a,d),g.setEnd(l,
25
+ c));return g};exports.createRectsFromDOMRange=function(a,b){var c=a.getRootElement();if(null===c)return[];a=c.getBoundingClientRect();c=getComputedStyle(c);c=parseFloat(c.paddingLeft)+parseFloat(c.paddingRight);b=Array.from(b.getClientRects());let e=b.length,d;for(let f=0;f<e;f++){let h=b[f],g=h.width+c===a.width;d&&d.top===h.top&&d.left===h.left&&d.width===h.width&&d.height===h.height||g?(b.splice(f--,1),e--):d=h}return b};exports.getStyleObjectFromCSS=z;
26
+ exports.trimTextContentFromAnchor=function(a,b,c){let e=b.getNode();if(k.$isElementNode(e)){var d=e.getDescendantByIndex(b.offset);null!==d&&(e=d)}for(;0<c&&null!==e;){var f=e.getPreviousSibling(),h=0;if(null===f){d=e.getParentOrThrow();for(var g=d.getPreviousSibling();null===g;){d=d.getParent();if(null===d){f=null;break}g=d.getPreviousSibling()}null!==d&&(h=d.isInline()?0:2,f=k.$isElementNode(g)?g.getLastDescendant():g)}g=e.getTextContent();""===g&&k.$isElementNode(e)&&!e.isInline()&&(g="\n\n");
27
+ d=e.getTextContentSize();if(!k.$isTextNode(e)||c>=d)g=e.getParent(),e.remove(),null==g||0!==g.getChildrenSize()||k.$isRootNode(g)||g.remove(),c-=d+h,e=f;else{let l=e.getKey();h=a.getEditorState().read(()=>{const q=k.$getNodeByKey(l);return k.$isTextNode(q)&&q.isSimpleText()?q.getTextContent():null});f=d-c;let m=g.slice(0,f);null!==h&&h!==g?(c=k.$getPreviousSelection(),d=e,e.isSimpleText()?e.setTextContent(h):(d=k.$createTextNode(h),e.replace(d)),k.$isRangeSelection(c)&&c.isCollapsed()&&(c=c.anchor.offset,
28
+ d.select(c,c))):e.isSimpleText()?(h=b.key===l,g=b.offset,g<c&&(g=d),c=h?g-c:0,d=h?g:f,h&&0===c?([c]=e.splitText(c,d),c.remove()):([,c]=e.splitText(c,d),c.remove())):(c=k.$createTextNode(m),e.replace(c));c=0}}}
package/README.md CHANGED
@@ -81,12 +81,12 @@ Expands the current Selection to cover all of the content in the editor.
81
81
  export function $selectAll(selection: RangeSelection): void;
82
82
  ```
83
83
 
84
- #### `$setBlocksType_experimental`
84
+ #### `$setBlocksType`
85
85
 
86
86
  Converts all nodes in the selection that are of one block type to another specified by parameter
87
87
 
88
88
  ```ts
89
- export function $setBlocksType_experimental(
89
+ export function $setBlocksType(
90
90
  selection: RangeSelection,
91
91
  createElement: () => ElementNode,
92
92
  ): void;
package/index.d.ts CHANGED
@@ -7,8 +7,8 @@
7
7
  *
8
8
  */
9
9
  import { $addNodeStyle, $cloneWithProperties, $isAtNodeEnd, $patchStyleText, $sliceSelectedTextNodeContent, trimTextContentFromAnchor } from './lexical-node';
10
- import { $getSelectionStyleValueForProperty, $isParentElementRTL, $moveCaretSelection, $moveCharacter, $selectAll, $setBlocksType_experimental, $shouldOverrideDefaultCharacterSelection, $wrapNodes } from './range-selection';
10
+ import { $getSelectionStyleValueForProperty, $isParentElementRTL, $moveCaretSelection, $moveCharacter, $selectAll, $setBlocksType, $shouldOverrideDefaultCharacterSelection, $wrapNodes } from './range-selection';
11
11
  import { createDOMRange, createRectsFromDOMRange, getStyleObjectFromCSS } from './utils';
12
12
  export { $addNodeStyle, $cloneWithProperties, $isAtNodeEnd, $patchStyleText, $sliceSelectedTextNodeContent, trimTextContentFromAnchor, };
13
- export { $getSelectionStyleValueForProperty, $isParentElementRTL, $moveCaretSelection, $moveCharacter, $selectAll, $setBlocksType_experimental, $shouldOverrideDefaultCharacterSelection, $wrapNodes, };
13
+ export { $getSelectionStyleValueForProperty, $isParentElementRTL, $moveCaretSelection, $moveCharacter, $selectAll, $setBlocksType, $shouldOverrideDefaultCharacterSelection, $wrapNodes, };
14
14
  export { createDOMRange, createRectsFromDOMRange, getStyleObjectFromCSS };
package/package.json CHANGED
@@ -9,10 +9,10 @@
9
9
  "selection"
10
10
  ],
11
11
  "license": "MIT",
12
- "version": "0.8.1",
12
+ "version": "0.9.0",
13
13
  "main": "LexicalSelection.js",
14
14
  "peerDependencies": {
15
- "lexical": "0.8.1"
15
+ "lexical": "0.9.0"
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",
@@ -13,7 +13,8 @@ import type { ElementNode, GridSelection, LexicalNode, RangeSelection } from 'le
13
13
  * @param createElement
14
14
  * @returns
15
15
  */
16
- export declare function $setBlocksType_experimental(selection: RangeSelection | GridSelection, createElement: () => ElementNode): void;
16
+ export declare function $setBlocksType(selection: RangeSelection | GridSelection, createElement: () => ElementNode): void;
17
+ /** @deprecated */
17
18
  export declare function $wrapNodes(selection: RangeSelection | GridSelection, createElement: () => ElementNode, wrappingElement?: null | ElementNode): void;
18
19
  export declare function $wrapNodesImpl(selection: RangeSelection | GridSelection, nodes: LexicalNode[], nodesLength: number, createElement: () => ElementNode, wrappingElement?: null | ElementNode): void;
19
20
  export declare function $shouldOverrideDefaultCharacterSelection(selection: RangeSelection, isBackward: boolean): boolean;