@lexical/react 0.3.7 → 0.3.10

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.
Files changed (35) hide show
  1. package/LexicalAutoEmbedPlugin.d.ts +46 -0
  2. package/LexicalAutoEmbedPlugin.dev.js +490 -0
  3. package/LexicalAutoEmbedPlugin.js +9 -0
  4. package/LexicalAutoEmbedPlugin.prod.js +21 -0
  5. package/LexicalAutoLinkPlugin.dev.js +1 -1
  6. package/LexicalAutoLinkPlugin.prod.js +2 -2
  7. package/LexicalCollaborationContext.d.ts +19 -0
  8. package/LexicalCollaborationContext.dev.js +38 -0
  9. package/LexicalCollaborationContext.js +9 -0
  10. package/LexicalCollaborationContext.js.flow +21 -0
  11. package/LexicalCollaborationContext.prod.js +8 -0
  12. package/LexicalCollaborationPlugin.d.ts +0 -10
  13. package/LexicalCollaborationPlugin.dev.js +13 -20
  14. package/LexicalCollaborationPlugin.js.flow +0 -9
  15. package/LexicalCollaborationPlugin.prod.js +9 -10
  16. package/LexicalLinkPlugin.dev.js +15 -2
  17. package/LexicalLinkPlugin.prod.js +2 -1
  18. package/LexicalNestedComposer.dev.js +11 -5
  19. package/LexicalNestedComposer.prod.js +3 -3
  20. package/LexicalOnChangePlugin.d.ts +2 -1
  21. package/LexicalOnChangePlugin.dev.js +6 -3
  22. package/LexicalOnChangePlugin.js.flow +2 -0
  23. package/LexicalOnChangePlugin.prod.js +2 -2
  24. package/LexicalTableOfContents__EXPERIMENTAL.d.ts +14 -0
  25. package/LexicalTableOfContents__EXPERIMENTAL.dev.js +144 -0
  26. package/LexicalTableOfContents__EXPERIMENTAL.js +9 -0
  27. package/LexicalTableOfContents__EXPERIMENTAL.js.flow +17 -0
  28. package/LexicalTableOfContents__EXPERIMENTAL.prod.js +10 -0
  29. package/LexicalTreeView.dev.js +43 -9
  30. package/LexicalTreeView.prod.js +13 -13
  31. package/LexicalTypeaheadMenuPlugin.d.ts +52 -0
  32. package/LexicalTypeaheadMenuPlugin.dev.js +520 -0
  33. package/LexicalTypeaheadMenuPlugin.js +9 -0
  34. package/LexicalTypeaheadMenuPlugin.prod.js +22 -0
  35. 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');
@@ -102,6 +103,7 @@ function useYjsCollaboration(editor, id, provider, docMap, name, color, shouldBo
102
103
  provider.off('reload', onProviderDocReload);
103
104
  awareness.off('update', onAwarenessUpdate);
104
105
  root.getSharedType().unobserveDeep(onYjsTreeChanges);
106
+ docMap.delete(id);
105
107
  removeListener();
106
108
  };
107
109
  }, [binding, color, connect, disconnect, docMap, editor, id, name, provider, shouldBootstrap]);
@@ -240,21 +242,29 @@ function clearEditorSkipCollab(editor, binding) {
240
242
  * LICENSE file in the root directory of this source tree.
241
243
  *
242
244
  */
243
- 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']];
244
- const randomEntry = entries[Math.floor(Math.random() * entries.length)];
245
245
  function CollaborationPlugin({
246
246
  id,
247
247
  providerFactory,
248
248
  shouldBootstrap,
249
249
  username
250
250
  }) {
251
- const collabContext = useCollaborationContext(username);
251
+ const collabContext = LexicalCollaborationContext.useCollaborationContext(username);
252
252
  const {
253
253
  yjsDocMap,
254
254
  name,
255
255
  color
256
256
  } = collabContext;
257
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]);
258
268
  const provider = React.useMemo(() => providerFactory(id, yjsDocMap), [id, providerFactory, yjsDocMap]);
