UNPKG

@lexical/react

Version:

This package provides Lexical components and hooks for React applications.

10 lines (8 loc) 4.96 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 C}from"react";import{mergeRegister as y}from"@lexical/utils";import{SKIP_COLLAB_TAG as h,COMMAND_PRIORITY_EDITOR as E,FOCUS_COMMAND as x,BLUR_COMMAND as b,UNDO_COMMAND as v,REDO_COMMAND as S,CAN_UNDO_COMMAND as D,CAN_REDO_COMMAND as k,$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,D=s){const k=m(!1),A=f((()=>c.connect()),[c]),B=f((()=>{try{c.disconnect()}catch(t){}}),[c]);p((()=>{const{root:n}=y,{awareness:s}=c,m=({status:e})=>{t.dispatchCommand(i,"connected"===e)},f=e=>{C&&e&&n.isEmpty()&&0===n._xmlText._length&&!1===k.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),k.current=!1},p=()=>{D(y,c)},g=(t,e)=>{const o=e.origin;if(o!==y){l(y,c,t,o instanceof P,D)}};o(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),k.current=!0};c.on("reload",E),c.on("status",m),c.on("sync",f),s.on("update",p),n.getSharedType().observeDeep(g);const b=t.registerUpdateListener((({prevEditorState:t,editorState:e,dirtyLeaves:o,dirtyElements:n,normalizedNodes:s,tags:a})=>{!1===a.has(h)&&r(y,c,t,e,n,o,s,a)})),L=A();return()=>{!1===k.current&&(L?L.then(B):B()),c.off("sync",f),c.off("status",m),c.off("reload",E),s.off("update",p),n.getSharedType().unobserveDeep(g),a.delete(e),b()}}),[y,u,A,B,a,t,e,v,d,c,C,S,x,D]);const M=g((()=>L(T("div",{ref:t=>{y.cursorsContainer=t}}),b&&b.current||document.body)),[y,b]);return p((()=>t.registerCommand(n,(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((()=>a(e,e.root.getSharedType())),[e]);p((()=>y(t.registerCommand(v,(()=>(o.undo(),!0)),E),t.registerCommand(S,(()=>(o.redo(),!0)),E))));const r=f((()=>{o.clear()}),[o]);return u.useEffect((()=>{const e=()=>{t.dispatchCommand(D,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,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,D]=C(),[k,j]=C();p((()=>{if(y.current)return;y.current=!0;const t=r(o,E);return D(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,k||E.get(o),E,l);return R(t),()=>{t.root.destroy(t)}}),[v,S,o,E,k,l]),S&&w?T(I,{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 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,syncCursorPositionsFn:g}){const C=B(t,e,o,r,n,s,a,m,f,i,l,d,g);return u.clientID=m.clientID,M(t,m),function(t,e,o,r,n){p((()=>y(t.registerCommand(x,(()=>(c(e,o,r,!0,n||{}),!1)),E),t.registerCommand(b,(()=>(c(e,o,r,!1,n||{}),!1)),E))),[r,t,o,e,n])}(t,o,n,s,d),C}export{_ as CollaborationPlugin};