@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.
- package/LexicalAutoEmbedPlugin.d.ts +3 -2
- package/LexicalAutoEmbedPlugin.dev.js +4 -14
- package/LexicalAutoEmbedPlugin.prod.js +4 -3
- package/LexicalAutoFocusPlugin.dev.js +0 -1
- package/LexicalAutoLinkPlugin.dev.js +126 -73
- package/LexicalAutoLinkPlugin.prod.js +11 -7
- package/LexicalBlockWithAlignableContents.dev.js +0 -10
- package/LexicalCharacterLimitPlugin.dev.js +7 -46
- package/LexicalCheckListPlugin.dev.js +10 -48
- package/LexicalClearEditorPlugin.dev.js +1 -1
- package/LexicalClickableLinkPlugin.dev.js +2 -20
- package/LexicalCollaborationContext.dev.js +0 -3
- package/LexicalCollaborationPlugin.dev.js +8 -37
- package/LexicalComposer.d.ts +3 -7
- package/LexicalComposer.dev.js +9 -11
- package/LexicalComposer.js.flow +4 -4
- package/LexicalComposer.prod.js +2 -1
- package/LexicalComposerContext.dev.js +0 -6
- package/LexicalContentEditable.dev.js +1 -2
- package/LexicalContextMenuPlugin.d.ts +3 -2
- package/LexicalContextMenuPlugin.dev.js +28 -82
- package/LexicalContextMenuPlugin.prod.js +16 -15
- package/LexicalDecoratorBlockNode.dev.js +0 -6
- package/LexicalEditorRefPlugin.dev.js +0 -3
- package/LexicalHashtagPlugin.dev.js +73 -43
- package/LexicalHorizontalRuleNode.dev.js +0 -21
- package/LexicalHorizontalRulePlugin.dev.js +0 -4
- package/LexicalLinkPlugin.dev.js +4 -10
- package/LexicalListPlugin.dev.js +0 -2
- package/LexicalMarkdownShortcutPlugin.dev.js +2 -2
- package/LexicalNestedComposer.d.ts +2 -2
- package/LexicalNestedComposer.dev.js +18 -16
- package/LexicalNestedComposer.js.flow +7 -2
- package/LexicalNestedComposer.prod.js +4 -3
- package/LexicalNodeEventPlugin.dev.js +2 -6
- package/LexicalNodeMenuPlugin.d.ts +3 -2
- package/LexicalNodeMenuPlugin.dev.js +27 -83
- package/LexicalNodeMenuPlugin.prod.js +15 -15
- package/LexicalOnChangePlugin.dev.js +1 -1
- package/LexicalPlainTextPlugin.dev.js +8 -12
- package/LexicalRichTextPlugin.dev.js +8 -12
- package/LexicalTabIndentationPlugin.dev.js +7 -16
- package/LexicalTableOfContents.dev.js +5 -33
- package/LexicalTablePlugin.dev.js +11 -28
- package/LexicalTreeView.dev.js +14 -79
- package/LexicalTypeaheadMenuPlugin.d.ts +4 -3
- package/LexicalTypeaheadMenuPlugin.dev.js +39 -176
- package/LexicalTypeaheadMenuPlugin.prod.js +19 -20
- package/package.json +19 -19
- package/shared/LexicalMenu.d.ts +3 -2
- package/useLexicalEditable.dev.js +1 -5
- package/useLexicalIsTextContentEmpty.dev.js +1 -0
- package/useLexicalNodeSelection.dev.js +0 -7
- 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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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
|
-
|
|
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 -
|
|
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
|
|
8
|
-
let
|
|
9
|
-
function
|
|
10
|
-
function
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
function
|
|
14
|
-
()=>{let e=a.getRootElement();null!==e&&e.removeAttribute("aria-activedescendant")},[a]);
|
|
15
|
-
e.preventDefault();e.stopImmediatePropagation()}return!0},
|
|
16
|
-
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
()=>{null!==
|
|
20
|
-
exports.LexicalNodeMenuPlugin=function({options:
|
|
21
|
-
|
|
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());
|
|
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]);
|
|
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));
|
|
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 {
|