UNPKG

@lexical/react

Version:

This package provides Lexical components and hooks for React applications.

10 lines (8 loc) 5.14 kB
/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ "use strict";var e=require("@lexical/react/LexicalCollaborationContext"),t=require("@lexical/react/LexicalComposerContext"),o=require("@lexical/yjs"),r=require("react"),n=require("@lexical/utils"),s=require("lexical"),a=require("react-dom"),c=require("yjs"),i=require("react/jsx-runtime");function l(e){var t=Object.create(null);if(e)for(var o in e)t[o]=e[o];return t.default=e,t}var u=l(r);function d(e,t,n,l,u,d,f,C,m,g,p,D,E=o.syncCursorPositions){const M=r.useRef(!1),O=r.useCallback((()=>n.connect()),[n]),R=r.useCallback((()=>{try{n.disconnect()}catch(e){}}),[n]);r.useEffect((()=>{const{root:r}=C,{awareness:a}=n,i=({status:t})=>{e.dispatchCommand(o.CONNECTED_COMMAND,"connected"===t)},g=t=>{f&&t&&r.isEmpty()&&0===r._xmlText._length&&!1===M.current&&function(e,t){e.update((()=>{const o=s.$getRoot();if(o.isEmpty())if(t)switch(typeof t){case"string":{const o=e.parseEditorState(t);e.setEditorState(o,{tag:"history-merge"});break}case"object":e.setEditorState(t,{tag:"history-merge"});break;case"function":e.update((()=>{s.$getRoot().isEmpty()&&t(e)}),{tag:"history-merge"})}else{const t=s.$createParagraphNode();o.append(t);const{activeElement:r}=document;(null!==s.$getSelection()||null!==r&&r===e.getRootElement())&&t.select()}}),{tag:"history-merge"})}(e,p),M.current=!1},y=()=>{E(C,n)},h=(e,t)=>{const r=t.origin;if(r!==C){const t=r instanceof c.UndoManager;o.syncYjsChangesToLexical(C,n,e,t,E)}};o.initLocalState(n,u,d,document.activeElement===e.getRootElement(),D||{});const x=o=>{!function(e,t){if(e.update((()=>{const e=s.$getRoot();e.clear(),e.select()}),{tag:"skip-collab"}),null==t.cursors)return;const o=t.cursors;if(null==o)return;const r=t.cursorsContainer;if(null==r)return;const n=Array.from(o.values());for(let e=0;e<n.length;e++){const t=n[e].selection;if(t&&null!=t.selections){const o=t.selections;for(let t=0;t<o.length;t++)r.removeChild(o[e])}}}(e,C),m(o),l.set(t,o),M.current=!0};n.on("reload",x),n.on("status",i),n.on("sync",g),a.on("update",y),r.getSharedType().observeDeep(h);const _=e.registerUpdateListener((({prevEditorState:e,editorState:t,dirtyLeaves:r,dirtyElements:s,normalizedNodes:a,tags:c})=>{!1===c.has("skip-collab")&&o.syncLexicalUpdateToYjs(C,n,e,t,s,r,a,c)})),b=O();return()=>{!1===M.current&&(b?b.then(R):R()),n.off("sync",g),n.off("status",i),n.off("reload",x),a.off("update",y),r.getSharedType().unobserveDeep(h),l.delete(t),_()}}),[C,d,O,R,l,e,t,p,u,n,f,D,m,E]);const y=r.useMemo((()=>a.createPortal(i.jsx("div",{ref:e=>{C.cursorsContainer=e}}),g&&g.current||document.body)),[C,g]);return r.useEffect((()=>e.registerCommand(o.TOGGLE_CONNECT_COMMAND,(e=>(e?(console.log("Collaboration connected!"),O()):(console.log("Collaboration disconnected!"),R()),!0)),s.COMMAND_PRIORITY_EDITOR)),[O,R,e]),y}function f(e,t){const a=r.useMemo((()=>o.createUndoManager(t,t.root.getSharedType())),[t]);r.useEffect((()=>n.mergeRegister(e.registerCommand(s.UNDO_COMMAND,(()=>(a.undo(),!0)),s.COMMAND_PRIORITY_EDITOR),e.registerCommand(s.REDO_COMMAND,(()=>(a.redo(),!0)),s.COMMAND_PRIORITY_EDITOR))));const c=r.useCallback((()=>{a.clear()}),[a]);return u.useEffect((()=>{const t=()=>{e.dispatchCommand(s.CAN_UNDO_COMMAND,a.undoStack.length>0),e.dispatchCommand(s.CAN_REDO_COMMAND,a.redoStack.length>0)};return a.on("stack-item-added",t),a.on("stack-item-popped",t),a.on("stack-cleared",t),()=>{a.off("stack-item-added",t),a.off("stack-item-popped",t),a.off("stack-cleared",t)}}),[e,a]),c}function C({editor:e,id:t,provider:a,yjsDocMap:c,name:i,color:l,shouldBootstrap:u,cursorsContainerRef:C,initialEditorState:m,awarenessData:g,collabContext:p,binding:D,setDoc:E}){const M=d(e,t,a,c,i,l,u,D,E,C,m,g);return p.clientID=D.clientID,f(e,D),function(e,t,a,c,i){r.useEffect((()=>n.mergeRegister(e.registerCommand(s.FOCUS_COMMAND,(()=>(o.setLocalStateFocus(t,a,c,!0,i||{}),!1)),s.COMMAND_PRIORITY_EDITOR),e.registerCommand(s.BLUR_COMMAND,(()=>(o.setLocalStateFocus(t,a,c,!1,i||{}),!1)),s.COMMAND_PRIORITY_EDITOR))),[c,e,a,t,i])}(e,a,i,l,g),M}exports.CollaborationPlugin=function({id:n,providerFactory:s,shouldBootstrap:a,username:c,cursorColor:l,cursorsContainerRef:u,initialEditorState:d,excludedProperties:f,awarenessData:m}){const g=r.useRef(!1),p=r.useRef(!1),D=e.useCollaborationContext(c,l),{yjsDocMap:E,name:M,color:O}=D,[R]=t.useLexicalComposerContext();r.useEffect((()=>(D.isCollabActive=!0,()=>{null==R._parentEditor&&(D.isCollabActive=!1)})),[D,R]);const[y,h]=r.useState();r.useEffect((()=>{if(p.current)return;p.current=!0;const e=s(n,E);return h(e),()=>{e.disconnect()}}),[n,s,E]);const[x,_]=r.useState(E.get(n)),[b,N]=r.useState();return r.useEffect((()=>{if(!y)return;if(g.current)return;g.current=!0;const e=o.createBinding(R,y,n,x||E.get(n),E,f);return N(e),()=>{e.root.destroy(e)}}),[R,y,n,E,x,f]),y&&b?i.jsx(C,{awarenessData:m,binding:b,collabContext:D,color:O,cursorsContainerRef:u,editor:R,id:n,initialEditorState:d,name:M,provider:y,setDoc:_,shouldBootstrap:a,yjsDocMap:E}):i.jsx(i.Fragment,{})};