@lexical/react 0.9.1 → 0.10.0
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.dev.js +4 -0
- package/LexicalAutoEmbedPlugin.prod.js +4 -4
- package/LexicalClickableLinkPlugin.d.ts +10 -0
- package/LexicalClickableLinkPlugin.dev.js +112 -0
- package/LexicalClickableLinkPlugin.js +9 -0
- package/LexicalClickableLinkPlugin.js.flow +12 -0
- package/LexicalClickableLinkPlugin.prod.js +10 -0
- package/LexicalCollaborationPlugin.d.ts +6 -3
- package/LexicalCollaborationPlugin.dev.js +5 -4
- package/LexicalCollaborationPlugin.prod.js +9 -9
- package/LexicalComposer.dev.js +1 -1
- package/LexicalComposer.prod.js +1 -1
- package/LexicalContentEditable.js.flow +1 -1
- package/LexicalHorizontalRuleNode.d.ts +1 -4
- package/LexicalHorizontalRulePlugin.js.flow +12 -0
- package/LexicalLinkPlugin.dev.js +4 -2
- package/LexicalLinkPlugin.prod.js +1 -1
- package/LexicalTablePlugin.d.ts +4 -1
- package/LexicalTablePlugin.dev.js +94 -31
- package/LexicalTablePlugin.js.flow +5 -1
- package/LexicalTablePlugin.prod.js +6 -4
- package/LexicalTreeView.d.ts +2 -1
- package/LexicalTreeView.dev.js +65 -10
- package/LexicalTreeView.prod.js +18 -17
- package/LexicalTypeaheadMenuPlugin.dev.js +1 -3
- package/LexicalTypeaheadMenuPlugin.prod.js +1 -1
- package/package.json +19 -19
- package/shared/useYjsCollaboration.d.ts +2 -2
|
@@ -107,6 +107,10 @@ function LexicalAutoEmbedPlugin({
|
|
|
107
107
|
|
|
108
108
|
if (result != null) {
|
|
109
109
|
editor.update(() => {
|
|
110
|
+
if (!lexical.$getSelection()) {
|
|
111
|
+
linkNode.selectEnd();
|
|
112
|
+
}
|
|
113
|
+
|
|
110
114
|
activeEmbedConfig.insertNode(editor, result);
|
|
111
115
|
|
|
112
116
|
if (linkNode.isAttached()) {
|
|
@@ -4,7 +4,7 @@
|
|
|
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 e=require("@lexical/link"),k=require("@lexical/react/LexicalComposerContext"),
|
|
8
|
-
exports.LexicalAutoEmbedPlugin=function({embedConfigs:f,onOpenEmbedModalForConfig:n,getMenuOptions:t,menuRenderFn:C}){let [
|
|
9
|
-
dirtyLeaves:p})=>{for(const [x,D]of a)"created"===D&&d.has("paste")&&1===p.size?w(x):x===g&&
|
|
10
|
-
await Promise.resolve(h.parseUrl(
|
|
7
|
+
'use strict';var e=require("@lexical/link"),k=require("@lexical/react/LexicalComposerContext"),l=require("@lexical/react/LexicalTypeaheadMenuPlugin"),q=require("@lexical/utils"),r=require("lexical"),z=require("react");let A=r.createCommand("INSERT_EMBED_COMMAND");class B extends l.TypeaheadOption{constructor(f,n){super(f);this.title=f;this.onSelect=n.onSelect.bind(this)}}exports.AutoEmbedOption=B;exports.INSERT_EMBED_COMMAND=A;
|
|
8
|
+
exports.LexicalAutoEmbedPlugin=function({embedConfigs:f,onOpenEmbedModalForConfig:n,getMenuOptions:t,menuRenderFn:C}){let [c]=k.useLexicalComposerContext(),[g,u]=z.useState(null),[h,v]=z.useState(null),m=z.useCallback(()=>{u(null);v(null)},[]),w=z.useCallback(b=>{c.getEditorState().read(async()=>{const a=r.$getNodeByKey(b);if(e.$isLinkNode(a))for(let d=0;d<f.length;d++){const p=f[d];null!=await Promise.resolve(p.parseUrl(a.__url))&&(v(p),u(a.getKey()))}})},[c,f]);z.useEffect(()=>{let b=(a,{updateTags:d,
|
|
9
|
+
dirtyLeaves:p})=>{for(const [x,D]of a)"created"===D&&d.has("paste")&&1===p.size?w(x):x===g&&m()};return q.mergeRegister(...[e.LinkNode,e.AutoLinkNode].map(a=>c.registerMutationListener(a,(...d)=>b(...d))))},[w,c,f,g,m]);z.useEffect(()=>c.registerCommand(A,b=>{let a=f.find(({type:d})=>d===b);return a?(n(a),!0):!1},r.COMMAND_PRIORITY_EDITOR),[c,f,n]);let y=z.useCallback(async()=>{if(null!=h&&null!=g){const b=c.getEditorState().read(()=>{const a=r.$getNodeByKey(g);return e.$isLinkNode(a)?a:null});if(e.$isLinkNode(b)){const a=
|
|
10
|
+
await Promise.resolve(h.parseUrl(b.__url));null!=a&&c.update(()=>{r.$getSelection()||b.selectEnd();h.insertNode(c,a);b.isAttached()&&b.remove()})}}},[h,c,g]),E=z.useMemo(()=>null!=h&&null!=g?t(h,y,m):[],[h,y,t,g,m]),F=z.useCallback((b,a,d)=>{c.update(()=>{b.onSelect(a);d()})},[c]);return null!=g?z.createElement(l.LexicalNodeMenuPlugin,{nodeKey:g,onClose:m,onSelectOption:F,options:E,menuRenderFn:C}):null};exports.URL_MATCHER=/((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
export default function LexicalClickableLinkPlugin({ newTab, }: {
|
|
9
|
+
newTab?: boolean;
|
|
10
|
+
}): null;
|
|
@@ -0,0 +1,112 @@
|
|
|
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
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
var link = require('@lexical/link');
|
|
10
|
+
var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
|
|
11
|
+
var utils = require('@lexical/utils');
|
|
12
|
+
var lexical = require('lexical');
|
|
13
|
+
var react = require('react');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
17
|
+
*
|
|
18
|
+
* This source code is licensed under the MIT license found in the
|
|
19
|
+
* LICENSE file in the root directory of this source tree.
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
function domGetParent(node, predicate) {
|
|
24
|
+
let parent = node.parentNode;
|
|
25
|
+
|
|
26
|
+
while (parent != null) {
|
|
27
|
+
if (predicate(parent)) {
|
|
28
|
+
return parent;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
parent = parent.parentNode;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function LexicalClickableLinkPlugin({
|
|
38
|
+
newTab = true
|
|
39
|
+
}) {
|
|
40
|
+
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
41
|
+
react.useEffect(() => {
|
|
42
|
+
const onClick = event => {
|
|
43
|
+
const target = event.target;
|
|
44
|
+
|
|
45
|
+
if (!(target instanceof Node)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const nearestEditor = lexical.getNearestEditorFromDOMNode(target);
|
|
50
|
+
|
|
51
|
+
if (nearestEditor === null) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let url = null;
|
|
56
|
+
let urlTarget = null;
|
|
57
|
+
nearestEditor.update(() => {
|
|
58
|
+
const clickedNode = lexical.$getNearestNodeFromDOMNode(target);
|
|
59
|
+
|
|
60
|
+
if (clickedNode !== null) {
|
|
61
|
+
const maybeLinkNode = utils.$findMatchingParent(clickedNode, lexical.$isElementNode);
|
|
62
|
+
|
|
63
|
+
if (link.$isLinkNode(maybeLinkNode)) {
|
|
64
|
+
url = maybeLinkNode.getURL();
|
|
65
|
+
urlTarget = maybeLinkNode.getTarget();
|
|
66
|
+
} else {
|
|
67
|
+
const a = utils.isHTMLAnchorElement(target) ? target : domGetParent(target, utils.isHTMLAnchorElement);
|
|
68
|
+
url = a.href;
|
|
69
|
+
urlTarget = a.target;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (url === null || url === '') {
|
|
75
|
+
return;
|
|
76
|
+
} // Allow user to select link text without follwing url
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
const selection = editor.getEditorState().read(lexical.$getSelection);
|
|
80
|
+
|
|
81
|
+
if (lexical.$isRangeSelection(selection) && !selection.isCollapsed()) {
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const isMiddle = event.type === 'auxclick' && event.button === 1;
|
|
87
|
+
window.open(url, newTab || isMiddle || event.metaKey || event.ctrlKey || urlTarget === '_blank' ? '_blank' : '_self');
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const onMouseUp = event => {
|
|
92
|
+
if (event.button === 1 && editor.isEditable()) {
|
|
93
|
+
onClick(event);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return editor.registerRootListener((rootElement, prevRootElement) => {
|
|
98
|
+
if (prevRootElement !== null) {
|
|
99
|
+
prevRootElement.removeEventListener('click', onClick);
|
|
100
|
+
prevRootElement.removeEventListener('mouseup', onMouseUp);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (rootElement !== null) {
|
|
104
|
+
rootElement.addEventListener('click', onClick);
|
|
105
|
+
rootElement.addEventListener('mouseup', onMouseUp);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}, [editor, newTab]);
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = LexicalClickableLinkPlugin;
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
'use strict'
|
|
8
|
+
const LexicalClickableLinkPlugin = process.env.NODE_ENV === 'development' ? require('./LexicalClickableLinkPlugin.dev.js') : require('./LexicalClickableLinkPlugin.prod.js')
|
|
9
|
+
module.exports = LexicalClickableLinkPlugin;
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
* @flow strict
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
declare export function MLCClickableLinkPlugin({
|
|
11
|
+
newTab?: boolean,
|
|
12
|
+
}): null;
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
'use strict';var e=require("@lexical/link"),k=require("@lexical/react/LexicalComposerContext"),q=require("@lexical/utils"),r=require("lexical"),t=require("react");
|
|
8
|
+
module.exports=function({newTab:n=!0}){let [h]=k.useLexicalComposerContext();t.useEffect(()=>{let m=a=>{const c=a.target;if(c instanceof Node){var d=r.getNearestEditorFromDOMNode(c);if(null!==d){var f=null,l=null;d.update(()=>{var b=r.$getNearestNodeFromDOMNode(c);if(null!==b)if(b=q.$findMatchingParent(b,r.$isElementNode),e.$isLinkNode(b))f=b.getURL(),l=b.getTarget();else{if(q.isHTMLAnchorElement(c))b=c;else a:{b=q.isHTMLAnchorElement;let g=c.parentNode;for(;null!=g;){if(b(g)){b=g;break a}g=g.parentNode}b=
|
|
9
|
+
null}f=b.href;l=b.target}});if(null!==f&&""!==f){d=h.getEditorState().read(r.$getSelection);if(!r.$isRangeSelection(d)||d.isCollapsed())d="auxclick"===a.type&&1===a.button,window.open(f,n||d||a.metaKey||a.ctrlKey||"_blank"===l?"_blank":"_self");a.preventDefault()}}}},p=a=>{1===a.button&&h.isEditable()&&m(a)};return h.registerRootListener((a,c)=>{null!==c&&(c.removeEventListener("click",m),c.removeEventListener("mouseup",p));null!==a&&(a.addEventListener("click",m),a.addEventListener("mouseup",p))})},
|
|
10
|
+
[h,n]);return null}
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/// <reference types="react" />
|
|
9
9
|
import type { Doc } from 'yjs';
|
|
10
|
-
import { Provider } from '@lexical/yjs';
|
|
10
|
+
import { ExcludedProperties, Provider } from '@lexical/yjs';
|
|
11
11
|
import { InitialEditorStateType } from './LexicalComposer';
|
|
12
12
|
import { CursorsContainerRef } from './shared/useYjsCollaboration';
|
|
13
|
-
|
|
13
|
+
declare type Props = {
|
|
14
14
|
id: string;
|
|
15
15
|
providerFactory: (id: string, yjsDocMap: Map<string, Doc>) => Provider;
|
|
16
16
|
shouldBootstrap: boolean;
|
|
@@ -18,4 +18,7 @@ export declare function CollaborationPlugin({ id, providerFactory, shouldBootstr
|
|
|
18
18
|
cursorColor?: string;
|
|
19
19
|
cursorsContainerRef?: CursorsContainerRef;
|
|
20
20
|
initialEditorState?: InitialEditorStateType;
|
|
21
|
-
|
|
21
|
+
excludedProperties?: ExcludedProperties;
|
|
22
|
+
};
|
|
23
|
+
export declare function CollaborationPlugin({ id, providerFactory, shouldBootstrap, username, cursorColor, cursorsContainerRef, initialEditorState, excludedProperties, }: Props): JSX.Element;
|
|
24
|
+
export {};
|
|
@@ -22,10 +22,10 @@ var yjs$1 = require('yjs');
|
|
|
22
22
|
* LICENSE file in the root directory of this source tree.
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
|
-
function useYjsCollaboration(editor, id, provider, docMap, name, color, shouldBootstrap, cursorsContainerRef, initialEditorState) {
|
|
25
|
+
function useYjsCollaboration(editor, id, provider, docMap, name, color, shouldBootstrap, cursorsContainerRef, initialEditorState, excludedProperties) {
|
|
26
26
|
const isReloadingDoc = React.useRef(false);
|
|
27
27
|
const [doc, setDoc] = React.useState(docMap.get(id));
|
|
28
|
-
const binding = React.useMemo(() => yjs.createBinding(editor, provider, id, doc, docMap), [editor, provider, id, docMap, doc]);
|
|
28
|
+
const binding = React.useMemo(() => yjs.createBinding(editor, provider, id, doc, docMap, excludedProperties), [editor, provider, id, docMap, doc, excludedProperties]);
|
|
29
29
|
const connect = React.useCallback(() => {
|
|
30
30
|
provider.connect();
|
|
31
31
|
}, [provider]);
|
|
@@ -290,7 +290,8 @@ function CollaborationPlugin({
|
|
|
290
290
|
username,
|
|
291
291
|
cursorColor,
|
|
292
292
|
cursorsContainerRef,
|
|
293
|
-
initialEditorState
|
|
293
|
+
initialEditorState,
|
|
294
|
+
excludedProperties
|
|
294
295
|
}) {
|
|
295
296
|
const collabContext = LexicalCollaborationContext.useCollaborationContext(username, cursorColor);
|
|
296
297
|
const {
|
|
@@ -310,7 +311,7 @@ function CollaborationPlugin({
|
|
|
310
311
|
};
|
|
311
312
|
}, [collabContext, editor]);
|
|
312
313
|
const provider = React.useMemo(() => providerFactory(id, yjsDocMap), [id, providerFactory, yjsDocMap]);
|
|
313
|
-
const [cursors, binding] = useYjsCollaboration(editor, id, provider, yjsDocMap, name, color, shouldBootstrap, cursorsContainerRef, initialEditorState);
|
|
314
|
+
const [cursors, binding] = useYjsCollaboration(editor, id, provider, yjsDocMap, name, color, shouldBootstrap, cursorsContainerRef, initialEditorState, excludedProperties);
|
|
314
315
|
collabContext.clientID = binding.clientID;
|
|
315
316
|
useYjsHistory(editor, binding);
|
|
316
317
|
useYjsFocusTracking(editor, provider, name, color);
|
|
@@ -4,12 +4,12 @@
|
|
|
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 e=require("@lexical/react/LexicalCollaborationContext"),f=require("@lexical/react/LexicalComposerContext"),h=require("react"),
|
|
8
|
-
function
|
|
9
|
-
a,k,u instanceof
|
|
10
|
-
|
|
11
|
-
function
|
|
12
|
-
function
|
|
13
|
-
function
|
|
14
|
-
function
|
|
15
|
-
exports.CollaborationPlugin=function({id:b,providerFactory:c,shouldBootstrap:a,username:d,cursorColor:p,cursorsContainerRef:
|
|
7
|
+
'use strict';var e=require("@lexical/react/LexicalCollaborationContext"),f=require("@lexical/react/LexicalComposerContext"),h=require("react"),A=require("@lexical/utils"),I=require("@lexical/yjs"),J=require("lexical"),K=require("react-dom"),L=require("yjs");
|
|
8
|
+
function M(b,c,a,d,p,y,z,v,m,t){let q=h.useRef(!1),[w,r]=h.useState(d.get(c)),g=h.useMemo(()=>I.createBinding(b,a,c,w,d,t),[b,a,c,d,w,t]),n=h.useCallback(()=>{a.connect()},[a]),x=h.useCallback(()=>{try{a.disconnect()}catch(l){}},[a]);h.useEffect(()=>{let {root:l}=g,{awareness:B}=a,C=({status:k})=>{b.dispatchCommand(I.CONNECTED_COMMAND,"connected"===k)},D=k=>{z&&k&&l.isEmpty()&&0===l._xmlText._length&&!1===q.current&&N(b,m);q.current=!1},E=()=>{I.syncCursorPositions(g,a)},F=(k,u)=>{u=u.origin;u!==
|
|
9
|
+
g&&I.syncYjsChangesToLexical(g,a,k,u instanceof L.UndoManager)};I.initLocalState(a,p,y,document.activeElement===b.getRootElement());let G=k=>{O(b,g);r(k);d.set(c,k);q.current=!0};a.on("reload",G);a.on("status",C);a.on("sync",D);B.on("update",E);l.getSharedType().observeDeep(F);let S=b.registerUpdateListener(({prevEditorState:k,editorState:u,dirtyLeaves:P,dirtyElements:Q,normalizedNodes:R,tags:H})=>{!1===H.has("skip-collab")&&I.syncLexicalUpdateToYjs(g,a,k,u,Q,P,R,H)});n();return()=>{!1===q.current&&
|
|
10
|
+
x();a.off("sync",D);a.off("status",C);a.off("reload",G);B.off("update",E);l.getSharedType().unobserveDeep(F);d.delete(c);S()}},[g,y,n,x,d,b,c,m,p,a,z]);let T=h.useMemo(()=>K.createPortal(h.createElement("div",{ref:l=>{g.cursorsContainer=l}}),v&&v.current||document.body),[g,v]);h.useEffect(()=>b.registerCommand(I.TOGGLE_CONNECT_COMMAND,l=>{void 0!==n&&void 0!==x&&(l?(console.log("Collaboration connected!"),n()):(console.log("Collaboration disconnected!"),x()));return!0},J.COMMAND_PRIORITY_EDITOR),
|
|
11
|
+
[n,x,b]);return[T,g]}function U(b,c,a,d){h.useEffect(()=>A.mergeRegister(b.registerCommand(J.FOCUS_COMMAND,()=>{I.setLocalStateFocus(c,a,d,!0);return!1},J.COMMAND_PRIORITY_EDITOR),b.registerCommand(J.BLUR_COMMAND,()=>{I.setLocalStateFocus(c,a,d,!1);return!1},J.COMMAND_PRIORITY_EDITOR)),[d,b,a,c])}
|
|
12
|
+
function V(b,c){let a=h.useMemo(()=>I.createUndoManager(c,c.root.getSharedType()),[c]);h.useEffect(()=>A.mergeRegister(b.registerCommand(J.UNDO_COMMAND,()=>{a.undo();return!0},J.COMMAND_PRIORITY_EDITOR),b.registerCommand(J.REDO_COMMAND,()=>{a.redo();return!0},J.COMMAND_PRIORITY_EDITOR)));return h.useCallback(()=>{a.clear()},[a])}
|
|
13
|
+
function N(b,c){b.update(()=>{var a=J.$getRoot();if(a.isEmpty())if(c)switch(typeof c){case "string":var d=b.parseEditorState(c);b.setEditorState(d,{tag:"history-merge"});break;case "object":b.setEditorState(c,{tag:"history-merge"});break;case "function":b.update(()=>{J.$getRoot().isEmpty()&&c(b)},{tag:"history-merge"})}else d=J.$createParagraphNode(),a.append(d),{activeElement:a}=document,(null!==J.$getSelection()||null!==a&&a===b.getRootElement())&&d.select()},{tag:"history-merge"})}
|
|
14
|
+
function O(b,c){b.update(()=>{let d=J.$getRoot();d.clear();d.select()},{tag:"skip-collab"});if(null!=c.cursors&&(b=c.cursors,null!=b&&(c=c.cursorsContainer,null!=c))){b=Array.from(b.values());for(let d=0;d<b.length;d++){var a=b[d].selection;if(a&&null!=a.selections){a=a.selections;for(let p=0;p<a.length;p++)c.removeChild(a[d])}}}}
|
|
15
|
+
exports.CollaborationPlugin=function({id:b,providerFactory:c,shouldBootstrap:a,username:d,cursorColor:p,cursorsContainerRef:y,initialEditorState:z,excludedProperties:v}){let m=e.useCollaborationContext(d,p),{yjsDocMap:t,name:q,color:w}=m,[r]=f.useLexicalComposerContext();h.useEffect(()=>{m.isCollabActive=!0;return()=>{null==r._parentEditor&&(m.isCollabActive=!1)}},[m,r]);d=h.useMemo(()=>c(b,t),[b,c,t]);let [g,n]=M(r,b,d,t,q,w,a,y,z,v);m.clientID=n.clientID;V(r,n);U(r,d,q,w);return g}
|
package/LexicalComposer.dev.js
CHANGED
package/LexicalComposer.prod.js
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*/
|
|
7
7
|
'use strict';var e=require("@lexical/react/LexicalComposerContext"),f=require("lexical"),g=require("react");let m="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement;var n=m?g.useLayoutEffect:g.useEffect;let p={tag:"history-merge"};
|
|
8
8
|
function q(a,c){if(null!==c)if(void 0===c)a.update(()=>{var b=f.$getRoot();if(b.isEmpty()){let d=f.$createParagraphNode();b.append(d);b=m?document.activeElement:null;(null!==f.$getSelection()||null!==b&&b===a.getRootElement())&&d.select()}},p);else if(null!==c)switch(typeof c){case "string":let b=a.parseEditorState(c);a.setEditorState(b,p);break;case "object":a.setEditorState(c,p);break;case "function":a.update(()=>{f.$getRoot().isEmpty()&&c(a)},p)}}
|
|
9
|
-
exports.LexicalComposer=function({initialConfig:a,children:c}){let b=g.useMemo(()=>{const {theme:d,namespace:h,editor__DEPRECATED:r,nodes:t,onError:u,editorState:v}=a,w=e.createLexicalComposerContext(null,d);let k=r||null;if(null===k){const l=f.createEditor({editable
|
|
9
|
+
exports.LexicalComposer=function({initialConfig:a,children:c}){let b=g.useMemo(()=>{const {theme:d,namespace:h,editor__DEPRECATED:r,nodes:t,onError:u,editorState:v}=a,w=e.createLexicalComposerContext(null,d);let k=r||null;if(null===k){const l=f.createEditor({editable:a.editable,namespace:h,nodes:t,onError:x=>u(x,l),theme:d});q(l,v);k=l}return[k,w]},[]);n(()=>{let d=a.editable,[h]=b;h.setEditable(void 0!==d?d:!0)},[]);return g.createElement(e.LexicalComposerContext.Provider,{value:b},c)}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import * as React from 'react';
|
|
11
11
|
|
|
12
12
|
export type Props = $ReadOnly<{
|
|
13
|
-
|
|
13
|
+
...Partial<HTMLDivElement>,
|
|
14
14
|
ariaActiveDescendant?: HTMLDivElement['aria-activedescendant'],
|
|
15
15
|
ariaAutoComplete?: HTMLDivElement['aria-autocomplete'],
|
|
16
16
|
ariaControls?: HTMLDivElement['aria-controls'],
|
|
@@ -8,10 +8,7 @@
|
|
|
8
8
|
/// <reference types="react" />
|
|
9
9
|
import type { DOMConversionMap, DOMExportOutput, LexicalCommand, LexicalNode, SerializedLexicalNode } from 'lexical';
|
|
10
10
|
import { DecoratorNode } from 'lexical';
|
|
11
|
-
export declare type SerializedHorizontalRuleNode = SerializedLexicalNode
|
|
12
|
-
type: 'horizontalrule';
|
|
13
|
-
version: 1;
|
|
14
|
-
};
|
|
11
|
+
export declare type SerializedHorizontalRuleNode = SerializedLexicalNode;
|
|
15
12
|
export declare const INSERT_HORIZONTAL_RULE_COMMAND: LexicalCommand<void>;
|
|
16
13
|
export declare class HorizontalRuleNode extends DecoratorNode<JSX.Element> {
|
|
17
14
|
static getType(): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
* @flow strict
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
type Props = $ReadOnly<{}>;
|
|
11
|
+
|
|
12
|
+
declare export function HorizontalRulePlugin(props: Props): null;
|
package/LexicalLinkPlugin.dev.js
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
'use strict';var b=require("@lexical/link"),c=require("@lexical/react/LexicalComposerContext"),k=require("@lexical/utils"),l=require("lexical"),m=require("react");
|
|
8
|
-
exports.LinkPlugin=function({validateUrl:d}){let [e]=c.useLexicalComposerContext();m.useEffect(()=>{if(!e.hasNodes([b.LinkNode]))throw Error("LinkPlugin: LinkNode not registered on editor");return k.mergeRegister(e.registerCommand(b.TOGGLE_LINK_COMMAND,a=>{if(null===a)return b.toggleLink(a),!0;if("string"===typeof a)return void 0===d||d(a)?(b.toggleLink(a),!0):!1;let {url:f,target:g,rel:h}=a;b.toggleLink(f,{rel:h,target:g});return!0},l.COMMAND_PRIORITY_LOW),void 0!==d?e.registerCommand(l.PASTE_COMMAND,
|
|
8
|
+
exports.LinkPlugin=function({validateUrl:d}){let [e]=c.useLexicalComposerContext();m.useEffect(()=>{if(!e.hasNodes([b.LinkNode]))throw Error("LinkPlugin: LinkNode not registered on editor");return k.mergeRegister(e.registerCommand(b.TOGGLE_LINK_COMMAND,a=>{if(null===a)return b.toggleLink(a),!0;if("string"===typeof a)return void 0===d||d(a)?(b.toggleLink(a),!0):!1;let {url:f,target:g,rel:h,title:n}=a;b.toggleLink(f,{rel:h,target:g,title:n});return!0},l.COMMAND_PRIORITY_LOW),void 0!==d?e.registerCommand(l.PASTE_COMMAND,
|
|
9
9
|
a=>{let f=l.$getSelection();if(!l.$isRangeSelection(f)||f.isCollapsed()||!(a instanceof ClipboardEvent)||null==a.clipboardData)return!1;let g=a.clipboardData.getData("text");return d(g)?f.getNodes().some(h=>l.$isElementNode(h))?!1:(e.dispatchCommand(b.TOGGLE_LINK_COMMAND,g),a.preventDefault(),!0):!1},l.COMMAND_PRIORITY_LOW):()=>{})},[e,d]);return null}
|
package/LexicalTablePlugin.d.ts
CHANGED
|
@@ -6,4 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
/// <reference types="react" />
|
|
9
|
-
export declare function TablePlugin(
|
|
9
|
+
export declare function TablePlugin({ hasCellMerge, hasCellBackgroundColor, }: {
|
|
10
|
+
hasCellMerge?: boolean;
|
|
11
|
+
hasCellBackgroundColor?: boolean;
|
|
12
|
+
}): JSX.Element | null;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
|
|
10
10
|
var table = require('@lexical/table');
|
|
11
|
+
var utils = require('@lexical/utils');
|
|
11
12
|
var lexical = require('lexical');
|
|
12
13
|
var react = require('react');
|
|
13
14
|
|
|
@@ -18,7 +19,21 @@ var react = require('react');
|
|
|
18
19
|
* LICENSE file in the root directory of this source tree.
|
|
19
20
|
*
|
|
20
21
|
*/
|
|
21
|
-
|
|
22
|
+
|
|
23
|
+
function $insertFirst(parent, node) {
|
|
24
|
+
const firstChild = parent.getFirstChild();
|
|
25
|
+
|
|
26
|
+
if (firstChild !== null) {
|
|
27
|
+
firstChild.insertBefore(node);
|
|
28
|
+
} else {
|
|
29
|
+
parent.append(node);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function TablePlugin({
|
|
34
|
+
hasCellMerge = true,
|
|
35
|
+
hasCellBackgroundColor = true
|
|
36
|
+
}) {
|
|
22
37
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
23
38
|
react.useEffect(() => {
|
|
24
39
|
if (!editor.hasNodes([table.TableNode, table.TableCellNode, table.TableRowNode])) {
|
|
@@ -32,36 +47,12 @@ function TablePlugin() {
|
|
|
32
47
|
rows,
|
|
33
48
|
includeHeaders
|
|
34
49
|
}) => {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const focus = selection.focus;
|
|
42
|
-
const focusNode = focus.getNode();
|
|
43
|
-
|
|
44
|
-
if (focusNode !== null) {
|
|
45
|
-
const tableNode = table.$createTableNodeWithDimensions(Number(rows), Number(columns), includeHeaders);
|
|
46
|
-
|
|
47
|
-
if (lexical.$isRootOrShadowRoot(focusNode)) {
|
|
48
|
-
const target = focusNode.getChildAtIndex(focus.offset);
|
|
49
|
-
|
|
50
|
-
if (target !== null) {
|
|
51
|
-
target.insertBefore(tableNode);
|
|
52
|
-
} else {
|
|
53
|
-
focusNode.append(tableNode);
|
|
54
|
-
}
|
|
50
|
+
const tableNode = table.$createTableNodeWithDimensions(Number(rows), Number(columns), includeHeaders);
|
|
51
|
+
utils.$insertNodeToNearestRoot(tableNode);
|
|
52
|
+
const firstDescendant = tableNode.getFirstDescendant();
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const topLevelNode = focusNode.getTopLevelElementOrThrow();
|
|
59
|
-
topLevelNode.insertAfter(tableNode);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
tableNode.insertAfter(lexical.$createParagraphNode());
|
|
63
|
-
const firstCell = tableNode.getFirstChildOrThrow().getFirstChildOrThrow();
|
|
64
|
-
firstCell.select();
|
|
54
|
+
if (lexical.$isTextNode(firstDescendant)) {
|
|
55
|
+
firstDescendant.select();
|
|
65
56
|
}
|
|
66
57
|
|
|
67
58
|
return true;
|
|
@@ -119,7 +110,79 @@ function TablePlugin() {
|
|
|
119
110
|
tableSelection.removeListeners();
|
|
120
111
|
}
|
|
121
112
|
};
|
|
122
|
-
}, [editor]);
|
|
113
|
+
}, [editor]); // Unmerge cells when the feature isn't enabled
|
|
114
|
+
|
|
115
|
+
react.useEffect(() => {
|
|
116
|
+
if (hasCellMerge) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return editor.registerNodeTransform(table.TableCellNode, node => {
|
|
121
|
+
if (node.getColSpan() > 1 || node.getRowSpan() > 1) {
|
|
122
|
+
// When we have rowSpan we have to map the entire Table to understand where the new Cells
|
|
123
|
+
// fit best; let's analyze all Cells at once to save us from further transform iterations
|
|
124
|
+
const [,, gridNode] = lexical.DEPRECATED_$getNodeTriplet(node);
|
|
125
|
+
const [gridMap] = lexical.DEPRECATED_$computeGridMap(gridNode, node, node); // TODO this function expects Tables to be normalized. Look into this once it exists
|
|
126
|
+
|
|
127
|
+
const rowsCount = gridMap.length;
|
|
128
|
+
const columnsCount = gridMap[0].length;
|
|
129
|
+
let row = gridNode.getFirstChild();
|
|
130
|
+
|
|
131
|
+
if (!lexical.DEPRECATED_$isGridRowNode(row)) {
|
|
132
|
+
throw Error(`Expected TableNode first child to be a RowNode`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const unmerged = [];
|
|
136
|
+
|
|
137
|
+
for (let i = 0; i < rowsCount; i++) {
|
|
138
|
+
if (i !== 0) {
|
|
139
|
+
row = row.getNextSibling();
|
|
140
|
+
|
|
141
|
+
if (!lexical.DEPRECATED_$isGridRowNode(row)) {
|
|
142
|
+
throw Error(`Expected TableNode first child to be a RowNode`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let lastRowCell = null;
|
|
147
|
+
|
|
148
|
+
for (let j = 0; j < columnsCount; j++) {
|
|
149
|
+
const cellMap = gridMap[i][j];
|
|
150
|
+
const cell = cellMap.cell;
|
|
151
|
+
|
|
152
|
+
if (cellMap.startRow === i && cellMap.startColumn === j) {
|
|
153
|
+
lastRowCell = cell;
|
|
154
|
+
unmerged.push(cell);
|
|
155
|
+
} else if (cell.getColSpan() > 1 || cell.getRowSpan() > 1) {
|
|
156
|
+
const newCell = table.$createTableCellNode(cell.__headerState);
|
|
157
|
+
|
|
158
|
+
if (lastRowCell !== null) {
|
|
159
|
+
lastRowCell.insertAfter(newCell);
|
|
160
|
+
} else {
|
|
161
|
+
$insertFirst(row, newCell);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
for (const cell of unmerged) {
|
|
168
|
+
cell.setColSpan(1);
|
|
169
|
+
cell.setRowSpan(1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}, [editor, hasCellMerge]); // Remove cell background color when feature is disabled
|
|
174
|
+
|
|
175
|
+
react.useEffect(() => {
|
|
176
|
+
if (hasCellBackgroundColor) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return editor.registerNodeTransform(table.TableCellNode, node => {
|
|
181
|
+
if (node.getBackgroundColor() !== null) {
|
|
182
|
+
node.setBackgroundColor(null);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}, [editor, hasCellBackgroundColor, hasCellMerge]);
|
|
123
186
|
return null;
|
|
124
187
|
}
|
|
125
188
|
|
|
@@ -4,7 +4,9 @@
|
|
|
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
|
-
exports.TablePlugin=function(){let [
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
'use strict';var c=require("@lexical/react/LexicalComposerContext"),h=require("@lexical/table"),n=require("@lexical/utils"),v=require("lexical"),w=require("react");
|
|
8
|
+
exports.TablePlugin=function({hasCellMerge:q=!0,hasCellBackgroundColor:t=!0}){let [d]=c.useLexicalComposerContext();w.useEffect(()=>{if(!d.hasNodes([h.TableNode,h.TableCellNode,h.TableRowNode]))throw Error("Minified Lexical error #10; visit https://lexical.dev/docs/error?code=10 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.");return d.registerCommand(h.INSERT_TABLE_COMMAND,({columns:a,rows:e,includeHeaders:g})=>{a=h.$createTableNodeWithDimensions(Number(e),
|
|
9
|
+
Number(a),g);n.$insertNodeToNearestRoot(a);a=a.getFirstDescendant();v.$isTextNode(a)&&a.select();return!0},v.COMMAND_PRIORITY_EDITOR)},[d]);w.useEffect(()=>{let a=new Map,e=b=>{const f=b.getKey(),l=d.getElementByKey(f);l&&!a.has(f)&&(b=h.applyTableHandlers(b,l,d),a.set(f,b))};d.getEditorState().read(()=>{let b=v.$nodesOfType(h.TableNode);for(let f of b)h.$isTableNode(f)&&e(f)});let g=d.registerMutationListener(h.TableNode,b=>{for(const [f,l]of b)"created"===l?d.getEditorState().read(()=>{const m=
|
|
10
|
+
v.$getNodeByKey(f);h.$isTableNode(m)&&e(m)}):"destroyed"===l&&(b=a.get(f),void 0!==b&&(b.removeListeners(),a.delete(f)))});return()=>{g();for(let [,b]of a)b.removeListeners()}},[d]);w.useEffect(()=>{if(!q)return d.registerNodeTransform(h.TableCellNode,a=>{if(1<a.getColSpan()||1<a.getRowSpan()){var [,,e]=v.DEPRECATED_$getNodeTriplet(a);[a]=v.DEPRECATED_$computeGridMap(e,a,a);let f=a.length,l=a[0].length;e=e.getFirstChild();if(!v.DEPRECATED_$isGridRowNode(e))throw Error("Expected TableNode first child to be a RowNode");
|
|
11
|
+
let m=[];for(let k=0;k<f;k++){if(0!==k&&(e=e.getNextSibling(),!v.DEPRECATED_$isGridRowNode(e)))throw Error("Expected TableNode first child to be a RowNode");let r=null;for(let p=0;p<l;p++){var g=a[k][p],b=g.cell;if(g.startRow===k&&g.startColumn===p)r=b,m.push(b);else if(1<b.getColSpan()||1<b.getRowSpan())if(b=h.$createTableCellNode(b.__headerState),null!==r)r.insertAfter(b);else{g=e;let u=g.getFirstChild();null!==u?u.insertBefore(b):g.append(b)}}}for(let k of m)k.setColSpan(1),k.setRowSpan(1)}})},
|
|
12
|
+
[d,q]);w.useEffect(()=>{if(!t)return d.registerNodeTransform(h.TableCellNode,a=>{null!==a.getBackgroundColor()&&a.setBackgroundColor(null)})},[d,t,q]);return null}
|
package/LexicalTreeView.d.ts
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/// <reference types="react" />
|
|
9
9
|
import type { LexicalEditor } from 'lexical';
|
|
10
|
-
export declare function TreeView({ timeTravelButtonClassName, timeTravelPanelSliderClassName, timeTravelPanelButtonClassName, viewClassName, timeTravelPanelClassName, editor, }: {
|
|
10
|
+
export declare function TreeView({ treeTypeButtonClassName, timeTravelButtonClassName, timeTravelPanelSliderClassName, timeTravelPanelButtonClassName, viewClassName, timeTravelPanelClassName, editor, }: {
|
|
11
11
|
editor: LexicalEditor;
|
|
12
|
+
treeTypeButtonClassName: string;
|
|
12
13
|
timeTravelButtonClassName: string;
|
|
13
14
|
timeTravelPanelButtonClassName: string;
|
|
14
15
|
timeTravelPanelClassName: string;
|
package/LexicalTreeView.dev.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
+
var html = require('@lexical/html');
|
|
9
10
|
var link = require('@lexical/link');
|
|
10
11
|
var mark = require('@lexical/mark');
|
|
11
12
|
var utils = require('@lexical/utils');
|
|
@@ -33,6 +34,7 @@ const SYMBOLS = Object.freeze({
|
|
|
33
34
|
selectedLine: '>'
|
|
34
35
|
});
|
|
35
36
|
function TreeView({
|
|
37
|
+
treeTypeButtonClassName,
|
|
36
38
|
timeTravelButtonClassName,
|
|
37
39
|
timeTravelPanelSliderClassName,
|
|
38
40
|
timeTravelPanelButtonClassName,
|
|
@@ -43,6 +45,7 @@ function TreeView({
|
|
|
43
45
|
const [timeStampedEditorStates, setTimeStampedEditorStates] = React.useState([]);
|
|
44
46
|
const [content, setContent] = React.useState('');
|
|
45
47
|
const [timeTravelEnabled, setTimeTravelEnabled] = React.useState(false);
|
|
48
|
+
const [showExportDOM, setShowExportDOM] = React.useState(false);
|
|
46
49
|
const playingIndexRef = React.useRef(0);
|
|
47
50
|
const treeElementRef = React.useRef(null);
|
|
48
51
|
const inputRef = React.useRef(null);
|
|
@@ -52,20 +55,20 @@ function TreeView({
|
|
|
52
55
|
const lastEditorStateRef = React.useRef(null);
|
|
53
56
|
const commandsLog = useLexicalCommandsLog(editor);
|
|
54
57
|
const generateTree = React.useCallback(editorState => {
|
|
55
|
-
const treeText = generateContent(editor
|
|
58
|
+
const treeText = generateContent(editor, commandsLog, showExportDOM);
|
|
56
59
|
setContent(treeText);
|
|
57
60
|
|
|
58
61
|
if (!timeTravelEnabled) {
|
|
59
62
|
setTimeStampedEditorStates(currentEditorStates => [...currentEditorStates, [Date.now(), editorState]]);
|
|
60
63
|
}
|
|
61
|
-
}, [commandsLog, editor, timeTravelEnabled]);
|
|
64
|
+
}, [commandsLog, editor, timeTravelEnabled, showExportDOM]);
|
|
62
65
|
React.useEffect(() => {
|
|
63
66
|
const editorState = editor.getEditorState();
|
|
64
67
|
|
|
65
|
-
if (!showLimited && editorState._nodeMap.size
|
|
66
|
-
setContent(generateContent(
|
|
68
|
+
if (!showLimited && editorState._nodeMap.size < 1000) {
|
|
69
|
+
setContent(generateContent(editor, commandsLog, showExportDOM));
|
|
67
70
|
}
|
|
68
|
-
}, [commandsLog, editor, showLimited]);
|
|
71
|
+
}, [commandsLog, editor, showLimited, showExportDOM]);
|
|
69
72
|
React.useEffect(() => {
|
|
70
73
|
return utils.mergeRegister(editor.registerUpdateListener(({
|
|
71
74
|
editorState
|
|
@@ -81,10 +84,10 @@ function TreeView({
|
|
|
81
84
|
|
|
82
85
|
generateTree(editorState);
|
|
83
86
|
}), editor.registerEditableListener(() => {
|
|
84
|
-
const treeText = generateContent(editor
|
|
87
|
+
const treeText = generateContent(editor, commandsLog, showExportDOM);
|
|
85
88
|
setContent(treeText);
|
|
86
89
|
}));
|
|
87
|
-
}, [commandsLog, editor, isLimited, generateTree, showLimited]);
|
|
90
|
+
}, [commandsLog, editor, showExportDOM, isLimited, generateTree, showLimited]);
|
|
88
91
|
const totalEditorStates = timeStampedEditorStates.length;
|
|
89
92
|
React.useEffect(() => {
|
|
90
93
|
if (isPlaying) {
|
|
@@ -160,7 +163,11 @@ function TreeView({
|
|
|
160
163
|
cursor: 'pointer',
|
|
161
164
|
padding: 5
|
|
162
165
|
}
|
|
163
|
-
}, "Show full tree")) : null, !
|
|
166
|
+
}, "Show full tree")) : null, !showLimited ? /*#__PURE__*/React.createElement("button", {
|
|
167
|
+
onClick: () => setShowExportDOM(!showExportDOM),
|
|
168
|
+
className: treeTypeButtonClassName,
|
|
169
|
+
type: "button"
|
|
170
|
+
}, showExportDOM ? 'Tree' : 'Export DOM') : null, !timeTravelEnabled && (showLimited || !isLimited) && totalEditorStates > 2 && /*#__PURE__*/React.createElement("button", {
|
|
164
171
|
onClick: () => {
|
|
165
172
|
const rootElement = editor.getRootElement();
|
|
166
173
|
|
|
@@ -275,7 +282,20 @@ function printGridSelection(selection) {
|
|
|
275
282
|
return `: grid\n └ { grid: ${selection.gridKey}, anchorCell: ${selection.anchor.key}, focusCell: ${selection.focus.key} }`;
|
|
276
283
|
}
|
|
277
284
|
|
|
278
|
-
function generateContent(
|
|
285
|
+
function generateContent(editor, commandsLog, exportDOM) {
|
|
286
|
+
const editorState = editor.getEditorState();
|
|
287
|
+
const editorConfig = editor._config;
|
|
288
|
+
const compositionKey = editor._compositionKey;
|
|
289
|
+
const editable = editor._editable;
|
|
290
|
+
|
|
291
|
+
if (exportDOM) {
|
|
292
|
+
let htmlString = '';
|
|
293
|
+
editorState.read(() => {
|
|
294
|
+
htmlString = printPrettyHTML(html.$generateHtmlFromNodes(editor));
|
|
295
|
+
});
|
|
296
|
+
return htmlString;
|
|
297
|
+
}
|
|
298
|
+
|
|
279
299
|
let res = ' root\n';
|
|
280
300
|
const selectionString = editorState.read(() => {
|
|
281
301
|
const selection = lexical.$getSelection();
|
|
@@ -364,7 +384,7 @@ function printAllTextNodeProperties(node) {
|
|
|
364
384
|
}
|
|
365
385
|
|
|
366
386
|
function printAllLinkNodeProperties(node) {
|
|
367
|
-
return [printTargetProperties(node), printRelProperties(node)].filter(Boolean).join(', ');
|
|
387
|
+
return [printTargetProperties(node), printRelProperties(node), printTitleProperties(node)].filter(Boolean).join(', ');
|
|
368
388
|
}
|
|
369
389
|
|
|
370
390
|
function printDetailProperties(nodeOrSelection) {
|
|
@@ -417,6 +437,16 @@ function printRelProperties(node) {
|
|
|
417
437
|
return str;
|
|
418
438
|
}
|
|
419
439
|
|
|
440
|
+
function printTitleProperties(node) {
|
|
441
|
+
let str = node.getTitle(); // TODO Fix nullish on LinkNode
|
|
442
|
+
|
|
443
|
+
if (str != null) {
|
|
444
|
+
str = 'title: ' + str;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return str;
|
|
448
|
+
}
|
|
449
|
+
|
|
420
450
|
function printSelectedCharsLine({
|
|
421
451
|
indent,
|
|
422
452
|
isSelected,
|
|
@@ -454,6 +484,31 @@ function printSelectedCharsLine({
|
|
|
454
484
|
return [SYMBOLS.selectedLine, indentionChars.join(' '), [...nodePrintSpaces, ...unselectedChars, ...selectedChars].join('')].join(' ') + '\n';
|
|
455
485
|
}
|
|
456
486
|
|
|
487
|
+
function printPrettyHTML(str) {
|
|
488
|
+
const div = document.createElement('div');
|
|
489
|
+
div.innerHTML = str.trim();
|
|
490
|
+
return prettifyHTML(div, 0).innerHTML;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
function prettifyHTML(node, level) {
|
|
494
|
+
const indentBefore = new Array(level++ + 1).join(' ');
|
|
495
|
+
const indentAfter = new Array(level - 1).join(' ');
|
|
496
|
+
let textNode;
|
|
497
|
+
|
|
498
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
499
|
+
textNode = document.createTextNode('\n' + indentBefore);
|
|
500
|
+
node.insertBefore(textNode, node.children[i]);
|
|
501
|
+
prettifyHTML(node.children[i], level);
|
|
502
|
+
|
|
503
|
+
if (node.lastElementChild === node.children[i]) {
|
|
504
|
+
textNode = document.createTextNode('\n' + indentAfter);
|
|
505
|
+
node.appendChild(textNode);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return node;
|
|
510
|
+
}
|
|
511
|
+
|
|
457
512
|
function $getSelectionStartEnd(node, selection) {
|
|
458
513
|
const anchor = selection.anchor;
|
|
459
514
|
const focus = selection.focus;
|
package/LexicalTreeView.prod.js
CHANGED
|
@@ -4,20 +4,21 @@
|
|
|
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
|
-
function
|
|
9
|
-
function
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
{
|
|
22
|
-
|
|
23
|
-
|
|
7
|
+
'use strict';var g=require("@lexical/html"),w=require("@lexical/link"),x=require("@lexical/mark"),I=require("@lexical/utils"),M=require("lexical"),N=require("react");let O=Object.freeze({"\t":"\\t","\n":"\\n"}),P=new RegExp(Object.keys(O).join("|"),"g"),Q=Object.freeze({ancestorHasNextSibling:"|",ancestorIsLastChild:" ",hasNextSibling:"\u251c",isLastChild:"\u2514",selectedChar:"^",selectedLine:">"});
|
|
8
|
+
function R(a){let [b,c]=N.useState([]);N.useEffect(()=>{let l=new Set;for(let [e]of a._commands)l.add(a.registerCommand(e,p=>{c(d=>{d=[...d];d.push({payload:p,type:e.type?e.type:"UNKNOWN"});10<d.length&&d.shift();return d});return!1},M.COMMAND_PRIORITY_HIGH));return()=>l.forEach(e=>e())},[a]);return N.useMemo(()=>b,[b])}
|
|
9
|
+
function U(a){let b="";var c=V(a);b+=`: range ${""!==c?`{ ${c} }`:""} ${""!==a.style?`{ style: ${a.style} } `:""}`;c=a.anchor;a=a.focus;let l=c.offset,e=a.offset;b+=`\n \u251c anchor { key: ${c.key}, offset: ${null===l?"null":l}, type: ${c.type} }`;return b+=`\n \u2514 focus { key: ${a.key}, offset: ${null===e?"null":e}, type: ${a.type} }`}
|
|
10
|
+
function W(a,b,c){let l=a.getEditorState(),e=a._config,p=a._compositionKey,d=a._editable;if(c){let m="";l.read(()=>{var k=g.$generateHtmlFromNodes(a);let t=document.createElement("div");t.innerHTML=k.trim();m=X(t,0).innerHTML});return m}let h=" root\n";c=l.read(()=>{const m=M.$getSelection();Y(M.$getRoot(),(k,t)=>{const y=`(${k.getKey()})`,v=k.getType()||"",q=k.isSelected(),J=x.$isMarkNode(k)?` id: [ ${k.getIDs().join(", ")} ] `:"";var A=h,H=q?Q.selectedLine:" ",F=t.join(" ");if(M.$isTextNode(k)){var n=
|
|
11
|
+
k.getTextContent();var u=0===n.length?"(empty)":`"${Z(n)}"`;n=[V(k),aa(k),ba(k)].filter(Boolean).join(", ");n=[u,0!==n.length?`{ ${n} }`:null].filter(Boolean).join(" ").trim()}else if(w.$isLinkNode(k)){n=k.getURL();n=0===n.length?"(empty)":`"${Z(n)}"`;u=k.getTarget();null!=u&&(u="target: "+u);var B=Boolean;var C=k.getRel();null!=C&&(C="rel: "+C);let r=k.getTitle();null!=r&&(r="title: "+r);u=[u,C,r].filter(B).join(", ");n=[n,0!==u.length?`{ ${u} }`:null].filter(Boolean).join(" ").trim()}else n="";
|
|
12
|
+
h=A+`${H} ${F} ${y} ${v} ${J} ${n}\n`;h+=ca({indent:t,isSelected:q,node:k,nodeKeyDisplay:y,selection:m,typeDisplay:v})});return null===m?": null":M.$isRangeSelection(m)?U(m):M.DEPRECATED_$isGridSelection(m)?`: grid\n \u2514 { grid: ${m.gridKey}, anchorCell: ${m.anchor.key}, focusCell: ${m.focus.key} }`:`: node\n \u2514 [${Array.from(m._nodes).join(", ")}]`});h+="\n selection"+c;h+="\n\n commands:";if(b.length)for(let {type:m,payload:k}of b)h+=`\n \u2514 { type: ${m}, payload: ${k instanceof Event?
|
|
13
|
+
k.constructor.name:k} }`;else h+="\n \u2514 None dispatched.";h+="\n\n editor:";h+=`\n \u2514 namespace ${e.namespace}`;null!==p&&(h+=`\n \u2514 compositionKey ${p}`);return h+=`\n \u2514 editable ${String(d)}`}function Y(a,b,c=[]){a=a.getChildren();let l=a.length;a.forEach((e,p)=>{b(e,c.concat(p===l-1?Q.isLastChild:Q.hasNextSibling));M.$isElementNode(e)&&Y(e,b,c.concat(p===l-1?Q.ancestorIsLastChild:Q.ancestorHasNextSibling))})}
|
|
14
|
+
function Z(a){return Object.entries(O).reduce((b,[c,l])=>b.replace(new RegExp(c,"g"),String(l)),a)}
|
|
15
|
+
let da=[a=>a.hasFormat("bold")&&"Bold",a=>a.hasFormat("code")&&"Code",a=>a.hasFormat("italic")&&"Italic",a=>a.hasFormat("strikethrough")&&"Strikethrough",a=>a.hasFormat("subscript")&&"Subscript",a=>a.hasFormat("superscript")&&"Superscript",a=>a.hasFormat("underline")&&"Underline"],ea=[a=>a.isDirectionless()&&"Directionless",a=>a.isUnmergeable()&&"Unmergeable"],fa=[a=>a.isToken()&&"Token",a=>a.isSegmented()&&"Segmented"];
|
|
16
|
+
function aa(a){let b=ea.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="detail: "+b);return b}function ba(a){let b=fa.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="mode: "+b);return b}function V(a){let b=da.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="format: "+b);return b}
|
|
17
|
+
function ca({indent:a,isSelected:b,node:c,nodeKeyDisplay:l,selection:e,typeDisplay:p}){if(!M.$isTextNode(c)||!M.$isRangeSelection(e)||!b||M.$isElementNode(c))return"";b=e.anchor;var d=e.focus;if(""===c.getTextContent()||b.getNode()===e.focus.getNode()&&b.offset===d.offset)return"";d=e.anchor;let h=e.focus,m=c.getTextContent(),k=m.length;b=e=-1;if("text"===d.type&&"text"===h.type){let v=d.getNode(),q=h.getNode();v===q&&c===v&&d.offset!==h.offset?[e,b]=d.offset<h.offset?[d.offset,h.offset]:[h.offset,
|
|
18
|
+
d.offset]:c===v?[e,b]=v.isBefore(q)?[d.offset,k]:[0,d.offset]:c===q?[e,b]=q.isBefore(v)?[h.offset,k]:[0,h.offset]:[e,b]=[0,k]}c=(m.slice(0,e).match(P)||[]).length;d=(m.slice(e,b).match(P)||[]).length;let [t,y]=[e+c,b+c+d];if(t===y)return"";c=a[a.length-1]===Q.hasNextSibling?Q.ancestorHasNextSibling:Q.ancestorIsLastChild;a=[...a.slice(0,a.length-1),c];c=Array(t+1).fill(" ");e=Array(y-t).fill(Q.selectedChar);l=Array(l.length+(p.length+3)).fill(" ");return[Q.selectedLine,a.join(" "),[...l,...c,...e].join("")].join(" ")+
|
|
19
|
+
"\n"}function X(a,b){let c=Array(b++ +1).join(" "),l=Array(b-1).join(" "),e;for(let p=0;p<a.children.length;p++)e=document.createTextNode("\n"+c),a.insertBefore(e,a.children[p]),X(a.children[p],b),a.lastElementChild===a.children[p]&&(e=document.createTextNode("\n"+l),a.appendChild(e));return a}
|
|
20
|
+
exports.TreeView=function({treeTypeButtonClassName:a,timeTravelButtonClassName:b,timeTravelPanelSliderClassName:c,timeTravelPanelButtonClassName:l,viewClassName:e,timeTravelPanelClassName:p,editor:d}){let [h,m]=N.useState([]),[k,t]=N.useState(""),[y,v]=N.useState(!1),[q,J]=N.useState(!1),A=N.useRef(0),H=N.useRef(null),F=N.useRef(null),[n,u]=N.useState(!1),[B,C]=N.useState(!1),[r,ha]=N.useState(!1),K=N.useRef(null),D=R(d),L=N.useCallback(f=>{const z=W(d,D,q);t(z);y||m(G=>[...G,[Date.now(),f]])},[D,
|
|
21
|
+
d,y,q]);N.useEffect(()=>{let f=d.getEditorState();!r&&1E3>f._nodeMap.size&&t(W(d,D,q))},[D,d,r,q]);N.useEffect(()=>I.mergeRegister(d.registerUpdateListener(({editorState:f})=>{if(!r&&1E3<f._nodeMap.size&&(K.current=f,C(!0),!r))return;L(f)}),d.registerEditableListener(()=>{let f=W(d,D,q);t(f)})),[D,d,q,B,L,r]);let E=h.length;N.useEffect(()=>{if(n){let f,z=()=>{const G=A.current;G===E-1?u(!1):f=setTimeout(()=>{A.current++;const S=A.current,T=F.current;null!==T&&(T.value=String(S));d.setEditorState(h[S][1]);
|
|
22
|
+
z()},h[G+1][0]-h[G][0])};z();return()=>{clearTimeout(f)}}},[h,n,d,E]);N.useEffect(()=>{let f=H.current;if(null!==f)return f.__lexicalEditor=d,()=>{f.__lexicalEditor=null}},[d]);return N.createElement("div",{className:e},!r&&B?N.createElement("div",{style:{padding:20}},N.createElement("span",{style:{marginRight:20}},"Detected large EditorState, this can impact debugging performance."),N.createElement("button",{onClick:()=>{ha(!0);let f=K.current;null!==f&&(K.current=null,L(f))},style:{background:"transparent",
|
|
23
|
+
border:"1px solid white",color:"white",cursor:"pointer",padding:5}},"Show full tree")):null,r?null:N.createElement("button",{onClick:()=>J(!q),className:a,type:"button"},q?"Tree":"Export DOM"),!y&&(r||!B)&&2<E&&N.createElement("button",{onClick:()=>{let f=d.getRootElement();null!==f&&(f.contentEditable="false",A.current=E-1,v(!0))},className:b,type:"button"},"Time Travel"),(r||!B)&&N.createElement("pre",{ref:H},k),y&&(r||!B)&&N.createElement("div",{className:p},N.createElement("button",{className:l,
|
|
24
|
+
onClick:()=>{A.current===E-1&&(A.current=1);u(!n)},type:"button"},n?"Pause":"Play"),N.createElement("input",{className:c,ref:F,onChange:f=>{f=Number(f.target.value);let z=h[f];z&&(A.current=f,d.setEditorState(z[1]))},type:"range",min:"1",max:E-1}),N.createElement("button",{className:l,onClick:()=>{var f=d.getRootElement();if(null!==f){f.contentEditable="true";f=h.length-1;d.setEditorState(h[f][1]);let z=F.current;null!==z&&(z.value=String(f));v(!1);u(!1)}},type:"button"},"Exit")))}
|
|
@@ -56,9 +56,7 @@ class TypeaheadOption {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
const scrollIntoViewIfNeeded = target => {
|
|
59
|
-
const
|
|
60
|
-
if (!container) return;
|
|
61
|
-
const typeaheadContainerNode = container.querySelector('.typeahead-popover');
|
|
59
|
+
const typeaheadContainerNode = document.getElementById('typeahead-menu');
|
|
62
60
|
if (!typeaheadContainerNode) return;
|
|
63
61
|
const typeaheadRect = typeaheadContainerNode.getBoundingClientRect();
|
|
64
62
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
'use strict';var k=require("@lexical/react/LexicalComposerContext"),n=require("@lexical/utils"),x=require("lexical"),y=require("react"),z="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?y.useLayoutEffect:y.useEffect;class A{constructor(c){this.key=c;this.ref={current:null};this.setRefElement=this.setRefElement.bind(this)}setRefElement(c){this.ref={current:c}}}
|
|
8
|
-
let B=c=>{
|
|
8
|
+
let B=c=>{const a=document.getElementById("typeahead-menu");if(a){var b=a.getBoundingClientRect();b.top+b.height>window.innerHeight&&a.scrollIntoView({block:"center"});0>b.top&&a.scrollIntoView({block:"center"});c.scrollIntoView({block:"nearest"})}};function C(c,a){var b=window.getSelection();if(null===b||!b.isCollapsed)return!1;let e=b.anchorNode;b=b.anchorOffset;if(null==e||null==b)return!1;try{a.setStart(e,c),a.setEnd(e,b)}catch(g){return!1}return!0}
|
|
9
9
|
function D(c){let a=null;c.getEditorState().read(()=>{var b=x.$getSelection();if(x.$isRangeSelection(b)){var e=b.anchor;"text"!==e.type?a=null:(b=e.getNode(),b.isSimpleText()?(e=e.offset,a=b.getTextContent().slice(0,e)):a=null)}});return a}
|
|
10
10
|
function E(c,a){c=x.$getSelection();if(!x.$isRangeSelection(c)||!c.isCollapsed())return null;var b=c.anchor;if("text"!==b.type)return null;c=b.getNode();if(!c.isSimpleText())return null;b=b.offset;let e=c.getTextContent().slice(0,b);var g=a.matchingString;a=a.replaceableString.length;for(let p=a;p<=g.length;p++)e.substr(-p)===g.substr(0,p)&&(a=p);a=b-a;if(0>a)return null;let q;0===a?[q]=c.splitText(b):[,q]=c.splitText(a,b);return q}
|
|
11
11
|
function F(c,a){return 0!==a?!1:c.getEditorState().read(()=>{var b=x.$getSelection();return x.$isRangeSelection(b)?(b=b.anchor.getNode().getPreviousSibling(),x.$isTextNode(b)&&b.isTextEntity()):!1})}function G(c){y.startTransition?y.startTransition(c):c()}
|
package/package.json
CHANGED
|
@@ -8,29 +8,29 @@
|
|
|
8
8
|
"rich-text"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.
|
|
11
|
+
"version": "0.10.0",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@lexical/clipboard": "0.
|
|
14
|
-
"@lexical/code": "0.
|
|
15
|
-
"@lexical/dragon": "0.
|
|
16
|
-
"@lexical/hashtag": "0.
|
|
17
|
-
"@lexical/history": "0.
|
|
18
|
-
"@lexical/link": "0.
|
|
19
|
-
"@lexical/list": "0.
|
|
20
|
-
"@lexical/mark": "0.
|
|
21
|
-
"@lexical/markdown": "0.
|
|
22
|
-
"@lexical/overflow": "0.
|
|
23
|
-
"@lexical/plain-text": "0.
|
|
24
|
-
"@lexical/rich-text": "0.
|
|
25
|
-
"@lexical/selection": "0.
|
|
26
|
-
"@lexical/table": "0.
|
|
27
|
-
"@lexical/text": "0.
|
|
28
|
-
"@lexical/utils": "0.
|
|
29
|
-
"@lexical/yjs": "0.
|
|
13
|
+
"@lexical/clipboard": "0.10.0",
|
|
14
|
+
"@lexical/code": "0.10.0",
|
|
15
|
+
"@lexical/dragon": "0.10.0",
|
|
16
|
+
"@lexical/hashtag": "0.10.0",
|
|
17
|
+
"@lexical/history": "0.10.0",
|
|
18
|
+
"@lexical/link": "0.10.0",
|
|
19
|
+
"@lexical/list": "0.10.0",
|
|
20
|
+
"@lexical/mark": "0.10.0",
|
|
21
|
+
"@lexical/markdown": "0.10.0",
|
|
22
|
+
"@lexical/overflow": "0.10.0",
|
|
23
|
+
"@lexical/plain-text": "0.10.0",
|
|
24
|
+
"@lexical/rich-text": "0.10.0",
|
|
25
|
+
"@lexical/selection": "0.10.0",
|
|
26
|
+
"@lexical/table": "0.10.0",
|
|
27
|
+
"@lexical/text": "0.10.0",
|
|
28
|
+
"@lexical/utils": "0.10.0",
|
|
29
|
+
"@lexical/yjs": "0.10.0",
|
|
30
30
|
"react-error-boundary": "^3.1.4"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"lexical": "0.
|
|
33
|
+
"lexical": "0.10.0",
|
|
34
34
|
"react": ">=17.x",
|
|
35
35
|
"react-dom": ">=17.x"
|
|
36
36
|
},
|
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
import type { Binding, Provider } from '@lexical/yjs';
|
|
8
|
+
import type { Binding, ExcludedProperties, Provider } from '@lexical/yjs';
|
|
9
9
|
import type { LexicalEditor } from 'lexical';
|
|
10
10
|
import * as React from 'react';
|
|
11
11
|
import { Doc } from 'yjs';
|
|
12
12
|
import { InitialEditorStateType } from '../LexicalComposer';
|
|
13
13
|
export declare type CursorsContainerRef = React.MutableRefObject<HTMLElement | null>;
|
|
14
|
-
export declare function useYjsCollaboration(editor: LexicalEditor, id: string, provider: Provider, docMap: Map<string, Doc>, name: string, color: string, shouldBootstrap: boolean, cursorsContainerRef?: CursorsContainerRef, initialEditorState?: InitialEditorStateType): [JSX.Element, Binding];
|
|
14
|
+
export declare function useYjsCollaboration(editor: LexicalEditor, id: string, provider: Provider, docMap: Map<string, Doc>, name: string, color: string, shouldBootstrap: boolean, cursorsContainerRef?: CursorsContainerRef, initialEditorState?: InitialEditorStateType, excludedProperties?: ExcludedProperties): [JSX.Element, Binding];
|
|
15
15
|
export declare function useYjsFocusTracking(editor: LexicalEditor, provider: Provider, name: string, color: string): void;
|
|
16
16
|
export declare function useYjsHistory(editor: LexicalEditor, binding: Binding): () => void;
|