@lexical/react 0.47.1-nightly.20260715.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/LexicalCharacterLimitPlugin.dev.js +13 -1
- package/dist/LexicalCharacterLimitPlugin.dev.mjs +13 -1
- package/dist/LexicalCharacterLimitPlugin.prod.js +2 -2
- package/dist/LexicalCharacterLimitPlugin.prod.mjs +2 -2
- package/dist/LexicalCollaborationPlugin.d.ts +6 -2
- package/dist/LexicalCollaborationPlugin.dev.js +19 -4
- package/dist/LexicalCollaborationPlugin.dev.mjs +20 -5
- package/dist/LexicalCollaborationPlugin.prod.js +1 -1
- package/dist/LexicalCollaborationPlugin.prod.mjs +1 -1
- package/dist/LexicalComposerContext.dev.js +1 -1
- package/dist/LexicalComposerContext.dev.mjs +1 -1
- package/dist/LexicalComposerContext.prod.js +1 -1
- package/dist/LexicalComposerContext.prod.mjs +1 -1
- package/dist/LexicalContentEditable.dev.js +1 -1
- package/dist/LexicalContentEditable.dev.mjs +1 -1
- package/dist/LexicalContentEditable.prod.js +2 -2
- package/dist/LexicalContentEditable.prod.mjs +2 -2
- package/package.json +20 -20
- package/src/LexicalCollaborationPlugin.tsx +21 -9
- package/src/shared/LexicalContentEditableElement.tsx +1 -1
- package/src/shared/useCharacterLimit.ts +13 -1
|
@@ -135,6 +135,14 @@ function $wrapOverflowedNodes(offset) {
|
|
|
135
135
|
node
|
|
136
136
|
} = dfsNodes[i];
|
|
137
137
|
|
|
138
|
+
// ElementNode.getTextContent() inserts '\n\n' after each non-inline
|
|
139
|
+
// element child that is not the last child. findOffset counts those
|
|
140
|
+
// separators (via $rootTextContent), so the DFS must count them too.
|
|
141
|
+
const prevSibling = node.getPreviousSibling();
|
|
142
|
+
if (lexical.$isElementNode(prevSibling) && !prevSibling.isInline()) {
|
|
143
|
+
accumulatedLength += 2;
|
|
144
|
+
}
|
|
145
|
+
|
|
138
146
|
// Slot value roots (a non-inline DecoratorNode slotted into a host) are
|
|
139
147
|
// leaf nodes with __parent === null; wrapping them in OverflowNode would
|
|
140
148
|
// call node.replace() and throw, so they stay out of the wrap loop. Their
|
|
@@ -199,6 +207,10 @@ function $wrapOverflowedNodes(offset) {
|
|
|
199
207
|
lexical.$setSelection(previousSelection);
|
|
200
208
|
}
|
|
201
209
|
$mergePrevious(overflowNode);
|
|
210
|
+
const nextNode = overflowNode.getNextSibling();
|
|
211
|
+
if (overflow.$isOverflowNode(nextNode)) {
|
|
212
|
+
$mergePrevious(nextNode);
|
|
213
|
+
}
|
|
202
214
|
}
|
|
203
215
|
}
|
|
204
216
|
}
|
|
@@ -229,7 +241,7 @@ function $mergePrevious(overflowNode) {
|
|
|
229
241
|
const anchor = selection.anchor;
|
|
230
242
|
const anchorNode = anchor.getNode();
|
|
231
243
|
const focus = selection.focus;
|
|
232
|
-
const focusNode =
|
|
244
|
+
const focusNode = focus.getNode();
|
|
233
245
|
if (anchorNode.is(previousNode)) {
|
|
234
246
|
anchor.set(overflowNode.getKey(), anchor.offset, 'element');
|
|
235
247
|
} else if (anchorNode.is(overflowNode)) {
|
|
@@ -133,6 +133,14 @@ function $wrapOverflowedNodes(offset) {
|
|
|
133
133
|
node
|
|
134
134
|
} = dfsNodes[i];
|
|
135
135
|
|
|
136
|
+
// ElementNode.getTextContent() inserts '\n\n' after each non-inline
|
|
137
|
+
// element child that is not the last child. findOffset counts those
|
|
138
|
+
// separators (via $rootTextContent), so the DFS must count them too.
|
|
139
|
+
const prevSibling = node.getPreviousSibling();
|
|
140
|
+
if ($isElementNode(prevSibling) && !prevSibling.isInline()) {
|
|
141
|
+
accumulatedLength += 2;
|
|
142
|
+
}
|
|
143
|
+
|
|
136
144
|
// Slot value roots (a non-inline DecoratorNode slotted into a host) are
|
|
137
145
|
// leaf nodes with __parent === null; wrapping them in OverflowNode would
|
|
138
146
|
// call node.replace() and throw, so they stay out of the wrap loop. Their
|
|
@@ -197,6 +205,10 @@ function $wrapOverflowedNodes(offset) {
|
|
|
197
205
|
$setSelection(previousSelection);
|
|
198
206
|
}
|
|
199
207
|
$mergePrevious(overflowNode);
|
|
208
|
+
const nextNode = overflowNode.getNextSibling();
|
|
209
|
+
if ($isOverflowNode(nextNode)) {
|
|
210
|
+
$mergePrevious(nextNode);
|
|
211
|
+
}
|
|
200
212
|
}
|
|
201
213
|
}
|
|
202
214
|
}
|
|
@@ -227,7 +239,7 @@ function $mergePrevious(overflowNode) {
|
|
|
227
239
|
const anchor = selection.anchor;
|
|
228
240
|
const anchorNode = anchor.getNode();
|
|
229
241
|
const focus = selection.focus;
|
|
230
|
-
const focusNode =
|
|
242
|
+
const focusNode = focus.getNode();
|
|
231
243
|
if (anchorNode.is(previousNode)) {
|
|
232
244
|
anchor.set(overflowNode.getKey(), anchor.offset, 'element');
|
|
233
245
|
} else if (anchorNode.is(overflowNode)) {
|
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
"use strict";var e=require("@lexical/react/LexicalComposerContext"),t=require("react"),n=require("@lexical/overflow"),r=require("@lexical/text"),i=require("@lexical/utils"),o=require("lexical"),s=require("react/jsx-runtime");function l(e,s,l=Object.freeze({})){const{strlen:
|
|
10
|
-
return s.jsx("span",{className:"characters-limit "+(e<0?"characters-limit-exceeded":""),children:e})}exports.CharacterLimitPlugin=function({charset:n="UTF-16",maxLength:r=5,renderer:i=u}){const[o]=e.useLexicalComposerContext(),[s,c]=t.useState(r),a=t.useMemo(()=>({remainingCharacters:c,strlen:e=>{if("UTF-8"===n)return
|
|
9
|
+
"use strict";var e=require("@lexical/react/LexicalComposerContext"),t=require("react"),n=require("@lexical/overflow"),r=require("@lexical/text"),i=require("@lexical/utils"),o=require("lexical"),s=require("react/jsx-runtime");function l(e,s,l=Object.freeze({})){const{strlen:g=e=>e.length,remainingCharacters:f=()=>{}}=l;t.useEffect(()=>{e.hasNodes([n.OverflowNode])||function(e,...t){const n=new URL("https://lexical.dev/docs/error"),r=new URLSearchParams;r.append("code",e);for(const e of t)r.append("v",e);throw n.search=r.toString(),Error(`Minified Lexical error #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}(57)},[e]),t.useEffect(()=>{let t=e.read("latest",r.$rootTextContent),l=0;return o.mergeRegister(e.registerTextContentListener(e=>{t=e}),e.registerUpdateListener(({dirtyLeaves:r,dirtyElements:u})=>{const d=e.isComposing(),m=r.size>0||u.size>0;if(d||!m)return;const h=g(t),x=h>s||null!==l&&l>s;if(f(s-h),null===l||x){const r=function(e,t,n){let r=0,i=0;if("function"==typeof Intl.Segmenter){const o=(new Intl.Segmenter).segment(e);for(const{segment:e}of o){const o=i+n(e);if(o>t)break;i=o,r+=e.length}}else{const o=Array.from(e),s=o.length;for(let e=0;e<s;e++){const s=o[e],l=i+n(s);if(l>t)break;i=l,r+=s.length}}return r}(t,s,g);e.update(()=>{!function(e){const t=i.$dfsWithSlots(),r=t.length;let s=0;for(let l=0;l<r;l+=1){const{node:r}=t[l],g=r.getPreviousSibling();o.$isElementNode(g)&&!g.isInline()&&(s+=2);const f=o.$isLeafNode(r)&&null!==o.$getSlotHost(r),u=o.$isLeafNode(r)&&!f&&!o.$findMatchingParent(r,n.$isOverflowNode);if(n.$isOverflowNode(r)){const t=s;if(s+r.getTextContentSize()<=e){const e=r.getParent(),t=r.getPreviousSibling(),n=r.getNextSibling();i.$unwrapNode(r);const s=o.$getSelection();!o.$isRangeSelection(s)||s.anchor.getNode().isAttached()&&s.focus.getNode().isAttached()||(o.$isTextNode(t)?t.select():o.$isTextNode(n)?n.select():null!==e&&e.select())}else if(t<e){const n=r.getFirstDescendant(),s=t+(null!==n?n.getTextContentSize():0);(o.$isTextNode(n)&&n.isSimpleText()||s<=e)&&i.$unwrapNode(r)}}else if(f)s+=r.getTextContentSize();else if(u){const t=s;if(s+=r.getTextContentSize(),s>e&&!n.$isOverflowNode(r.getParent())){const i=o.$getSelection();let s;if(t<e&&o.$isTextNode(r)&&r.isSimpleText()){const[,n]=r.splitText(e-t);s=c(n)}else s=c(r);null!==i&&o.$setSelection(i),a(s);const l=s.getNextSibling();n.$isOverflowNode(l)&&a(l)}}}}(r)},{tag:o.HISTORY_MERGE_TAG})}l=h}),e.registerCommand(o.DELETE_CHARACTER_COMMAND,e=>{const t=o.$getSelection();if(!o.$isRangeSelection(t))return!1;const n=t.anchor.getNode().getParent(),r=n?n.getParent():null,i=r?r.getNextSibling():null;return t.deleteCharacter(e),r&&r.isEmpty()?r.remove():o.$isElementNode(i)&&i.isEmpty()&&i.remove(),!0},o.COMMAND_PRIORITY_LOW))},[e,s,f,g])}function c(e){const t=n.$createOverflowNode();return e.replace(t),t.append(e),t}function a(e){const t=e.getPreviousSibling();if(!n.$isOverflowNode(t))return;const r=e.getFirstChild(),i=t.getChildren(),s=i.length;if(null===r)e.append(...i);else for(let e=0;e<s;e++)r.insertBefore(i[e]);const l=o.$getSelection();if(o.$isRangeSelection(l)){const n=l.anchor,r=n.getNode(),i=l.focus,o=i.getNode();r.is(t)?n.set(e.getKey(),n.offset,"element"):r.is(e)&&n.set(e.getKey(),s+n.offset,"element"),o.is(t)?i.set(e.getKey(),i.offset,"element"):o.is(e)&&i.set(e.getKey(),s+i.offset,"element")}t.remove()}let g=null;function f(e){const t=void 0===window.TextEncoder?null:(null===g&&(g=new window.TextEncoder),g);if(null===t){const t=encodeURIComponent(e).match(/%[89ABab]/g);return e.length+(t?t.length:0)}return t.encode(e).length}function u({remainingCharacters:e}){
|
|
10
|
+
return s.jsx("span",{className:"characters-limit "+(e<0?"characters-limit-exceeded":""),children:e})}exports.CharacterLimitPlugin=function({charset:n="UTF-16",maxLength:r=5,renderer:i=u}){const[o]=e.useLexicalComposerContext(),[s,c]=t.useState(r),a=t.useMemo(()=>({remainingCharacters:c,strlen:e=>{if("UTF-8"===n)return f(e);if("UTF-16"===n)return e.length;throw new Error("Unrecognized charset")}}),[n]);return l(o,r,a),i({remainingCharacters:s})};
|
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import{useLexicalComposerContext as e}from"@lexical/react/LexicalComposerContext";import{useEffect as t,useState as n,useMemo as r}from"react";import{OverflowNode as o,$isOverflowNode as i,$createOverflowNode as s}from"@lexical/overflow";import{$rootTextContent as l}from"@lexical/text";import{$dfsWithSlots as c,$unwrapNode as a}from"@lexical/utils";import{mergeRegister as f,HISTORY_MERGE_TAG as g,DELETE_CHARACTER_COMMAND as m,$getSelection as u,$isRangeSelection as d,$isElementNode as h,COMMAND_PRIORITY_LOW as p,$isLeafNode as x,$getSlotHost as C,$findMatchingParent as S,$isTextNode as v,$setSelection as w}from"lexical";import{jsx as T}from"react/jsx-runtime";function
|
|
10
|
-
return T("span",{className:"characters-limit "+(e<0?"characters-limit-exceeded":""),children:e})}function
|
|
9
|
+
import{useLexicalComposerContext as e}from"@lexical/react/LexicalComposerContext";import{useEffect as t,useState as n,useMemo as r}from"react";import{OverflowNode as o,$isOverflowNode as i,$createOverflowNode as s}from"@lexical/overflow";import{$rootTextContent as l}from"@lexical/text";import{$dfsWithSlots as c,$unwrapNode as a}from"@lexical/utils";import{mergeRegister as f,HISTORY_MERGE_TAG as g,DELETE_CHARACTER_COMMAND as m,$getSelection as u,$isRangeSelection as d,$isElementNode as h,COMMAND_PRIORITY_LOW as p,$isLeafNode as x,$getSlotHost as C,$findMatchingParent as S,$isTextNode as v,$setSelection as w}from"lexical";import{jsx as T}from"react/jsx-runtime";function b(e,n,r=Object.freeze({})){const{strlen:s=e=>e.length,remainingCharacters:T=()=>{}}=r;t(()=>{e.hasNodes([o])||function(e,...t){const n=new URL("https://lexical.dev/docs/error"),r=new URLSearchParams;r.append("code",e);for(const e of t)r.append("v",e);throw n.search=r.toString(),Error(`Minified Lexical error #${e}; visit ${n.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}(57)},[e]),t(()=>{let t=e.read("latest",l),r=0;return f(e.registerTextContentListener(e=>{t=e}),e.registerUpdateListener(({dirtyLeaves:o,dirtyElements:l})=>{const f=e.isComposing(),m=o.size>0||l.size>0;if(f||!m)return;const p=s(t),b=p>n||null!==r&&r>n;if(T(n-p),null===r||b){const r=function(e,t,n){let r=0,o=0;if("function"==typeof Intl.Segmenter){const i=(new Intl.Segmenter).segment(e);for(const{segment:e}of i){const i=o+n(e);if(i>t)break;o=i,r+=e.length}}else{const i=Array.from(e),s=i.length;for(let e=0;e<s;e++){const s=i[e],l=o+n(s);if(l>t)break;o=l,r+=s.length}}return r}(t,n,s);e.update(()=>{!function(e){const t=c(),n=t.length;let r=0;for(let o=0;o<n;o+=1){const{node:n}=t[o],s=n.getPreviousSibling();h(s)&&!s.isInline()&&(r+=2);const l=x(n)&&null!==C(n),c=x(n)&&!l&&!S(n,i);if(i(n)){const t=r;if(r+n.getTextContentSize()<=e){const e=n.getParent(),t=n.getPreviousSibling(),r=n.getNextSibling();a(n);const o=u();!d(o)||o.anchor.getNode().isAttached()&&o.focus.getNode().isAttached()||(v(t)?t.select():v(r)?r.select():null!==e&&e.select())}else if(t<e){const r=n.getFirstDescendant(),o=t+(null!==r?r.getTextContentSize():0);(v(r)&&r.isSimpleText()||o<=e)&&a(n)}}else if(l)r+=n.getTextContentSize();else if(c){const t=r;if(r+=n.getTextContentSize(),r>e&&!i(n.getParent())){const r=u();let o;if(t<e&&v(n)&&n.isSimpleText()){const[,r]=n.splitText(e-t);o=y(r)}else o=y(n);null!==r&&w(r),N(o);const s=o.getNextSibling();i(s)&&N(s)}}}}(r)},{tag:g})}r=p}),e.registerCommand(m,e=>{const t=u();if(!d(t))return!1;const n=t.anchor.getNode().getParent(),r=n?n.getParent():null,o=r?r.getNextSibling():null;return t.deleteCharacter(e),r&&r.isEmpty()?r.remove():h(o)&&o.isEmpty()&&o.remove(),!0},p))},[e,n,T,s])}function y(e){const t=s();return e.replace(t),t.append(e),t}function N(e){const t=e.getPreviousSibling();if(!i(t))return;const n=e.getFirstChild(),r=t.getChildren(),o=r.length;if(null===n)e.append(...r);else for(let e=0;e<o;e++)n.insertBefore(r[e]);const s=u();if(d(s)){const n=s.anchor,r=n.getNode(),i=s.focus,l=i.getNode();r.is(t)?n.set(e.getKey(),n.offset,"element"):r.is(e)&&n.set(e.getKey(),o+n.offset,"element"),l.is(t)?i.set(e.getKey(),i.offset,"element"):l.is(e)&&i.set(e.getKey(),o+i.offset,"element")}t.remove()}let z=null;function L(e){const t=void 0===window.TextEncoder?null:(null===z&&(z=new window.TextEncoder),z);if(null===t){const t=encodeURIComponent(e).match(/%[89ABab]/g);return e.length+(t?t.length:0)}return t.encode(e).length}function P({remainingCharacters:e}){
|
|
10
|
+
return T("span",{className:"characters-limit "+(e<0?"characters-limit-exceeded":""),children:e})}function U({charset:t="UTF-16",maxLength:o=5,renderer:i=P}){const[s]=e(),[l,c]=n(o);return b(s,o,r(()=>({remainingCharacters:c,strlen:e=>{if("UTF-8"===t)return L(e);if("UTF-16"===t)return e.length;throw new Error("Unrecognized charset")}}),[t])),i({remainingCharacters:l})}export{U as CharacterLimitPlugin};
|
|
@@ -26,6 +26,8 @@ type CollaborationPluginProps = {
|
|
|
26
26
|
* Fallback to legacy method if not enabled or not supported.
|
|
27
27
|
*/
|
|
28
28
|
selectionHighlight?: boolean;
|
|
29
|
+
/** Customize the Yjs shared-type key used for the root `XmlText`. Defaults to `'root'`. */
|
|
30
|
+
rootName?: string;
|
|
29
31
|
};
|
|
30
32
|
/**
|
|
31
33
|
* Connects the editor to a Yjs document for real-time collaboration, syncing
|
|
@@ -36,7 +38,7 @@ type CollaborationPluginProps = {
|
|
|
36
38
|
* @returns The element that renders collaborators' cursors (or an empty
|
|
37
39
|
* fragment until the provider and binding are initialized).
|
|
38
40
|
*/
|
|
39
|
-
export declare function CollaborationPlugin({ id, providerFactory, shouldBootstrap, username, cursorColor, cursorsContainerRef, initialEditorState, excludedProperties, awarenessData, syncCursorPositionsFn, selectionHighlight, }: CollaborationPluginProps): JSX.Element;
|
|
41
|
+
export declare function CollaborationPlugin({ id, providerFactory, shouldBootstrap, username, cursorColor, cursorsContainerRef, initialEditorState, excludedProperties, awarenessData, syncCursorPositionsFn, selectionHighlight, rootName, }: CollaborationPluginProps): JSX.Element;
|
|
40
42
|
type CollaborationPluginV2Props = {
|
|
41
43
|
id: string;
|
|
42
44
|
doc: Doc;
|
|
@@ -51,6 +53,8 @@ type CollaborationPluginV2Props = {
|
|
|
51
53
|
* Fallback to legacy method if not enabled or not supported.
|
|
52
54
|
*/
|
|
53
55
|
selectionHighlight?: boolean;
|
|
56
|
+
/** Customize the Yjs shared-type key used for the root `XmlElement`. Defaults to `'root-v2'`. */
|
|
57
|
+
rootName?: string;
|
|
54
58
|
};
|
|
55
59
|
/**
|
|
56
60
|
* A variant of {@link CollaborationPlugin} that takes an already-created Yjs
|
|
@@ -61,5 +65,5 @@ type CollaborationPluginV2Props = {
|
|
|
61
65
|
* @experimental The API may change in a future release.
|
|
62
66
|
* @returns The element that renders collaborators' cursors.
|
|
63
67
|
*/
|
|
64
|
-
export declare function CollaborationPluginV2__EXPERIMENTAL({ id, doc, provider, __shouldBootstrapUnsafe, username, cursorColor, cursorsContainerRef, excludedProperties, awarenessData, selectionHighlight, }: CollaborationPluginV2Props): JSX.Element;
|
|
68
|
+
export declare function CollaborationPluginV2__EXPERIMENTAL({ id, doc, provider, __shouldBootstrapUnsafe, username, cursorColor, cursorsContainerRef, excludedProperties, awarenessData, selectionHighlight, rootName, }: CollaborationPluginV2Props): JSX.Element;
|
|
65
69
|
export {};
|
|
@@ -500,7 +500,8 @@ function CollaborationPlugin({
|
|
|
500
500
|
excludedProperties,
|
|
501
501
|
awarenessData,
|
|
502
502
|
syncCursorPositionsFn,
|
|
503
|
-
selectionHighlight
|
|
503
|
+
selectionHighlight,
|
|
504
|
+
rootName
|
|
504
505
|
}) {
|
|
505
506
|
const isBindingInitialized = React.useRef(false);
|
|
506
507
|
const isProviderInitialized = React.useRef(false);
|
|
@@ -534,13 +535,25 @@ function CollaborationPlugin({
|
|
|
534
535
|
if (isBindingInitialized.current) {
|
|
535
536
|
return;
|
|
536
537
|
}
|
|
538
|
+
const resolvedDoc = doc || yjsDocMap.get(id);
|
|
539
|
+
if (!resolvedDoc) {
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
537
542
|
isBindingInitialized.current = true;
|
|
538
|
-
const newBinding = yjs.
|
|
543
|
+
const newBinding = yjs.createYjsBinding({
|
|
544
|
+
doc: resolvedDoc,
|
|
545
|
+
docMap: yjsDocMap,
|
|
546
|
+
editor,
|
|
547
|
+
excludedProperties,
|
|
548
|
+
id,
|
|
549
|
+
rootName
|
|
550
|
+
});
|
|
551
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
539
552
|
setBinding(newBinding);
|
|
540
553
|
return () => {
|
|
541
554
|
newBinding.root.destroy(newBinding);
|
|
542
555
|
};
|
|
543
|
-
}, [editor, provider, id, yjsDocMap, doc, excludedProperties]);
|
|
556
|
+
}, [editor, provider, id, yjsDocMap, doc, excludedProperties, rootName]);
|
|
544
557
|
if (!provider || !binding) {
|
|
545
558
|
return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {});
|
|
546
559
|
}
|
|
@@ -603,7 +616,8 @@ function CollaborationPluginV2__EXPERIMENTAL({
|
|
|
603
616
|
cursorsContainerRef,
|
|
604
617
|
excludedProperties,
|
|
605
618
|
awarenessData,
|
|
606
|
-
selectionHighlight
|
|
619
|
+
selectionHighlight,
|
|
620
|
+
rootName
|
|
607
621
|
}) {
|
|
608
622
|
const collabContext = LexicalCollaborationContext.useCollaborationContext(username, cursorColor);
|
|
609
623
|
const {
|
|
@@ -617,6 +631,7 @@ function CollaborationPluginV2__EXPERIMENTAL({
|
|
|
617
631
|
__shouldBootstrapUnsafe,
|
|
618
632
|
awarenessData,
|
|
619
633
|
excludedProperties,
|
|
634
|
+
rootName,
|
|
620
635
|
selectionHighlight
|
|
621
636
|
});
|
|
622
637
|
useYjsHistoryV2(editor, binding);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { useCollaborationContext } from '@lexical/react/LexicalCollaborationContext';
|
|
10
10
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
11
|
-
import { syncCursorPositions, syncLexicalUpdateToYjs, createUndoManager, setLocalStateFocus, createBindingV2__EXPERIMENTAL, CLEAR_DIFF_VERSIONS_COMMAND__EXPERIMENTAL, syncYjsStateToLexicalV2__EXPERIMENTAL, DIFF_VERSIONS_COMMAND__EXPERIMENTAL, renderSnapshot__EXPERIMENTAL, syncLexicalUpdateToYjsV2__EXPERIMENTAL, syncYjsChangesToLexical, initLocalState, TOGGLE_CONNECT_COMMAND, syncYjsChangesToLexicalV2__EXPERIMENTAL, removeCursorHighlightRule, CONNECTED_COMMAND,
|
|
11
|
+
import { syncCursorPositions, syncLexicalUpdateToYjs, createUndoManager, setLocalStateFocus, createBindingV2__EXPERIMENTAL, CLEAR_DIFF_VERSIONS_COMMAND__EXPERIMENTAL, syncYjsStateToLexicalV2__EXPERIMENTAL, DIFF_VERSIONS_COMMAND__EXPERIMENTAL, renderSnapshot__EXPERIMENTAL, syncLexicalUpdateToYjsV2__EXPERIMENTAL, syncYjsChangesToLexical, initLocalState, TOGGLE_CONNECT_COMMAND, syncYjsChangesToLexicalV2__EXPERIMENTAL, removeCursorHighlightRule, CONNECTED_COMMAND, createYjsBinding } from '@lexical/yjs';
|
|
12
12
|
import * as React from 'react';
|
|
13
13
|
import { useRef, useCallback, useEffect, useMemo, useState } from 'react';
|
|
14
14
|
import { SKIP_COLLAB_TAG, mergeRegister, FOCUS_COMMAND, COMMAND_PRIORITY_EDITOR, BLUR_COMMAND, $getRoot, HISTORY_MERGE_TAG, $createParagraphNode, $getSelection, getActiveElement, registerEventListeners, UNDO_COMMAND, REDO_COMMAND, CAN_UNDO_COMMAND, CAN_REDO_COMMAND } from 'lexical';
|
|
@@ -486,7 +486,8 @@ function CollaborationPlugin({
|
|
|
486
486
|
excludedProperties,
|
|
487
487
|
awarenessData,
|
|
488
488
|
syncCursorPositionsFn,
|
|
489
|
-
selectionHighlight
|
|
489
|
+
selectionHighlight,
|
|
490
|
+
rootName
|
|
490
491
|
}) {
|
|
491
492
|
const isBindingInitialized = useRef(false);
|
|
492
493
|
const isProviderInitialized = useRef(false);
|
|
@@ -520,13 +521,25 @@ function CollaborationPlugin({
|
|
|
520
521
|
if (isBindingInitialized.current) {
|
|
521
522
|
return;
|
|
522
523
|
}
|
|
524
|
+
const resolvedDoc = doc || yjsDocMap.get(id);
|
|
525
|
+
if (!resolvedDoc) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
523
528
|
isBindingInitialized.current = true;
|
|
524
|
-
const newBinding =
|
|
529
|
+
const newBinding = createYjsBinding({
|
|
530
|
+
doc: resolvedDoc,
|
|
531
|
+
docMap: yjsDocMap,
|
|
532
|
+
editor,
|
|
533
|
+
excludedProperties,
|
|
534
|
+
id,
|
|
535
|
+
rootName
|
|
536
|
+
});
|
|
537
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
525
538
|
setBinding(newBinding);
|
|
526
539
|
return () => {
|
|
527
540
|
newBinding.root.destroy(newBinding);
|
|
528
541
|
};
|
|
529
|
-
}, [editor, provider, id, yjsDocMap, doc, excludedProperties]);
|
|
542
|
+
}, [editor, provider, id, yjsDocMap, doc, excludedProperties, rootName]);
|
|
530
543
|
if (!provider || !binding) {
|
|
531
544
|
return /*#__PURE__*/jsx(Fragment, {});
|
|
532
545
|
}
|
|
@@ -589,7 +602,8 @@ function CollaborationPluginV2__EXPERIMENTAL({
|
|
|
589
602
|
cursorsContainerRef,
|
|
590
603
|
excludedProperties,
|
|
591
604
|
awarenessData,
|
|
592
|
-
selectionHighlight
|
|
605
|
+
selectionHighlight,
|
|
606
|
+
rootName
|
|
593
607
|
}) {
|
|
594
608
|
const collabContext = useCollaborationContext(username, cursorColor);
|
|
595
609
|
const {
|
|
@@ -603,6 +617,7 @@ function CollaborationPluginV2__EXPERIMENTAL({
|
|
|
603
617
|
__shouldBootstrapUnsafe,
|
|
604
618
|
awarenessData,
|
|
605
619
|
excludedProperties,
|
|
620
|
+
rootName,
|
|
606
621
|
selectionHighlight
|
|
607
622
|
});
|
|
608
623
|
useYjsHistoryV2(editor, binding);
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
"use strict";var e=require("@lexical/react/LexicalCollaborationContext"),t=require("@lexical/react/LexicalComposerContext"),o=require("@lexical/yjs"),r=require("react"),n=require("lexical"),s=require("react-dom"),a=require("yjs"),c=require("react/jsx-runtime");function i(e){var t=Object.create(null);if(e)for(var o in e)t[o]=e[o];return t.default=e,t}var l=/*#__PURE__*/i(r);const u=Symbol.for("@lexical/yjs/UndoManager");function d(e,t,s,c,i,l,u,d,C,p,m,h,M=o.syncCursorPositions,R=!1){const O=r.useRef(!1),
|
|
9
|
+
"use strict";var e=require("@lexical/react/LexicalCollaborationContext"),t=require("@lexical/react/LexicalComposerContext"),o=require("@lexical/yjs"),r=require("react"),n=require("lexical"),s=require("react-dom"),a=require("yjs"),c=require("react/jsx-runtime");function i(e){var t=Object.create(null);if(e)for(var o in e)t[o]=e[o];return t.default=e,t}var l=/*#__PURE__*/i(r);const u=Symbol.for("@lexical/yjs/UndoManager");function d(e,t,s,c,i,l,u,d,C,p,m,h,M=o.syncCursorPositions,R=!1){const O=r.useRef(!1),N=r.useCallback(()=>{const{root:t}=d;u&&t.isEmpty()&&0===t._xmlText._length&&_(e,m)},[d,e,m,u]);return r.useEffect(()=>{const{root:t}=d,r=(e,t)=>{const r=t.origin;if(r!==d){const t=r instanceof a.UndoManager;o.syncYjsChangesToLexical(d,s,e,t,M)}};t.getSharedType().observeDeep(r);const c=e.registerUpdateListener(({prevEditorState:e,editorState:t,dirtyLeaves:r,dirtyElements:a,normalizedNodes:c,tags:i})=>{i.has(n.SKIP_COLLAB_TAG)||o.syncLexicalUpdateToYjs(d,s,e,t,a,r,c,i)});return()=>{t.getSharedType().unobserveDeep(r),c()}},[d,s,e,C,c,t,M]),r.useEffect(()=>{const r=r=>{!function(e,t){if(e.update(()=>{const e=n.$getRoot();e.clear(),e.select()},{tag:n.SKIP_COLLAB_TAG}),null==t.cursors)return;const r=t.cursors;if(null==r)return;const s=t.cursorsContainer;if(null==s)return;for(const e of r.values()){const r=e.selection;if(null!==r){null!==r.highlight&&(CSS.highlights.delete(r.highlightName),o.removeCursorHighlightRule(t,r.highlightName)),r.caret.parentNode===s&&s.removeChild(r.caret);for(const e of r.selections)e.parentNode===s&&s.removeChild(e);e.selection=null}}}(e,d),C(r),c.set(t,r),O.current=!0},a=()=>{O.current=!1};return s.on("reload",r),s.on("sync",a),()=>{s.off("reload",r),s.off("sync",a)}},[d,s,e,C,c,t]),f(e,s,i,l,O,h,N),g(d,s,R),E(d,p)}function f(e,t,s,a,c,i,l){const u=r.useCallback(()=>t.connect(),[t]),d=r.useCallback(()=>{try{t.disconnect()}catch(e){}},[t]);r.useEffect(()=>{const r=({status:t})=>{e.dispatchCommand(o.CONNECTED_COMMAND,"connected"===t)},f=e=>{e&&!1===c.current&&l&&l()},g=e.getRootElement();o.initLocalState(t,s,a,null!==g&&n.getActiveElement(g)===g,i||{}),t.on("status",r),t.on("sync",f);const E=u();return()=>{!1===c.current&&(E?E.then(d):d()),t.off("sync",f),t.off("status",r)}},[e,t,s,a,c,i,l,u,d]),r.useEffect(()=>e.registerCommand(o.TOGGLE_CONNECT_COMMAND,e=>(e?(console.log("Collaboration connected!"),u()):(console.log("Collaboration disconnected!"),d()),!0),n.COMMAND_PRIORITY_EDITOR),[u,d,e]),r.useEffect(()=>{const e=()=>{try{t.awareness.setLocalState(null)}catch(e){}};return n.registerEventListeners(window,{beforeunload:e,pagehide:e})},[t])}function g(e,t,n){r.useEffect(()=>{const{awareness:r}=t,s=()=>{o.syncCursorPositions(e,t,{selectionHighlight:n})};return r.on("update",s),()=>{r.off("update",s)}},[e,t,n])}function E(e,t){return r.useMemo(()=>/*#__PURE__*/s.createPortal(/*#__PURE__*/c.jsx("div",{ref:t=>{e.cursorsContainer=t}}),t&&t.current||document.body),[e,t])}function C(e,t,s,a,c){r.useEffect(()=>n.mergeRegister(e.registerCommand(n.FOCUS_COMMAND,()=>(o.setLocalStateFocus(t,s,a,!0,c||{}),!1),n.COMMAND_PRIORITY_EDITOR),e.registerCommand(n.BLUR_COMMAND,()=>(o.setLocalStateFocus(t,s,a,!1,c||{}),!1),n.COMMAND_PRIORITY_EDITOR)),[a,e,s,t,c])}function p(e,t){r.useEffect(()=>n.mergeRegister(e.registerCommand(n.UNDO_COMMAND,()=>(t.undo(),!0),n.COMMAND_PRIORITY_EDITOR),e.registerCommand(n.REDO_COMMAND,()=>(t.redo(),!0),n.COMMAND_PRIORITY_EDITOR))),r.useEffect(()=>{const o=e;return o[u]=t,()=>{o[u]===t&&delete o[u]}},[e,t]);const o=r.useCallback(()=>{t.clear()},[t]);return l.useEffect(()=>{const o=()=>{e.dispatchCommand(n.CAN_UNDO_COMMAND,t.undoStack.length>0),e.dispatchCommand(n.CAN_REDO_COMMAND,t.redoStack.length>0)};return t.on("stack-item-added",o),t.on("stack-item-popped",o),t.on("stack-cleared",o),()=>{t.off("stack-item-added",o),t.off("stack-item-popped",o),t.off("stack-cleared",o)}},[e,t]),o}function _(e,t){e.update(()=>{const o=n.$getRoot();if(o.isEmpty())if(t)switch(typeof t){case"string":{const o=e.parseEditorState(t);e.setEditorState(o,{tag:n.HISTORY_MERGE_TAG});break}case"object":e.setEditorState(t,{tag:n.HISTORY_MERGE_TAG});break;case"function":e.update(()=>{n.$getRoot().isEmpty()&&t(e)},{tag:n.HISTORY_MERGE_TAG})}else{const t=n.$createParagraphNode();o.append(t);const r=e.getRootElement();(null!==n.$getSelection()||null!==r&&n.getActiveElement(r)===r)&&t.select()}},{tag:n.HISTORY_MERGE_TAG})}function m({editor:e,id:t,provider:n,yjsDocMap:s,name:a,color:c,shouldBootstrap:i,cursorsContainerRef:l,initialEditorState:u,awarenessData:f,collabContext:g,binding:E,setDoc:_,syncCursorPositionsFn:m,selectionHighlight:h}){const M=d(e,t,n,s,a,c,i,E,_,l,u,f,m,h);return function(e,t){p(e,r.useMemo(()=>o.createUndoManager(t,t.root.getSharedType()),[t]))}(e,E),C(e,n,a,c,f),M}const h=(e,t)=>{r.useEffect(()=>(e.isCollabActive=!0,()=>{null==t._parentEditor&&(e.isCollabActive=!1)}),[e,t])};exports.CollaborationPlugin=function({id:n,providerFactory:s,shouldBootstrap:a,username:i,cursorColor:l,cursorsContainerRef:u,initialEditorState:d,excludedProperties:f,awarenessData:g,syncCursorPositionsFn:E,selectionHighlight:C,rootName:p}){const _=r.useRef(!1),M=r.useRef(!1),R=e.useCollaborationContext(i,l),{yjsDocMap:O,name:N,color:D}=R,[T]=t.useLexicalComposerContext();h(R,T);const[S,A]=r.useState(),[I,y]=r.useState();r.useEffect(()=>{if(M.current)return;M.current=!0;const e=s(n,O);return A(e),y(O.get(n)),()=>{e.disconnect()}},[n,s,O]);const[x,L]=r.useState();return r.useEffect(()=>{if(!S)return;if(_.current)return;const e=I||O.get(n);if(!e)return;_.current=!0;const t=o.createYjsBinding({doc:e,docMap:O,editor:T,excludedProperties:f,id:n,rootName:p});return L(t),()=>{t.root.destroy(t)}},[T,S,n,O,I,f,p]),S&&x?/*#__PURE__*/c.jsx(m,{awarenessData:g,binding:x,collabContext:R,color:D,cursorsContainerRef:u,editor:T,id:n,initialEditorState:d,name:N,provider:S,setDoc:y,shouldBootstrap:a,yjsDocMap:O,syncCursorPositionsFn:E,selectionHighlight:C}):/*#__PURE__*/c.jsx(c.Fragment,{})},exports.CollaborationPluginV2__EXPERIMENTAL=function({id:s,doc:c,provider:i,__shouldBootstrapUnsafe:l,username:u,cursorColor:d,cursorsContainerRef:m,excludedProperties:M,awarenessData:R,selectionHighlight:O,rootName:N}){const D=e.useCollaborationContext(u,d),{yjsDocMap:T,name:S,color:A}=D,[I]=t.useLexicalComposerContext();h(D,I);const y=function(e,t,s,c,i,l,u,d={}){const{awarenessData:E,excludedProperties:C,rootName:p,selectionHighlight:m=!1,__shouldBootstrapUnsafe:h}=d,M=r.useMemo(()=>({current:!1}),[]),R=r.useMemo(()=>o.createBindingV2__EXPERIMENTAL(e,t,s,i,{excludedProperties:C,rootName:p}),[e,t,s,i,C,p]);r.useEffect(()=>(i.set(t,s),()=>{i.delete(t)}),[s,i,t]);const O=r.useCallback(()=>{const{root:t}=R;h&&0===t._length&&_(e)},[R,e,h]),[N,D]=r.useState();return r.useEffect(()=>{n.mergeRegister(e.registerCommand(o.CLEAR_DIFF_VERSIONS_COMMAND__EXPERIMENTAL,()=>(D(null),o.syncYjsStateToLexicalV2__EXPERIMENTAL(R,c),!0),n.COMMAND_PRIORITY_EDITOR),e.registerCommand(o.DIFF_VERSIONS_COMMAND__EXPERIMENTAL,({prevSnapshot:e,snapshot:t})=>(D({prevSnapshot:e,snapshot:t}),!0),n.COMMAND_PRIORITY_EDITOR))},[e,R,c]),r.useEffect(()=>{const{root:t}=R;if(N)return void o.renderSnapshot__EXPERIMENTAL(R,N.snapshot,N.prevSnapshot);const r=(e,t)=>{const r=t.origin;if(r!==R){const n=r instanceof a.UndoManager;o.syncYjsChangesToLexicalV2__EXPERIMENTAL(R,c,e,t,n)}};t.observeDeep(r);const s=e.registerUpdateListener(({prevEditorState:e,editorState:t,dirtyElements:r,dirtyLeaves:s,normalizedNodes:a,tags:i})=>{i.has(n.SKIP_COLLAB_TAG)||o.syncLexicalUpdateToYjsV2__EXPERIMENTAL(R,c,e,t,r,s,a,i)});return()=>{t.unobserveDeep(r),s()}},[R,c,e,N]),f(e,c,l,u,M,E,O),g(R,c,m),R}(I,s,c,i,T,S,A,{__shouldBootstrapUnsafe:l,awarenessData:R,excludedProperties:M,rootName:N,selectionHighlight:O});return function(e,t){p(e,r.useMemo(()=>o.createUndoManager(t,t.root),[t]))}(I,y),C(I,i,S,A,R),E(y,m)};
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import{useCollaborationContext as t}from"@lexical/react/LexicalCollaborationContext";import{useLexicalComposerContext as e}from"@lexical/react/LexicalComposerContext";import{syncCursorPositions as o,syncLexicalUpdateToYjs as r,createUndoManager as n,setLocalStateFocus as s,createBindingV2__EXPERIMENTAL as a,CLEAR_DIFF_VERSIONS_COMMAND__EXPERIMENTAL as i,syncYjsStateToLexicalV2__EXPERIMENTAL as c,DIFF_VERSIONS_COMMAND__EXPERIMENTAL as l,renderSnapshot__EXPERIMENTAL as d,syncLexicalUpdateToYjsV2__EXPERIMENTAL as u,syncYjsChangesToLexical as p,initLocalState as
|
|
9
|
+
import{useCollaborationContext as t}from"@lexical/react/LexicalCollaborationContext";import{useLexicalComposerContext as e}from"@lexical/react/LexicalComposerContext";import{syncCursorPositions as o,syncLexicalUpdateToYjs as r,createUndoManager as n,setLocalStateFocus as s,createBindingV2__EXPERIMENTAL as a,CLEAR_DIFF_VERSIONS_COMMAND__EXPERIMENTAL as i,syncYjsStateToLexicalV2__EXPERIMENTAL as c,DIFF_VERSIONS_COMMAND__EXPERIMENTAL as l,renderSnapshot__EXPERIMENTAL as d,syncLexicalUpdateToYjsV2__EXPERIMENTAL as u,syncYjsChangesToLexical as p,initLocalState as m,TOGGLE_CONNECT_COMMAND as f,syncYjsChangesToLexicalV2__EXPERIMENTAL as g,removeCursorHighlightRule as h,CONNECTED_COMMAND as C,createYjsBinding as y}from"@lexical/yjs";import*as v from"react";import{useRef as S,useCallback as x,useEffect as b,useMemo as E,useState as D}from"react";import{SKIP_COLLAB_TAG as N,mergeRegister as w,FOCUS_COMMAND as k,COMMAND_PRIORITY_EDITOR as _,BLUR_COMMAND as j,$getRoot as P,HISTORY_MERGE_TAG as H,$createParagraphNode as L,$getSelection as B,getActiveElement as M,registerEventListeners as R,UNDO_COMMAND as U,REDO_COMMAND as F,CAN_UNDO_COMMAND as T,CAN_REDO_COMMAND as z}from"lexical";import{createPortal as A}from"react-dom";import{UndoManager as q}from"yjs";import{jsx as G,Fragment as I}from"react/jsx-runtime";const J=Symbol.for("@lexical/yjs/UndoManager");function K(t,e,n,s,a,i,c,l,d,u,m,f,g=o,C=!1){const y=S(!1),v=x(()=>{const{root:e}=l;c&&e.isEmpty()&&0===e._xmlText._length&&Y(t,m)},[l,t,m,c]);return b(()=>{const{root:e}=l,o=(t,e)=>{const o=e.origin;if(o!==l){p(l,n,t,o instanceof q,g)}};e.getSharedType().observeDeep(o);const s=t.registerUpdateListener(({prevEditorState:t,editorState:e,dirtyLeaves:o,dirtyElements:s,normalizedNodes:a,tags:i})=>{i.has(N)||r(l,n,t,e,s,o,a,i)});return()=>{e.getSharedType().unobserveDeep(o),s()}},[l,n,t,d,s,e,g]),b(()=>{const o=o=>{!function(t,e){if(t.update(()=>{const t=P();t.clear(),t.select()},{tag:N}),null==e.cursors)return;const o=e.cursors;if(null==o)return;const r=e.cursorsContainer;if(null==r)return;for(const t of o.values()){const o=t.selection;if(null!==o){null!==o.highlight&&(CSS.highlights.delete(o.highlightName),h(e,o.highlightName)),o.caret.parentNode===r&&r.removeChild(o.caret);for(const t of o.selections)t.parentNode===r&&r.removeChild(t);t.selection=null}}}(t,l),d(o),s.set(e,o),y.current=!0},r=()=>{y.current=!1};return n.on("reload",o),n.on("sync",r),()=>{n.off("reload",o),n.off("sync",r)}},[l,n,t,d,s,e]),O(t,n,a,i,y,f,v),Q(l,n,C),V(l,u)}function O(t,e,o,r,n,s,a){const i=x(()=>e.connect(),[e]),c=x(()=>{try{e.disconnect()}catch(t){}},[e]);b(()=>{const l=({status:e})=>{t.dispatchCommand(C,"connected"===e)},d=t=>{t&&!1===n.current&&a&&a()},u=t.getRootElement();m(e,o,r,null!==u&&M(u)===u,s||{}),e.on("status",l),e.on("sync",d);const p=i();return()=>{!1===n.current&&(p?p.then(c):c()),e.off("sync",d),e.off("status",l)}},[t,e,o,r,n,s,a,i,c]),b(()=>t.registerCommand(f,t=>(t?(console.log("Collaboration connected!"),i()):(console.log("Collaboration disconnected!"),c()),!0),_),[i,c,t]),b(()=>{const t=()=>{try{e.awareness.setLocalState(null)}catch(t){}};return R(window,{beforeunload:t,pagehide:t})},[e])}function Q(t,e,r){b(()=>{const{awareness:n}=e,s=()=>{o(t,e,{selectionHighlight:r})};return n.on("update",s),()=>{n.off("update",s)}},[t,e,r])}function V(t,e){return E(()=>/*#__PURE__*/A(/*#__PURE__*/G("div",{ref:e=>{t.cursorsContainer=e}}),e&&e.current||document.body),[t,e])}function W(t,e,o,r,n){b(()=>w(t.registerCommand(k,()=>(s(e,o,r,!0,n||{}),!1),_),t.registerCommand(j,()=>(s(e,o,r,!1,n||{}),!1),_)),[r,t,o,e,n])}function X(t,e){b(()=>w(t.registerCommand(U,()=>(e.undo(),!0),_),t.registerCommand(F,()=>(e.redo(),!0),_))),b(()=>{const o=t;return o[J]=e,()=>{o[J]===e&&delete o[J]}},[t,e]);const o=x(()=>{e.clear()},[e]);return v.useEffect(()=>{const o=()=>{t.dispatchCommand(T,e.undoStack.length>0),t.dispatchCommand(z,e.redoStack.length>0)};return e.on("stack-item-added",o),e.on("stack-item-popped",o),e.on("stack-cleared",o),()=>{e.off("stack-item-added",o),e.off("stack-item-popped",o),e.off("stack-cleared",o)}},[t,e]),o}function Y(t,e){t.update(()=>{const o=P();if(o.isEmpty())if(e)switch(typeof e){case"string":{const o=t.parseEditorState(e);t.setEditorState(o,{tag:H});break}case"object":t.setEditorState(e,{tag:H});break;case"function":t.update(()=>{P().isEmpty()&&e(t)},{tag:H})}else{const e=L();o.append(e);const r=t.getRootElement();(null!==B()||null!==r&&M(r)===r)&&e.select()}},{tag:H})}function Z({id:o,providerFactory:r,shouldBootstrap:n,username:s,cursorColor:a,cursorsContainerRef:i,initialEditorState:c,excludedProperties:l,awarenessData:d,syncCursorPositionsFn:u,selectionHighlight:p,rootName:m}){const f=S(!1),g=S(!1),h=t(s,a),{yjsDocMap:C,name:v,color:x}=h,[E]=e();et(h,E);const[N,w]=D(),[k,_]=D();b(()=>{if(g.current)return;g.current=!0;const t=r(o,C);return w(t),_(C.get(o)),()=>{t.disconnect()}},[o,r,C]);const[j,P]=D();return b(()=>{if(!N)return;if(f.current)return;const t=k||C.get(o);if(!t)return;f.current=!0;const e=y({doc:t,docMap:C,editor:E,excludedProperties:l,id:o,rootName:m});return P(e),()=>{e.root.destroy(e)}},[E,N,o,C,k,l,m]),N&&j?/*#__PURE__*/G($,{awarenessData:d,binding:j,collabContext:h,color:x,cursorsContainerRef:i,editor:E,id:o,initialEditorState:c,name:v,provider:N,setDoc:_,shouldBootstrap:n,yjsDocMap:C,syncCursorPositionsFn:u,selectionHighlight:p}):/*#__PURE__*/G(I,{})}function $({editor:t,id:e,provider:o,yjsDocMap:r,name:s,color:a,shouldBootstrap:i,cursorsContainerRef:c,initialEditorState:l,awarenessData:d,collabContext:u,binding:p,setDoc:m,syncCursorPositionsFn:f,selectionHighlight:g}){const h=K(t,e,o,r,s,a,i,p,m,c,l,d,f,g);return function(t,e){X(t,E(()=>n(e,e.root.getSharedType()),[e]))}(t,p),W(t,o,s,a,d),h}function tt({id:o,doc:r,provider:s,__shouldBootstrapUnsafe:p,username:m,cursorColor:f,cursorsContainerRef:h,excludedProperties:C,awarenessData:y,selectionHighlight:v,rootName:S}){const k=t(m,f),{yjsDocMap:j,name:P,color:H}=k,[L]=e();et(k,L);const B=function(t,e,o,r,n,s,p,m={}){const{awarenessData:f,excludedProperties:h,rootName:C,selectionHighlight:y=!1,__shouldBootstrapUnsafe:v}=m,S=E(()=>({current:!1}),[]),k=E(()=>a(t,e,o,n,{excludedProperties:h,rootName:C}),[t,e,o,n,h,C]);b(()=>(n.set(e,o),()=>{n.delete(e)}),[o,n,e]);const j=x(()=>{const{root:e}=k;v&&0===e._length&&Y(t)},[k,t,v]),[P,H]=D();return b(()=>{w(t.registerCommand(i,()=>(H(null),c(k,r),!0),_),t.registerCommand(l,({prevSnapshot:t,snapshot:e})=>(H({prevSnapshot:t,snapshot:e}),!0),_))},[t,k,r]),b(()=>{const{root:e}=k;if(P)return void d(k,P.snapshot,P.prevSnapshot);const o=(t,e)=>{const o=e.origin;o!==k&&g(k,r,t,e,o instanceof q)};e.observeDeep(o);const n=t.registerUpdateListener(({prevEditorState:t,editorState:e,dirtyElements:o,dirtyLeaves:n,normalizedNodes:s,tags:a})=>{a.has(N)||u(k,r,t,e,o,n,s,a)});return()=>{e.unobserveDeep(o),n()}},[k,r,t,P]),O(t,r,s,p,S,f,j),Q(k,r,y),k}(L,o,r,s,j,P,H,{__shouldBootstrapUnsafe:p,awarenessData:y,excludedProperties:C,rootName:S,selectionHighlight:v});return function(t,e){X(t,E(()=>n(e,e.root),[e]))}(L,B),W(L,s,P,H,y),V(B,h)}const et=(t,e)=>{b(()=>(t.isCollabActive=!0,()=>{null==e._parentEditor&&(t.isCollabActive=!1)}),[t,e])};export{Z as CollaborationPlugin,tt as CollaborationPluginV2__EXPERIMENTAL};
|
|
@@ -43,7 +43,7 @@ function formatDevErrorMessage(message) {
|
|
|
43
43
|
* Most code should read it through {@link useLexicalComposerContext} rather than
|
|
44
44
|
* consuming the context directly.
|
|
45
45
|
*/
|
|
46
|
-
const LexicalComposerContext =
|
|
46
|
+
const LexicalComposerContext = react.createContext(null);
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Creates a {@link LexicalComposerContextType} for a composer. Theme resolution
|
|
@@ -41,7 +41,7 @@ function formatDevErrorMessage(message) {
|
|
|
41
41
|
* Most code should read it through {@link useLexicalComposerContext} rather than
|
|
42
42
|
* consuming the context directly.
|
|
43
43
|
*/
|
|
44
|
-
const LexicalComposerContext =
|
|
44
|
+
const LexicalComposerContext = createContext(null);
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* Creates a {@link LexicalComposerContextType} for a composer. Theme resolution
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
"use strict";var e=require("react");const n
|
|
9
|
+
"use strict";var e=require("react");const n=e.createContext(null);exports.LexicalComposerContext=n,exports.createLexicalComposerContext=function(e,n){let t=null;return null!=e&&(t=e[1]),{getTheme:function(){return null!=n?n:null!=t?t.getTheme():null}}},exports.useLexicalComposerContext=function(){const t=e.useContext(n);return null==t&&function(e,...n){const t=new URL("https://lexical.dev/docs/error"),r=new URLSearchParams;r.append("code",e);for(const e of n)r.append("v",e);throw t.search=r.toString(),Error(`Minified Lexical error #${e}; visit ${t.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}(8),t};
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import{createContext as n,useContext as e}from"react";const r
|
|
9
|
+
import{createContext as n,useContext as e}from"react";const r=n(null);function t(n,e){let r=null;return null!=n&&(r=n[1]),{getTheme:function(){return null!=e?e:null!=r?r.getTheme():null}}}function o(){const n=e(r);return null==n&&function(n,...e){const r=new URL("https://lexical.dev/docs/error"),t=new URLSearchParams;t.append("code",n);for(const n of e)t.append("v",n);throw r.search=t.toString(),Error(`Minified Lexical error #${n}; visit ${r.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`)}(8),n}export{r as LexicalComposerContext,t as createLexicalComposerContext,o as useLexicalComposerContext};
|
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
"use strict";var e=require("@lexical/react/LexicalComposerContext"),t=require("react"),a=require("lexical"),r=require("react/jsx-runtime"),i=require("@lexical/text");const n=a.CAN_USE_DOM?t.useLayoutEffect:t.useEffect;function
|
|
10
|
-
return r.jsxs(r.Fragment,{children:[/*#__PURE__*/r.jsx(
|
|
9
|
+
"use strict";var e=require("@lexical/react/LexicalComposerContext"),t=require("react"),a=require("lexical"),r=require("react/jsx-runtime"),i=require("@lexical/text");const n=a.CAN_USE_DOM?t.useLayoutEffect:t.useEffect;function o({editor:e,ariaActiveDescendant:a,ariaAutoComplete:i,ariaControls:o,ariaDescribedBy:l,ariaErrorMessage:s,ariaExpanded:d,ariaInvalid:u,ariaLabel:c,ariaLabelledBy:f,ariaMultiline:b,ariaOwns:x,ariaRequired:m,autoCapitalize:E,className:p,id:C,role:v="textbox",spellCheck:y=!0,style:g,tabIndex:L,"data-testid":h,...w},q){const[j,R]=t.useState(e.isEditable()),D=t.useCallback(t=>{t&&t.ownerDocument&&t.ownerDocument.defaultView?e.setRootElement(t):e.setRootElement(null)},[e]),S=t.useMemo(()=>function(...e){return t=>{for(const a of e)"function"==typeof a?a(t):null!=a&&(a.current=t)}}(q,D),[D,q]);return n(()=>(R(e.isEditable()),e.registerEditableListener(e=>{R(e)})),[e]),/*#__PURE__*/r.jsx("div",{"aria-activedescendant":j?a:void 0,"aria-autocomplete":j?i:"none","aria-controls":j?o:void 0,"aria-describedby":l,...null!=s?{"aria-errormessage":s}:{},"aria-expanded":j&&"combobox"===v?!!d:void 0,...null!=u?{"aria-invalid":u}:{},"aria-label":c,"aria-labelledby":f,"aria-multiline":b,"aria-owns":j?x:void 0,"aria-readonly":!j||void 0,"aria-required":m,autoCapitalize:E,className:p,contentEditable:j,"data-testid":h,id:C,ref:S,role:v,spellCheck:y,style:g,tabIndex:L??(j?void 0:-1),...w})}const l=/*#__PURE__*/t.forwardRef(o);function s(e){return e.read("latest",i.$canShowPlaceholderCurry(e.isComposing()))}const d=/*#__PURE__*/t.forwardRef(u);function u(t,a){const{placeholder:i,...n}=t,[o]=e.useLexicalComposerContext();
|
|
10
|
+
return r.jsxs(r.Fragment,{children:[/*#__PURE__*/r.jsx(l,{editor:o,...n,ref:a}),null!=i&&/*#__PURE__*/r.jsx(c,{editor:o,content:i})]})}function c({content:e,editor:i}){const o=function(e){const[r,i]=t.useState(()=>s(e));return n(()=>{function t(){const t=s(e);i(t)}return t(),a.mergeRegister(e.registerUpdateListener(()=>{t()}),e.registerEditableListener(()=>{t()}))},[e]),r}(i),[l,d]=t.useState(i.isEditable());if(t.useLayoutEffect(()=>(d(i.isEditable()),i.registerEditableListener(e=>{d(e)})),[i]),!o)return null;let u=null;return"function"==typeof e?u=e(l):null!==e&&(u=e),null===u?null:/*#__PURE__*/r.jsx("div",{"aria-hidden":!0,children:u})}exports.ContentEditable=d,exports.ContentEditableElement=l;
|
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import{useLexicalComposerContext as e}from"@lexical/react/LexicalComposerContext";import{useLayoutEffect as t,useEffect as i,forwardRef as a,useState as r,useCallback as n,useMemo as o}from"react";import{CAN_USE_DOM as l,mergeRegister as d}from"lexical";import{jsx as s,jsxs as c,Fragment as u}from"react/jsx-runtime";import{$canShowPlaceholderCurry as m}from"@lexical/text";const f=l?t:i;function b({editor:e,ariaActiveDescendant:t,ariaAutoComplete:i,ariaControls:a,ariaDescribedBy:l,ariaErrorMessage:d,ariaExpanded:c,ariaInvalid:u,ariaLabel:m,ariaLabelledBy:b,ariaMultiline:p,ariaOwns:x,ariaRequired:
|
|
10
|
-
return c(u,{children:[/*#__PURE__*/s(p,{editor:n,...r,ref:i}),null!=a&&/*#__PURE__*/s(y,{editor:n,content:a})]})}function y({content:e,editor:i}){const a=function(e){const[t,i]=r(()=>x(e));return f(()=>{function t(){const t=x(e);i(t)}return t(),d(e.registerUpdateListener(()=>{t()}),e.registerEditableListener(()=>{t()}))},[e]),t}(i),[n,o]=r(i.isEditable());if(t(()=>(o(i.isEditable()),i.registerEditableListener(e=>{o(e)})),[i]),!a)return null;let l=null;return"function"==typeof e?l=e(n):null!==e&&(l=e),null===l?null:/*#__PURE__*/s("div",{"aria-hidden":!0,children:l})}export{
|
|
9
|
+
import{useLexicalComposerContext as e}from"@lexical/react/LexicalComposerContext";import{useLayoutEffect as t,useEffect as i,forwardRef as a,useState as r,useCallback as n,useMemo as o}from"react";import{CAN_USE_DOM as l,mergeRegister as d}from"lexical";import{jsx as s,jsxs as c,Fragment as u}from"react/jsx-runtime";import{$canShowPlaceholderCurry as m}from"@lexical/text";const f=l?t:i;function b({editor:e,ariaActiveDescendant:t,ariaAutoComplete:i,ariaControls:a,ariaDescribedBy:l,ariaErrorMessage:d,ariaExpanded:c,ariaInvalid:u,ariaLabel:m,ariaLabelledBy:b,ariaMultiline:p,ariaOwns:x,ariaRequired:v,autoCapitalize:E,className:y,id:C,role:g="textbox",spellCheck:L=!0,style:h,tabIndex:w,"data-testid":D,...I},R){const[k,q]=r(e.isEditable()),z=n(t=>{t&&t.ownerDocument&&t.ownerDocument.defaultView?e.setRootElement(t):e.setRootElement(null)},[e]),A=o(()=>function(...e){return t=>{for(const i of e)"function"==typeof i?i(t):null!=i&&(i.current=t)}}(R,z),[z,R]);return f(()=>(q(e.isEditable()),e.registerEditableListener(e=>{q(e)})),[e]),/*#__PURE__*/s("div",{"aria-activedescendant":k?t:void 0,"aria-autocomplete":k?i:"none","aria-controls":k?a:void 0,"aria-describedby":l,...null!=d?{"aria-errormessage":d}:{},"aria-expanded":k&&"combobox"===g?!!c:void 0,...null!=u?{"aria-invalid":u}:{},"aria-label":m,"aria-labelledby":b,"aria-multiline":p,"aria-owns":k?x:void 0,"aria-readonly":!k||void 0,"aria-required":v,autoCapitalize:E,className:y,contentEditable:k,"data-testid":D,id:C,ref:A,role:g,spellCheck:L,style:h,tabIndex:w??(k?void 0:-1),...I})}const p=/*#__PURE__*/a(b);function x(e){return e.read("latest",m(e.isComposing()))}const v=/*#__PURE__*/a(E);function E(t,i){const{placeholder:a,...r}=t,[n]=e();
|
|
10
|
+
return c(u,{children:[/*#__PURE__*/s(p,{editor:n,...r,ref:i}),null!=a&&/*#__PURE__*/s(y,{editor:n,content:a})]})}function y({content:e,editor:i}){const a=function(e){const[t,i]=r(()=>x(e));return f(()=>{function t(){const t=x(e);i(t)}return t(),d(e.registerUpdateListener(()=>{t()}),e.registerEditableListener(()=>{t()}))},[e]),t}(i),[n,o]=r(i.isEditable());if(t(()=>(o(i.isEditable()),i.registerEditableListener(e=>{o(e)})),[i]),!a)return null;let l=null;return"function"==typeof e?l=e(n):null!==e&&(l=e),null===l?null:/*#__PURE__*/s("div",{"aria-hidden":!0,children:l})}export{v as ContentEditable,p as ContentEditableElement};
|
package/package.json
CHANGED
|
@@ -8,28 +8,28 @@
|
|
|
8
8
|
"rich-text"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.
|
|
11
|
+
"version": "0.48.0",
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@floating-ui/react": "^0.27.19",
|
|
14
|
-
"@lexical/
|
|
15
|
-
"@lexical/
|
|
16
|
-
"@lexical/
|
|
17
|
-
"@lexical/
|
|
18
|
-
"@lexical/
|
|
19
|
-
"@lexical/
|
|
20
|
-
"@lexical/
|
|
21
|
-
"@lexical/
|
|
22
|
-
"@lexical/
|
|
23
|
-
"@lexical/
|
|
24
|
-
"@lexical/
|
|
25
|
-
"@lexical/
|
|
26
|
-
"@lexical/rich-text": "0.
|
|
27
|
-
"@lexical/
|
|
28
|
-
"@lexical/
|
|
29
|
-
"@lexical/text": "0.
|
|
30
|
-
"@lexical/yjs": "0.
|
|
31
|
-
"
|
|
32
|
-
"lexical": "0.
|
|
14
|
+
"@lexical/a11y": "0.48.0",
|
|
15
|
+
"@lexical/devtools-core": "0.48.0",
|
|
16
|
+
"@lexical/dragon": "0.48.0",
|
|
17
|
+
"@lexical/hashtag": "0.48.0",
|
|
18
|
+
"@lexical/extension": "0.48.0",
|
|
19
|
+
"@lexical/history": "0.48.0",
|
|
20
|
+
"@lexical/link": "0.48.0",
|
|
21
|
+
"@lexical/mark": "0.48.0",
|
|
22
|
+
"@lexical/internal": "0.48.0",
|
|
23
|
+
"@lexical/list": "0.48.0",
|
|
24
|
+
"@lexical/markdown": "0.48.0",
|
|
25
|
+
"@lexical/plain-text": "0.48.0",
|
|
26
|
+
"@lexical/rich-text": "0.48.0",
|
|
27
|
+
"@lexical/table": "0.48.0",
|
|
28
|
+
"@lexical/overflow": "0.48.0",
|
|
29
|
+
"@lexical/text": "0.48.0",
|
|
30
|
+
"@lexical/yjs": "0.48.0",
|
|
31
|
+
"lexical": "0.48.0",
|
|
32
|
+
"@lexical/utils": "0.48.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"react": ">=18.x",
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
|
|
18
18
|
import {
|
|
19
19
|
type Binding,
|
|
20
|
-
|
|
20
|
+
createYjsBinding,
|
|
21
21
|
type ExcludedProperties,
|
|
22
22
|
type Provider,
|
|
23
23
|
type SyncCursorPositionsFn,
|
|
@@ -52,6 +52,8 @@ type CollaborationPluginProps = {
|
|
|
52
52
|
* Fallback to legacy method if not enabled or not supported.
|
|
53
53
|
*/
|
|
54
54
|
selectionHighlight?: boolean;
|
|
55
|
+
/** Customize the Yjs shared-type key used for the root `XmlText`. Defaults to `'root'`. */
|
|
56
|
+
rootName?: string;
|
|
55
57
|
};
|
|
56
58
|
|
|
57
59
|
/**
|
|
@@ -75,6 +77,7 @@ export function CollaborationPlugin({
|
|
|
75
77
|
awarenessData,
|
|
76
78
|
syncCursorPositionsFn,
|
|
77
79
|
selectionHighlight,
|
|
80
|
+
rootName,
|
|
78
81
|
}: CollaborationPluginProps): JSX.Element {
|
|
79
82
|
const isBindingInitialized = useRef(false);
|
|
80
83
|
const isProviderInitialized = useRef(false);
|
|
@@ -116,22 +119,27 @@ export function CollaborationPlugin({
|
|
|
116
119
|
return;
|
|
117
120
|
}
|
|
118
121
|
|
|
119
|
-
|
|
122
|
+
const resolvedDoc = doc || yjsDocMap.get(id);
|
|
123
|
+
if (!resolvedDoc) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
120
126
|
|
|
121
|
-
|
|
127
|
+
isBindingInitialized.current = true;
|
|
128
|
+
const newBinding = createYjsBinding({
|
|
129
|
+
doc: resolvedDoc,
|
|
130
|
+
docMap: yjsDocMap,
|
|
122
131
|
editor,
|
|
123
|
-
provider,
|
|
124
|
-
id,
|
|
125
|
-
doc || yjsDocMap.get(id),
|
|
126
|
-
yjsDocMap,
|
|
127
132
|
excludedProperties,
|
|
128
|
-
|
|
133
|
+
id,
|
|
134
|
+
rootName,
|
|
135
|
+
});
|
|
136
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
129
137
|
setBinding(newBinding);
|
|
130
138
|
|
|
131
139
|
return () => {
|
|
132
140
|
newBinding.root.destroy(newBinding);
|
|
133
141
|
};
|
|
134
|
-
}, [editor, provider, id, yjsDocMap, doc, excludedProperties]);
|
|
142
|
+
}, [editor, provider, id, yjsDocMap, doc, excludedProperties, rootName]);
|
|
135
143
|
|
|
136
144
|
if (!provider || !binding) {
|
|
137
145
|
return <></>;
|
|
@@ -232,6 +240,8 @@ type CollaborationPluginV2Props = {
|
|
|
232
240
|
* Fallback to legacy method if not enabled or not supported.
|
|
233
241
|
*/
|
|
234
242
|
selectionHighlight?: boolean;
|
|
243
|
+
/** Customize the Yjs shared-type key used for the root `XmlElement`. Defaults to `'root-v2'`. */
|
|
244
|
+
rootName?: string;
|
|
235
245
|
};
|
|
236
246
|
|
|
237
247
|
/**
|
|
@@ -254,6 +264,7 @@ export function CollaborationPluginV2__EXPERIMENTAL({
|
|
|
254
264
|
excludedProperties,
|
|
255
265
|
awarenessData,
|
|
256
266
|
selectionHighlight,
|
|
267
|
+
rootName,
|
|
257
268
|
}: CollaborationPluginV2Props): JSX.Element {
|
|
258
269
|
const collabContext = useCollaborationContext(username, cursorColor);
|
|
259
270
|
const {yjsDocMap, name, color} = collabContext;
|
|
@@ -273,6 +284,7 @@ export function CollaborationPluginV2__EXPERIMENTAL({
|
|
|
273
284
|
__shouldBootstrapUnsafe,
|
|
274
285
|
awarenessData,
|
|
275
286
|
excludedProperties,
|
|
287
|
+
rootName,
|
|
276
288
|
selectionHighlight,
|
|
277
289
|
},
|
|
278
290
|
);
|
|
@@ -180,6 +180,14 @@ export function $wrapOverflowedNodes(offset: number): void {
|
|
|
180
180
|
for (let i = 0; i < dfsNodesLength; i += 1) {
|
|
181
181
|
const {node} = dfsNodes[i];
|
|
182
182
|
|
|
183
|
+
// ElementNode.getTextContent() inserts '\n\n' after each non-inline
|
|
184
|
+
// element child that is not the last child. findOffset counts those
|
|
185
|
+
// separators (via $rootTextContent), so the DFS must count them too.
|
|
186
|
+
const prevSibling = node.getPreviousSibling();
|
|
187
|
+
if ($isElementNode(prevSibling) && !prevSibling.isInline()) {
|
|
188
|
+
accumulatedLength += 2;
|
|
189
|
+
}
|
|
190
|
+
|
|
183
191
|
// Slot value roots (a non-inline DecoratorNode slotted into a host) are
|
|
184
192
|
// leaf nodes with __parent === null; wrapping them in OverflowNode would
|
|
185
193
|
// call node.replace() and throw, so they stay out of the wrap loop. Their
|
|
@@ -266,6 +274,10 @@ export function $wrapOverflowedNodes(offset: number): void {
|
|
|
266
274
|
}
|
|
267
275
|
|
|
268
276
|
$mergePrevious(overflowNode);
|
|
277
|
+
const nextNode = overflowNode.getNextSibling();
|
|
278
|
+
if ($isOverflowNode(nextNode)) {
|
|
279
|
+
$mergePrevious(nextNode);
|
|
280
|
+
}
|
|
269
281
|
}
|
|
270
282
|
}
|
|
271
283
|
}
|
|
@@ -303,7 +315,7 @@ export function $mergePrevious(overflowNode: OverflowNode): void {
|
|
|
303
315
|
const anchor = selection.anchor;
|
|
304
316
|
const anchorNode = anchor.getNode();
|
|
305
317
|
const focus = selection.focus;
|
|
306
|
-
const focusNode =
|
|
318
|
+
const focusNode = focus.getNode();
|
|
307
319
|
|
|
308
320
|
if (anchorNode.is(previousNode)) {
|
|
309
321
|
anchor.set(overflowNode.getKey(), anchor.offset, 'element');
|