@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,131 +46,105 @@ 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(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
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
 
147
+ // Reposition the menu on scroll, window resize, and element resize.
173
148
  function useDynamicPositioning(resolution, targetElement, onReposition, onVisibilityChange) {
174
149
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
175
150
  React.useEffect(() => {
@@ -178,7 +153,6 @@ function useDynamicPositioning(resolution, targetElement, onReposition, onVisibi
178
153
  const rootScrollParent = rootElement != null ? getScrollParent(rootElement, false) : document.body;
179
154
  let ticking = false;
180
155
  let previousIsInView = isTriggerVisibleInNearestScrollContainer(targetElement, rootScrollParent);
181
-
182
156
  const handleScroll = function () {
183
157
  if (!ticking) {
184
158
  window.requestAnimationFrame(function () {
@@ -187,18 +161,14 @@ function useDynamicPositioning(resolution, targetElement, onReposition, onVisibi
187
161
  });
188
162
  ticking = true;
189
163
  }
190
-
191
164
  const isInView = isTriggerVisibleInNearestScrollContainer(targetElement, rootScrollParent);
192
-
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(resolution, targetElement, onReposition, onVisibi
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, {
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
  }
@@ -439,7 +386,6 @@ function useMenuAnchorRef(resolution, setResolution, className) {
439
386
  * LICENSE file in the root directory of this source tree.
440
387
  *
441
388
  */
442
-
443
389
  function startTransition(callback) {
444
390
  if (React.startTransition) {
445
391
  React.startTransition(callback);
@@ -447,7 +393,6 @@ function startTransition(callback) {
447
393
  callback();
448
394
  }
449
395
  }
450
-
451
396
  function LexicalNodeMenuPlugin({
452
397
  options,
453
398
  nodeKey,
@@ -455,21 +400,20 @@ function LexicalNodeMenuPlugin({
455
400
  onOpen,
456
401
  onSelectOption,
457
402
  menuRenderFn,
458
- anchorClassName
403
+ anchorClassName,
404
+ commandPriority = lexical.COMMAND_PRIORITY_LOW
459
405
  }) {
460
406
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
461
407
  const [resolution, setResolution] = React.useState(null);
462
408
  const anchorElementRef = useMenuAnchorRef(resolution, setResolution, anchorClassName);
463
409
  const closeNodeMenu = React.useCallback(() => {
464
410
  setResolution(null);
465
-
466
411
  if (onClose != null && resolution !== null) {
467
412
  onClose();
468
413
  }
469
414
  }, [onClose, resolution]);
470
415
  const openNodeMenu = React.useCallback(res => {
471
416
  setResolution(res);
472
-
473
417
  if (onOpen != null && resolution === null) {
474
418
  onOpen(res);
475
419
  }
@@ -479,7 +423,6 @@ function LexicalNodeMenuPlugin({
479
423
  editor.update(() => {
480
424
  const node = lexical.$getNodeByKey(nodeKey);
481
425
  const domElement = editor.getElementByKey(nodeKey);
482
-
483
426
  if (node != null && domElement != null) {
484
427
  if (resolution == null) {
485
428
  startTransition(() => openNodeMenu({
@@ -513,7 +456,8 @@ function LexicalNodeMenuPlugin({
513
456
  anchorElementRef: anchorElementRef,
514
457
  options: options,
515
458
  menuRenderFn: menuRenderFn,
516
- onSelectOption: onSelectOption
459
+ onSelectOption: onSelectOption,
460
+ commandPriority: commandPriority
517
461
  });
518
462
  }
519
463
 
@@ -4,18 +4,18 @@
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 h=require("@lexical/react/LexicalComposerContext"),r=require("lexical"),w=require("react"),x=require("@lexical/utils"),y="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?w.useLayoutEffect:w.useEffect;class z{constructor(c){this.key=c;this.ref={current:null};this.setRefElement=this.setRefElement.bind(this)}setRefElement(c){this.ref={current:c}}}
8
- let A=c=>{const a=document.getElementById("typeahead-menu");if(a){var d=a.getBoundingClientRect();d.top+d.height>window.innerHeight&&a.scrollIntoView({block:"center"});0>d.top&&a.scrollIntoView({block:"center"});c.scrollIntoView({block:"nearest"})}};
9
- function B(c){var a=r.$getSelection();if(!r.$isRangeSelection(a)||!a.isCollapsed())return null;var d=a.anchor;if("text"!==d.type)return null;a=d.getNode();if(!a.isSimpleText())return null;d=d.offset;let g=a.getTextContent().slice(0,d);var f=c.matchingString;c=c.replaceableString.length;for(let p=c;p<=f.length;p++)g.substr(-p)===f.substr(0,p)&&(c=p);c=d-c;if(0>c)return null;let t;0===c?[t]=a.splitText(d):[,t]=a.splitText(c,d);return t}
10
- function C(c,a){let d=getComputedStyle(c),g="absolute"===d.position;a=a?/(auto|scroll|hidden)/:/(auto|scroll)/;if("fixed"===d.position)return document.body;for(;c=c.parentElement;)if(d=getComputedStyle(c),(!g||"static"!==d.position)&&a.test(d.overflow+d.overflowY+d.overflowX))return c;return document.body}function D(c,a){c=c.getBoundingClientRect();a=a.getBoundingClientRect();return c.top>a.top&&c.top<a.bottom}
11
- function E(c,a,d,g){let [f]=h.useLexicalComposerContext();w.useEffect(()=>{if(null!=a&&null!=c){let t=f.getRootElement(),p=null!=t?C(t,!1):document.body,k=!1,b=D(a,p),m=function(){k||(window.requestAnimationFrame(function(){d();k=!1}),k=!0);const q=D(a,p);q!==b&&(b=q,null!=g&&g(q))},n=new ResizeObserver(d);window.addEventListener("resize",d);document.addEventListener("scroll",m,{capture:!0,passive:!0});n.observe(a);return()=>{n.unobserve(a);window.removeEventListener("resize",d);document.removeEventListener("scroll",
12
- m)}}},[a,f,g,d,c])}let F=r.createCommand("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");
13
- function G({close:c,editor:a,anchorElementRef:d,resolution:g,options:f,menuRenderFn:t,onSelectOption:p,shouldSplitNodeWithQuery:k=!1}){let [b,m]=w.useState(null);w.useEffect(()=>{m(0)},[g.match&&g.match.matchingString]);let n=w.useCallback(e=>{a.update(()=>{const l=null!=g.match&&k?B(g.match):null;p(e,l,c,g.match?g.match.matchingString:"")})},[a,k,g.match,p,c]),q=w.useCallback(e=>{const l=a.getRootElement();null!==l&&(l.setAttribute("aria-activedescendant","typeahead-item-"+e),m(e))},[a]);w.useEffect(()=>
14
- ()=>{let e=a.getRootElement();null!==e&&e.removeAttribute("aria-activedescendant")},[a]);y(()=>{null===f?m(null):null===b&&q(0)},[f,b,q]);w.useEffect(()=>x.mergeRegister(a.registerCommand(F,({option:e})=>e.ref&&null!=e.ref.current?(A(e.ref.current),!0):!1,r.COMMAND_PRIORITY_LOW)),[a,q]);w.useEffect(()=>x.mergeRegister(a.registerCommand(r.KEY_ARROW_DOWN_COMMAND,e=>{if(null!==f&&f.length&&null!==b){let l=b!==f.length-1?b+1:0;q(l);let v=f[l];null!=v.ref&&v.ref.current&&a.dispatchCommand(F,{index:l,option:v});
15
- e.preventDefault();e.stopImmediatePropagation()}return!0},r.COMMAND_PRIORITY_LOW),a.registerCommand(r.KEY_ARROW_UP_COMMAND,e=>{if(null!==f&&f.length&&null!==b){var l=0!==b?b-1:f.length-1;q(l);l=f[l];null!=l.ref&&l.ref.current&&A(l.ref.current);e.preventDefault();e.stopImmediatePropagation()}return!0},r.COMMAND_PRIORITY_LOW),a.registerCommand(r.KEY_ESCAPE_COMMAND,e=>{e.preventDefault();e.stopImmediatePropagation();c();return!0},r.COMMAND_PRIORITY_LOW),a.registerCommand(r.KEY_TAB_COMMAND,e=>{if(null===
16
- f||null===b||null==f[b])return!1;e.preventDefault();e.stopImmediatePropagation();n(f[b]);return!0},r.COMMAND_PRIORITY_LOW),a.registerCommand(r.KEY_ENTER_COMMAND,e=>{if(null===f||null===b||null==f[b])return!1;null!==e&&(e.preventDefault(),e.stopImmediatePropagation());n(f[b]);return!0},r.COMMAND_PRIORITY_LOW)),[n,c,a,f,b,q]);let u=w.useMemo(()=>({options:f,selectOptionAndCleanUp:n,selectedIndex:b,setHighlightedIndex:m}),[n,b,f]);return t(d,u,g.match?g.match.matchingString:"")}
17
- function H(c,a,d){let [g]=h.useLexicalComposerContext(),f=w.useRef(document.createElement("div")),t=w.useCallback(()=>{const k=g.getRootElement(),b=f.current;var m=b.firstChild;if(null!==k&&null!==c){const {left:q,top:u,width:e,height:l}=c.getRect();b.style.top=`${u+window.pageYOffset}px`;b.style.left=`${q+window.pageXOffset}px`;b.style.height=`${l}px`;b.style.width=`${e}px`;if(null!==m){var n=m.getBoundingClientRect();m=n.height;n=n.width;const v=k.getBoundingClientRect();q+n>v.right&&(b.style.left=
18
- `${v.right-n+window.pageXOffset}px`);(u+m>window.innerHeight||u+m>v.bottom)&&u-v.top>m&&(b.style.top=`${u-m+window.pageYOffset-(l+10)}px`)}b.isConnected||(null!=d&&(b.className=d),b.setAttribute("aria-label","Typeahead menu"),b.setAttribute("id","typeahead-menu"),b.setAttribute("role","listbox"),b.style.display="block",b.style.position="absolute",document.body.append(b));f.current=b;k.setAttribute("aria-controls","typeahead-menu")}},[g,c,d]);w.useEffect(()=>{let k=g.getRootElement();if(null!==c)return t(),
19
- ()=>{null!==k&&k.removeAttribute("aria-controls");let b=f.current;null!==b&&b.isConnected&&b.remove()}},[g,t,c]);let p=w.useCallback(k=>{null!==c&&(k||a(null))},[c,a]);E(c,f.current,t,p);return f}function I(c){w.startTransition?w.startTransition(c):c()}
20
- exports.LexicalNodeMenuPlugin=function({options:c,nodeKey:a,onClose:d,onOpen:g,onSelectOption:f,menuRenderFn:t,anchorClassName:p}){let [k]=h.useLexicalComposerContext(),[b,m]=w.useState(null);p=H(b,m,p);let n=w.useCallback(()=>{m(null);null!=d&&null!==b&&d()},[d,b]),q=w.useCallback(e=>{m(e);null!=g&&null===b&&g(e)},[g,b]),u=w.useCallback(()=>{a?k.update(()=>{const e=r.$getNodeByKey(a),l=k.getElementByKey(a);null!=e&&null!=l&&null==b&&I(()=>q({getRect:()=>l.getBoundingClientRect()}))}):null==a&&null!=
21
- b&&n()},[n,k,a,q,b]);w.useEffect(()=>{u()},[u,a]);w.useEffect(()=>{if(null!=a)return k.registerUpdateListener(({dirtyElements:e})=>{e.get(a)&&u()})},[k,u,a]);return null===b||null===k?null:w.createElement(G,{close:n,resolution:b,editor:k,anchorElementRef:p,options:c,menuRenderFn:t,onSelectOption:f})};exports.MenuOption=z
7
+ 'use strict';var k=require("@lexical/react/LexicalComposerContext"),u=require("lexical"),w=require("react"),y=require("@lexical/utils"),z="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?w.useLayoutEffect:w.useEffect;class A{constructor(b){this.key=b;this.ref={current:null};this.setRefElement=this.setRefElement.bind(this)}setRefElement(b){this.ref={current:b}}}
8
+ let B=b=>{const a=document.getElementById("typeahead-menu");if(a){var f=a.getBoundingClientRect();f.top+f.height>window.innerHeight&&a.scrollIntoView({block:"center"});0>f.top&&a.scrollIntoView({block:"center"});b.scrollIntoView({block:"nearest"})}};
9
+ function C(b){var a=u.$getSelection();if(!u.$isRangeSelection(a)||!a.isCollapsed())return null;var f=a.anchor;if("text"!==f.type)return null;a=f.getNode();if(!a.isSimpleText())return null;f=f.offset;let h=a.getTextContent().slice(0,f);var g=b.matchingString;b=b.replaceableString.length;for(let m=b;m<=g.length;m++)h.substr(-m)===g.substr(0,m)&&(b=m);b=f-b;if(0>b)return null;let t;0===b?[t]=a.splitText(f):[,t]=a.splitText(b,f);return t}
10
+ function D(b,a){let f=getComputedStyle(b),h="absolute"===f.position;a=a?/(auto|scroll|hidden)/:/(auto|scroll)/;if("fixed"===f.position)return document.body;for(;b=b.parentElement;)if(f=getComputedStyle(b),(!h||"static"!==f.position)&&a.test(f.overflow+f.overflowY+f.overflowX))return b;return document.body}function E(b,a){b=b.getBoundingClientRect();a=a.getBoundingClientRect();return b.top>a.top&&b.top<a.bottom}
11
+ function F(b,a,f,h){let [g]=k.useLexicalComposerContext();w.useEffect(()=>{if(null!=a&&null!=b){let t=g.getRootElement(),m=null!=t?D(t,!1):document.body,n=!1,c=E(a,m),d=function(){n||(window.requestAnimationFrame(function(){f();n=!1}),n=!0);const q=E(a,m);q!==c&&(c=q,null!=h&&h(q))},p=new ResizeObserver(f);window.addEventListener("resize",f);document.addEventListener("scroll",d,{capture:!0,passive:!0});p.observe(a);return()=>{p.unobserve(a);window.removeEventListener("resize",f);document.removeEventListener("scroll",
12
+ d,!0)}}},[a,g,h,f,b])}let G=u.createCommand("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");
13
+ function H({close:b,editor:a,anchorElementRef:f,resolution:h,options:g,menuRenderFn:t,onSelectOption:m,shouldSplitNodeWithQuery:n=!1,commandPriority:c=u.COMMAND_PRIORITY_LOW}){let [d,p]=w.useState(null);w.useEffect(()=>{p(0)},[h.match&&h.match.matchingString]);let q=w.useCallback(e=>{a.update(()=>{const l=null!=h.match&&n?C(h.match):null;m(e,l,b,h.match?h.match.matchingString:"")})},[a,n,h.match,m,b]),r=w.useCallback(e=>{const l=a.getRootElement();null!==l&&(l.setAttribute("aria-activedescendant",
14
+ "typeahead-item-"+e),p(e))},[a]);w.useEffect(()=>()=>{let e=a.getRootElement();null!==e&&e.removeAttribute("aria-activedescendant")},[a]);z(()=>{null===g?p(null):null===d&&r(0)},[g,d,r]);w.useEffect(()=>y.mergeRegister(a.registerCommand(G,({option:e})=>e.ref&&null!=e.ref.current?(B(e.ref.current),!0):!1,c)),[a,r,c]);w.useEffect(()=>y.mergeRegister(a.registerCommand(u.KEY_ARROW_DOWN_COMMAND,e=>{if(null!==g&&g.length&&null!==d){let l=d!==g.length-1?d+1:0;r(l);let x=g[l];null!=x.ref&&x.ref.current&&
15
+ a.dispatchCommand(G,{index:l,option:x});e.preventDefault();e.stopImmediatePropagation()}return!0},c),a.registerCommand(u.KEY_ARROW_UP_COMMAND,e=>{if(null!==g&&g.length&&null!==d){var l=0!==d?d-1:g.length-1;r(l);l=g[l];null!=l.ref&&l.ref.current&&B(l.ref.current);e.preventDefault();e.stopImmediatePropagation()}return!0},c),a.registerCommand(u.KEY_ESCAPE_COMMAND,e=>{e.preventDefault();e.stopImmediatePropagation();b();return!0},c),a.registerCommand(u.KEY_TAB_COMMAND,e=>{if(null===g||null===d||null==
16
+ g[d])return!1;e.preventDefault();e.stopImmediatePropagation();q(g[d]);return!0},c),a.registerCommand(u.KEY_ENTER_COMMAND,e=>{if(null===g||null===d||null==g[d])return!1;null!==e&&(e.preventDefault(),e.stopImmediatePropagation());q(g[d]);return!0},c)),[q,b,a,g,d,r,c]);let v=w.useMemo(()=>({options:g,selectOptionAndCleanUp:q,selectedIndex:d,setHighlightedIndex:p}),[q,d,g]);return t(f,v,h.match?h.match.matchingString:"")}
17
+ function I(b,a,f){let [h]=k.useLexicalComposerContext(),g=w.useRef(document.createElement("div")),t=w.useCallback(()=>{g.current.style.top=g.current.style.bottom;const n=h.getRootElement(),c=g.current;var d=c.firstChild;if(null!==n&&null!==b){const {left:q,top:r,width:v,height:e}=b.getRect();c.style.top=`${r+window.pageYOffset+g.current.offsetHeight+3}px`;c.style.left=`${q+window.pageXOffset}px`;c.style.height=`${e}px`;c.style.width=`${v}px`;if(null!==d){d.style.top=`${r}`;var p=d.getBoundingClientRect();
18
+ d=p.height;p=p.width;const l=n.getBoundingClientRect();q+p>l.right&&(c.style.left=`${l.right-p+window.pageXOffset}px`);(r+d>window.innerHeight||r+d>l.bottom)&&r-l.top>d&&(c.style.top=`${r-d+window.pageYOffset-e}px`)}c.isConnected||(null!=f&&(c.className=f),c.setAttribute("aria-label","Typeahead menu"),c.setAttribute("id","typeahead-menu"),c.setAttribute("role","listbox"),c.style.display="block",c.style.position="absolute",document.body.append(c));g.current=c;n.setAttribute("aria-controls","typeahead-menu")}},
19
+ [h,b,f]);w.useEffect(()=>{let n=h.getRootElement();if(null!==b)return t(),()=>{null!==n&&n.removeAttribute("aria-controls");let c=g.current;null!==c&&c.isConnected&&c.remove()}},[h,t,b]);let m=w.useCallback(n=>{null!==b&&(n||a(null))},[b,a]);F(b,g.current,t,m);return g}function J(b){w.startTransition?w.startTransition(b):b()}
20
+ exports.LexicalNodeMenuPlugin=function({options:b,nodeKey:a,onClose:f,onOpen:h,onSelectOption:g,menuRenderFn:t,anchorClassName:m,commandPriority:n=u.COMMAND_PRIORITY_LOW}){let [c]=k.useLexicalComposerContext(),[d,p]=w.useState(null);m=I(d,p,m);let q=w.useCallback(()=>{p(null);null!=f&&null!==d&&f()},[f,d]),r=w.useCallback(e=>{p(e);null!=h&&null===d&&h(e)},[h,d]),v=w.useCallback(()=>{a?c.update(()=>{const e=u.$getNodeByKey(a),l=c.getElementByKey(a);null!=e&&null!=l&&null==d&&J(()=>r({getRect:()=>l.getBoundingClientRect()}))}):
21
+ null==a&&null!=d&&q()},[q,c,a,r,d]);w.useEffect(()=>{v()},[v,a]);w.useEffect(()=>{if(null!=a)return c.registerUpdateListener(({dirtyElements:e})=>{e.get(a)&&v()})},[c,v,a]);return null===d||null===c?null:w.createElement(H,{close:q,resolution:d,editor:c,anchorElementRef:m,options:b,menuRenderFn:t,onSelectOption:g,commandPriority:n})};exports.MenuOption=A
@@ -16,6 +16,7 @@ var react = require('react');
16
16
  * LICENSE file in the root directory of this source tree.
17
17
  *
18
18
  */
19
+
19
20
  const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
20
21
 
21
22
  /**
@@ -53,7 +54,6 @@ function OnChangePlugin({
53
54
  if (ignoreSelectionChange && dirtyElements.size === 0 && dirtyLeaves.size === 0 || ignoreHistoryMergeTagChange && tags.has('history-merge') || prevEditorState.isEmpty()) {
54
55
  return;
55
56
  }
56
-
57
57
  onChange(editorState, editor, tags);
58
58
  });
59
59
  }
@@ -22,6 +22,7 @@ var plainText = require('@lexical/plain-text');
22
22
  * LICENSE file in the root directory of this source tree.
23
23
  *
24
24
  */
25
+
25
26
  const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
26
27
 
27
28
  /**
@@ -41,12 +42,10 @@ var useLayoutEffect = useLayoutEffectImpl;
41
42
  * LICENSE file in the root directory of this source tree.
42
43
  *
43
44
  */
44
-
45
45
  function canShowPlaceholderFromCurrentEditorState(editor) {
46
46
  const currentCanShowPlaceholder = editor.getEditorState().read(text.$canShowPlaceholderCurry(editor.isComposing()));
47
47
  return currentCanShowPlaceholder;
48
48
  }
49
-
50
49
  function useCanShowPlaceholder(editor) {
51
50
  const [canShowPlaceholder, setCanShowPlaceholder] = React.useState(() => canShowPlaceholderFromCurrentEditorState(editor));
52
51
  useLayoutEffect(() => {
@@ -54,7 +53,6 @@ function useCanShowPlaceholder(editor) {
54
53
  const currentCanShowPlaceholder = canShowPlaceholderFromCurrentEditorState(editor);
55
54
  setCanShowPlaceholder(currentCanShowPlaceholder);
56
55
  }
57
-
58
56
  resetCanShowPlaceholder();
59
57
  return utils.mergeRegister(editor.registerUpdateListener(() => {
60
58
  resetCanShowPlaceholder();
@@ -73,8 +71,9 @@ function useCanShowPlaceholder(editor) {
73
71
  *
74
72
  */
75
73
  function useDecorators(editor, ErrorBoundary) {
76
- const [decorators, setDecorators] = React.useState(() => editor.getDecorators()); // Subscribe to changes
74
+ const [decorators, setDecorators] = React.useState(() => editor.getDecorators());
77
75
 
76
+ // Subscribe to changes
78
77
  useLayoutEffect(() => {
79
78
  return editor.registerDecoratorListener(nextDecorators => {
80
79
  reactDom.flushSync(() => {
@@ -87,12 +86,12 @@ function useDecorators(editor, ErrorBoundary) {
87
86
  // nothing will be rendered on initial pass. We can get around that by
88
87
  // ensuring that we set the value.
89
88
  setDecorators(editor.getDecorators());
90
- }, [editor]); // Return decorators defined as React Portals
89
+ }, [editor]);
91
90
 
91
+ // Return decorators defined as React Portals
92
92
  return React.useMemo(() => {
93
93
  const decoratedPortals = [];
94
94
  const decoratorKeys = Object.keys(decorators);
95
-
96
95
  for (let i = 0; i < decoratorKeys.length; i++) {
97
96
  const nodeKey = decoratorKeys[i];
98
97
  const reactDecorator = /*#__PURE__*/React.createElement(ErrorBoundary, {
@@ -101,12 +100,10 @@ function useDecorators(editor, ErrorBoundary) {
101
100
  fallback: null
102
101
  }, decorators[nodeKey]));
103
102
  const element = editor.getElementByKey(nodeKey);
104
-
105
103
  if (element !== null) {
106
104
  decoratedPortals.push( /*#__PURE__*/reactDom.createPortal(reactDecorator, element, nodeKey));
107
105
  }
108
106
  }
109
-
110
107
  return decoratedPortals;
111
108
  }, [ErrorBoundary, decorators, editor]);
112
109
  }
@@ -120,7 +117,9 @@ function useDecorators(editor, ErrorBoundary) {
120
117
  */
121
118
  function usePlainTextSetup(editor) {
122
119
  useLayoutEffect(() => {
123
- return utils.mergeRegister(plainText.registerPlainText(editor), dragon.registerDragonSupport(editor)); // We only do this for init
120
+ return utils.mergeRegister(plainText.registerPlainText(editor), dragon.registerDragonSupport(editor));
121
+
122
+ // We only do this for init
124
123
  // eslint-disable-next-line react-hooks/exhaustive-deps
125
124
  }, [editor]);
126
125
  }
@@ -144,18 +143,15 @@ function PlainTextPlugin({
144
143
  content: placeholder
145
144
  }), decorators);
146
145
  }
147
-
148
146
  function Placeholder({
149
147
  content
150
148
  }) {
151
149
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
152
150
  const showPlaceholder = useCanShowPlaceholder(editor);
153
151
  const editable = useLexicalEditable();
154
-
155
152
  if (!showPlaceholder) {
156
153
  return null;
157
154
  }
158
-
159
155
  if (typeof content === 'function') {
160
156
  return content(editable);
161
157
  } else {