@lexical/react 0.12.2 → 0.12.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/LexicalAutoEmbedPlugin.d.ts +3 -2
  2. package/LexicalAutoEmbedPlugin.dev.js +4 -14
  3. package/LexicalAutoEmbedPlugin.prod.js +4 -3
  4. package/LexicalAutoFocusPlugin.dev.js +0 -1
  5. package/LexicalAutoLinkPlugin.dev.js +126 -73
  6. package/LexicalAutoLinkPlugin.prod.js +11 -7
  7. package/LexicalBlockWithAlignableContents.dev.js +0 -10
  8. package/LexicalCharacterLimitPlugin.dev.js +7 -46
  9. package/LexicalCheckListPlugin.dev.js +10 -48
  10. package/LexicalClearEditorPlugin.dev.js +1 -1
  11. package/LexicalClickableLinkPlugin.dev.js +2 -20
  12. package/LexicalCollaborationContext.dev.js +0 -3
  13. package/LexicalCollaborationPlugin.dev.js +8 -37
  14. package/LexicalComposer.d.ts +3 -7
  15. package/LexicalComposer.dev.js +9 -11
  16. package/LexicalComposer.js.flow +4 -4
  17. package/LexicalComposer.prod.js +2 -1
  18. package/LexicalComposerContext.dev.js +0 -6
  19. package/LexicalContentEditable.dev.js +1 -2
  20. package/LexicalContextMenuPlugin.d.ts +3 -2
  21. package/LexicalContextMenuPlugin.dev.js +28 -82
  22. package/LexicalContextMenuPlugin.prod.js +16 -15
  23. package/LexicalDecoratorBlockNode.dev.js +0 -6
  24. package/LexicalEditorRefPlugin.dev.js +0 -3
  25. package/LexicalHashtagPlugin.dev.js +73 -43
  26. package/LexicalHorizontalRuleNode.dev.js +0 -21
  27. package/LexicalHorizontalRulePlugin.dev.js +0 -4
  28. package/LexicalLinkPlugin.dev.js +4 -10
  29. package/LexicalListPlugin.dev.js +0 -2
  30. package/LexicalMarkdownShortcutPlugin.dev.js +2 -2
  31. package/LexicalNestedComposer.d.ts +2 -2
  32. package/LexicalNestedComposer.dev.js +18 -16
  33. package/LexicalNestedComposer.js.flow +7 -2
  34. package/LexicalNestedComposer.prod.js +4 -3
  35. package/LexicalNodeEventPlugin.dev.js +2 -6
  36. package/LexicalNodeMenuPlugin.d.ts +3 -2
  37. package/LexicalNodeMenuPlugin.dev.js +27 -83
  38. package/LexicalNodeMenuPlugin.prod.js +15 -15
  39. package/LexicalOnChangePlugin.dev.js +1 -1
  40. package/LexicalPlainTextPlugin.dev.js +8 -12
  41. package/LexicalRichTextPlugin.dev.js +8 -12
  42. package/LexicalTabIndentationPlugin.dev.js +7 -16
  43. package/LexicalTableOfContents.dev.js +5 -33
  44. package/LexicalTablePlugin.dev.js +11 -28
  45. package/LexicalTreeView.dev.js +14 -79
  46. package/LexicalTypeaheadMenuPlugin.d.ts +4 -3
  47. package/LexicalTypeaheadMenuPlugin.dev.js +39 -176
  48. package/LexicalTypeaheadMenuPlugin.prod.js +19 -20
  49. package/package.json +19 -19
  50. package/shared/LexicalMenu.d.ts +3 -2
  51. package/useLexicalEditable.dev.js +1 -5
  52. package/useLexicalIsTextContentEmpty.dev.js +1 -0
  53. package/useLexicalNodeSelection.dev.js +0 -7
  54. package/useLexicalSubscription.dev.js +1 -3