259
269
  const [cursors, binding] = useYjsCollaboration(editor, id, provider, yjsDocMap, name, color, shouldBootstrap);
260
270
  collabContext.clientID = binding.clientID;
@@ -262,22 +272,5 @@ function CollaborationPlugin({
262
272
  useYjsFocusTracking(editor, provider, name, color);
263
273
  return cursors;
264
274
  }
265
- const CollaborationContext = /*#__PURE__*/React.createContext({
266
- clientID: 0,
267
- color: randomEntry[1],
268
- name: randomEntry[0],
269
- yjsDocMap: new Map()
270
- });
271
- function useCollaborationContext(username) {
272
- const collabContext = React.useContext(CollaborationContext);
273
-
274
- if (username != null) {
275
- collabContext.name = username;
276
- }
277
-
278
- return collabContext;
279
- }
280
275
 
281
- exports.CollaborationContext = CollaborationContext;
282
276
  exports.CollaborationPlugin = CollaborationPlugin;
283
- 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/LexicalComposerContext"),f=require("react"),h=require("@lexical/utils"),x=require("@lexical/yjs"),F=require("lexical"),G=require("react-dom");
8
- function H(b,c,a,d,l,p,q){let n=f.useRef(!1),[r,v]=f.useState(d.get(c)),g=f.useMemo(()=>x.createBinding(b,a,c,r,d),[b,a,c,d,r]),t=f.useCallback(()=>{a.connect()},[a]),u=f.useCallback(()=>{try{a.disconnect()}catch(m){}},[a]);f.useEffect(()=>{let {root:m}=g,{awareness:y}=a,z=({status:k})=>{b.dispatchCommand(x.CONNECTED_COMMAND,"connected"===k)},A=k=>{q&&k&&m.isEmpty()&&0===m._xmlText._length&&!1===n.current&&I(b);n.current=!1},B=()=>{x.syncCursorPositions(g,a)},C=(k,w)=>{w.origin!==g&&x.syncYjsChangesToLexical(g,
9
- a,k)};x.initLocalState(a,l,p,document.activeElement===b.getRootElement());let D=k=>{J(b,g);v(k);d.set(c,k);n.current=!0};a.on("reload",D);a.on("status",z);a.on("sync",A);y.on("update",B);m.getSharedType().observeDeep(C);let R=b.registerUpdateListener(({prevEditorState:k,editorState:w,dirtyLeaves:O,dirtyElements:P,normalizedNodes:Q,tags:E})=>{!1===E.has("skip-collab")&&x.syncLexicalUpdateToYjs(g,a,k,w,P,O,Q,E)});t();return()=>{!1===n.current&&u();a.off("sync",A);a.off("status",z);a.off("reload",D);
10
- y.off("update",B);m.getSharedType().unobserveDeep(C);R()}},[g,p,t,u,d,b,c,l,a,q]);let S=f.useMemo(()=>G.createPortal(f.createElement("div",{ref:m=>{g.cursorsContainer=m}}),document.body),[g]);f.useEffect(()=>b.registerCommand(x.TOGGLE_CONNECT_COMMAND,m=>{void 0!==t&&void 0!==u&&(m?(console.log("Collaboration connected!"),t()):(console.log("Collaboration disconnected!"),u()));return!0},F.COMMAND_PRIORITY_EDITOR),[t,u,b]);return[S,g]}
11
- function K(b,c,a,d){f.useEffect(()=>h.mergeRegister(b.registerCommand(F.FOCUS_COMMAND,()=>{x.setLocalStateFocus(c,a,d,!0);return!0},F.COMMAND_PRIORITY_EDITOR),b.registerCommand(F.BLUR_COMMAND,()=>{x.setLocalStateFocus(c,a,d,!1);return!0},F.COMMAND_PRIORITY_EDITOR)),[d,b,a,c])}
12
- function L(b,c){let a=f.useMemo(()=>x.createUndoManager(c,c.root.getSharedType()),[c]);f.useEffect(()=>h.mergeRegister(b.registerCommand(F.UNDO_COMMAND,()=>{a.undo();return!0},F.COMMAND_PRIORITY_EDITOR),b.registerCommand(F.REDO_COMMAND,()=>{a.redo();return!0},F.COMMAND_PRIORITY_EDITOR)));return f.useCallback(()=>{a.clear()},[a])}
13
- function I(b){b.update(()=>{var c=F.$getRoot();if(null===c.getFirstChild()){let a=F.$createParagraphNode();c.append(a);c=document.activeElement;(null!==F.$getSelection()||null!==c&&c===b.getRootElement())&&a.select()}},{tag:"history-merge"})}
14
- function J(b,c){b.update(()=>{let d=F.$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 l=0;l<a.length;l++)c.removeChild(a[d])}}}}
15
- let M=[["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"]],N=M[Math.floor(Math.random()*M.length)],T=f.createContext({clientID:0,color:N[1],name:N[0],yjsDocMap:new Map});
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}
@@ -26,8 +26,21 @@ function LinkPlugin() {
26
26
  }
