UNPKG

@lexical/react

Version:

This package provides Lexical components and hooks for React applications.

10 lines (8 loc) 4.92 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. * */ 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,syncCursorPositions as s,setLocalStateFocus as c,createUndoManager 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 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,c,a,d,u,y,C,b,E,x,v,S=s){const k=m(!1),A=f((()=>c.connect()),[c]),B=f((()=>{try{c.disconnect()}catch(t){}}),[c]);p((()=>{const{root:n}=C,{awareness:s}=c,m=({status:e})=>{t.dispatchCommand(i,"connected"===e)},f=e=>{y&&e&&n.isEmpty()&&0===n._xmlText._length&&!1===k.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),k.current=!1},p=()=>{S(C,c)},g=(t,e)=>{const o=e.origin;if(o!==C){l(C,c,t,o instanceof L,S)}};o(c,d,u,document.activeElement===t.getRootElement(),v||{});const h=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),a.set(e,o),k.current=!0};c.on("reload",h),c.on("status",m),c.on("sync",f),s.on("update",p),n.getSharedType().observeDeep(g);const E=t.registerUpdateListener((({prevEditorState:t,editorState:e,dirtyLeaves:o,dirtyElements:n,normalizedNodes:s,tags:a})=>{!1===a.has("skip-collab")&&r(C,c,t,e,n,o,s,a)})),R=A();return()=>{!1===k.current&&(R?R.then(B):B()),c.off("sync",f),c.off("status",m),c.off("reload",h),s.off("update",p),n.getSharedType().unobserveDeep(g),a.delete(e),E()}}),[C,u,A,B,a,t,e,x,d,c,y,v,b,S]);const M=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!"),A()):(console.log("Collaboration disconnected!"),B()),!0)),h)),[A,B,t]),M}function M(t,e){const o=g((()=>a(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:s,shouldBootstrap:a,cursorsContainerRef:i,initialEditorState:l,awarenessData:d,collabContext:u,binding:m,setDoc:f}){const g=B(t,e,o,r,n,s,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,(()=>(c(e,o,r,!0,n||{}),!1)),h),t.registerCommand(E,(()=>(c(e,o,r,!1,n||{}),!1)),h))),[r,t,o,e,n])}(t,o,n,s,d),g}export{_ as CollaborationPlugin};