@@ -18,6 +18,7 @@ var utils = require('@lexical/utils');
18
18
  * LICENSE file in the root directory of this source tree.
19
19
  *
20
20
  */
21
+
21
22
  const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
22
23
 
23
24
  /**
@@ -45,140 +46,113 @@ class MenuOption {
45
46
  };
46
47
  this.setRefElement = this.setRefElement.bind(this);
47
48
  }
48
-
49
49
  setRefElement(element) {
50
50
  this.ref = {
51
51
  current: element
52
52
  };
53
53
  }
54
-
55
54
  }
56
-
57
55
  const scrollIntoViewIfNeeded = target => {
58
56
  const typeaheadContainerNode = document.getElementById('typeahead-menu');
59
57
  if (!typeaheadContainerNode) return;
60
58
  const typeaheadRect = typeaheadContainerNode.getBoundingClientRect();
61
-
62
59
  if (typeaheadRect.top + typeaheadRect.height > window.innerHeight) {
63
60
  typeaheadContainerNode.scrollIntoView({
64
61
  block: 'center'
65
62
  });
66
63
  }
67
-
68
64
  if (typeaheadRect.top < 0) {
69
65
  typeaheadContainerNode.scrollIntoView({
70
66
  block: 'center'
71
67
  });
72
68
  }
73
-
74
69
  target.scrollIntoView({
75
70
  block: 'nearest'
76
71
  });
77
72
  };
73
+
78
74
  /**
79
75
  * Walk backwards along user input and forward through entity title to try
80
76
  * and replace more of the user's text with entity.
81
77
  */
82
-
83
-
84
78
  function getFullMatchOffset(documentText, entryText, offset) {
85
79
  let triggerOffset = offset;
86
-
87
80
  for (let i = triggerOffset; i <= entryText.length; i++) {
88
81
  if (documentText.substr(-i) === entryText.substr(0, i)) {
89
82
  triggerOffset = i;
90
83
  }
91
84
  }
92
-
93
85
  return triggerOffset;
94
86
  }
87
+
95
88
  /**
96
89
  * Split Lexical TextNode and return a new TextNode only containing matched text.
97
90
  * Common use cases include: removing the node, replacing with a new node.
98
91
  */
99
-
100
-
101
92
  function $splitNodeContainingQuery(match) {
102
93
  const selection = lexical.$getSelection();
103
-
104
94
  if (!lexical.$isRangeSelection(selection) || !selection.isCollapsed()) {
105
95
  return null;
106
96
  }
107
-
108
97
  const anchor = selection.anchor;
109
-
110
98
  if (anchor.type !== 'text') {
111
99
  return null;
112
100
  }
113
-
114
101
  const anchorNode = anchor.getNode();
115
-
116
102
  if (!anchorNode.isSimpleText()) {
117
103
  return null;
118
104
  }
119
-
120
105
  const selectionOffset = anchor.offset;
121
106
  const textContent = anchorNode.getTextContent().slice(0, selectionOffset);
122
107
  const characterOffset = match.replaceableString.length;
123
108
  const queryOffset = getFullMatchOffset(textContent, match.matchingString, characterOffset);
124
109
  const startOffset = selectionOffset - queryOffset;
125
-
126
110
  if (startOffset < 0) {
127
111
  return null;
128
112
  }
129
-
130
113
  let newNode;
131
-
132
114
  if (startOffset === 0) {
133
115
  [newNode] = anchorNode.splitText(selectionOffset);
134
116
  } else {
135
117
  [, newNode] = anchorNode.splitText(startOffset, selectionOffset);
136
118
  }
137
-
138
119
  return newNode;
139
- } // Got from https://stackoverflow.com/a/42543908/2013580
140
-
120
+ }
141
121
 
