@lexical/react 0.12.2 → 0.12.3
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
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
9
|
var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
|
|
10
|
+
var lexical = require('lexical');
|
|
10
11
|
var React = require('react');
|
|
11
12
|
var utils = require('@lexical/utils');
|
|
12
|
-
var lexical = require('lexical');
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -18,6 +18,7 @@ var lexical = require('lexical');
|
|
|
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
|
}
|
|
@@ -446,7 +393,8 @@ function LexicalContextMenuPlugin({
|
|
|
446
393
|
onOpen,
|
|
447
394
|
onSelectOption,
|
|
448
395
|
menuRenderFn: contextMenuRenderFn,
|
|
449
|
-
anchorClassName
|
|
396
|
+
anchorClassName,
|
|
397
|
+
commandPriority = lexical.COMMAND_PRIORITY_LOW
|
|
450
398
|
}) {
|
|
451
399
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
452
400
|
const [resolution, setResolution] = React.useState(null);
|
|
@@ -454,14 +402,12 @@ function LexicalContextMenuPlugin({
|
|
|
454
402
|
const anchorElementRef = useMenuAnchorRef(resolution, setResolution, anchorClassName);
|
|
455
403
|
const closeNodeMenu = React.useCallback(() => {
|
|
456
404
|
setResolution(null);
|
|
457
|
-
|
|
458
405
|
if (onClose != null && resolution !== null) {
|
|
459
406
|
onClose();
|
|
460
407
|
}
|
|
461
408
|
}, [onClose, resolution]);
|
|
462
409
|
const openNodeMenu = React.useCallback(res => {
|
|
463
410
|
setResolution(res);
|
|
464
|
-
|
|
465
411
|
if (onOpen != null && resolution === null) {
|
|
466
412
|
onOpen(res);
|
|
467
413
|
}
|
|
@@ -479,7 +425,6 @@ function LexicalContextMenuPlugin({
|
|
|
479
425
|
}, [closeNodeMenu, resolution]);
|
|
480
426
|
React.useEffect(() => {
|
|
481
427
|
const editorElement = editor.getRootElement();
|
|
482
|
-
|
|
483
428
|
if (editorElement) {
|
|
484
429
|
editorElement.addEventListener('contextmenu', handleContextMenu);
|
|
485
430
|
return () => editorElement.removeEventListener('contextmenu', handleContextMenu);
|
|
@@ -500,7 +445,8 @@ function LexicalContextMenuPlugin({
|
|
|
500
445
|
menuRef.current = ref;
|
|
501
446
|
}
|
|
502
447
|
}),
|
|
503
|
-
onSelectOption: onSelectOption
|
|
448
|
+
onSelectOption: onSelectOption,
|
|
449
|
+
commandPriority: commandPriority
|
|
504
450
|
});
|
|
505
451
|
}
|
|
506
452
|
|
|
@@ -4,18 +4,19 @@
|
|
|
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 k=require("@lexical/react/LexicalComposerContext"),
|
|
8
|
-
let
|
|
9
|
-
function
|
|
10
|
-
function
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
function
|
|
14
|
-
()=>{let g=a.getRootElement();null!==g&&g.removeAttribute("aria-activedescendant")},[a]);
|
|
15
|
-
g.preventDefault();g.stopImmediatePropagation()}return!0},
|
|
16
|
-
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
()=>{null!==
|
|
20
|
-
exports.LexicalContextMenuPlugin=function({options:b,onClose:a,onOpen:d,onSelectOption:l,menuRenderFn:
|
|
21
|
-
|
|
7
|
+
'use strict';var k=require("@lexical/react/LexicalComposerContext"),u=require("lexical"),x=require("react"),y=require("@lexical/utils"),z="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?x.useLayoutEffect:x.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 d=a.getBoundingClientRect();d.top+d.height>window.innerHeight&&a.scrollIntoView({block:"center"});0>d.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 d=a.anchor;if("text"!==d.type)return null;a=d.getNode();if(!a.isSimpleText())return null;d=d.offset;let l=a.getTextContent().slice(0,d);var e=b.matchingString;b=b.replaceableString.length;for(let t=b;t<=e.length;t++)l.substr(-t)===e.substr(0,t)&&(b=t);b=d-b;if(0>b)return null;let p;0===b?[p]=a.splitText(d):[,p]=a.splitText(b,d);return p}
|
|
10
|
+
function D(b,a){let d=getComputedStyle(b),l="absolute"===d.position;a=a?/(auto|scroll|hidden)/:/(auto|scroll)/;if("fixed"===d.position)return document.body;for(;b=b.parentElement;)if(d=getComputedStyle(b),(!l||"static"!==d.position)&&a.test(d.overflow+d.overflowY+d.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,d,l){let [e]=k.useLexicalComposerContext();x.useEffect(()=>{if(null!=a&&null!=b){let p=e.getRootElement(),t=null!=p?D(p,!1):document.body,m=!1,c=E(a,t),h=function(){m||(window.requestAnimationFrame(function(){d();m=!1}),m=!0);const q=E(a,t);q!==c&&(c=q,null!=l&&l(q))},n=new ResizeObserver(d);window.addEventListener("resize",d);document.addEventListener("scroll",h,{capture:!0,passive:!0});n.observe(a);return()=>{n.unobserve(a);window.removeEventListener("resize",d);document.removeEventListener("scroll",
|
|
12
|
+
h,!0)}}},[a,e,l,d,b])}let G=u.createCommand("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");
|
|
13
|
+
function H({close:b,editor:a,anchorElementRef:d,resolution:l,options:e,menuRenderFn:p,onSelectOption:t,shouldSplitNodeWithQuery:m=!1,commandPriority:c=u.COMMAND_PRIORITY_LOW}){let [h,n]=x.useState(null);x.useEffect(()=>{n(0)},[l.match&&l.match.matchingString]);let q=x.useCallback(g=>{a.update(()=>{const f=null!=l.match&&m?C(l.match):null;t(g,f,b,l.match?l.match.matchingString:"")})},[a,m,l.match,t,b]),r=x.useCallback(g=>{const f=a.getRootElement();null!==f&&(f.setAttribute("aria-activedescendant",
|
|
14
|
+
"typeahead-item-"+g),n(g))},[a]);x.useEffect(()=>()=>{let g=a.getRootElement();null!==g&&g.removeAttribute("aria-activedescendant")},[a]);z(()=>{null===e?n(null):null===h&&r(0)},[e,h,r]);x.useEffect(()=>y.mergeRegister(a.registerCommand(G,({option:g})=>g.ref&&null!=g.ref.current?(B(g.ref.current),!0):!1,c)),[a,r,c]);x.useEffect(()=>y.mergeRegister(a.registerCommand(u.KEY_ARROW_DOWN_COMMAND,g=>{if(null!==e&&e.length&&null!==h){let f=h!==e.length-1?h+1:0;r(f);let w=e[f];null!=w.ref&&w.ref.current&&
|
|
15
|
+
a.dispatchCommand(G,{index:f,option:w});g.preventDefault();g.stopImmediatePropagation()}return!0},c),a.registerCommand(u.KEY_ARROW_UP_COMMAND,g=>{if(null!==e&&e.length&&null!==h){var f=0!==h?h-1:e.length-1;r(f);f=e[f];null!=f.ref&&f.ref.current&&B(f.ref.current);g.preventDefault();g.stopImmediatePropagation()}return!0},c),a.registerCommand(u.KEY_ESCAPE_COMMAND,g=>{g.preventDefault();g.stopImmediatePropagation();b();return!0},c),a.registerCommand(u.KEY_TAB_COMMAND,g=>{if(null===e||null===h||null==
|
|
16
|
+
e[h])return!1;g.preventDefault();g.stopImmediatePropagation();q(e[h]);return!0},c),a.registerCommand(u.KEY_ENTER_COMMAND,g=>{if(null===e||null===h||null==e[h])return!1;null!==g&&(g.preventDefault(),g.stopImmediatePropagation());q(e[h]);return!0},c)),[q,b,a,e,h,r,c]);let v=x.useMemo(()=>({options:e,selectOptionAndCleanUp:q,selectedIndex:h,setHighlightedIndex:n}),[q,h,e]);return p(d,v,l.match?l.match.matchingString:"")}
|
|
17
|
+
function I(b,a,d){let [l]=k.useLexicalComposerContext(),e=x.useRef(document.createElement("div")),p=x.useCallback(()=>{e.current.style.top=e.current.style.bottom;const m=l.getRootElement(),c=e.current;var h=c.firstChild;if(null!==m&&null!==b){const {left:q,top:r,width:v,height:g}=b.getRect();c.style.top=`${r+window.pageYOffset+e.current.offsetHeight+3}px`;c.style.left=`${q+window.pageXOffset}px`;c.style.height=`${g}px`;c.style.width=`${v}px`;if(null!==h){h.style.top=`${r}`;var n=h.getBoundingClientRect();
|
|
18
|
+
h=n.height;n=n.width;const f=m.getBoundingClientRect();q+n>f.right&&(c.style.left=`${f.right-n+window.pageXOffset}px`);(r+h>window.innerHeight||r+h>f.bottom)&&r-f.top>h&&(c.style.top=`${r-h+window.pageYOffset-g}px`)}c.isConnected||(null!=d&&(c.className=d),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));e.current=c;m.setAttribute("aria-controls","typeahead-menu")}},
|
|
19
|
+
[l,b,d]);x.useEffect(()=>{let m=l.getRootElement();if(null!==b)return p(),()=>{null!==m&&m.removeAttribute("aria-controls");let c=e.current;null!==c&&c.isConnected&&c.remove()}},[l,p,b]);let t=x.useCallback(m=>{null!==b&&(m||a(null))},[b,a]);F(b,e.current,p,t);return e}
|
|
20
|
+
exports.LexicalContextMenuPlugin=function({options:b,onClose:a,onOpen:d,onSelectOption:l,menuRenderFn:e,anchorClassName:p,commandPriority:t=u.COMMAND_PRIORITY_LOW}){let [m]=k.useLexicalComposerContext(),[c,h]=x.useState(null),n=x.useRef(null);p=I(c,h,p);let q=x.useCallback(()=>{h(null);null!=a&&null!==c&&a()},[a,c]),r=x.useCallback(f=>{h(f);null!=d&&null===c&&d(f)},[d,c]),v=x.useCallback(f=>{f.preventDefault();r({getRect:()=>new DOMRect(f.clientX,f.clientY,1,1)})},[r]),g=x.useCallback(f=>{null===
|
|
21
|
+
c||null==n.current||null==f.target||n.current.contains(f.target)||q()},[q,c]);x.useEffect(()=>{let f=m.getRootElement();if(f)return f.addEventListener("contextmenu",v),()=>f.removeEventListener("contextmenu",v)},[m,v]);x.useEffect(()=>{document.addEventListener("click",g);return()=>document.removeEventListener("click",g)},[m,g]);return null===c||null===m?null:x.createElement(H,{close:q,resolution:c,editor:m,anchorElementRef:p,options:b,menuRenderFn:(f,w)=>e(f,w,{setMenuRef:J=>{n.current=J}}),onSelectOption:l,
|
|
22
|
+
commandPriority:t})};exports.MenuOption=A
|
|
@@ -20,7 +20,6 @@ class DecoratorBlockNode extends lexical.DecoratorNode {
|
|
|
20
20
|
super(key);
|
|
21
21
|
this.__format = format || '';
|
|
22
22
|
}
|
|
23
|
-
|
|
24
23
|
exportJSON() {
|
|
25
24
|
return {
|
|
26
25
|
format: this.__format || '',
|
|
@@ -28,24 +27,19 @@ class DecoratorBlockNode extends lexical.DecoratorNode {
|
|
|
28
27
|
version: 1
|
|
29
28
|
};
|
|
30
29
|
}
|
|
31
|
-
|
|
32
30
|
createDOM() {
|
|
33
31
|
return document.createElement('div');
|
|
34
32
|
}
|
|
35
|
-
|
|
36
33
|
updateDOM() {
|
|
37
34
|
return false;
|
|
38
35
|
}
|
|
39
|
-
|
|
40
36
|
setFormat(format) {
|
|
41
37
|
const self = this.getWritable();
|
|
42
38
|
self.__format = format;
|
|
43
39
|
}
|
|
44
|
-
|
|
45
40
|
isInline() {
|
|
46
41
|
return false;
|
|
47
42
|
}
|
|
48
|
-
|
|
49
43
|
}
|
|
50
44
|
function $isDecoratorBlockNode(node) {
|
|
51
45
|
return node instanceof DecoratorBlockNode;
|
|
@@ -15,7 +15,6 @@ var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
|
|
|
15
15
|
* LICENSE file in the root directory of this source tree.
|
|
16
16
|
*
|
|
17
17
|
*/
|
|
18
|
-
|
|
19
18
|
/**
|
|
20
19
|
*
|
|
21
20
|
* Use this plugin to access the editor instance outside of the
|
|
@@ -27,13 +26,11 @@ function EditorRefPlugin({
|
|
|
27
26
|
editorRef
|
|
28
27
|
}) {
|
|
29
28
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
30
|
-
|
|
31
29
|
if (typeof editorRef === 'function') {
|
|
32
30
|
editorRef(editor);
|
|
33
31
|
} else if (typeof editorRef === 'object') {
|
|
34
32
|
editorRef.current = editor;
|
|
35
33
|
}
|
|
36
|
-
|
|
37
34
|
return null;
|
|
38
35
|
}
|
|
39
36
|
|