@lexical/react 0.1.11 → 0.1.12
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/DEPRECATED_useLexical.dev.js +3 -7
- package/DEPRECATED_useLexical.prod.js +1 -1
- package/DEPRECATED_useLexicalAutoFormatter.dev.js +14 -9
- package/DEPRECATED_useLexicalAutoFormatter.prod.js +18 -18
- package/DEPRECATED_useLexicalPlainText.dev.js +33 -27
- package/DEPRECATED_useLexicalPlainText.prod.js +12 -12
- package/DEPRECATED_useLexicalRichText.dev.js +43 -388
- package/DEPRECATED_useLexicalRichText.prod.js +17 -25
- package/LexicalAutoFormatterPlugin.d.ts +9 -0
- package/LexicalAutoFormatterPlugin.dev.js +14 -9
- package/LexicalAutoFormatterPlugin.prod.js +18 -18
- package/LexicalAutoLinkPlugin.d.ts +20 -0
- package/LexicalCharacterLimitPlugin.d.ts +11 -0
- package/LexicalClearEditorPlugin.d.ts +14 -0
- package/LexicalClearEditorPlugin.dev.js +22 -1
- package/LexicalClearEditorPlugin.prod.js +2 -1
- package/LexicalCollaborationPlugin.d.ts +49 -0
- package/LexicalCollaborationPlugin.js.flow +1 -1
- package/LexicalComposer.d.ts +22 -0
- package/LexicalComposer.dev.js +27 -5
- package/LexicalComposer.js.flow +2 -1
- package/LexicalComposer.prod.js +3 -3
- package/LexicalComposerContext.d.ts +24 -0
- package/LexicalComposerContext.js.flow +1 -1
- package/LexicalContentEditable.d.ts +32 -0
- package/LexicalContentEditable.dev.js +22 -1
- package/LexicalContentEditable.prod.js +3 -3
- package/LexicalHashtagPlugin.d.ts +9 -0
- package/LexicalHashtagPlugin.js.flow +0 -10
- package/LexicalHistoryPlugin.d.ts +29 -0
- package/LexicalHorizontalRuleNode.d.ts +23 -0
- package/LexicalLinkPlugin.d.ts +9 -0
- package/LexicalListPlugin.d.ts +9 -0
- package/LexicalNestedComposer.d.ts +20 -0
- package/LexicalOnChangePlugin.d.ts +12 -0
- package/LexicalPlainTextPlugin.d.ts +15 -0
- package/LexicalPlainTextPlugin.dev.js +11 -26
- package/LexicalPlainTextPlugin.prod.js +8 -8
- package/LexicalRichTextPlugin.d.ts +15 -0
- package/LexicalRichTextPlugin.dev.js +24 -390
- package/LexicalRichTextPlugin.prod.js +13 -21
- package/LexicalTablePlugin.d.ts +9 -0
- package/LexicalTreeView.d.ts +17 -0
- package/package.json +6 -5
- package/useLexicalDecoratorMap.d.ts +14 -0
- package/useLexicalIsTextContentEmpty.d.ts +13 -0
- package/useLexicalNodeSelection.d.ts +12 -0
- package/withSubscriptions.d.ts +12 -0
|
@@ -10,6 +10,7 @@ var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
|
|
|
10
10
|
var React = require('react');
|
|
11
11
|
var lexical = require('lexical');
|
|
12
12
|
var reactDom = require('react-dom');
|
|
13
|
+
var clipboard = require('@lexical/clipboard');
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -181,6 +182,10 @@ function $moveCharacter(selection, isHoldingShift, isBackward) {
|
|
|
181
182
|
const isRTL = $isParentElementRTL(selection);
|
|
182
183
|
$moveCaretSelection(selection, isHoldingShift, isBackward ? !isRTL : isRTL, 'character');
|
|
183
184
|
}
|
|
185
|
+
function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
|
|
186
|
+
const possibleNode = lexical.$getDecoratorNode(selection.focus, isBackward);
|
|
187
|
+
return lexical.$isDecoratorNode(possibleNode) && !possibleNode.isIsolated();
|
|
188
|
+
}
|
|
184
189
|
|
|
185
190
|
/**
|
|
186
191
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -190,17 +195,6 @@ function $moveCharacter(selection, isHoldingShift, isBackward) {
|
|
|
190
195
|
*
|
|
191
196
|
*
|
|
192
197
|
*/
|
|
193
|
-
function $insertDataTransferForPlainText(dataTransfer, selection) {
|
|
194
|
-
const text = dataTransfer.getData('text/plain');
|
|
195
|
-
|
|
196
|
-
if (text != null) {
|
|
197
|
-
selection.insertRawText(text);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
|
|
201
|
-
const possibleNode = lexical.$getDecoratorNode(selection.focus, isBackward);
|
|
202
|
-
return lexical.$isDecoratorNode(possibleNode) && !possibleNode.isIsolated();
|
|
203
|
-
}
|
|
204
198
|
function onPasteForPlainText(event, editor) {
|
|
205
199
|
event.preventDefault();
|
|
206
200
|
editor.update(() => {
|
|
@@ -208,7 +202,7 @@ function onPasteForPlainText(event, editor) {
|
|
|
208
202
|
const clipboardData = event.clipboardData;
|
|
209
203
|
|
|
210
204
|
if (clipboardData != null && lexical.$isRangeSelection(selection)) {
|
|
211
|
-
|
|
205
|
+
clipboard.$insertDataTransferForPlainText(clipboardData, selection);
|
|
212
206
|
}
|
|
213
207
|
});
|
|
214
208
|
}
|
|
@@ -230,19 +224,10 @@ function onCopyForPlainText(event, editor) {
|
|
|
230
224
|
|
|
231
225
|
if (selection !== null) {
|
|
232
226
|
if (clipboardData != null) {
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
if (domSelection.isCollapsed) {
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const range = domSelection.getRangeAt(0);
|
|
227
|
+
const htmlString = clipboard.getHtmlContent(editor);
|
|
240
228
|
|
|
241
|
-
if (
|
|
242
|
-
|
|
243
|
-
const frag = range.cloneContents();
|
|
244
|
-
container.appendChild(frag);
|
|
245
|
-
clipboardData.setData('text/html', container.innerHTML);
|
|
229
|
+
if (htmlString !== null) {
|
|
230
|
+
clipboardData.setData('text/html', htmlString);
|
|
246
231
|
}
|
|
247
232
|
|
|
248
233
|
clipboardData.setData('text/plain', selection.getTextContent());
|
|
@@ -404,7 +389,7 @@ function useLexicalDragonSupport(editor) {
|
|
|
404
389
|
*
|
|
405
390
|
*/
|
|
406
391
|
function usePlainTextSetup(editor, initialEditorState) {
|
|
407
|
-
|
|
392
|
+
useLayoutEffect(() => {
|
|
408
393
|
const removeListener = editor.addListener('command', (type, payload) => {
|
|
409
394
|
const selection = lexical.$getSelection();
|
|
410
395
|
|
|
@@ -444,7 +429,7 @@ function usePlainTextSetup(editor, initialEditorState) {
|
|
|
444
429
|
const dataTransfer = eventOrText.dataTransfer;
|
|
445
430
|
|
|
446
431
|
if (dataTransfer != null) {
|
|
447
|
-
|
|
432
|
+
clipboard.$insertDataTransferForPlainText(dataTransfer, selection);
|
|
448
433
|
} else {
|
|
449
434
|
const data = eventOrText.data;
|
|
450
435
|
|
|
@@ -4,15 +4,15 @@
|
|
|
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
|
-
var g=require("@lexical/react/LexicalComposerContext"),h=require("react"),t=require("lexical"),u=require("react-dom");function
|
|
8
|
-
function
|
|
9
|
-
function
|
|
10
|
-
function
|
|
11
|
-
function
|
|
7
|
+
var g=require("@lexical/react/LexicalComposerContext"),h=require("react"),t=require("lexical"),u=require("react-dom"),v=require("@lexical/clipboard");function w(a,d=!0){if(a)return!1;a=t.$getRoot().getTextContent();d&&(a=a.trim());return""===a}
|
|
8
|
+
function x(a){if(!w(a,!1))return!1;a=t.$getRoot().getChildren();const d=a.length;if(1<d)return!1;for(let c=0;c<d;c++){var e=a[c];if(t.$isElementNode(e)){if("paragraph"!==e.__type||0!==e.__indent)return!1;e=e.getChildren();const b=e.length;for(let f=0;f<b;f++)if(!t.$isTextNode(e[c]))return!1}}return!0}function y(a){return()=>x(a)}var z="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?h.useLayoutEffect:h.useEffect;
|
|
9
|
+
function A(a){const [d,e]=h.useState(a.getEditorState().read(y(a.isComposing())));z(()=>a.addListener("update",({editorState:c})=>{const b=a.isComposing();c=c.read(y(b));e(c)}),[a]);return d}function C(a){const [d,e]=h.useState(()=>a.getDecorators());z(()=>a.addListener("decorator",c=>{u.flushSync(()=>{e(c)})}),[a]);return h.useMemo(()=>{const c=[],b=Object.keys(d);for(let p=0;p<b.length;p++){var f=b[p];const r=d[f];f=a.getElementByKey(f);null!==f&&c.push(u.createPortal(r,f))}return c},[d,a])}
|
|
10
|
+
function D(a){a=a.anchor.getNode();return"rtl"===(t.$isRootNode(a)?a:a.getParentOrThrow()).getDirection()}function E(a,d){a=t.$getDecoratorNode(a.focus,d);return t.$isDecoratorNode(a)&&!a.isIsolated()}function F(a,d){a.preventDefault();d.update(()=>{const e=t.$getSelection(),c=a.clipboardData;null!=c&&t.$isRangeSelection(e)&&v.$insertDataTransferForPlainText(c,e)})}function G(a,d){H(a,d);d.update(()=>{const e=t.$getSelection();t.$isRangeSelection(e)&&e.removeText()})}
|
|
11
|
+
function H(a,d){a.preventDefault();d.update(()=>{const e=a.clipboardData,c=t.$getSelection();if(null!==c&&null!=e){const b=v.getHtmlContent(d);null!==b&&e.setData("text/html",b);e.setData("text/plain",c.getTextContent())}})}const I={tag:"history-merge"};
|
|
12
12
|
function J(a,d){if(null!==d)if(void 0===d)a.update(()=>{var e=t.$getRoot();if(null===e.getFirstChild()){const c=t.$createParagraphNode();e.append(c);e=document.activeElement;(null!==t.$getSelection()||null!==e&&e===a.getRootElement())&&c.select()}},I);else if(null!==d)switch(typeof d){case "string":d=a.parseEditorState(d);a.setEditorState(d,I);break;case "object":a.setEditorState(d,I);break;case "function":a.update(d,I)}}
|
|
13
13
|
function K(a){h.useEffect(()=>{const d=e=>{var c=a.getRootElement();if(document.activeElement===c&&(c=e.data,"string"===typeof c)){try{var b=JSON.parse(c)}catch(f){return}if(b&&"nuanria_messaging"===b.protocol&&"request"===b.type&&(b=b.payload)&&"makeChanges"===b.functionId&&(b=b.args)){const [f,p,r,B,L]=b;a.update(()=>{const q=t.$getSelection();if(t.$isRangeSelection(q)){var n=q.anchor;let k=n.getNode(),l=0,m=0;t.$isTextNode(k)&&0<=f&&0<=p&&(l=f,m=f+p,q.setTextNodeRange(k,l,k,m));if(l!==m||""!==
|
|
14
14
|
r)q.insertRawText(r),k=n.getNode();t.$isTextNode(k)&&(l=B,m=B+L,n=k.getTextContentSize(),l=l>n?n:l,m=m>n?n:m,q.setTextNodeRange(k,l,k,m));e.stopImmediatePropagation()}})}}};window.addEventListener("message",d,!0);return()=>{window.removeEventListener("message",d,!0)}},[a])}
|
|
15
|
-
function M(a,d){
|
|
16
|
-
!0;case "insertParagraph":return f.insertLineBreak(),!0;case "indentContent":case "outdentContent":case "insertHorizontalRule":case "insertImage":case "insertTable":case "formatElement":case "formatText":return!0;case "keyArrowLeft":c=b.shiftKey;if(E(f,!0))return b.preventDefault(),b=c,c=
|
|
15
|
+
function M(a,d){z(()=>{const e=a.addListener("command",(c,b)=>{const f=t.$getSelection();if(!t.$isRangeSelection(f))return!1;switch(c){case "deleteCharacter":return f.deleteCharacter(b),!0;case "deleteWord":return f.deleteWord(b),!0;case "deleteLine":return f.deleteLine(b),!0;case "insertText":return"string"===typeof b?f.insertText(b):(c=b.dataTransfer,null!=c?v.$insertDataTransferForPlainText(c,f):(b=b.data)&&f.insertText(b)),!0;case "removeText":return f.removeText(),!0;case "insertLineBreak":return f.insertLineBreak(b),
|
|
16
|
+
!0;case "insertParagraph":return f.insertLineBreak(),!0;case "indentContent":case "outdentContent":case "insertHorizontalRule":case "insertImage":case "insertTable":case "formatElement":case "formatText":return!0;case "keyArrowLeft":c=b.shiftKey;if(E(f,!0))return b.preventDefault(),b=c,c=D(f),f.modify(b?"extend":"move",!c,"character"),!0;break;case "keyArrowRight":c=b.shiftKey;if(E(f,!1))return b.preventDefault(),b=c,c=D(f),f.modify(b?"extend":"move",c,"character"),!0;break;case "keyBackspace":return b.preventDefault(),
|
|
17
17
|
a.execCommand("deleteCharacter",!0);case "keyDelete":return b.preventDefault(),a.execCommand("deleteCharacter",!1);case "keyEnter":return b.preventDefault(),a.execCommand("insertLineBreak");case "copy":return H(b,a),!0;case "cut":return G(b,a),!0;case "paste":return F(b,a),!0;case "drop":case "dragstart":return b.preventDefault(),!0}return!1},0);J(a,d);return e},[a]);K(a)}
|
|
18
|
-
module.exports=function({contentEditable:a,placeholder:d,initialEditorState:e}){const [c]=g.useLexicalComposerContext(),b=
|
|
18
|
+
module.exports=function({contentEditable:a,placeholder:d,initialEditorState:e}){const [c]=g.useLexicalComposerContext(),b=A(c);M(c,e);e=C(c);return h.createElement(h.Fragment,null,a,b&&d,e)};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {EditorState} from 'lexical';
|
|
10
|
+
type InitialEditorStateType = null | string | EditorState | (() => void);
|
|
11
|
+
export default function RichTextPlugin(arg0: {
|
|
12
|
+
contentEditable: React.ReactNode;
|
|
13
|
+
initialEditorState?: InitialEditorStateType;
|
|
14
|
+
placeholder: React.ReactNode;
|
|
15
|
+
}): React.ReactNode;
|
|
@@ -10,6 +10,7 @@ var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
|
|
|
10
10
|
var React = require('react');
|
|
11
11
|
var lexical = require('lexical');
|
|
12
12
|
var reactDom = require('react-dom');
|
|
13
|
+
var clipboard = require('@lexical/clipboard');
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -169,188 +170,6 @@ function useDecorators(editor) {
|
|
|
169
170
|
*
|
|
170
171
|
*/
|
|
171
172
|
|
|
172
|
-
function $cloneWithProperties(node) {
|
|
173
|
-
const latest = node.getLatest();
|
|
174
|
-
const constructor = latest.constructor;
|
|
175
|
-
const clone = constructor.clone(latest);
|
|
176
|
-
clone.__parent = latest.__parent;
|
|
177
|
-
|
|
178
|
-
if (lexical.$isElementNode(latest) && lexical.$isElementNode(clone)) {
|
|
179
|
-
clone.__children = Array.from(latest.__children);
|
|
180
|
-
clone.__format = latest.__format;
|
|
181
|
-
clone.__indent = latest.__indent;
|
|
182
|
-
clone.__dir = latest.__dir;
|
|
183
|
-
} else if (lexical.$isTextNode(latest) && lexical.$isTextNode(clone)) {
|
|
184
|
-
clone.__format = latest.__format;
|
|
185
|
-
clone.__style = latest.__style;
|
|
186
|
-
clone.__mode = latest.__mode;
|
|
187
|
-
clone.__detail = latest.__detail;
|
|
188
|
-
} else if (lexical.$isDecoratorNode(latest) && lexical.$isDecoratorNode(clone)) {
|
|
189
|
-
clone.__state = latest.__state;
|
|
190
|
-
} // $FlowFixMe
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
return clone;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function $getIndexFromPossibleClone(node, parent, nodeMap) {
|
|
197
|
-
const parentClone = nodeMap.get(parent.getKey());
|
|
198
|
-
|
|
199
|
-
if (lexical.$isElementNode(parentClone)) {
|
|
200
|
-
return parentClone.__children.indexOf(node.getKey());
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return node.getIndexWithinParent();
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
function $getParentAvoidingExcludedElements(node) {
|
|
207
|
-
let parent = node.getParent();
|
|
208
|
-
|
|
209
|
-
while (parent !== null && parent.excludeFromCopy()) {
|
|
210
|
-
parent = parent.getParent();
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return parent;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function $copyLeafNodeBranchToRoot(leaf, startingOffset, isLeftSide, range, nodeMap) {
|
|
217
|
-
let node = leaf;
|
|
218
|
-
let offset = startingOffset;
|
|
219
|
-
|
|
220
|
-
while (node !== null) {
|
|
221
|
-
const parent = $getParentAvoidingExcludedElements(node);
|
|
222
|
-
|
|
223
|
-
if (parent === null) {
|
|
224
|
-
break;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if (!lexical.$isElementNode(node) || !node.excludeFromCopy()) {
|
|
228
|
-
const key = node.getKey();
|
|
229
|
-
let clone = nodeMap.get(key);
|
|
230
|
-
const needsClone = clone === undefined;
|
|
231
|
-
|
|
232
|
-
if (needsClone) {
|
|
233
|
-
clone = $cloneWithProperties(node);
|
|
234
|
-
nodeMap.set(key, clone);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (lexical.$isTextNode(clone) && !clone.isSegmented() && !clone.isToken()) {
|
|
238
|
-
clone.__text = clone.__text.slice(isLeftSide ? offset : 0, isLeftSide ? undefined : offset);
|
|
239
|
-
} else if (lexical.$isElementNode(clone)) {
|
|
240
|
-
clone.__children = clone.__children.slice(isLeftSide ? offset : 0, isLeftSide ? undefined : offset + 1);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (lexical.$isRootNode(parent)) {
|
|
244
|
-
if (needsClone) {
|
|
245
|
-
// We only want to collect a range of top level nodes.
|
|
246
|
-
// So if the parent is the root, we know this is a top level.
|
|
247
|
-
range.push(key);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
offset = $getIndexFromPossibleClone(node, parent, nodeMap);
|
|
255
|
-
node = parent;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function $cloneContents(selection) {
|
|
260
|
-
if (!lexical.$isRangeSelection(selection)) {
|
|
261
|
-
{
|
|
262
|
-
throw Error(`TODO`);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const anchor = selection.anchor;
|
|
267
|
-
const focus = selection.focus;
|
|
268
|
-
const anchorOffset = anchor.getCharacterOffset();
|
|
269
|
-
const focusOffset = focus.getCharacterOffset();
|
|
270
|
-
const anchorNode = anchor.getNode();
|
|
271
|
-
const focusNode = focus.getNode();
|
|
272
|
-
const anchorNodeParent = anchorNode.getParentOrThrow(); // Handle a single text node extraction
|
|
273
|
-
|
|
274
|
-
if (anchorNode === focusNode && lexical.$isTextNode(anchorNode) && (anchorNodeParent.canBeEmpty() || anchorNodeParent.getChildrenSize() > 1)) {
|
|
275
|
-
const clonedFirstNode = $cloneWithProperties(anchorNode);
|
|
276
|
-
const isBefore = focusOffset > anchorOffset;
|
|
277
|
-
const startOffset = isBefore ? anchorOffset : focusOffset;
|
|
278
|
-
const endOffset = isBefore ? focusOffset : anchorOffset;
|
|
279
|
-
clonedFirstNode.__text = clonedFirstNode.__text.slice(startOffset, endOffset);
|
|
280
|
-
const key = clonedFirstNode.getKey();
|
|
281
|
-
return {
|
|
282
|
-
nodeMap: [[key, clonedFirstNode]],
|
|
283
|
-
range: [key]
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
const nodes = selection.getNodes();
|
|
288
|
-
|
|
289
|
-
if (nodes.length === 0) {
|
|
290
|
-
return {
|
|
291
|
-
nodeMap: [],
|
|
292
|
-
range: []
|
|
293
|
-
};
|
|
294
|
-
} // Check if we can use the parent of the nodes, if the
|
|
295
|
-
// parent can't be empty, then it's important that we
|
|
296
|
-
// also copy that element node along with its children.
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
let nodesLength = nodes.length;
|
|
300
|
-
const firstNode = nodes[0];
|
|
301
|
-
const firstNodeParent = firstNode.getParent();
|
|
302
|
-
|
|
303
|
-
if (firstNodeParent !== null && (!firstNodeParent.canBeEmpty() || lexical.$isRootNode(firstNodeParent))) {
|
|
304
|
-
const parentChildren = firstNodeParent.__children;
|
|
305
|
-
const parentChildrenLength = parentChildren.length;
|
|
306
|
-
|
|
307
|
-
if (parentChildrenLength === nodesLength) {
|
|
308
|
-
let areTheSame = true;
|
|
309
|
-
|
|
310
|
-
for (let i = 0; i < parentChildren.length; i++) {
|
|
311
|
-
if (parentChildren[i] !== nodes[i].__key) {
|
|
312
|
-
areTheSame = false;
|
|
313
|
-
break;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
if (areTheSame) {
|
|
318
|
-
nodesLength++;
|
|
319
|
-
nodes.push(firstNodeParent);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
const lastNode = nodes[nodesLength - 1];
|
|
325
|
-
const isBefore = anchor.isBefore(focus);
|
|
326
|
-
const nodeMap = new Map();
|
|
327
|
-
const range = []; // Do first node to root
|
|
328
|
-
|
|
329
|
-
$copyLeafNodeBranchToRoot(firstNode, isBefore ? anchorOffset : focusOffset, true, range, nodeMap); // Copy all nodes between
|
|
330
|
-
|
|
331
|
-
for (let i = 0; i < nodesLength; i++) {
|
|
332
|
-
const node = nodes[i];
|
|
333
|
-
const key = node.getKey();
|
|
334
|
-
|
|
335
|
-
if (!nodeMap.has(key) && (!lexical.$isElementNode(node) || !node.excludeFromCopy())) {
|
|
336
|
-
const clone = $cloneWithProperties(node);
|
|
337
|
-
|
|
338
|
-
if (lexical.$isRootNode(node.getParent())) {
|
|
339
|
-
range.push(node.getKey());
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
nodeMap.set(key, clone);
|
|
343
|
-
}
|
|
344
|
-
} // Do last node to root
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
$copyLeafNodeBranchToRoot(lastNode, isBefore ? focusOffset : anchorOffset, false, range, nodeMap);
|
|
348
|
-
return {
|
|
349
|
-
nodeMap: Array.from(nodeMap.entries()),
|
|
350
|
-
range
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
|
|
354
173
|
function $moveCaretSelection(selection, isHoldingShift, isBackward, granularity) {
|
|
355
174
|
selection.modify(isHoldingShift ? 'extend' : 'move', isBackward, granularity);
|
|
356
175
|
}
|
|
@@ -363,6 +182,10 @@ function $moveCharacter(selection, isHoldingShift, isBackward) {
|
|
|
363
182
|
const isRTL = $isParentElementRTL(selection);
|
|
364
183
|
$moveCaretSelection(selection, isHoldingShift, isBackward ? !isRTL : isRTL, 'character');
|
|
365
184
|
}
|
|
185
|
+
function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
|
|
186
|
+
const possibleNode = lexical.$getDecoratorNode(selection.focus, isBackward);
|
|
187
|
+
return lexical.$isDecoratorNode(possibleNode) && !possibleNode.isIsolated();
|
|
188
|
+
}
|
|
366
189
|
|
|
367
190
|
/**
|
|
368
191
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -372,197 +195,6 @@ function $moveCharacter(selection, isHoldingShift, isBackward) {
|
|
|
372
195
|
*
|
|
373
196
|
*
|
|
374
197
|
*/
|
|
375
|
-
|
|
376
|
-
function $generateNodes(nodeRange) {
|
|
377
|
-
const {
|
|
378
|
-
range,
|
|
379
|
-
nodeMap
|
|
380
|
-
} = nodeRange;
|
|
381
|
-
const parsedNodeMap = new Map(nodeMap);
|
|
382
|
-
const nodes = [];
|
|
383
|
-
|
|
384
|
-
for (let i = 0; i < range.length; i++) {
|
|
385
|
-
const key = range[i];
|
|
386
|
-
const parsedNode = parsedNodeMap.get(key);
|
|
387
|
-
|
|
388
|
-
if (parsedNode !== undefined) {
|
|
389
|
-
const node = lexical.$createNodeFromParse(parsedNode, parsedNodeMap);
|
|
390
|
-
nodes.push(node);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
return nodes;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function getConversionFunction(domNode, editor) {
|
|
398
|
-
const {
|
|
399
|
-
nodeName
|
|
400
|
-
} = domNode;
|
|
401
|
-
|
|
402
|
-
const cachedConversions = editor._htmlConversions.get(nodeName.toLowerCase());
|
|
403
|
-
|
|
404
|
-
let currentConversion = null;
|
|
405
|
-
|
|
406
|
-
if (cachedConversions !== undefined) {
|
|
407
|
-
cachedConversions.forEach(cachedConversion => {
|
|
408
|
-
const domConversion = cachedConversion(domNode);
|
|
409
|
-
|
|
410
|
-
if (domConversion !== null) {
|
|
411
|
-
if (currentConversion === null || currentConversion.priority < domConversion.priority) {
|
|
412
|
-
currentConversion = domConversion;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
return currentConversion !== null ? currentConversion.conversion : null;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
function $createNodesFromDOM(node, editor, forChildMap = new Map()) {
|
|
422
|
-
let lexicalNodes = [];
|
|
423
|
-
let currentLexicalNode = null;
|
|
424
|
-
const transformFunction = getConversionFunction(node, editor);
|
|
425
|
-
const transformOutput = transformFunction ? transformFunction(node) : null;
|
|
426
|
-
let postTransform = null;
|
|
427
|
-
|
|
428
|
-
if (transformOutput !== null) {
|
|
429
|
-
postTransform = transformOutput.after;
|
|
430
|
-
currentLexicalNode = transformOutput.node;
|
|
431
|
-
|
|
432
|
-
if (currentLexicalNode !== null) {
|
|
433
|
-
lexicalNodes.push(currentLexicalNode);
|
|
434
|
-
const forChildFunctions = Array.from(forChildMap.values());
|
|
435
|
-
|
|
436
|
-
for (let i = 0; i < forChildFunctions.length; i++) {
|
|
437
|
-
forChildFunctions[i](currentLexicalNode);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
if (transformOutput.forChild != null) {
|
|
442
|
-
forChildMap.set(node.nodeName, transformOutput.forChild);
|
|
443
|
-
}
|
|
444
|
-
} // If the DOM node doesn't have a transformer, we don't know what
|
|
445
|
-
// to do with it but we still need to process any childNodes.
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const children = node.childNodes;
|
|
449
|
-
let childLexicalNodes = [];
|
|
450
|
-
|
|
451
|
-
for (let i = 0; i < children.length; i++) {
|
|
452
|
-
childLexicalNodes.push(...$createNodesFromDOM(children[i], editor, forChildMap));
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
if (postTransform != null) {
|
|
456
|
-
childLexicalNodes = postTransform(childLexicalNodes);
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
if (currentLexicalNode == null) {
|
|
460
|
-
// If it hasn't been converted to a LexicalNode, we hoist its children
|
|
461
|
-
// up to the same level as it.
|
|
462
|
-
lexicalNodes = lexicalNodes.concat(childLexicalNodes);
|
|
463
|
-
} else {
|
|
464
|
-
if (lexical.$isElementNode(currentLexicalNode)) {
|
|
465
|
-
// If the current node is a ElementNode after conversion,
|
|
466
|
-
// we can append all the children to it.
|
|
467
|
-
currentLexicalNode.append(...childLexicalNodes);
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
return lexicalNodes;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
function $generateNodesFromDOM(dom, editor) {
|
|
475
|
-
let lexicalNodes = [];
|
|
476
|
-
const elements = dom.body ? Array.from(dom.body.childNodes) : [];
|
|
477
|
-
const elementsLength = elements.length;
|
|
478
|
-
|
|
479
|
-
for (let i = 0; i < elementsLength; i++) {
|
|
480
|
-
const lexicalNode = $createNodesFromDOM(elements[i], editor);
|
|
481
|
-
|
|
482
|
-
if (lexicalNode !== null) {
|
|
483
|
-
lexicalNodes = lexicalNodes.concat(lexicalNode);
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
return lexicalNodes;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
function $insertDataTransferForRichText(dataTransfer, selection, editor) {
|
|
491
|
-
const lexicalNodesString = dataTransfer.getData('application/x-lexical-editor');
|
|
492
|
-
|
|
493
|
-
if (lexicalNodesString) {
|
|
494
|
-
const namespace = editor._config.namespace;
|
|
495
|
-
|
|
496
|
-
try {
|
|
497
|
-
const lexicalClipboardData = JSON.parse(lexicalNodesString);
|
|
498
|
-
|
|
499
|
-
if (lexicalClipboardData.namespace === namespace) {
|
|
500
|
-
const nodeRange = lexicalClipboardData.state;
|
|
501
|
-
const nodes = $generateNodes(nodeRange);
|
|
502
|
-
selection.insertNodes(nodes);
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
} catch (e) {// Malformed, missing nodes..
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
const textHtmlMimeType = 'text/html';
|
|
510
|
-
const htmlString = dataTransfer.getData(textHtmlMimeType);
|
|
511
|
-
|
|
512
|
-
if (htmlString) {
|
|
513
|
-
const parser = new DOMParser();
|
|
514
|
-
const dom = parser.parseFromString(htmlString, textHtmlMimeType);
|
|
515
|
-
const nodes = $generateNodesFromDOM(dom, editor); // Wrap text and inline nodes in paragraph nodes so we have all blocks at the top-level
|
|
516
|
-
|
|
517
|
-
const topLevelBlocks = [];
|
|
518
|
-
let currentBlock = null;
|
|
519
|
-
|
|
520
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
521
|
-
const node = nodes[i];
|
|
522
|
-
|
|
523
|
-
if (!lexical.$isElementNode(node) || node.isInline()) {
|
|
524
|
-
if (currentBlock === null) {
|
|
525
|
-
currentBlock = lexical.$createParagraphNode();
|
|
526
|
-
topLevelBlocks.push(currentBlock);
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
if (currentBlock !== null) {
|
|
530
|
-
currentBlock.append(node);
|
|
531
|
-
}
|
|
532
|
-
} else {
|
|
533
|
-
topLevelBlocks.push(node);
|
|
534
|
-
currentBlock = null;
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
selection.insertNodes(topLevelBlocks);
|
|
539
|
-
return;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
$insertDataTransferForPlainText(dataTransfer, selection);
|
|
543
|
-
}
|
|
544
|
-
function $insertDataTransferForPlainText(dataTransfer, selection) {
|
|
545
|
-
const text = dataTransfer.getData('text/plain');
|
|
546
|
-
|
|
547
|
-
if (text != null) {
|
|
548
|
-
selection.insertRawText(text);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
|
|
552
|
-
const possibleNode = lexical.$getDecoratorNode(selection.focus, isBackward);
|
|
553
|
-
return lexical.$isDecoratorNode(possibleNode) && !possibleNode.isIsolated();
|
|
554
|
-
}
|
|
555
|
-
function onPasteForRichText(event, editor) {
|
|
556
|
-
event.preventDefault();
|
|
557
|
-
editor.update(() => {
|
|
558
|
-
const selection = lexical.$getSelection();
|
|
559
|
-
const clipboardData = event.clipboardData;
|
|
560
|
-
|
|
561
|
-
if (clipboardData != null && lexical.$isRangeSelection(selection)) {
|
|
562
|
-
$insertDataTransferForRichText(clipboardData, selection, editor);
|
|
563
|
-
}
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
198
|
function onCutForRichText(event, editor) {
|
|
567
199
|
onCopyForRichText(event, editor);
|
|
568
200
|
editor.update(() => {
|
|
@@ -581,31 +213,33 @@ function onCopyForRichText(event, editor) {
|
|
|
581
213
|
|
|
582
214
|
if (selection !== null) {
|
|
583
215
|
if (clipboardData != null) {
|
|
584
|
-
const
|
|
216
|
+
const htmlString = clipboard.getHtmlContent(editor);
|
|
217
|
+
const lexicalString = clipboard.$getLexicalContent(editor);
|
|
585
218
|
|
|
586
|
-
if (
|
|
587
|
-
|
|
219
|
+
if (htmlString !== null) {
|
|
220
|
+
clipboardData.setData('text/html', htmlString);
|
|
588
221
|
}
|
|
589
222
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
if (range) {
|
|
593
|
-
const container = document.createElement('div');
|
|
594
|
-
const frag = range.cloneContents();
|
|
595
|
-
container.appendChild(frag);
|
|
596
|
-
clipboardData.setData('text/html', container.innerHTML);
|
|
223
|
+
if (lexicalString !== null) {
|
|
224
|
+
clipboardData.setData('application/x-lexical-editor', lexicalString);
|
|
597
225
|
}
|
|
598
226
|
|
|
599
227
|
clipboardData.setData('text/plain', selection.getTextContent());
|
|
600
|
-
const namespace = editor._config.namespace;
|
|
601
|
-
clipboardData.setData('application/x-lexical-editor', JSON.stringify({
|
|
602
|
-
namespace,
|
|
603
|
-
state: $cloneContents(selection)
|
|
604
|
-
}));
|
|
605
228
|
}
|
|
606
229
|
}
|
|
607
230
|
});
|
|
608
231
|
}
|
|
232
|
+
function onPasteForRichText(event, editor) {
|
|
233
|
+
event.preventDefault();
|
|
234
|
+
editor.update(() => {
|
|
235
|
+
const selection = lexical.$getSelection();
|
|
236
|
+
const clipboardData = event.clipboardData;
|
|
237
|
+
|
|
238
|
+
if (clipboardData != null && lexical.$isRangeSelection(selection)) {
|
|
239
|
+
clipboard.$insertDataTransferForRichText(clipboardData, selection, editor);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
609
243
|
|
|
610
244
|
/**
|
|
611
245
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -760,7 +394,7 @@ function useLexicalDragonSupport(editor) {
|
|
|
760
394
|
*
|
|
761
395
|
*/
|
|
762
396
|
function useRichTextSetup(editor, initialEditorState) {
|
|
763
|
-
|
|
397
|
+
useLayoutEffect(() => {
|
|
764
398
|
const removeListener = editor.addListener('command', (type, payload) => {
|
|
765
399
|
const selection = lexical.$getSelection();
|
|
766
400
|
|
|
@@ -805,7 +439,7 @@ function useRichTextSetup(editor, initialEditorState) {
|
|
|
805
439
|
const dataTransfer = eventOrText.dataTransfer;
|
|
806
440
|
|
|
807
441
|
if (dataTransfer != null) {
|
|
808
|
-
|
|
442
|
+
clipboard.$insertDataTransferForRichText(dataTransfer, selection, editor);
|
|
809
443
|
} else {
|
|
810
444
|
const data = eventOrText.data;
|
|
811
445
|
|