@lexical/react 0.3.8 → 0.3.9
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 +46 -0
- package/LexicalAutoEmbedPlugin.dev.js +490 -0
- package/LexicalAutoEmbedPlugin.js +9 -0
- package/LexicalAutoEmbedPlugin.prod.js +21 -0
- package/LexicalAutoLinkPlugin.dev.js +1 -1
- package/LexicalAutoLinkPlugin.prod.js +2 -2
- package/LexicalCollaborationContext.d.ts +19 -0
- package/LexicalCollaborationContext.dev.js +38 -0
- package/LexicalCollaborationContext.js +9 -0
- package/LexicalCollaborationContext.js.flow +21 -0
- package/LexicalCollaborationContext.prod.js +8 -0
- package/LexicalCollaborationPlugin.d.ts +0 -10
- package/LexicalCollaborationPlugin.dev.js +12 -20
- package/LexicalCollaborationPlugin.js.flow +0 -9
- package/LexicalCollaborationPlugin.prod.js +9 -10
- package/LexicalLinkPlugin.dev.js +15 -2
- package/LexicalLinkPlugin.prod.js +2 -1
- package/LexicalNestedComposer.dev.js +11 -5
- package/LexicalNestedComposer.prod.js +3 -3
- package/LexicalOnChangePlugin.d.ts +2 -1
- package/LexicalOnChangePlugin.dev.js +6 -3
- package/LexicalOnChangePlugin.js.flow +2 -0
- package/LexicalOnChangePlugin.prod.js +2 -2
- package/LexicalTableOfContents__EXPERIMENTAL.js.flow +2 -2
- package/LexicalTreeView.dev.js +43 -9
- package/LexicalTreeView.prod.js +13 -13
- package/LexicalTypeaheadMenuPlugin.d.ts +11 -3
- package/LexicalTypeaheadMenuPlugin.dev.js +115 -58
- package/LexicalTypeaheadMenuPlugin.prod.js +16 -13
- package/package.json +19 -19
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
import type {Doc} from 'yjs';
|
|
11
|
+
|
|
12
|
+
type CollaborationContextType = {
|
|
13
|
+
clientID: number,
|
|
14
|
+
color: string,
|
|
15
|
+
isCollabActive: boolean,
|
|
16
|
+
name: string,
|
|
17
|
+
yjsDocMap: Map<string, Doc>,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
declare export var CollaborationContext: React$Context<CollaborationContextType>;
|
|
21
|
+
declare export function useCollaborationContext(): CollaborationContextType;
|
|
@@ -0,0 +1,8 @@
|
|
|
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 a=require("react");let b=[["Cat","255,165,0"],["Dog","0,200,55"],["Rabbit","160,0,200"],["Frog","0,172,200"],["Fox","197,200,0"],["Hedgehog","31,200,0"],["Pigeon","200,0,0"],["Squirrel","200,0,148"],["Bear","255,235,0"],["Tiger","86,255,0"],["Leopard","0,255,208"],["Zebra","0,243,255"],["Wolf","0,102,255"],["Owl","147,0,255"],["Gull","255,0,153"],["Squid","0,220,255"]],c=b[Math.floor(Math.random()*b.length)],d=a.createContext({clientID:0,color:c[1],isCollabActive:!1,name:c[0],yjsDocMap:new Map});
|
|
8
|
+
exports.CollaborationContext=d;exports.useCollaborationContext=function(e){let f=a.useContext(d);null!=e&&(f.name=e);return f}
|
|
@@ -5,21 +5,11 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
/// <reference types="react" />
|
|
9
8
|
import type { Doc } from 'yjs';
|
|
10
9
|
import { WebsocketProvider } from 'y-websocket';
|
|
11
|
-
declare type CollaborationContextType = {
|
|
12
|
-
clientID: number;
|
|
13
|
-
color: string;
|
|
14
|
-
name: string;
|
|
15
|
-
yjsDocMap: Map<string, Doc>;
|
|
16
|
-
};
|
|
17
10
|
export declare function CollaborationPlugin({ id, providerFactory, shouldBootstrap, username, }: {
|
|
18
11
|
id: string;
|
|
19
12
|
providerFactory: (id: string, yjsDocMap: Map<string, Doc>) => WebsocketProvider;
|
|
20
13
|
shouldBootstrap: boolean;
|
|
21
14
|
username?: string;
|
|
22
15
|
}): JSX.Element;
|
|
23
|
-
export declare const CollaborationContext: React.Context<CollaborationContextType>;
|
|
24
|
-
export declare function useCollaborationContext(username?: string): CollaborationContextType;
|
|
25
|
-
export {};
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
+
var LexicalCollaborationContext = require('@lexical/react/LexicalCollaborationContext');
|
|
9
10
|
var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
|
|
10
11
|
var React = require('react');
|
|
11
12
|
var utils = require('@lexical/utils');
|
|
@@ -241,21 +242,29 @@ function clearEditorSkipCollab(editor, binding) {
|
|
|
241
242
|
* LICENSE file in the root directory of this source tree.
|
|
242
243
|
*
|
|
243
244
|
*/
|
|
244
|
-
const entries = [['Cat', '255,165,0'], ['Dog', '0,200,55'], ['Rabbit', '160,0,200'], ['Frog', '0,172,200'], ['Fox', '197,200,0'], ['Hedgehog', '31,200,0'], ['Pigeon', '200,0,0'], ['Squirrel', '200,0,148'], ['Bear', '255,235,0'], ['Tiger', '86,255,0'], ['Leopard', '0,255,208'], ['Zebra', '0,243,255'], ['Wolf', '0,102,255'], ['Owl', '147,0,255'], ['Gull', '255,0,153'], ['Squid', '0,220,255']];
|
|
245
|
-
const randomEntry = entries[Math.floor(Math.random() * entries.length)];
|
|
246
245
|
function CollaborationPlugin({
|
|
247
246
|
id,
|
|
248
247
|
providerFactory,
|
|
249
248
|
shouldBootstrap,
|
|
250
249
|
username
|
|
251
250
|
}) {
|
|
252
|
-
const collabContext = useCollaborationContext(username);
|
|
251
|
+
const collabContext = LexicalCollaborationContext.useCollaborationContext(username);
|
|
253
252
|
const {
|
|
254
253
|
yjsDocMap,
|
|
255
254
|
name,
|
|
256
255
|
color
|
|
257
256
|
} = collabContext;
|
|
258
257
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
258
|
+
React.useEffect(() => {
|
|
259
|
+
collabContext.isCollabActive = true;
|
|
260
|
+
return () => {
|
|
261
|
+
// Reseting flag only when unmount top level editor collab plugin. Nested
|
|
262
|
+
// editors (e.g. image caption) should unmount without affecting it
|
|
263
|
+
if (editor._parentEditor == null) {
|
|
264
|
+
collabContext.isCollabActive = false;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}, [collabContext, editor]);
|
|
259
268
|
const provider = React.useMemo(() => providerFactory(id, yjsDocMap), [id, providerFactory, yjsDocMap]);
|
|
260
269
|
const [cursors, binding] = useYjsCollaboration(editor, id, provider, yjsDocMap, name, color, shouldBootstrap);
|
|
261
270
|
collabContext.clientID = binding.clientID;
|
|
@@ -263,22 +272,5 @@ function CollaborationPlugin({
|
|
|
263
272
|
useYjsFocusTracking(editor, provider, name, color);
|
|
264
273
|
return cursors;
|
|
265
274
|
}
|
|
266
|
-
const CollaborationContext = /*#__PURE__*/React.createContext({
|
|
267
|
-
clientID: 0,
|
|
268
|
-
color: randomEntry[1],
|
|
269
|
-
name: randomEntry[0],
|
|
270
|
-
yjsDocMap: new Map()
|
|
271
|
-
});
|
|
272
|
-
function useCollaborationContext(username) {
|
|
273
|
-
const collabContext = React.useContext(CollaborationContext);
|
|
274
|
-
|
|
275
|
-
if (username != null) {
|
|
276
|
-
collabContext.name = username;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return collabContext;
|
|
280
|
-
}
|
|
281
275
|
|
|
282
|
-
exports.CollaborationContext = CollaborationContext;
|
|
283
276
|
exports.CollaborationPlugin = CollaborationPlugin;
|
|
284
|
-
exports.useCollaborationContext = useCollaborationContext;
|
|
@@ -41,13 +41,6 @@ export interface Provider {
|
|
|
41
41
|
off(type: 'reload', cb: (doc: Doc) => void): void;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
type CollaborationContextType = {
|
|
45
|
-
clientID: number,
|
|
46
|
-
color: string,
|
|
47
|
-
name: string,
|
|
48
|
-
yjsDocMap: Map<string, Doc>,
|
|
49
|
-
};
|
|
50
|
-
|
|
51
44
|
export type ProviderFactory = (
|
|
52
45
|
id: string,
|
|
53
46
|
yjsDocMap: Map<string, Doc>,
|
|
@@ -59,5 +52,3 @@ declare export function CollaborationPlugin(arg0: {
|
|
|
59
52
|
shouldBootstrap: boolean,
|
|
60
53
|
username?: string,
|
|
61
54
|
}): React$Node;
|
|
62
|
-
declare export var CollaborationContext: React$Context<CollaborationContextType>;
|
|
63
|
-
declare export function useCollaborationContext(): CollaborationContextType;
|
|
@@ -4,13 +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/
|
|
8
|
-
function
|
|
9
|
-
a,
|
|
10
|
-
y.off("update",B);m.getSharedType().unobserveDeep(C);d.delete(c);
|
|
11
|
-
function
|
|
12
|
-
function
|
|
13
|
-
function
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
function U(b){let c=f.useContext(T);null!=b&&(c.name=b);return c}exports.CollaborationContext=T;exports.CollaborationPlugin=function({id:b,providerFactory:c,shouldBootstrap:a,username:d}){d=U(d);let {yjsDocMap:l,name:p,color:q}=d,[n]=e.useLexicalComposerContext(),r=f.useMemo(()=>c(b,l),[b,c,l]),[v,g]=H(n,b,r,l,p,q,a);d.clientID=g.clientID;L(n,g);K(n,r,p,q);return v};exports.useCollaborationContext=U
|
|
7
|
+
'use strict';var e=require("@lexical/react/LexicalCollaborationContext"),f=require("@lexical/react/LexicalComposerContext"),k=require("react"),x=require("@lexical/utils"),F=require("@lexical/yjs"),G=require("lexical"),H=require("react-dom");
|
|
8
|
+
function I(b,c,a,d,h,q,r){let p=k.useRef(!1),[n,v]=k.useState(d.get(c)),g=k.useMemo(()=>F.createBinding(b,a,c,n,d),[b,a,c,d,n]),t=k.useCallback(()=>{a.connect()},[a]),u=k.useCallback(()=>{try{a.disconnect()}catch(m){}},[a]);k.useEffect(()=>{let {root:m}=g,{awareness:y}=a,z=({status:l})=>{b.dispatchCommand(F.CONNECTED_COMMAND,"connected"===l)},A=l=>{r&&l&&m.isEmpty()&&0===m._xmlText._length&&!1===p.current&&J(b);p.current=!1},B=()=>{F.syncCursorPositions(g,a)},C=(l,w)=>{w.origin!==g&&F.syncYjsChangesToLexical(g,
|
|
9
|
+
a,l)};F.initLocalState(a,h,q,document.activeElement===b.getRootElement());let D=l=>{K(b,g);v(l);d.set(c,l);p.current=!0};a.on("reload",D);a.on("status",z);a.on("sync",A);y.on("update",B);m.getSharedType().observeDeep(C);let O=b.registerUpdateListener(({prevEditorState:l,editorState:w,dirtyLeaves:L,dirtyElements:M,normalizedNodes:N,tags:E})=>{!1===E.has("skip-collab")&&F.syncLexicalUpdateToYjs(g,a,l,w,M,L,N,E)});t();return()=>{!1===p.current&&u();a.off("sync",A);a.off("status",z);a.off("reload",D);
|
|
10
|
+
y.off("update",B);m.getSharedType().unobserveDeep(C);d.delete(c);O()}},[g,q,t,u,d,b,c,h,a,r]);let P=k.useMemo(()=>H.createPortal(k.createElement("div",{ref:m=>{g.cursorsContainer=m}}),document.body),[g]);k.useEffect(()=>b.registerCommand(F.TOGGLE_CONNECT_COMMAND,m=>{void 0!==t&&void 0!==u&&(m?(console.log("Collaboration connected!"),t()):(console.log("Collaboration disconnected!"),u()));return!0},G.COMMAND_PRIORITY_EDITOR),[t,u,b]);return[P,g]}
|
|
11
|
+
function Q(b,c,a,d){k.useEffect(()=>x.mergeRegister(b.registerCommand(G.FOCUS_COMMAND,()=>{F.setLocalStateFocus(c,a,d,!0);return!0},G.COMMAND_PRIORITY_EDITOR),b.registerCommand(G.BLUR_COMMAND,()=>{F.setLocalStateFocus(c,a,d,!1);return!0},G.COMMAND_PRIORITY_EDITOR)),[d,b,a,c])}
|
|
12
|
+
function R(b,c){let a=k.useMemo(()=>F.createUndoManager(c,c.root.getSharedType()),[c]);k.useEffect(()=>x.mergeRegister(b.registerCommand(G.UNDO_COMMAND,()=>{a.undo();return!0},G.COMMAND_PRIORITY_EDITOR),b.registerCommand(G.REDO_COMMAND,()=>{a.redo();return!0},G.COMMAND_PRIORITY_EDITOR)));return k.useCallback(()=>{a.clear()},[a])}
|
|
13
|
+
function J(b){b.update(()=>{var c=G.$getRoot();if(null===c.getFirstChild()){let a=G.$createParagraphNode();c.append(a);c=document.activeElement;(null!==G.$getSelection()||null!==c&&c===b.getRootElement())&&a.select()}},{tag:"history-merge"})}
|
|
14
|
+
function K(b,c){b.update(()=>{let d=G.$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 h=0;h<a.length;h++)c.removeChild(a[d])}}}}
|
|
15
|
+
exports.CollaborationPlugin=function({id:b,providerFactory:c,shouldBootstrap:a,username:d}){let h=e.useCollaborationContext(d),{yjsDocMap:q,name:r,color:p}=h,[n]=f.useLexicalComposerContext();k.useEffect(()=>{h.isCollabActive=!0;return()=>{null==n._parentEditor&&(h.isCollabActive=!1)}},[h,n]);d=k.useMemo(()=>c(b,q),[b,c,q]);let [v,g]=I(n,b,d,q,r,p,a);h.clientID=g.clientID;R(n,g);Q(n,d,r,p);return v}
|
package/LexicalLinkPlugin.dev.js
CHANGED
|
@@ -26,8 +26,21 @@ function LinkPlugin() {
|
|
|
26
26
|
}
|
|
27
27
|
}, [editor]);
|
|
28
28
|
react.useEffect(() => {
|
|
29
|
-
return editor.registerCommand(link.TOGGLE_LINK_COMMAND,
|
|
30
|
-
|
|
29
|
+
return editor.registerCommand(link.TOGGLE_LINK_COMMAND, payload => {
|
|
30
|
+
if (typeof payload === 'string' || payload === null) {
|
|
31
|
+
link.toggleLink(payload);
|
|
32
|
+
} else {
|
|
33
|
+
const {
|
|
34
|
+
url,
|
|
35
|
+
target,
|
|
36
|
+
rel
|
|
37
|
+
} = payload;
|
|
38
|
+
link.toggleLink(url, {
|
|
39
|
+
rel,
|
|
40
|
+
target
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
31
44
|
return true;
|
|
32
45
|
}, lexical.COMMAND_PRIORITY_EDITOR);
|
|
33
46
|
}, [editor]);
|
|
@@ -4,4 +4,5 @@
|
|
|
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
|
|
7
|
+
'use strict';var a=require("@lexical/link"),d=require("@lexical/react/LexicalComposerContext"),e=require("lexical"),f=require("react");
|
|
8
|
+
exports.LinkPlugin=function(){let [b]=d.useLexicalComposerContext();f.useEffect(()=>{if(!b.hasNodes([a.LinkNode]))throw Error("LinkPlugin: LinkNode not registered on editor");},[b]);f.useEffect(()=>b.registerCommand(a.TOGGLE_LINK_COMMAND,c=>{if("string"===typeof c||null===c)a.toggleLink(c);else{let {url:g,target:h,rel:k}=c;a.toggleLink(g,{rel:k,target:h})}return!0},e.COMMAND_PRIORITY_EDITOR),[b]);return null}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
var
|
|
9
|
+
var LexicalCollaborationContext = require('@lexical/react/LexicalCollaborationContext');
|
|
10
10
|
var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
|
|
11
11
|
var React = require('react');
|
|
12
12
|
|
|
@@ -22,6 +22,7 @@ function LexicalNestedComposer({
|
|
|
22
22
|
children,
|
|
23
23
|
initialTheme
|
|
24
24
|
}) {
|
|
25
|
+
const wasCollabPreviouslyReadyRef = React.useRef(false);
|
|
25
26
|
const parentContext = React.useContext(LexicalComposerContext.LexicalComposerContext);
|
|
26
27
|
|
|
27
28
|
if (parentContext == null) {
|
|
@@ -49,13 +50,18 @@ function LexicalNestedComposer({
|
|
|
49
50
|
// until the collaboration subdocument is ready.
|
|
50
51
|
|
|
51
52
|
const {
|
|
53
|
+
isCollabActive,
|
|
52
54
|
yjsDocMap
|
|
53
|
-
} =
|
|
54
|
-
const
|
|
55
|
-
|
|
55
|
+
} = LexicalCollaborationContext.useCollaborationContext();
|
|
56
|
+
const isCollabReady = wasCollabPreviouslyReadyRef.current || yjsDocMap.has(initialEditor.getKey());
|
|
57
|
+
React.useEffect(() => {
|
|
58
|
+
if (isCollabReady) {
|
|
59
|
+
wasCollabPreviouslyReadyRef.current = true;
|
|
60
|
+
}
|
|
61
|
+
}, [isCollabReady]);
|
|
56
62
|
return /*#__PURE__*/React.createElement(LexicalComposerContext.LexicalComposerContext.Provider, {
|
|
57
63
|
value: composerContext
|
|
58
|
-
}, !
|
|
64
|
+
}, !isCollabActive || isCollabReady ? children : null);
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
exports.LexicalNestedComposer = LexicalNestedComposer;
|
|
@@ -4,6 +4,6 @@
|
|
|
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.LexicalNestedComposer=function({initialEditor:a,children:
|
|
9
|
-
a._config.namespace=
|
|
7
|
+
'use strict';var b=require("@lexical/react/LexicalCollaborationContext"),c=require("@lexical/react/LexicalComposerContext"),k=require("react");
|
|
8
|
+
exports.LexicalNestedComposer=function({initialEditor:a,children:l,initialTheme:m}){let h=k.useRef(!1),d=k.useContext(c.LexicalComposerContext);if(null==d)throw Error("Minified Lexical error #9; visit https://lexical.dev/docs/error?code=9 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.");let q=k.useMemo(()=>{const [e,n]=d,f=m||n.getTheme()||void 0,p=c.createLexicalComposerContext(d,f);void 0!==f&&(a._config.theme=f);a._parentEditor=e;a._nodes=
|
|
9
|
+
e._nodes;a._config.namespace=e._config.namespace;return[a,p]},[]),{isCollabActive:r,yjsDocMap:t}=b.useCollaborationContext(),g=h.current||t.has(a.getKey());k.useEffect(()=>{g&&(h.current=!0)},[g]);return k.createElement(c.LexicalComposerContext.Provider,{value:q},!r||g?l:null)}
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
import type { EditorState, LexicalEditor } from 'lexical';
|
|
9
|
-
export declare function OnChangePlugin({ ignoreInitialChange, ignoreSelectionChange, onChange, }: {
|
|
9
|
+
export declare function OnChangePlugin({ ignoreHistoryMergeTagChange, ignoreInitialChange, ignoreSelectionChange, onChange, }: {
|
|
10
|
+
ignoreHistoryMergeTagChange?: boolean;
|
|
10
11
|
ignoreInitialChange?: boolean;
|
|
11
12
|
ignoreSelectionChange?: boolean;
|
|
12
13
|
onChange: (editorState: EditorState, editor: LexicalEditor) => void;
|
|
@@ -36,6 +36,8 @@ var useLayoutEffect = useLayoutEffectImpl;
|
|
|
36
36
|
*
|
|
37
37
|
*/
|
|
38
38
|
function OnChangePlugin({
|
|
39
|
+
// TODO 0.4 flip to true
|
|
40
|
+
ignoreHistoryMergeTagChange = false,
|
|
39
41
|
ignoreInitialChange = true,
|
|
40
42
|
ignoreSelectionChange = false,
|
|
41
43
|
onChange
|
|
@@ -47,9 +49,10 @@ function OnChangePlugin({
|
|
|
47
49
|
editorState,
|
|
48
50
|
dirtyElements,
|
|
49
51
|
dirtyLeaves,
|
|
50
|
-
prevEditorState
|
|
52
|
+
prevEditorState,
|
|
53
|
+
tags
|
|
51
54
|
}) => {
|
|
52
|
-
if (ignoreSelectionChange && dirtyElements.size === 0 && dirtyLeaves.size === 0) {
|
|
55
|
+
if (ignoreSelectionChange && dirtyElements.size === 0 && dirtyLeaves.size === 0 || ignoreHistoryMergeTagChange && tags.has('history-merge')) {
|
|
53
56
|
return;
|
|
54
57
|
}
|
|
55
58
|
|
|
@@ -60,7 +63,7 @@ function OnChangePlugin({
|
|
|
60
63
|
onChange(editorState, editor);
|
|
61
64
|
});
|
|
62
65
|
}
|
|
63
|
-
}, [editor, ignoreInitialChange, ignoreSelectionChange, onChange]);
|
|
66
|
+
}, [editor, ignoreHistoryMergeTagChange, ignoreInitialChange, ignoreSelectionChange, onChange]);
|
|
64
67
|
return null;
|
|
65
68
|
}
|
|
66
69
|
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
import type {EditorState, LexicalEditor} from 'lexical';
|
|
11
11
|
|
|
12
12
|
declare export function OnChangePlugin({
|
|
13
|
+
ignoreHistoryMergeTagChange?: boolean,
|
|
14
|
+
// TODO 0.4 remove
|
|
13
15
|
ignoreInitialChange?: boolean,
|
|
14
16
|
ignoreSelectionChange?: boolean,
|
|
15
17
|
onChange: (editorState: EditorState, editor: LexicalEditor) => void,
|
|
@@ -4,5 +4,5 @@
|
|
|
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 c=require("@lexical/react/LexicalComposerContext"),
|
|
8
|
-
exports.OnChangePlugin=function({
|
|
7
|
+
'use strict';var c=require("@lexical/react/LexicalComposerContext"),g=require("react"),h="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?g.useLayoutEffect:g.useEffect;
|
|
8
|
+
exports.OnChangePlugin=function({ignoreHistoryMergeTagChange:d=!1,ignoreInitialChange:e=!0,ignoreSelectionChange:f=!1,onChange:a}){let [b]=c.useLexicalComposerContext();h(()=>{if(a)return b.registerUpdateListener(({editorState:k,dirtyElements:l,dirtyLeaves:m,prevEditorState:n,tags:p})=>{f&&0===l.size&&0===m.size||d&&p.has("history-merge")||e&&n.isEmpty()||a(k,b)})},[b,d,e,f,a]);return null}
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
import type {HeadingTagType} from '@lexical/rich-text';
|
|
11
11
|
import type {NodeKey} from 'lexical';
|
|
12
12
|
|
|
13
|
-
declare export function LexicalTableOfContentsPlugin(
|
|
13
|
+
declare export function LexicalTableOfContentsPlugin({
|
|
14
14
|
children: (
|
|
15
15
|
tableOfContents: Array<[NodeKey, string, HeadingTagType]>,
|
|
16
16
|
) => React$Node,
|
|
17
|
-
): React$Node;
|
|
17
|
+
}): React$Node;
|
package/LexicalTreeView.dev.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
+
var link = require('@lexical/link');
|
|
9
10
|
var mark = require('@lexical/mark');
|
|
10
11
|
var lexical = require('lexical');
|
|
11
12
|
var React = require('react');
|
|
@@ -92,7 +93,7 @@ function TreeView({
|
|
|
92
93
|
|
|
93
94
|
play();
|
|
94
95
|
return () => {
|
|
95
|
-
|
|
96
|
+
clearTimeout(timeoutId);
|
|
96
97
|
};
|
|
97
98
|
}
|
|
98
99
|
}, [timeStampedEditorStates, isPlaying, editor, totalEditorStates]);
|
|
@@ -120,7 +121,8 @@ function TreeView({
|
|
|
120
121
|
setTimeTravelEnabled(true);
|
|
121
122
|
}
|
|
122
123
|
},
|
|
123
|
-
className: timeTravelButtonClassName
|
|
124
|
+
className: timeTravelButtonClassName,
|
|
125
|
+
type: "button"
|
|
124
126
|
}, "Time Travel"), /*#__PURE__*/React.createElement("pre", {
|
|
125
127
|
ref: treeElementRef
|
|
126
128
|
}, content), timeTravelEnabled && /*#__PURE__*/React.createElement("div", {
|
|
@@ -129,7 +131,8 @@ function TreeView({
|
|
|
129
131
|
className: timeTravelPanelButtonClassName,
|
|
130
132
|
onClick: () => {
|
|
131
133
|
setIsPlaying(!isPlaying);
|
|
132
|
-
}
|
|
134
|
+
},
|
|
135
|
+
type: "button"
|
|
133
136
|
}, isPlaying ? 'Pause' : 'Play'), /*#__PURE__*/React.createElement("input", {
|
|
134
137
|
className: timeTravelPanelSliderClassName,
|
|
135
138
|
ref: inputRef,
|
|
@@ -164,7 +167,8 @@ function TreeView({
|
|
|
164
167
|
setTimeTravelEnabled(false);
|
|
165
168
|
setIsPlaying(false);
|
|
166
169
|
}
|
|
167
|
-
}
|
|
170
|
+
},
|
|
171
|
+
type: "button"
|
|
168
172
|
}, "Exit")));
|
|
169
173
|
}
|
|
170
174
|
|
|
@@ -228,27 +232,37 @@ function visitTree(currentNode, visitor, indent = []) {
|
|
|
228
232
|
|
|
229
233
|
function normalize(text) {
|
|
230
234
|
return Object.entries(NON_SINGLE_WIDTH_CHARS_REPLACEMENT).reduce((acc, [key, value]) => acc.replace(new RegExp(key, 'g'), String(value)), text);
|
|
231
|
-
}
|
|
235
|
+
} // TODO Pass via props to allow customizability
|
|
236
|
+
|
|
232
237
|
|
|
233
238
|
function printNode(node) {
|
|
234
239
|
if (lexical.$isTextNode(node)) {
|
|
235
240
|
const text = node.getTextContent(true);
|
|
236
241
|
const title = text.length === 0 ? '(empty)' : `"${normalize(text)}"`;
|
|
237
|
-
const properties =
|
|
242
|
+
const properties = printAllTextNodeProperties(node);
|
|
238
243
|
return [title, properties.length !== 0 ? `{ ${properties} }` : null].filter(Boolean).join(' ').trim();
|
|
244
|
+
} else if (link.$isLinkNode(node)) {
|
|
245
|
+
const link = node.getURL();
|
|
246
|
+
const title = link.length === 0 ? '(empty)' : `"${normalize(link)}"`;
|
|
247
|
+
const properties = printAllLinkNodeProperties(node);
|
|
248
|
+
return [title, properties.length !== 0 ? `{ ${properties} }` : null].filter(Boolean).join(' ').trim();
|
|
249
|
+
} else {
|
|
250
|
+
return '';
|
|
239
251
|
}
|
|
240
|
-
|
|
241
|
-
return '';
|
|
242
252
|
}
|
|
243
253
|
|
|
244
254
|
const FORMAT_PREDICATES = [node => node.hasFormat('bold') && 'Bold', node => node.hasFormat('code') && 'Code', node => node.hasFormat('italic') && 'Italic', node => node.hasFormat('strikethrough') && 'Strikethrough', node => node.hasFormat('subscript') && 'Subscript', node => node.hasFormat('superscript') && 'Superscript', node => node.hasFormat('underline') && 'Underline'];
|
|
245
255
|
const DETAIL_PREDICATES = [node => node.isDirectionless() && 'Directionless', node => node.isUnmergeable() && 'Unmergeable'];
|
|
246
256
|
const MODE_PREDICATES = [node => node.isToken() && 'Token', node => node.isSegmented() && 'Segmented', node => node.isInert() && 'Inert'];
|
|
247
257
|
|
|
248
|
-
function
|
|
258
|
+
function printAllTextNodeProperties(node) {
|
|
249
259
|
return [printFormatProperties(node), printDetailProperties(node), printModeProperties(node)].filter(Boolean).join(', ');
|
|
250
260
|
}
|
|
251
261
|
|
|
262
|
+
function printAllLinkNodeProperties(node) {
|
|
263
|
+
return [printTargetProperties(node), printRelProperties(node)].filter(Boolean).join(', ');
|
|
264
|
+
}
|
|
265
|
+
|
|
252
266
|
function printDetailProperties(nodeOrSelection) {
|
|
253
267
|
let str = DETAIL_PREDICATES.map(predicate => predicate(nodeOrSelection)).filter(Boolean).join(', ').toLocaleLowerCase();
|
|
254
268
|
|
|
@@ -279,6 +293,26 @@ function printFormatProperties(nodeOrSelection) {
|
|
|
279
293
|
return str;
|
|
280
294
|
}
|
|
281
295
|
|
|
296
|
+
function printTargetProperties(node) {
|
|
297
|
+
let str = node.getTarget(); // TODO Fix nullish on LinkNode
|
|
298
|
+
|
|
299
|
+
if (str != null) {
|
|
300
|
+
str = 'target: ' + str;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return str;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function printRelProperties(node) {
|
|
307
|
+
let str = node.getRel(); // TODO Fix nullish on LinkNode
|
|
308
|
+
|
|
309
|
+
if (str != null) {
|
|
310
|
+
str = 'rel: ' + str;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return str;
|
|
314
|
+
}
|
|
315
|
+
|
|
282
316
|
function printSelectedCharsLine({
|
|
283
317
|
indent,
|
|
284
318
|
isSelected,
|
package/LexicalTreeView.prod.js
CHANGED
|
@@ -4,17 +4,17 @@
|
|
|
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 l=require("@lexical/mark"),
|
|
8
|
-
function
|
|
9
|
-
function
|
|
10
|
-
b+=
|
|
11
|
-
function
|
|
12
|
-
let
|
|
13
|
-
function
|
|
14
|
-
function
|
|
15
|
-
|
|
7
|
+
'use strict';var l=require("@lexical/link"),q=require("@lexical/mark"),t=require("lexical"),D=require("react");let E=Object.freeze({"\t":"\\t","\n":"\\n"}),F=new RegExp(Object.keys(E).join("|"),"g"),G=Object.freeze({ancestorHasNextSibling:"|",ancestorIsLastChild:" ",hasNextSibling:"\u251c",isLastChild:"\u2514",selectedChar:"^",selectedLine:">"});
|
|
8
|
+
function H(a){let b="",c=I(a),d=a.anchor;a=a.focus;let e=d.offset,g=a.offset;b=b+`: range ${""!==c?`{ ${c} }`:""}`+`\n \u251c anchor { key: ${d.key}, offset: ${null===e?"null":e}, type: ${d.type} }`;return b+=`\n \u2514 focus { key: ${a.key}, offset: ${null===g?"null":g}, type: ${a.type} }`}
|
|
9
|
+
function K(a){let b=" root\n";a=a.read(()=>{const c=t.$getSelection();L(t.$getRoot(),(d,e)=>{const g=`(${d.getKey()})`,h=d.getType()||"",n=d.isSelected(),w=q.$isMarkNode(d)?` id: [ ${d.getIDs().join(", ")} ] `:"";var v=b,r=n?G.selectedLine:" ",x=e.join(" ");if(t.$isTextNode(d)){var f=d.getTextContent(!0);var m=0===f.length?"(empty)":`"${M(f)}"`;f=[I(d),N(d),O(d)].filter(Boolean).join(", ");f=[m,0!==f.length?`{ ${f} }`:null].filter(Boolean).join(" ").trim()}else if(l.$isLinkNode(d)){f=d.getURL();f=
|
|
10
|
+
0===f.length?"(empty)":`"${M(f)}"`;m=d.getTarget();null!=m&&(m="target: "+m);var y=Boolean;let u=d.getRel();null!=u&&(u="rel: "+u);m=[m,u].filter(y).join(", ");f=[f,0!==m.length?`{ ${m} }`:null].filter(Boolean).join(" ").trim()}else f="";b=v+`${r} ${x} ${g} ${h} ${w} ${f}\n`;b+=P({indent:e,isSelected:n,node:d,nodeKeyDisplay:g,selection:c,typeDisplay:h})});return null===c?": null":t.$isRangeSelection(c)?H(c):t.$isGridSelection(c)?`: grid\n \u2514 { grid: ${c.gridKey}, anchorCell: ${c.anchor.key}, focusCell: ${c.focus.key} }`:
|
|
11
|
+
`: node\n \u2514 [${Array.from(c._nodes).join(", ")}]`});return b+"\n selection"+a}function L(a,b,c=[]){a=a.getChildren();let d=a.length;a.forEach((e,g)=>{b(e,c.concat(g===d-1?G.isLastChild:G.hasNextSibling));t.$isElementNode(e)&&L(e,b,c.concat(g===d-1?G.ancestorIsLastChild:G.ancestorHasNextSibling))})}function M(a){return Object.entries(E).reduce((b,[c,d])=>b.replace(new RegExp(c,"g"),String(d)),a)}
|
|
12
|
+
let Q=[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"],R=[a=>a.isDirectionless()&&"Directionless",a=>a.isUnmergeable()&&"Unmergeable"],S=[a=>a.isToken()&&"Token",a=>a.isSegmented()&&"Segmented",a=>a.isInert()&&"Inert"];
|
|
13
|
+
function N(a){let b=R.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="detail: "+b);return b}function O(a){let b=S.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="mode: "+b);return b}function I(a){let b=Q.map(c=>c(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==b&&(b="format: "+b);return b}
|
|
14
|
+
function P({indent:a,isSelected:b,node:c,nodeKeyDisplay:d,selection:e,typeDisplay:g}){if(!t.$isTextNode(c)||!t.$isRangeSelection(e)||!b||t.$isElementNode(c))return"";b=e.anchor;var h=e.focus;if(""===c.getTextContent()||b.getNode()===e.focus.getNode()&&b.offset===h.offset)return"";h=e.anchor;let n=e.focus,w=c.getTextContent(!0),v=w.length;b=e=-1;if("text"===h.type&&"text"===n.type){let f=h.getNode(),m=n.getNode();f===m&&c===f&&h.offset!==n.offset?[e,b]=h.offset<n.offset?[h.offset,n.offset]:[n.offset,
|
|
15
|
+
h.offset]:c===f?[e,b]=f.isBefore(m)?[h.offset,v]:[0,h.offset]:c===m?[e,b]=m.isBefore(f)?[n.offset,v]:[0,n.offset]:[e,b]=[0,v]}c=(w.slice(0,e).match(F)||[]).length;h=(w.slice(e,b).match(F)||[]).length;let [r,x]=[e+c,b+c+h];if(r===x)return"";c=a[a.length-1]===G.hasNextSibling?G.ancestorHasNextSibling:G.ancestorIsLastChild;a=[...a.slice(0,a.length-1),c];c=Array(r+1).fill(" ");e=Array(x-r).fill(G.selectedChar);d=Array(d.length+(g.length+3)).fill(" ");return[G.selectedLine,a.join(" "),[...d,...c,...e].join("")].join(" ")+
|
|
16
16
|
"\n"}
|
|
17
|
-
exports.TreeView=function({timeTravelButtonClassName:a,timeTravelPanelSliderClassName:b,timeTravelPanelButtonClassName:c,viewClassName:
|
|
18
|
-
|
|
19
|
-
{let
|
|
20
|
-
if(null!==
|
|
17
|
+
exports.TreeView=function({timeTravelButtonClassName:a,timeTravelPanelSliderClassName:b,timeTravelPanelButtonClassName:c,viewClassName:d,timeTravelPanelClassName:e,editor:g}){let [h,n]=D.useState([]),[w,v]=D.useState(""),[r,x]=D.useState(!1),f=D.useRef(0),m=D.useRef(null),y=D.useRef(null),[u,C]=D.useState(!1);D.useEffect(()=>{v(K(g.getEditorState()));return g.registerUpdateListener(({editorState:k})=>{let p=g._compositionKey,z=K(g.getEditorState());v([z,null!==p&&`Composition key: ${p}`].filter(Boolean).join("\n\n"));r||
|
|
18
|
+
n(B=>[...B,[Date.now(),k]])})},[r,g]);let A=h.length;D.useEffect(()=>{if(u){let k,p=()=>{const z=f.current;z===A-1?C(!1):k=setTimeout(()=>{f.current++;const B=f.current,J=y.current;null!==J&&(J.value=String(B));g.setEditorState(h[B][1]);p()},h[z+1][0]-h[z][0])};p();return()=>{clearTimeout(k)}}},[h,u,g,A]);D.useEffect(()=>{let k=m.current;if(null!==k)return k.__lexicalEditor=g,()=>{k.__lexicalEditor=null}},[g]);return D.createElement("div",{className:d},!r&&2<A&&D.createElement("button",{onClick:()=>
|
|
19
|
+
{let k=g.getRootElement();null!==k&&(k.contentEditable="false",f.current=A-1,x(!0))},className:a,type:"button"},"Time Travel"),D.createElement("pre",{ref:m},w),r&&D.createElement("div",{className:e},D.createElement("button",{className:c,onClick:()=>{C(!u)},type:"button"},u?"Pause":"Play"),D.createElement("input",{className:b,ref:y,onChange:k=>{k=Number(k.target.value);let p=h[k];p&&(f.current=k,g.setEditorState(p[1]))},type:"range",min:"1",max:A-1}),D.createElement("button",{className:c,onClick:()=>
|
|
20
|
+
{var k=g.getRootElement();if(null!==k){k.contentEditable="true";k=h.length-1;g.setEditorState(h[k][1]);let p=y.current;null!==p&&(p.value=String(k));x(!1);C(!1)}},type:"button"},"Exit")))}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
import { TextNode } from 'lexical';
|
|
8
|
+
import { LexicalEditor, NodeKey, TextNode } from 'lexical';
|
|
9
9
|
import { MutableRefObject, ReactPortal } from 'react';
|
|
10
10
|
export declare type QueryMatch = {
|
|
11
11
|
leadOffset: number;
|
|
@@ -14,7 +14,7 @@ export declare type QueryMatch = {
|
|
|
14
14
|
};
|
|
15
15
|
export declare type Resolution = {
|
|
16
16
|
match: QueryMatch;
|
|
17
|
-
|
|
17
|
+
getRect: () => ClientRect;
|
|
18
18
|
};
|
|
19
19
|
export declare const PUNCTUATION = "\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%'\"~=<>_:;";
|
|
20
20
|
export declare class TypeaheadOption {
|
|
@@ -39,6 +39,14 @@ declare type TypeaheadMenuPluginArgs<TOption extends TypeaheadOption> = {
|
|
|
39
39
|
menuRenderFn: MenuRenderFn<TOption>;
|
|
40
40
|
triggerFn: TriggerFn;
|
|
41
41
|
};
|
|
42
|
-
declare type TriggerFn = (text: string) => QueryMatch | null;
|
|
42
|
+
declare type TriggerFn = (text: string, editor: LexicalEditor) => QueryMatch | null;
|
|
43
43
|
export declare function LexicalTypeaheadMenuPlugin<TOption extends TypeaheadOption>({ options, onQueryChange, onSelectOption, menuRenderFn, triggerFn, }: TypeaheadMenuPluginArgs<TOption>): JSX.Element | null;
|
|
44
|
+
declare type NodeMenuPluginArgs<TOption extends TypeaheadOption> = {
|
|
45
|
+
onSelectOption: (option: TOption, textNodeContainingQuery: TextNode | null, closeMenu: () => void, matchingString: string) => void;
|
|
46
|
+
options: Array<TOption>;
|
|
47
|
+
nodeKey: NodeKey | null;
|
|
48
|
+
onClose: () => void;
|
|
49
|
+
menuRenderFn: MenuRenderFn<TOption>;
|
|
50
|
+
};
|
|
51
|
+
export declare function LexicalNodeMenuPlugin<TOption extends TypeaheadOption>({ options, nodeKey, onClose, onSelectOption, menuRenderFn, }: NodeMenuPluginArgs<TOption>): JSX.Element | null;
|
|
44
52
|
export {};
|