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