27
27
  }, [editor]);
28
28
  react.useEffect(() => {
29
- return editor.registerCommand(link.TOGGLE_LINK_COMMAND, url => {
30
- link.toggleLink(url);
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 b=require("@lexical/link"),c=require("@lexical/react/LexicalComposerContext"),d=require("lexical"),e=require("react");exports.LinkPlugin=function(){let [a]=c.useLexicalComposerContext();e.useEffect(()=>{if(!a.hasNodes([b.LinkNode]))throw Error("LinkPlugin: LinkNode not registered on editor");},[a]);e.useEffect(()=>a.registerCommand(b.TOGGLE_LINK_COMMAND,f=>{b.toggleLink(f);return!0},d.COMMAND_PRIORITY_EDITOR),[a]);return null}
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 LexicalCollaborationPlugin = require('@lexical/react/LexicalCollaborationPlugin');
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
- } = LexicalCollaborationPlugin.useCollaborationContext();
54
- const isCollab = yjsDocMap.get('main') !== undefined;
55
- const isCollabReady = yjsDocMap.has(initialEditor.getKey());
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
- }, !isCollab || isCollabReady ? children : null);
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 c=require("@lexical/react/LexicalCollaborationPlugin"),d=require("@lexical/react/LexicalComposerContext"),h=require("react");
8
- exports.LexicalNestedComposer=function({initialEditor:a,children:k,initialTheme:l}){let e=h.useContext(d.LexicalComposerContext);if(null==e)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 p=h.useMemo(()=>{const [f,m]=e,g=l||m.getTheme()||void 0,n=d.createLexicalComposerContext(e,g);void 0!==g&&(a._config.theme=g);a._parentEditor=f;a._nodes=f._nodes;
9
- a._config.namespace=f._config.namespace;return[a,n]},[]);var {yjsDocMap:b}=c.useCollaborationContext();let q=void 0!==b.get("main");b=b.has(a.getKey());return h.createElement(d.LexicalComposerContext.Provider,{value:p},!q||b?k:null)}
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"),f=require("react"),g="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?f.useLayoutEffect:f.useEffect;
8
- exports.OnChangePlugin=function({ignoreInitialChange:d=!0,ignoreSelectionChange:e=!1,onChange:a}){let [b]=c.useLexicalComposerContext();g(()=>{if(a)return b.registerUpdateListener(({editorState:h,dirtyElements:k,dirtyLeaves:l,prevEditorState:m})=>{e&&0===k.size&&0===l.size||d&&m.isEmpty()||a(h,b)})},[b,d,e,a]);return null}
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}
@@ -0,0 +1,14 @@
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
+ import type { LexicalEditor, NodeKey } from 'lexical';
9
+ import { HeadingTagType } from '@lexical/rich-text';
10
+ declare type Props = {
11
+ children: (values: Array<[key: NodeKey, text: string, tag: HeadingTagType]>, editor: LexicalEditor) => JSX.Element;
12
+ };
13
+ export default function LexicalTableOfContentsPlugin({ children, }: Props): JSX.Element;
14
+ export {};
@@ -0,0 +1,144 @@
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 LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
10
+ var richText = require('@lexical/rich-text');
11
+ var lexical = require('lexical');
12
+ var react = require('react');
13
+
14
+ /**
15
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
16
+ *
17
+ * This source code is licensed under the MIT license found in the
18
+ * LICENSE file in the root directory of this source tree.
19
+ *
20
+ */
21
+
22
+ function $insertHeadingIntoTableOfContents(prevHeading, newHeading, currentTableOfContents) {
23
+ if (newHeading === null) {
24
+ return currentTableOfContents;
25
+ }
26
+
27
+ const newEntry = [newHeading.getKey(), newHeading.getTextContent(), newHeading.getTag()];
28
+ let newTableOfContents = [];
29
+
30
+ if (prevHeading === null) {
31
+ newTableOfContents = [newEntry, ...currentTableOfContents];
32
+ } else {
33
+ for (let i = 0; i < currentTableOfContents.length; i++) {
34
+ const key = currentTableOfContents[i][0];
35
+ newTableOfContents.push(currentTableOfContents[i]);
36
+
37
+ if (key === prevHeading.getKey() && key !== newHeading.getKey()) {
38
+ newTableOfContents.push(newEntry);
39
+ }
40
+ }
41
+ }
42
+
43
+ return newTableOfContents;
44
+ }
45
+
46
+ function $deleteHeadingFromTableOfContents(key, currentTableOfContents) {
47
+ const newTableOfContents = [];
48
+
49
+ for (const heading of currentTableOfContents) {
50
+ if (heading[0] !== key) {
51
+ newTableOfContents.push(heading);
52
+ }
53
+ }
54
+
55
+ return newTableOfContents;
56
+ }
57
+
58
+ function $updateHeadingInTableOfContents(heading, currentTableOfContents) {
59
+ const newTextContent = heading.getTextContent();
60
+ const newTableOfContents = [];
61
+
62
+ for (const oldHeading of currentTableOfContents) {
63
+ if (oldHeading[0] === heading.getKey()) {
64
+ newTableOfContents.push([heading.getKey(), newTextContent, heading.getTag()]);
65
+ } else {
66
+ newTableOfContents.push(oldHeading);
67
+ }
68
+ }
69
+
70
+ return newTableOfContents;
71
+ }
72
+
73
+ function LexicalTableOfContentsPlugin({
74
+ children
75
+ }) {
76
+ const [tableOfContents, setTableOfContents] = react.useState([]);
77
+ const [editor] = LexicalComposerContext.useLexicalComposerContext();
78
+ react.useEffect(() => {
79
+ // Set table of contents initial state
80
+ let currentTableOfContents = [];
81
+ editor.getEditorState().read(() => {
82
+ const root = lexical.$getRoot();
83
+ const rootChildren = root.getChildren();
84
+
85
+ for (const child of rootChildren) {
86
+ if (richText.$isHeadingNode(child)) {
87
+ currentTableOfContents.push([child.getKey(), child.getTextContent(), child.getTag()]);
88
+ }
89
+ }
90
+
91
+ setTableOfContents(currentTableOfContents);
92
+ }); // Listen to updates to heading mutations and update state
93
+
94
+ const removeHeaderMutationListener = editor.registerMutationListener(richText.HeadingNode, mutatedNodes => {
95
+ editor.getEditorState().read(() => {
96
+ for (const [nodeKey, mutation] of mutatedNodes) {
97
+ if (mutation === 'created') {
98
+ const newHeading = lexical.$getNodeByKey(nodeKey);
99
+
100
+ if (newHeading !== null) {
101
+ let prevHeading = newHeading.getPreviousSibling();
102
+
103
+ while (prevHeading && !richText.$isHeadingNode(prevHeading)) {
104
+ prevHeading = prevHeading.getPreviousSibling();
105
+ }
106
+
107
+ currentTableOfContents = $insertHeadingIntoTableOfContents(prevHeading, newHeading, currentTableOfContents);
108
+ setTableOfContents(currentTableOfContents);
109
+ }
110
+ } else if (mutation === 'destroyed') {
111
+ currentTableOfContents = $deleteHeadingFromTableOfContents(nodeKey, currentTableOfContents);
112
+ setTableOfContents(currentTableOfContents);
113
+ }
114
+ }
115
+ });
116
+ }); // Listen to text node mutation updates
117
+
118
+ const removeTextNodeMutationListener = editor.registerMutationListener(lexical.TextNode, mutatedNodes => {
119
+ editor.getEditorState().read(() => {
120
+ for (const [nodeKey, mutation] of mutatedNodes) {
121
+ if (mutation === 'updated') {
122
+ const currNode = lexical.$getNodeByKey(nodeKey);
123
+
124
+ if (currNode !== null) {
125
+ const parentNode = currNode.getParentOrThrow();
126
+
127
+ if (richText.$isHeadingNode(parentNode)) {
128
+ currentTableOfContents = $updateHeadingInTableOfContents(parentNode, currentTableOfContents);
129
+ setTableOfContents(currentTableOfContents);
130
+ }
131
+ }
132
+ }
133
+ }
134
+ });
135
+ });
136
+ return () => {
137
+ removeHeaderMutationListener();
138
+ removeTextNodeMutationListener();
139
+ };
140
+ }, [editor]);
141
+ return children(tableOfContents, editor);
142
+ }
143
+
144
+ module.exports = LexicalTableOfContentsPlugin;
@@ -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 LexicalTableOfContents__EXPERIMENTAL = process.env.NODE_ENV === 'development' ? require('./LexicalTableOfContents__EXPERIMENTAL.dev.js') : require('./LexicalTableOfContents__EXPERIMENTAL.prod.js')
9
+ module.exports = LexicalTableOfContents__EXPERIMENTAL;
@@ -0,0 +1,17 @@
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 {HeadingTagType} from '@lexical/rich-text';
11
+ import type {NodeKey} from 'lexical';
12
+
13
+ declare export function LexicalTableOfContentsPlugin({
14
+ children: (
15
+ tableOfContents: Array<[NodeKey, string, HeadingTagType]>,
16
+ ) => React$Node,
17
+ }): React$Node;
@@ -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 k=require("@lexical/react/LexicalComposerContext"),l=require("@lexical/rich-text"),r=require("lexical"),u=require("react");
8
+ module.exports=function({children:v}){let [w,m]=u.useState([]),[f]=k.useLexicalComposerContext();u.useEffect(()=>{let b=[];f.getEditorState().read(()=>{let h=r.$getRoot().getChildren();for(let a of h)l.$isHeadingNode(a)&&b.push([a.getKey(),a.getTextContent(),a.getTag()]);m(b)});let x=f.registerMutationListener(l.HeadingNode,h=>{f.getEditorState().read(()=>{for(const [n,p]of h)if("created"===p){var a=r.$getNodeByKey(n);if(null!==a){for(var c=a.getPreviousSibling();c&&!l.$isHeadingNode(c);)c=c.getPreviousSibling();
9
+ a:{var d=b;if(null===a){b=d;break a}let e=[a.getKey(),a.getTextContent(),a.getTag()],g=[];if(null===c)g=[e,...d];else for(let q=0;q<d.length;q++){let t=d[q][0];g.push(d[q]);t===c.getKey()&&t!==a.getKey()&&g.push(e)}b=g}m(b)}}else if("destroyed"===p){c=n;a=b;d=[];for(let e of a)e[0]!==c&&d.push(e);b=d;m(b)}})}),y=f.registerMutationListener(r.TextNode,h=>{f.getEditorState().read(()=>{for(const [d,n]of h)if("updated"===n){var a=r.$getNodeByKey(d);if(null!==a&&(a=a.getParentOrThrow(),l.$isHeadingNode(a))){var c=
10
+ b;let p=a.getTextContent(),e=[];for(let g of c)g[0]===a.getKey()?e.push([a.getKey(),p,a.getTag()]):e.push(g);b=e;m(b)}}})});return()=>{x();y()}},[f]);return v(w,f)}