122
+ // Got from https://stackoverflow.com/a/42543908/2013580
142
123
  function getScrollParent$1(element, includeHidden) {
143
124
  let style = getComputedStyle(element);
144
125
  const excludeStaticParent = style.position === 'absolute';
145
126
  const overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;
146
-
147
127
  if (style.position === 'fixed') {
148
128
  return document.body;
149
129
  }
150
-
151
130
  for (let parent = element; parent = parent.parentElement;) {
152
131
  style = getComputedStyle(parent);
153
-
154
132
  if (excludeStaticParent && style.position === 'static') {
155
133
  continue;
156
134
  }
157
-
158
135
  if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) {
159
136
  return parent;
160
137
  }
161
138
  }
162
-
163
139
  return document.body;
164
140
  }
165
-
166
- function isTriggerVisibleInNearestScrollContainer$1(targetElement, containerElement) {
141
+ function isTriggerVisibleInNearestScrollContainer(targetElement, containerElement) {
167
142
  const tRect = targetElement.getBoundingClientRect();
168
143
  const cRect = containerElement.getBoundingClientRect();
169
144
  return tRect.top > cRect.top && tRect.top < cRect.bottom;
170
- } // Reposition the menu on scroll, window resize, and element resize.
171
-
145
+ }
172
146
 
