@lexical/selection 0.8.0 → 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,40 +386,36 @@ function $addNodeStyle(node) {
323
386
  const styles = getStyleObjectFromRawCSS(CSSText);
324
387
  CSS_TO_STYLES.set(CSSText, styles);
325
388
  }
326
- function $patchNodeStyle(node, patch) {
327
- const prevStyles = getStyleObjectFromCSS(node.getStyle());
389
+
390
+ function $patchStyle(target, patch) {
391
+ const prevStyles = getStyleObjectFromCSS('getStyle' in target ? target.getStyle() : target.style);
328
392
  const newStyles = Object.entries(patch).reduce((styles, [key, value]) => {
329
393
  if (value === null) {
330
394
  delete styles[key];
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
- node.setStyle(newCSSText);
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
- const styles = getStyleObjectFromCSS(selection.style);
350
- Object.entries(patch).forEach(([key, value]) => {
351
- if (value !== null) {
352
- styles[key] = value;
353
- }
354
- return styles;
355
- });
356
- const style = getCSSFromStyleObject(styles);
357
- selection.setStyle(style);
415
+ $patchStyle(selection, patch);
358
416
  return;
359
417
  }
418
+
360
419
  const anchor = selection.anchor;
361
420
  const focus = selection.focus;
362
421
  const firstNodeText = firstNode.getTextContent();
@@ -368,44 +427,44 @@ function $patchStyleText(selection, patch) {
368
427
  let endOffset = isBefore ? focusOffset : anchorOffset;
369
428
  const startType = isBefore ? anchor.type : focus.type;
370
429
  const endType = isBefore ? focus.type : anchor.type;
371
- const endKey = isBefore ? focus.key : anchor.key;
372
-
373
- // 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
374
431
  // first node so we don't want to include it in the formatting change.
432
+
375
433
  if (lexical.$isTextNode(firstNode) && startOffset === firstNodeTextLength) {
376
434
  const nextSibling = firstNode.getNextSibling();
435
+
377
436
  if (lexical.$isTextNode(nextSibling)) {
378
437
  // we basically make the second node the firstNode, changing offsets accordingly
379
438
  anchorOffset = 0;
380
439
  startOffset = 0;
381
440
  firstNode = nextSibling;
382
441
  }
383
- }
442
+ } // This is the case where we only selected a single node
384
443
 
385
- // This is the case where we only selected a single node
386
- if (firstNode.is(lastNode)) {
444
+
445
+ if (selectedNodes.length === 1) {
387
446
  if (lexical.$isTextNode(firstNode)) {
388
447
  startOffset = startType === 'element' ? 0 : anchorOffset > focusOffset ? focusOffset : anchorOffset;
389
- 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.
390
449
 
391
- // No actual text is selected, so do nothing.
392
450
  if (startOffset === endOffset) {
393
451
  return;
394
- }
452
+ } // The entire node is selected, so just format it
453
+
395
454
 
396
- // The entire node is selected, so just format it
397
455
  if (startOffset === 0 && endOffset === firstNodeTextLength) {
398
- $patchNodeStyle(firstNode, patch);
456
+ $patchStyle(firstNode, patch);
399
457
  firstNode.select(startOffset, endOffset);
400
458
  } else {
401
459
  // The node is partially selected, so split it into two nodes
402
460
  // and style the selected one.
403
461
  const splitNodes = firstNode.splitText(startOffset, endOffset);
404
462
  const replacement = startOffset === 0 ? splitNodes[0] : splitNodes[1];
405
- $patchNodeStyle(replacement, patch);
463
+ $patchStyle(replacement, patch);
406
464
  replacement.select(0, endOffset - startOffset);
407
465
  }
408
466
  } // multiple nodes selected.
467
+
409
468
  } else {
410
469
  if (lexical.$isTextNode(firstNode) && startOffset < firstNode.getTextContentSize()) {
411
470
  if (startOffset !== 0) {
@@ -413,35 +472,38 @@ function $patchStyleText(selection, patch) {
413
472
  firstNode = firstNode.splitText(startOffset)[1];
414
473
  startOffset = 0;
415
474
  }
416
- $patchNodeStyle(firstNode, patch);
475
+
476
+ $patchStyle(firstNode, patch);
417
477
  }
478
+
418
479
  if (lexical.$isTextNode(lastNode)) {
419
480
  const lastNodeText = lastNode.getTextContent();
420
- const lastNodeTextLength = lastNodeText.length;
421
-
422
- // 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
423
482
  //
424
483
  // If not, assume the last node is fully-selected unless the end offset is
425
484
  // zero.
485
+
426
486
  if (lastNode.__key !== endKey && endOffset !== 0) {
427
487
  endOffset = lastNodeTextLength;
428
- }
488
+ } // if the entire last node isn't selected, split it
489
+
429
490
 
430
- // if the entire last node isn't selected, split it
431
491
  if (endOffset !== lastNodeTextLength) {
432
492
  [lastNode] = lastNode.splitText(endOffset);
433
493
  }
494
+
434
495
  if (endOffset !== 0) {
435
- $patchNodeStyle(lastNode, patch);
496
+ $patchStyle(lastNode, patch);
436
497
  }
437
- }
498
+ } // style all the text nodes in between
499
+
438
500
 
439
- // style all the text nodes in between
440
501
  for (let i = 1; i < lastIndex; i++) {
441
502
  const selectedNode = selectedNodes[i];
442
503
  const selectedNodeKey = selectedNode.getKey();
504
+
443
505
  if (lexical.$isTextNode(selectedNode) && selectedNodeKey !== firstNode.getKey() && selectedNodeKey !== lastNode.getKey() && !selectedNode.isToken()) {
444
- $patchNodeStyle(selectedNode, patch);
506
+ $patchStyle(selectedNode, patch);
445
507
  }
446
508
  }
447
509
  }
@@ -454,7 +516,6 @@ function $patchStyleText(selection, patch) {
454
516
  * LICENSE file in the root directory of this source tree.
455
517
  *
456
518
  */
457
-
458
519
  /**
459
520
  * Converts all nodes in the selection that are of one block type to another specified by parameter
460
521
  *
@@ -462,50 +523,87 @@ function $patchStyleText(selection, patch) {
462
523
  * @param createElement
463
524
  * @returns
464
525
  */
465
- function $setBlocksType_experimental(selection, createElement) {
526
+
527
+ function $setBlocksType(selection, createElement) {
466
528
  if (selection.anchor.key === 'root') {
467
529
  const element = createElement();
468
530
  const root = lexical.$getRoot();
469
531
  const firstChild = root.getFirstChild();
470
- 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
+
471
539
  return;
472
540
  }
541
+
473
542
  const nodes = selection.getNodes();
474
- if (selection.anchor.type === 'text') {
475
- let firstBlock = selection.anchor.getNode().getParent();
476
- firstBlock = firstBlock.isInline() ? firstBlock.getParent() : firstBlock;
477
- 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
+ }
478
555
  }
556
+
479
557
  for (let i = 0; i < nodes.length; i++) {
480
558
  const node = nodes[i];
481
- if (!isBlock(node)) continue;
559
+
560
+ if (!isBlock(node)) {
561
+ continue;
562
+ }
563
+
482
564
  const targetElement = createElement();
483
565
  targetElement.setFormat(node.getFormatType());
484
566
  targetElement.setIndent(node.getIndent());
485
567
  node.replace(targetElement, true);
486
568
  }
487
569
  }
570
+
488
571
  function isBlock(node) {
489
- 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;
490
579
  }
580
+
491
581
  function isPointAttached(point) {
492
582
  return point.getNode().isAttached();
493
583
  }
584
+
494
585
  function $removeParentEmptyElements(startingNode) {
495
586
  let node = startingNode;
587
+
496
588
  while (node !== null && !lexical.$isRootOrShadowRoot(node)) {
497
589
  const latest = node.getLatest();
498
590
  const parentNode = node.getParent();
591
+
499
592
  if (latest.getChildrenSize() === 0) {
500
593
  node.remove(true);
501
594
  }
595
+
502
596
  node = parentNode;
503
597
  }
504
598
  }
599
+ /** @deprecated */
600
+
601
+
505
602
  function $wrapNodes(selection, createElement, wrappingElement = null) {
506
603
  const nodes = selection.getNodes();
507
604
  const nodesLength = nodes.length;
508
605
  const anchor = selection.anchor;
606
+
509
607
  if (nodesLength === 0 || nodesLength === 1 && anchor.type === 'element' && anchor.getNode().getChildrenSize() === 0) {
510
608
  const target = anchor.type === 'text' ? anchor.getNode().getParentOrThrow() : anchor.getNode();
511
609
  const children = target.getChildren();
@@ -513,20 +611,24 @@ function $wrapNodes(selection, createElement, wrappingElement = null) {
513
611
  element.setFormat(target.getFormatType());
514
612
  element.setIndent(target.getIndent());
515
613
  children.forEach(child => element.append(child));
614
+
516
615
  if (wrappingElement) {
517
616
  element = wrappingElement.append(element);
518
617
  }
618
+
519
619
  target.replace(element);
520
620
  return;
521
621
  }
622
+
522
623
  let topLevelNode = null;
523
624
  let descendants = [];
625
+
524
626
  for (let i = 0; i < nodesLength; i++) {
525
- const node = nodes[i];
526
- // 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
527
628
  // user selected multiple Root-like nodes that have to be treated separately as if they are
528
629
  // their own branch. I.e. you don't want to wrap a whole table, but rather the contents of each
529
630
  // of each of the cell nodes.
631
+
530
632
  if (lexical.$isRootOrShadowRoot(node)) {
531
633
  $wrapNodesImpl(selection, descendants, descendants.length, createElement, wrappingElement);
532
634
  descendants = [];
@@ -538,69 +640,82 @@ function $wrapNodes(selection, createElement, wrappingElement = null) {
538
640
  descendants = [node];
539
641
  }
540
642
  }
643
+
541
644
  $wrapNodesImpl(selection, descendants, descendants.length, createElement, wrappingElement);
542
645
  }
543
646
  function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingElement = null) {
544
647
  if (nodes.length === 0) {
545
648
  return;
546
649
  }
650
+
547
651
  const firstNode = nodes[0];
548
652
  const elementMapping = new Map();
549
- const elements = [];
550
- // 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
551
654
  // either insertAfter/insertBefore/append the corresponding
552
655
  // elements to. This is made more complicated due to nested
553
656
  // structures.
657
+
554
658
  let target = lexical.$isElementNode(firstNode) ? firstNode : firstNode.getParentOrThrow();
659
+
555
660
  if (target.isInline()) {
556
661
  target = target.getParentOrThrow();
557
662
  }
663
+
558
664
  let targetIsPrevSibling = false;
665
+
559
666
  while (target !== null) {
560
667
  const prevSibling = target.getPreviousSibling();
668
+
561
669
  if (prevSibling !== null) {
562
670
  target = prevSibling;
563
671
  targetIsPrevSibling = true;
564
672
  break;
565
673
  }
674
+
566
675
  target = target.getParentOrThrow();
676
+
567
677
  if (lexical.$isRootOrShadowRoot(target)) {
568
678
  break;
569
679
  }
570
680
  }
571
- const emptyElements = new Set();
572
681
 
573
- // Find any top level empty elements
682
+ const emptyElements = new Set(); // Find any top level empty elements
683
+
574
684
  for (let i = 0; i < nodesLength; i++) {
575
685
  const node = nodes[i];
686
+
576
687
  if (lexical.$isElementNode(node) && node.getChildrenSize() === 0) {
577
688
  emptyElements.add(node.getKey());
578
689
  }
579
690
  }
580
- const movedNodes = new Set();
581
691
 
582
- // Move out all leaf nodes into our elements array.
692
+ const movedNodes = new Set(); // Move out all leaf nodes into our elements array.
583
693
  // If we find a top level empty element, also move make
584
694
  // an element for that.
695
+
585
696
  for (let i = 0; i < nodesLength; i++) {
586
697
  const node = nodes[i];
587
698
  let parent = node.getParent();
699
+
588
700
  if (parent !== null && parent.isInline()) {
589
701
  parent = parent.getParent();
590
702
  }
703
+
591
704
  if (parent !== null && lexical.$isLeafNode(node) && !movedNodes.has(node.getKey())) {
592
705
  const parentKey = parent.getKey();
706
+
593
707
  if (elementMapping.get(parentKey) === undefined) {
594
708
  const targetElement = createElement();
595
709
  targetElement.setFormat(parent.getFormatType());
596
710
  targetElement.setIndent(parent.getIndent());
597
711
  elements.push(targetElement);
598
- elementMapping.set(parentKey, targetElement);
599
- // Move node and its siblings to the new
712
+ elementMapping.set(parentKey, targetElement); // Move node and its siblings to the new
600
713
  // element.
714
+
601
715
  parent.getChildren().forEach(child => {
602
716
  targetElement.append(child);
603
717
  movedNodes.add(child.getKey());
718
+
604
719
  if (lexical.$isElementNode(child)) {
605
720
  // Skip nested leaf nodes if the parent has already been moved
606
721
  child.getChildrenKeys().forEach(key => movedNodes.add(key));
@@ -616,16 +731,17 @@ function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingEl
616
731
  node.remove(true);
617
732
  }
618
733
  }
734
+
619
735
  if (wrappingElement !== null) {
620
736
  for (let i = 0; i < elements.length; i++) {
621
737
  const element = elements[i];
622
738
  wrappingElement.append(element);
623
739
  }
624
740
  }
625
- let lastElement = null;
626
741
 
627
- // 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
628
743
  // so that the target is the first child instead.
744
+
629
745
  if (lexical.$isRootOrShadowRoot(target)) {
630
746
  if (targetIsPrevSibling) {
631
747
  if (wrappingElement !== null) {
@@ -638,9 +754,11 @@ function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingEl
638
754
  }
639
755
  } else {
640
756
  const firstChild = target.getFirstChild();
757
+
641
758
  if (lexical.$isElementNode(firstChild)) {
642
759
  target = firstChild;
643
760
  }
761
+
644
762
  if (firstChild === null) {
645
763
  if (wrappingElement) {
646
764
  target.append(wrappingElement);
@@ -674,7 +792,9 @@ function $wrapNodesImpl(selection, nodes, nodesLength, createElement, wrappingEl
674
792
  }
675
793
  }
676
794
  }
795
+
677
796
  const prevSelection = lexical.$getPreviousSelection();
797
+
678
798
  if (lexical.$isRangeSelection(prevSelection) && isPointAttached(prevSelection.anchor) && isPointAttached(prevSelection.focus)) {
679
799
  lexical.$setSelection(prevSelection.clone());
680
800
  } else if (lastElement !== null) {
@@ -710,30 +830,37 @@ function $selectAll(selection) {
710
830
  let firstType = 'element';
711
831
  let lastType = 'element';
712
832
  let lastOffset = 0;
833
+
713
834
  if (lexical.$isTextNode(firstNode)) {
714
835
  firstType = 'text';
715
836
  } else if (!lexical.$isElementNode(firstNode) && firstNode !== null) {
716
837
  firstNode = firstNode.getParentOrThrow();
717
838
  }
839
+
718
840
  if (lexical.$isTextNode(lastNode)) {
719
841
  lastType = 'text';
720
842
  lastOffset = lastNode.getTextContentSize();
721
843
  } else if (!lexical.$isElementNode(lastNode) && lastNode !== null) {
722
844
  lastNode = lastNode.getParentOrThrow();
723
845
  }
846
+
724
847
  if (firstNode && lastNode) {
725
848
  anchor.set(firstNode.getKey(), 0, firstType);
726
849
  focus.set(lastNode.getKey(), lastOffset, lastType);
727
850
  }
728
851
  }
852
+
729
853
  function $getNodeStyleValueForProperty(node, styleProperty, defaultValue) {
730
854
  const css = node.getStyle();
731
855
  const styleObject = getStyleObjectFromCSS(css);
856
+
732
857
  if (styleObject !== null) {
733
858
  return styleObject[styleProperty] || defaultValue;
734
859
  }
860
+
735
861
  return defaultValue;
736
862
  }
863
+
737
864
  function $getSelectionStyleValueForProperty(selection, styleProperty, defaultValue = '') {
738
865
  let styleValue = null;
739
866
  const nodes = selection.getNodes();
@@ -742,44 +869,39 @@ function $getSelectionStyleValueForProperty(selection, styleProperty, defaultVal
742
869
  const isBackward = selection.isBackward();
743
870
  const endOffset = isBackward ? focus.offset : anchor.offset;
744
871
  const endNode = isBackward ? focus.getNode() : anchor.getNode();
872
+
745
873
  if (selection.style !== '') {
746
874
  const css = selection.style;
747
875
  const styleObject = getStyleObjectFromCSS(css);
748
- let nodeStyleValue;
749
- if (styleObject !== null) {
750
- nodeStyleValue = styleObject[styleProperty] || defaultValue;
751
- } else {
752
- nodeStyleValue = defaultValue;
753
- }
754
- if (styleValue === null) {
755
- styleValue = nodeStyleValue;
756
- } else if (styleValue !== nodeStyleValue) {
757
- // multiple text nodes are in the selection and they don't all
758
- // have the same font size.
759
- styleValue = '';
876
+
877
+ if (styleObject !== null && styleProperty in styleObject) {
878
+ return styleObject[styleProperty];
760
879
  }
761
880
  }
762
- for (let i = 0; i < nodes.length; i++) {
763
- const node = nodes[i];
764
881
 
765
- // 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
766
884
  // include it in the selection for purposes of determining style
767
885
  // value
886
+
768
887
  if (i !== 0 && endOffset === 0 && node.is(endNode)) {
769
888
  continue;
770
889
  }
890
+
771
891
  if (lexical.$isTextNode(node)) {
772
892
  const nodeStyleValue = $getNodeStyleValueForProperty(node, styleProperty, defaultValue);
893
+
773
894
  if (styleValue === null) {
774
895
  styleValue = nodeStyleValue;
775
896
  } else if (styleValue !== nodeStyleValue) {
776
897
  // multiple text nodes are in the selection and they don't all
777
- // have the same font size.
898
+ // have the same style.
778
899
  styleValue = '';
779
900
  break;
780
901
  }
781
902
  }
782
903
  }
904
+
783
905
  return styleValue === null ? defaultValue : styleValue;
784
906
  }
785
907
 
@@ -792,7 +914,7 @@ exports.$moveCaretSelection = $moveCaretSelection;
792
914
  exports.$moveCharacter = $moveCharacter;
793
915
  exports.$patchStyleText = $patchStyleText;
794
916
  exports.$selectAll = $selectAll;
795
- exports.$setBlocksType_experimental = $setBlocksType_experimental;
917
+ exports.$setBlocksType = $setBlocksType;
796
918
  exports.$shouldOverrideDefaultCharacterSelection = $shouldOverrideDefaultCharacterSelection;
797
919
  exports.$sliceSelectedTextNodeContent = $sliceSelectedTextNodeContent;
798
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 v=new Map;function w(a){for(;null!=a;){if(a.nodeType===Node.TEXT_NODE)return a;a=a.firstChild}return null}function x(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 A(a){let b=v.get(a);void 0===b&&(b=y(a),v.set(a,b));return b}
8
- function B(a){let b="";for(let c in a)c&&(b+=`${c}: ${a[c]};`);return b}function C(a,b){var c=A(a.getStyle());b=Object.entries(b).reduce((e,[d,f])=>{null===f?delete e[d]:e[d]=f;return e},{...c});c=B(b);a.setStyle(c);v.set(c,b)}function D(a){for(;null!==a&&!l.$isRootOrShadowRoot(a);){let b=a.getLatest(),c=a.getParent();0===b.getChildrenSize()&&a.remove(!0);a=c}}
9
- function E(a,b,c,e,d=null){if(0!==b.length){var f=b[0],h=new Map,g=[];f=l.$isElementNode(f)?f:f.getParentOrThrow();f.isInline()&&(f=f.getParentOrThrow());for(var k=!1;null!==f;){var n=f.getPreviousSibling();if(null!==n){f=n;k=!0;break}f=f.getParentOrThrow();if(l.$isRootOrShadowRoot(f))break}n=new Set;for(var q=0;q<c;q++){var p=b[q];l.$isElementNode(p)&&0===p.getChildrenSize()&&n.add(p.getKey())}var m=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&&l.$isLeafNode(p)&&!m.has(p.getKey())){if(p=r.getKey(),void 0===h.get(p)){let u=e();u.setFormat(r.getFormatType());u.setIndent(r.getIndent());g.push(u);h.set(p,u);r.getChildren().forEach(t=>{u.append(t);m.add(t.getKey());l.$isElementNode(t)&&t.getChildrenKeys().forEach(z=>m.add(z))});D(r)}}else n.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(l.$isRootOrShadowRoot(f))if(k)if(null!==
11
- d)f.insertAfter(d);else for(d=g.length-1;0<=d;d--)f.insertAfter(g[d]);else if(k=f.getFirstChild(),l.$isElementNode(k)&&(f=k),null===k)if(d)f.append(d);else for(d=0;d<g.length;d++)k=g[d],f.append(k),b=k;else if(null!==d)k.insertBefore(d);else for(f=0;f<g.length;f++)d=g[f],k.insertBefore(d),b=d;else if(d)f.insertAfter(d);else for(d=g.length-1;0<=d;d--)k=g[d],f.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 F(a,b,c,e){a.modify(b?"extend":"move",c,e)}function H(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);v.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 e=null,d=a.getNodes();var f=a.anchor,h=a.focus,g=a.isBackward();let k=g?h.offset:f.offset;f=g?h.getNode():f.getNode();""!==a.style&&(a=A(a.style),a=null!==a?a[b]||c:c,null===e?e=a:e!==a&&(e=""));for(a=0;a<d.length;a++){var n=d[a];if((0===a||0!==k||!n.is(f))&&l.$isTextNode(n))if(h=b,g=c,n=n.getStyle(),n=A(n),h=null!==n?n[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=H;exports.$moveCaretSelection=F;exports.$moveCharacter=function(a,b,c){let e=H(a);F(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()){let t=A(a.style);Object.entries(b).forEach(([z,G])=>{null!==G&&(t[z]=G);return t});b=B(t);a.setStyle(b)}else{var h=a.anchor,g=a.focus,k=d.getTextContent().length,n=g.offset,q=h.offset,p=h.isBefore(g),m=p?q:n;a=p?n:q;var r=p?h.type:g.type,u=p?g.type:h.type;h=p?g.key:h.key;l.$isTextNode(d)&&m===k&&(g=d.getNextSibling(),l.$isTextNode(g)&&(m=q=0,d=g));if(d.is(f))l.$isTextNode(d)&&(m="element"===
17
- r?0:q>n?n:q,a="element"===u?k:q>n?q:n,m!==a&&(0===m&&a===k?(C(d,b),d.select(m,a)):(c=d.splitText(m,a),c=0===m?c[0]:c[1],C(c,b),c.select(0,a-m))));else for(l.$isTextNode(d)&&m<d.getTextContentSize()&&(0!==m&&(d=d.splitText(m)[1],m=0),C(d,b)),l.$isTextNode(f)&&(m=f.getTextContent().length,f.__key!==h&&0!==a&&(a=m),a!==m&&([f]=f.splitText(a)),0!==a&&C(f,b)),a=1;a<e;a++)m=c[a],k=m.getKey(),l.$isTextNode(m)&&k!==d.getKey()&&k!==f.getKey()&&!m.isToken()&&C(m,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;l.$isTextNode(e)?d="text":l.$isElementNode(e)||null===e||(e=e.getParentOrThrow());l.$isTextNode(c)?(f="text",h=c.getTextContentSize()):l.$isElementNode(c)||null===c||(c=c.getParentOrThrow());e&&c&&(b.set(e.getKey(),0,d),a.set(c.getKey(),h,f))};
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 e=d;!l.$isElementNode(e)||l.$isRootOrShadowRoot(e)||e.isInline()||(e=b(),e.setFormat(d.getFormatType()),e.setIndent(d.getIndent()),d.replace(e,!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(),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 k=void 0;a?(c=h>g?g:h,k=h>g?h:g):f?(c=d?g:h,k=void 0):e&&(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 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(k=>g.append(k));c&&(g=c.append(g));a.replace(g)}else{f=null;var h=[];for(let g=0;g<d;g++){let k=e[g];l.$isRootOrShadowRoot(k)?(E(a,h,h.length,b,c),h=[],f=k):null===f||null!==f&&l.$hasAncestor(k,
23
- f)?h.push(k):(E(a,h,h.length,b,c),h=[k])}E(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(),k=a.getElementByKey(f);a=a.getElementByKey(h);l.$isTextNode(b)&&(k=w(k));l.$isTextNode(e)&&(a=w(a));if(void 0===b||void 0===e||null===k||null===a)return null;"BR"===k.nodeName&&([k,c]=x(k));"BR"===a.nodeName&&([a,d]=x(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(n){return null}!g.collapsed||c===d&&f===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 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=A;
26
- exports.trimTextContentFromAnchor=function(a,b,c){let e=b.getNode();if(l.$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=l.$isElementNode(g)?g.getLastDescendant():g)}let k=e.getTextContent();""===k&&l.$isElementNode(e)&&!e.isInline()&&(k="\n\n");
27
- d=k.length;g=d-c;let n=k.slice(0,g);if(!l.$isTextNode(e)||c>=d)g=e.getParent(),e.remove(),null!=g&&0===g.getChildrenSize()&&g.remove(),c-=d+h,e=f;else{let q=e.getKey();f=a.getEditorState().read(()=>{const p=l.$getNodeByKey(q);return l.$isTextNode(p)&&p.isSimpleText()?p.getTextContent():null});null!==f&&f!==k?(c=l.$getPreviousSelection(),d=e,e.isSimpleText()?e.setTextContent(f):(d=l.$createTextNode(f),e.replace(d)),l.$isRangeSelection(c)&&c.isCollapsed()&&(c=c.anchor.offset,d.select(c,c))):e.isSimpleText()?
28
- (f=b.key===q,h=b.offset,h<c&&(h=d),c=f?h-c:0,d=f?h:g,f&&0===c?([c]=e.splitText(c,d),c.remove()):([,c]=e.splitText(c,d),c.remove())):(c=l.$createTextNode(n),e.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.0",
12
+ "version": "0.9.0",
13
13
  "main": "LexicalSelection.js",
14
14
  "peerDependencies": {
15
- "lexical": "0.8.0"
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;