@lexical/react
Version:
This package provides Lexical components and hooks for React applications.
10 lines (8 loc) • 4.89 kB
JavaScript
/**
* 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.
*
*/
import{useCollaborationContext as t}from"@lexical/react/LexicalCollaborationContext";import{useLexicalComposerContext as e}from"@lexical/react/LexicalComposerContext";import{syncCursorPositions as o,initLocalState as r,syncLexicalUpdateToYjs as n,TOGGLE_CONNECT_COMMAND as s,createUndoManager as c,setLocalStateFocus as a,CONNECTED_COMMAND as i,syncYjsChangesToLexical as l,createBinding as d}from"@lexical/yjs";import*as u from"react";import{useRef as m,useCallback as f,useEffect as p,useMemo as g,useState as C}from"react";import{mergeRegister as y}from"@lexical/utils";import{SKIP_COLLAB_TAG as h,COMMAND_PRIORITY_EDITOR as E,UNDO_COMMAND as x,REDO_COMMAND as b,FOCUS_COMMAND as v,BLUR_COMMAND as S,CAN_UNDO_COMMAND as k,CAN_REDO_COMMAND as D,$getRoot as j,HISTORY_MERGE_TAG as w,$createParagraphNode as R,$getSelection as F}from"lexical";import{createPortal as L}from"react-dom";import{UndoManager as P}from"yjs";import{jsx as T,Fragment as A}from"react/jsx-runtime";function B(t,e,c,a,d,u,C,y,x,b,v,S,k=o){const D=m(!1),A=f(()=>c.connect(),[c]),B=f(()=>{try{c.disconnect()}catch(t){}},[c]);p(()=>{const{root:o}=y,{awareness:s}=c,m=({status:e})=>{t.dispatchCommand(i,"connected"===e)},f=e=>{C&&e&&o.isEmpty()&&0===o._xmlText._length&&!1===D.current&&function(t,e){t.update(()=>{const o=j();if(o.isEmpty())if(e)switch(typeof e){case"string":{const o=t.parseEditorState(e);t.setEditorState(o,{tag:w});break}case"object":t.setEditorState(e,{tag:w});break;case"function":t.update(()=>{j().isEmpty()&&e(t)},{tag:w})}else{const e=R();o.append(e);const{activeElement:r}=document;(null!==F()||null!==r&&r===t.getRootElement())&&e.select()}},{tag:w})}(t,v),D.current=!1},p=()=>{k(y,c)},g=(t,e)=>{const o=e.origin;if(o!==y){l(y,c,t,o instanceof P,k)}};r(c,d,u,document.activeElement===t.getRootElement(),S||{});const E=o=>{!function(t,e){if(t.update(()=>{const t=j();t.clear(),t.select()},{tag:h}),null==e.cursors)return;const o=e.cursors;if(null==o)return;const r=e.cursorsContainer;if(null==r)return;const n=Array.from(o.values());for(let t=0;t<n.length;t++){const e=n[t].selection;if(e&&null!=e.selections){const o=e.selections;for(let e=0;e<o.length;e++)r.removeChild(o[t])}}}(t,y),x(o),a.set(e,o),D.current=!0};c.on("reload",E),c.on("status",m),c.on("sync",f),s.on("update",p),o.getSharedType().observeDeep(g);const b=t.registerUpdateListener(({prevEditorState:t,editorState:e,dirtyLeaves:o,dirtyElements:r,normalizedNodes:s,tags:a})=>{!1===a.has(h)&&n(y,c,t,e,r,o,s,a)}),L=A();return()=>{!1===D.current&&(L?L.then(B):B()),c.off("sync",f),c.off("status",m),c.off("reload",E),s.off("update",p),o.getSharedType().unobserveDeep(g),a.delete(e),b()}},[y,u,A,B,a,t,e,v,d,c,C,S,x,k]);const M=g(()=>L(T("div",{ref:t=>{y.cursorsContainer=t}}),b&&b.current||document.body),[y,b]);return p(()=>t.registerCommand(s,t=>(t?(console.log("Collaboration connected!"),A()):(console.log("Collaboration disconnected!"),B()),!0),E),[A,B,t]),M}function M(t,e){const o=g(()=>c(e,e.root.getSharedType()),[e]);p(()=>y(t.registerCommand(x,()=>(o.undo(),!0),E),t.registerCommand(b,()=>(o.redo(),!0),E)));const r=f(()=>{o.clear()},[o]);return u.useEffect(()=>{const e=()=>{t.dispatchCommand(k,o.undoStack.length>0),t.dispatchCommand(D,o.redoStack.length>0)};return o.on("stack-item-added",e),o.on("stack-item-popped",e),o.on("stack-cleared",e),()=>{o.off("stack-item-added",e),o.off("stack-item-popped",e),o.off("stack-cleared",e)}},[t,o]),r}function _({id:o,providerFactory:r,shouldBootstrap:n,username:s,cursorColor:c,cursorsContainerRef:a,initialEditorState:i,excludedProperties:l,awarenessData:u,syncCursorPositionsFn:f}){const g=m(!1),y=m(!1),h=t(s,c),{yjsDocMap:E,name:x,color:b}=h,[v]=e();p(()=>(h.isCollabActive=!0,()=>{null==v._parentEditor&&(h.isCollabActive=!1)}),[h,v]);const[S,k]=C(),[D,j]=C();p(()=>{if(y.current)return;y.current=!0;const t=r(o,E);return k(t),j(E.get(o)),()=>{t.disconnect()}},[o,r,E]);const[w,R]=C();return p(()=>{if(!S)return;if(g.current)return;g.current=!0;const t=d(v,S,o,D||E.get(o),E,l);return R(t),()=>{t.root.destroy(t)}},[v,S,o,E,D,l]),S&&w?T(z,{awarenessData:u,binding:w,collabContext:h,color:b,cursorsContainerRef:a,editor:v,id:o,initialEditorState:i,name:x,provider:S,setDoc:j,shouldBootstrap:n,yjsDocMap:E,syncCursorPositionsFn:f}):T(A,{})}function z({editor:t,id:e,provider:o,yjsDocMap:r,name:n,color:s,shouldBootstrap:c,cursorsContainerRef:i,initialEditorState:l,awarenessData:d,collabContext:u,binding:m,setDoc:f,syncCursorPositionsFn:g}){const C=B(t,e,o,r,n,s,c,m,f,i,l,d,g);return M(t,m),function(t,e,o,r,n){p(()=>y(t.registerCommand(v,()=>(a(e,o,r,!0,n||{}),!1),E),t.registerCommand(S,()=>(a(e,o,r,!1,n||{}),!1),E)),[r,t,o,e,n])}(t,o,n,s,d),C}export{_ as CollaborationPlugin};