173
- function useDynamicPositioning$1(resolution, targetElement, onReposition, onVisibilityChange) {
147
+ // Reposition the menu on scroll, window resize, and element resize.
148
+ function useDynamicPositioning(resolution, targetElement, onReposition, onVisibilityChange) {
174
149
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
175
150
  React.useEffect(() => {
176
151
  if (targetElement != null && resolution != null) {
177
152
  const rootElement = editor.getRootElement();
178
153
  const rootScrollParent = rootElement != null ? getScrollParent$1(rootElement, false) : document.body;
179
154
  let ticking = false;
180
- let previousIsInView = isTriggerVisibleInNearestScrollContainer$1(targetElement, rootScrollParent);
181
-
155
+ let previousIsInView = isTriggerVisibleInNearestScrollContainer(targetElement, rootScrollParent);
182
156
  const handleScroll = function () {
183
157
  if (!ticking) {
184
158
  window.requestAnimationFrame(function () {
@@ -187,18 +161,14 @@ function useDynamicPositioning$1(resolution, targetElement, onReposition, onVisi
187
161
  });
188
162
  ticking = true;
189
163
  }
190
-
191
- const isInView = isTriggerVisibleInNearestScrollContainer$1(targetElement, rootScrollParent);
192
-
164
+ const isInView = isTriggerVisibleInNearestScrollContainer(targetElement, rootScrollParent);
193
165
  if (isInView !== previousIsInView) {
194
166
  previousIsInView = isInView;
195
-
196
167
  if (onVisibilityChange != null) {
197
168
  onVisibilityChange(isInView);
198
169
  }
199
170
  }
200
171
  };
201
-
202
172
  const resizeObserver = new ResizeObserver(onReposition);
203
173
  window.addEventListener('resize', onReposition);
204
174
  document.addEventListener('scroll', handleScroll, {
@@ -209,7 +179,7 @@ function useDynamicPositioning$1(resolution, targetElement, onReposition, onVisi
209
179
  return () => {
210
180
  resizeObserver.unobserve(targetElement);
211
181
  window.removeEventListener('resize', onReposition);
212
- document.removeEventListener('scroll', handleScroll);
182
+ document.removeEventListener('scroll', handleScroll, true);
213
183
  };
214
184
  }
215
185
  }, [targetElement, editor, onVisibilityChange, onReposition, resolution]);
@@ -223,7 +193,8 @@ function LexicalMenu({
223
193
  options,
224
194
  menuRenderFn,
225
195
  onSelectOption,
226
- shouldSplitNodeWithQuery = false
196
+ shouldSplitNodeWithQuery = false,
197
+ commandPriority = lexical.COMMAND_PRIORITY_LOW
227
198
  }) {
228
199
  const [selectedIndex, setHighlightedIndex] = React.useState(null);
229
200
  const matchingString = resolution.match && resolution.match.matchingString;
@@ -238,7 +209,6 @@ function LexicalMenu({
238
209
  }, [editor, shouldSplitNodeWithQuery, resolution.match, onSelectOption, close]);
239
210
  const updateSelectedIndex = React.useCallback(index => {
240
211
  const rootElem = editor.getRootElement();
241
-
242
212
  if (rootElem !== null) {
243
213
  rootElem.setAttribute('aria-activedescendant', 'typeahead-item-' + index);
244
214
  setHighlightedIndex(index);
@@ -247,7 +217,6 @@ function LexicalMenu({
247
217
  React.useEffect(() => {
248
218
  return () => {
249
219
  const rootElem = editor.getRootElement();
250
-
251
220
  if (rootElem !== null) {
252
221
  rootElem.removeAttribute('aria-activedescendant');
253
222
  }
@@ -268,79 +237,66 @@ function LexicalMenu({
268
237
  scrollIntoViewIfNeeded(option.ref.current);
269
238
  return true;
270
239
  }
271
-
272
240
  return false;
273
- }, lexical.COMMAND_PRIORITY_LOW));
274
- }, [editor, updateSelectedIndex]);
241
+ }, commandPriority));
242
+ }, [editor, updateSelectedIndex, commandPriority]);
275
243
  React.useEffect(() => {
276
244
  return utils.mergeRegister(editor.registerCommand(lexical.KEY_ARROW_DOWN_COMMAND, payload => {
277
245
  const event = payload;
278
-
279
246
  if (options !== null && options.length && selectedIndex !== null) {
280
247
  const newSelectedIndex = selectedIndex !== options.length - 1 ? selectedIndex + 1 : 0;
281
248
  updateSelectedIndex(newSelectedIndex);
282
249
  const option = options[newSelectedIndex];
283
-
284
250
  if (option.ref != null && option.ref.current) {
285
251
  editor.dispatchCommand(SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND$1, {
286
252
  index: newSelectedIndex,
287
253
  option
288
254
  });
289
255
  }
290
-
291
256
  event.preventDefault();
292
257
  event.stopImmediatePropagation();
293
258
  }
294
-
295
259
  return true;
296
- }, lexical.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical.KEY_ARROW_UP_COMMAND, payload => {
260
+ }, commandPriority), editor.registerCommand(lexical.KEY_ARROW_UP_COMMAND, payload => {
297
261
  const event = payload;
298
-
299
262
  if (options !== null && options.length && selectedIndex !== null) {
300
263
  const newSelectedIndex = selectedIndex !== 0 ? selectedIndex - 1 : options.length - 1;
301
264
  updateSelectedIndex(newSelectedIndex);
302
265
  const option = options[newSelectedIndex];
303
-
304
266
  if (option.ref != null && option.ref.current) {
305
267
  scrollIntoViewIfNeeded(option.ref.current);
306
268
  }
307
-
308
269
  event.preventDefault();
309
270
  event.stopImmediatePropagation();
310
271
  }
311
-
312
272
  return true;
313
- }, lexical.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical.KEY_ESCAPE_COMMAND, payload => {
273
+ }, commandPriority), editor.registerCommand(lexical.KEY_ESCAPE_COMMAND, payload => {
314
274
  const event = payload;
315
275
  event.preventDefault();
316
276
  event.stopImmediatePropagation();
317
277
  close();
318
278
  return true;
319
- }, lexical.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical.KEY_TAB_COMMAND, payload => {
279
+ }, commandPriority), editor.registerCommand(lexical.KEY_TAB_COMMAND, payload => {
320
280
  const event = payload;
321
-
322
281
  if (options === null || selectedIndex === null || options[selectedIndex] == null) {
323
282
  return false;
324
283
  }
325
-
326
284
  event.preventDefault();
327
285
  event.stopImmediatePropagation();
328
286
  selectOptionAndCleanUp(options[selectedIndex]);
329
287
  return true;
330
- }, lexical.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical.KEY_ENTER_COMMAND, event => {
288
+ }, commandPriority), editor.registerCommand(lexical.KEY_ENTER_COMMAND, event => {
331
289
  if (options === null || selectedIndex === null || options[selectedIndex] == null) {
332
290
  return false;
333
291
  }
334
-
335
292
  if (event !== null) {
336
293
  event.preventDefault();
337
294
  event.stopImmediatePropagation();
338
295
  }
339
-
340
296
  selectOptionAndCleanUp(options[selectedIndex]);
341
297
  return true;
342
- }, lexical.COMMAND_PRIORITY_LOW));
343
- }, [selectOptionAndCleanUp, close, editor, options, selectedIndex, updateSelectedIndex]);
298
+ }, commandPriority));
299
+ }, [selectOptionAndCleanUp, close, editor, options, selectedIndex, updateSelectedIndex, commandPriority]);
344
300
  const listItemProps = React.useMemo(() => ({
345
301
  options,
346
302
  selectOptionAndCleanUp,
@@ -353,10 +309,10 @@ function useMenuAnchorRef(resolution, setResolution, className) {
353
309
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
354
310
  const anchorElementRef = React.useRef(document.createElement('div'));
355
311
  const positionMenu = React.useCallback(() => {
312
+ anchorElementRef.current.style.top = anchorElementRef.current.style.bottom;
356
313
  const rootElement = editor.getRootElement();
357
314
  const containerDiv = anchorElementRef.current;
358
315
  const menuEle = containerDiv.firstChild;
359
-
360
316
  if (rootElement !== null && resolution !== null) {
361
317
  const {
362
318
  left,
@@ -364,33 +320,28 @@ function useMenuAnchorRef(resolution, setResolution, className) {
364
320
  width,
365
321
  height
366
322
  } = resolution.getRect();
367
- containerDiv.style.top = `${top + window.pageYOffset}px`;
323
+ const anchorHeight = anchorElementRef.current.offsetHeight; // use to position under anchor
324
+ containerDiv.style.top = `${top + window.pageYOffset + anchorHeight + 3}px`;
368
325
  containerDiv.style.left = `${left + window.pageXOffset}px`;
369
326
  containerDiv.style.height = `${height}px`;
370
327
  containerDiv.style.width = `${width}px`;
371
-
372
328
  if (menuEle !== null) {
329
+ menuEle.style.top = `${top}`;
373
330
  const menuRect = menuEle.getBoundingClientRect();
374
331
  const menuHeight = menuRect.height;
375
332
  const menuWidth = menuRect.width;
376
333
  const rootElementRect = rootElement.getBoundingClientRect();
377
-
378
334
  if (left + menuWidth > rootElementRect.right) {
379
335
  containerDiv.style.left = `${rootElementRect.right - menuWidth + window.pageXOffset}px`;
380
336
  }
381
-
382
- const margin = 10;
383
-
384
337
  if ((top + menuHeight > window.innerHeight || top + menuHeight > rootElementRect.bottom) && top - rootElementRect.top > menuHeight) {
385
- containerDiv.style.top = `${top - menuHeight + window.pageYOffset - (height + margin)}px`;
338
+ containerDiv.style.top = `${top - menuHeight + window.pageYOffset - height}px`;
386
339
  }
387
340
  }
388
-
389
341
  if (!containerDiv.isConnected) {
390
342
  if (className != null) {
391
343
  containerDiv.className = className;
392
344
  }
393
-
394
345
  containerDiv.setAttribute('aria-label', 'Typeahead menu');
395
346
  containerDiv.setAttribute('id', 'typeahead-menu');
396
347
  containerDiv.setAttribute('role', 'listbox');
@@ -398,23 +349,19 @@ function useMenuAnchorRef(resolution, setResolution, className) {
398
349
  containerDiv.style.position = 'absolute';
399
350
  document.body.append(containerDiv);
400
351
  }
401
-
402
352
  anchorElementRef.current = containerDiv;
403
353
  rootElement.setAttribute('aria-controls', 'typeahead-menu');
404
354
  }
405
355
  }, [editor, resolution, className]);
406
356
  React.useEffect(() => {
407
357
  const rootElement = editor.getRootElement();
408
-
409
358
  if (resolution !== null) {
410
359
  positionMenu();
411
360
  return () => {
412
361
  if (rootElement !== null) {
413
362
  rootElement.removeAttribute('aria-controls');
414
363
  }
415
-
416
364
  const containerDiv = anchorElementRef.current;
417
-
418
365
  if (containerDiv !== null && containerDiv.isConnected) {
419
366
  containerDiv.remove();
420
367
  }
@@ -428,7 +375,7 @@ function useMenuAnchorRef(resolution, setResolution, className) {
428
375
  }
429
376
  }
430
377
  }, [resolution, setResolution]);
431
- useDynamicPositioning$1(resolution, anchorElementRef.current, positionMenu, onVisibilityChange);
378
+ useDynamicPositioning(resolution, anchorElementRef.current, positionMenu, onVisibilityChange);
432
379
  return anchorElementRef;
433
380
  }
434
381
 
@@ -440,166 +387,90 @@ function useMenuAnchorRef(resolution, setResolution, className) {
440
387
  *
441
388
  */
442
389
  const PUNCTUATION = '\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%\'"~=<>_:;';
443
-
444
390
  function getTextUpToAnchor(selection) {
445
391
  const anchor = selection.anchor;
446
-
447
392
  if (anchor.type !== 'text') {
448
393
  return null;
449
394
  }
450
-
451
395
  const anchorNode = anchor.getNode();
452
-
453
396
  if (!anchorNode.isSimpleText()) {
454
397
  return null;
455
398
  }
456
-
457
399
  const anchorOffset = anchor.offset;
458
400
  return anchorNode.getTextContent().slice(0, anchorOffset);
459
401
  }
460
-
461
- function tryToPositionRange(leadOffset, range) {
462
- const domSelection = window.getSelection();
463
-
402
+ function tryToPositionRange(leadOffset, range, editorWindow) {
403
+ const domSelection = editorWindow.getSelection();
464
404
  if (domSelection === null || !domSelection.isCollapsed) {
465
405
  return false;
466
406
  }
467
-
468
407
  const anchorNode = domSelection.anchorNode;
469
408
  const startOffset = leadOffset;
470
409
  const endOffset = domSelection.anchorOffset;
471
-
472
410
  if (anchorNode == null || endOffset == null) {
473
411
  return false;
474
412
  }
475
-
476
413
  try {
477
414
  range.setStart(anchorNode, startOffset);
478
415
  range.setEnd(anchorNode, endOffset);
479
416
  } catch (error) {
480
417
  return false;
481
418
  }
482
-
483
419
  return true;
484
420
  }
485
-
486
421
  function getQueryTextForSearch(editor) {
487
422
  let text = null;
488
423
  editor.getEditorState().read(() => {
489
424
  const selection = lexical.$getSelection();
490
-
491
425
  if (!lexical.$isRangeSelection(selection)) {
492
426
  return;
493
427
  }
494
-
495
428
  text = getTextUpToAnchor(selection);
496
429
  });
497
430
  return text;
498
431
  }
499
-
500
432
  function isSelectionOnEntityBoundary(editor, offset) {
501
433
  if (offset !== 0) {
502
434
  return false;
503
435
  }
504
-
505
436
  return editor.getEditorState().read(() => {
506
437
  const selection = lexical.$getSelection();
507
-
508
438
  if (lexical.$isRangeSelection(selection)) {
509
439
  const anchor = selection.anchor;
510
440
  const anchorNode = anchor.getNode();
511
441
  const prevSibling = anchorNode.getPreviousSibling();
512
442
  return lexical.$isTextNode(prevSibling) && prevSibling.isTextEntity();
513
443
  }
514
-
515
444
  return false;
516
445
  });
517
446
  }
518
-
519
447
  function startTransition(callback) {
520
448
  if (React.startTransition) {
521
449
  React.startTransition(callback);
522
450
  } else {
523
451
  callback();
524
452
  }
525
- } // Got from https://stackoverflow.com/a/42543908/2013580
526
-
453
+ }
527
454
 
455
+ // Got from https://stackoverflow.com/a/42543908/2013580
528
456
  function getScrollParent(element, includeHidden) {
529
457
  let style = getComputedStyle(element);
530
458
  const excludeStaticParent = style.position === 'absolute';
531
459
  const overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;
532
-
533
460
  if (style.position === 'fixed') {
534
461
  return document.body;
535
462
  }
536
-
537
463
  for (let parent = element; parent = parent.parentElement;) {
538
464
  style = getComputedStyle(parent);
539
-
540
465
  if (excludeStaticParent && style.position === 'static') {
541
466
  continue;
542
467
  }
543
-
544
468
  if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) {
545
469
  return parent;
546
470
  }
547
471
  }
548
-
549
472
  return document.body;
550
473
  }
551
-
552
- function isTriggerVisibleInNearestScrollContainer(targetElement, containerElement) {
553
- const tRect = targetElement.getBoundingClientRect();
554
- const cRect = containerElement.getBoundingClientRect();
555
- return tRect.top > cRect.top && tRect.top < cRect.bottom;
556
- } // Reposition the menu on scroll, window resize, and element resize.
557
-
558
-
559
- function useDynamicPositioning(resolution, targetElement, onReposition, onVisibilityChange) {
560
- const [editor] = LexicalComposerContext.useLexicalComposerContext();
561
- React.useEffect(() => {
562
- if (targetElement != null && resolution != null) {
563
- const rootElement = editor.getRootElement();
564
- const rootScrollParent = rootElement != null ? getScrollParent(rootElement, false) : document.body;
565
- let ticking = false;
566
- let previousIsInView = isTriggerVisibleInNearestScrollContainer(targetElement, rootScrollParent);
567
-
568
- const handleScroll = function () {
569
- if (!ticking) {
570
- window.requestAnimationFrame(function () {
571
- onReposition();
572
- ticking = false;
573
- });
574
- ticking = true;
575
- }
576
-
577
- const isInView = isTriggerVisibleInNearestScrollContainer(targetElement, rootScrollParent);
578
-
579
- if (isInView !== previousIsInView) {
580
- previousIsInView = isInView;
581
-
582
- if (onVisibilityChange != null) {
583
- onVisibilityChange(isInView);
584
- }
585
- }
586
- };
587
-
588
- const resizeObserver = new ResizeObserver(onReposition);
589
- window.addEventListener('resize', onReposition);
590
- document.addEventListener('scroll', handleScroll, {
591
- capture: true,
592
- passive: true
593
- });
594
- resizeObserver.observe(targetElement);
595
- return () => {
596
- resizeObserver.unobserve(targetElement);
597
- window.removeEventListener('resize', onReposition);
598
- document.removeEventListener('scroll', handleScroll);
599
- };
600
- }
601
- }, [targetElement, editor, onVisibilityChange, onReposition, resolution]);
602
- }
603
474
  const SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND = lexical.createCommand('SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND');
604
475
  function useBasicTypeaheadTriggerMatch(trigger, {
605
476
  minLength = 1,
@@ -609,11 +480,9 @@ function useBasicTypeaheadTriggerMatch(trigger, {
609
480
  const validChars = '[^' + trigger + PUNCTUATION + '\\s]';
610
481
  const TypeaheadTriggerRegex = new RegExp('(^|\\s|\\()(' + '[' + trigger + ']' + '((?:' + validChars + '){0,' + maxLength + '})' + ')$');
611
482
  const match = TypeaheadTriggerRegex.exec(text);
612
-
613
483
  if (match !== null) {
614
484
  const maybeLeadingWhitespace = match[1];
615
485
  const matchingString = match[3];
616
-
617
486
  if (matchingString.length >= minLength) {
618
487
  return {
619
488
  leadOffset: match.index + maybeLeadingWhitespace.length,
@@ -622,7 +491,6 @@ function useBasicTypeaheadTriggerMatch(trigger, {
622
491
  };
623
492
  }
624
493
  }
625
-
626
494
  return null;
627
495
  }, [maxLength, minLength, trigger]);
628
496
  }
@@ -634,21 +502,20 @@ function LexicalTypeaheadMenuPlugin({
634
502
  onClose,
635
503
  menuRenderFn,
636
504
  triggerFn,
637
- anchorClassName
505
+ anchorClassName,
506
+ commandPriority = lexical.COMMAND_PRIORITY_LOW
638
507
  }) {
639
508
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
640
509
  const [resolution, setResolution] = React.useState(null);
641
510
  const anchorElementRef = useMenuAnchorRef(resolution, setResolution, anchorClassName);
642
511
  const closeTypeahead = React.useCallback(() => {
643
512
  setResolution(null);
644
-
645
513
  if (onClose != null && resolution !== null) {
646
514
  onClose();
647
515
  }
648
516
  }, [onClose, resolution]);
649
517
  const openTypeahead = React.useCallback(res => {
650
518
  setResolution(res);
651
-
652
519
  if (onOpen != null && resolution === null) {
653
520
  onOpen(res);
654
521
  }
@@ -656,21 +523,18 @@ function LexicalTypeaheadMenuPlugin({
656
523
  React.useEffect(() => {
657
524
  const updateListener = () => {
658
525
  editor.getEditorState().read(() => {
659
- const range = document.createRange();
526
+ const editorWindow = editor._window || window;
527
+ const range = editorWindow.document.createRange();
660
528
  const selection = lexical.$getSelection();
661
529
  const text = getQueryTextForSearch(editor);
662
-
663
530
  if (!lexical.$isRangeSelection(selection) || !selection.isCollapsed() || text === null || range === null) {
664
531
  closeTypeahead();
665
532
  return;
666
533
  }
667
-
668
534
  const match = triggerFn(text, editor);
669
535
  onQueryChange(match ? match.matchingString : null);
670
-
671
536
  if (match !== null && !isSelectionOnEntityBoundary(editor, match.leadOffset)) {
672
- const isRangePositioned = tryToPositionRange(match.leadOffset, range);
673
-
537
+ const isRangePositioned = tryToPositionRange(match.leadOffset, range, editorWindow);
674
538
  if (isRangePositioned !== null) {
675
539
  startTransition(() => openTypeahead({
676
540
  getRect: () => range.getBoundingClientRect(),
@@ -679,11 +543,9 @@ function LexicalTypeaheadMenuPlugin({
679
543
  return;
680
544
  }
681
545
  }
682
-
683
546
  closeTypeahead();
684
547
  });
685
548
  };
686
-
687
549
  const removeUpdateListener = editor.registerUpdateListener(updateListener);
688
550
  return () => {
689
551
  removeUpdateListener();
@@ -697,7 +559,8 @@ function LexicalTypeaheadMenuPlugin({
697
559
  options: options,
698
560
  menuRenderFn: menuRenderFn,
699
561
  shouldSplitNodeWithQuery: true,
700
- onSelectOption: onSelectOption
562
+ onSelectOption: onSelectOption,
563
+ commandPriority: commandPriority
701
564
  });
702
565
  }
703
566