@lexical/react 0.1.4 → 0.1.8

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.
Files changed (101) hide show
  1. package/DEPRECATED_useLexical.dev.js +84 -0
  2. package/DEPRECATED_useLexical.js +9 -2
  3. package/DEPRECATED_useLexical.prod.js +8 -0
  4. package/DEPRECATED_useLexicalAutoFormatter.dev.js +642 -0
  5. package/DEPRECATED_useLexicalAutoFormatter.js +9 -12
  6. package/DEPRECATED_useLexicalAutoFormatter.prod.js +22 -0
  7. package/DEPRECATED_useLexicalCanShowPlaceholder.dev.js +136 -0
  8. package/DEPRECATED_useLexicalCanShowPlaceholder.js +9 -3
  9. package/DEPRECATED_useLexicalCanShowPlaceholder.prod.js +8 -0
  10. package/DEPRECATED_useLexicalCharacterLimit.dev.js +294 -0
  11. package/DEPRECATED_useLexicalCharacterLimit.js +9 -9
  12. package/DEPRECATED_useLexicalCharacterLimit.prod.js +14 -0
  13. package/DEPRECATED_useLexicalDecorators.dev.js +82 -0
  14. package/DEPRECATED_useLexicalDecorators.js +9 -2
  15. package/DEPRECATED_useLexicalDecorators.prod.js +8 -0
  16. package/DEPRECATED_useLexicalEditor.dev.js +52 -0
  17. package/DEPRECATED_useLexicalEditor.js +9 -1
  18. package/DEPRECATED_useLexicalEditor.prod.js +7 -0
  19. package/DEPRECATED_useLexicalEditorEvents.dev.js +96 -0
  20. package/DEPRECATED_useLexicalEditorEvents.js +9 -2
  21. package/DEPRECATED_useLexicalEditorEvents.prod.js +8 -0
  22. package/DEPRECATED_useLexicalHistory.dev.js +339 -0
  23. package/DEPRECATED_useLexicalHistory.js +9 -7
  24. package/DEPRECATED_useLexicalHistory.prod.js +13 -0
  25. package/DEPRECATED_useLexicalList.dev.js +64 -0
  26. package/DEPRECATED_useLexicalList.js +9 -12
  27. package/DEPRECATED_useLexicalList.prod.js +7 -0
  28. package/DEPRECATED_useLexicalPlainText.dev.js +755 -0
  29. package/DEPRECATED_useLexicalPlainText.js +9 -17
  30. package/DEPRECATED_useLexicalPlainText.prod.js +22 -0
  31. package/DEPRECATED_useLexicalRichText.dev.js +1326 -0
  32. package/DEPRECATED_useLexicalRichText.js +9 -30
  33. package/DEPRECATED_useLexicalRichText.prod.js +35 -0
  34. package/LexicalAutoFormatterPlugin.dev.js +645 -0
  35. package/LexicalAutoFormatterPlugin.js +9 -13
  36. package/LexicalAutoFormatterPlugin.prod.js +23 -0
  37. package/LexicalAutoLinkPlugin.dev.js +227 -0
  38. package/LexicalAutoLinkPlugin.js +9 -5
  39. package/LexicalAutoLinkPlugin.prod.js +12 -0
  40. package/LexicalBootstrapPlugin.dev.js +124 -0
  41. package/LexicalBootstrapPlugin.js +9 -0
  42. package/LexicalBootstrapPlugin.prod.js +8 -0
  43. package/LexicalCharacterLimitPlugin.dev.js +352 -0
  44. package/LexicalCharacterLimitPlugin.js +9 -10
  45. package/LexicalCharacterLimitPlugin.prod.js +14 -0
  46. package/LexicalCollaborationPlugin.dev.js +235 -0
  47. package/LexicalCollaborationPlugin.js +9 -8
  48. package/LexicalCollaborationPlugin.prod.js +14 -0
  49. package/LexicalComposer.dev.js +76 -0
  50. package/LexicalComposer.js +9 -2
  51. package/LexicalComposer.prod.js +9 -0
  52. package/LexicalComposerContext.dev.js +53 -0
  53. package/LexicalComposerContext.js +9 -1
  54. package/LexicalComposerContext.prod.js +7 -0
  55. package/LexicalContentEditable.dev.js +71 -0
  56. package/LexicalContentEditable.js +9 -3
  57. package/LexicalContentEditable.prod.js +9 -0
  58. package/LexicalHashtagPlugin.dev.js +152 -0
  59. package/LexicalHashtagPlugin.js +9 -4
  60. package/LexicalHashtagPlugin.prod.js +10 -0
  61. package/LexicalHistoryPlugin.dev.js +344 -0
  62. package/LexicalHistoryPlugin.js +9 -7
  63. package/LexicalHistoryPlugin.prod.js +13 -0
  64. package/LexicalHorizontalRulePlugin.dev.js +51 -0
  65. package/LexicalHorizontalRulePlugin.js +9 -1
  66. package/LexicalHorizontalRulePlugin.prod.js +7 -0
  67. package/LexicalLinkPlugin.dev.js +137 -0
  68. package/LexicalLinkPlugin.js +9 -3
  69. package/LexicalLinkPlugin.prod.js +9 -0
  70. package/LexicalListPlugin.dev.js +67 -0
  71. package/LexicalListPlugin.js +9 -12
  72. package/LexicalListPlugin.prod.js +8 -0
  73. package/LexicalNestedComposer.dev.js +60 -0
  74. package/LexicalNestedComposer.js +9 -1
  75. package/LexicalNestedComposer.prod.js +8 -0
  76. package/LexicalOnChangePlugin.dev.js +57 -0
  77. package/LexicalOnChangePlugin.js +9 -1
  78. package/LexicalOnChangePlugin.prod.js +7 -0
  79. package/LexicalPlainTextPlugin.dev.js +565 -0
  80. package/LexicalPlainTextPlugin.js +9 -13
  81. package/LexicalPlainTextPlugin.prod.js +17 -0
  82. package/LexicalRichTextPlugin.dev.js +1136 -0
  83. package/LexicalRichTextPlugin.js +9 -26
  84. package/LexicalRichTextPlugin.prod.js +31 -0
  85. package/LexicalTablePlugin.dev.js +95 -0
  86. package/LexicalTablePlugin.js +9 -4
  87. package/LexicalTablePlugin.prod.js +9 -0
  88. package/LexicalTreeView.dev.js +340 -0
  89. package/LexicalTreeView.js +9 -12
  90. package/LexicalTreeView.prod.js +19 -0
  91. package/README.md +11 -6
  92. package/package.json +4 -4
  93. package/useLexicalDecoratorMap.dev.js +83 -0
  94. package/useLexicalDecoratorMap.js +9 -1
  95. package/useLexicalDecoratorMap.prod.js +8 -0
  96. package/useLexicalIsTextContentEmpty.dev.js +84 -0
  97. package/useLexicalIsTextContentEmpty.js +9 -2
  98. package/useLexicalIsTextContentEmpty.prod.js +8 -0
  99. package/withSubscriptions.dev.js +23 -0
  100. package/withSubscriptions.js +9 -1
  101. package/withSubscriptions.prod.js +7 -0
@@ -0,0 +1,352 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ 'use strict';
8
+
9
+ var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
10
+ var React = require('react');
11
+ var lexical = require('lexical');
12
+ var withSubscriptions = require('@lexical/react/withSubscriptions');
13
+ var OverflowNode = require('lexical/OverflowNode');
14
+
15
+ /**
16
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
17
+ *
18
+ * This source code is licensed under the MIT license found in the
19
+ * LICENSE file in the root directory of this source tree.
20
+ *
21
+ *
22
+ */
23
+ function $dfs__DEPRECATED(startingNode, nextNode) {
24
+ let node = startingNode;
25
+ nextNode(node);
26
+
27
+ while (node !== null) {
28
+ if (lexical.$isElementNode(node) && node.getChildrenSize() > 0) {
29
+ node = node.getFirstChild();
30
+ } else {
31
+ // Find immediate sibling or nearest parent sibling
32
+ let sibling = null;
33
+
34
+ while (sibling === null && node !== null) {
35
+ sibling = node.getNextSibling();
36
+
37
+ if (sibling === null) {
38
+ node = node.getParent();
39
+ } else {
40
+ node = sibling;
41
+ }
42
+ }
43
+ }
44
+
45
+ if (node !== null) {
46
+ node = nextNode(node);
47
+ }
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
53
+ *
54
+ * This source code is licensed under the MIT license found in the
55
+ * LICENSE file in the root directory of this source tree.
56
+ *
57
+ *
58
+ */
59
+ function $textContent() {
60
+ const root = lexical.$getRoot();
61
+ return root.getTextContent();
62
+ }
63
+ const $textContentCurry = $textContent;
64
+
65
+ /**
66
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
67
+ *
68
+ * This source code is licensed under the MIT license found in the
69
+ * LICENSE file in the root directory of this source tree.
70
+ *
71
+ *
72
+ */
73
+ function useCharacterLimit(editor, maxCharacters, optional = Object.freeze({})) {
74
+ const {
75
+ strlen = input => input.length,
76
+ // UTF-16
77
+ remainingCharacters = characters => {}
78
+ } = optional;
79
+ React.useEffect(() => {
80
+ if (!editor.hasNodes([OverflowNode.OverflowNode])) {
81
+ {
82
+ throw Error(`useCharacterLimit: OverflowNode not registered on editor`);
83
+ }
84
+ }
85
+ }, [editor]);
86
+ React.useEffect(() => {
87
+ let text = editor.getEditorState().read($textContentCurry);
88
+ let lastComputedTextLength = 0;
89
+ return withSubscriptions(editor.addListener('textcontent', currentText => {
90
+ text = currentText;
91
+ }), editor.addListener('update', ({
92
+ dirtyLeaves
93
+ }) => {
94
+ const isComposing = editor.isComposing();
95
+ const hasDirtyLeaves = dirtyLeaves.size > 0;
96
+
97
+ if (isComposing || !hasDirtyLeaves) {
98
+ return;
99
+ }
100
+
101
+ const textLength = strlen(text);
102
+ const textLengthAboveThreshold = textLength > maxCharacters || lastComputedTextLength !== null && lastComputedTextLength > maxCharacters;
103
+ const diff = maxCharacters - textLength;
104
+ remainingCharacters(diff);
105
+
106
+ if (lastComputedTextLength === null || textLengthAboveThreshold) {
107
+ const offset = findOffset(text, maxCharacters, strlen);
108
+ editor.update(() => {
109
+ lexical.$log('CharacterLimit');
110
+ $wrapOverflowedNodes(offset);
111
+ }, {
112
+ tag: 'without-history'
113
+ });
114
+ }
115
+
116
+ lastComputedTextLength = textLength;
117
+ }));
118
+ }, [editor, maxCharacters, remainingCharacters, strlen]);
119
+ }
120
+
121
+ function findOffset(text, maxCharacters, strlen) {
122
+ const Segmenter = Intl.Segmenter;
123
+ let offsetUtf16 = 0;
124
+ let offset = 0;
125
+
126
+ if (typeof Segmenter === 'function') {
127
+ const segmenter = new Segmenter();
128
+ const graphemes = segmenter.segment(text); // eslint-disable-next-line no-for-of-loops/no-for-of-loops
129
+
130
+ for (const {
131
+ segment: grapheme
132
+ } of graphemes) {
133
+ const nextOffset = offset + strlen(grapheme);
134
+
135
+ if (nextOffset > maxCharacters) {
136
+ break;
137
+ }
138
+
139
+ offset = nextOffset;
140
+ offsetUtf16 += grapheme.length;
141
+ }
142
+ } else {
143
+ const codepoints = Array.from(text);
144
+ const codepointsLength = codepoints.length;
145
+
146
+ for (let i = 0; i < codepointsLength; i++) {
147
+ const codepoint = codepoints[i];
148
+ const nextOffset = offset + strlen(codepoint);
149
+
150
+ if (nextOffset > maxCharacters) {
151
+ break;
152
+ }
153
+
154
+ offset = nextOffset;
155
+ offsetUtf16 += codepoint.length;
156
+ }
157
+ }
158
+
159
+ return offsetUtf16;
160
+ }
161
+
162
+ function $wrapOverflowedNodes(offset) {
163
+ const root = lexical.$getRoot();
164
+ let accumulatedLength = 0;
165
+ let previousNode = root;
166
+ $dfs__DEPRECATED(root, node => {
167
+ if (OverflowNode.$isOverflowNode(node)) {
168
+ const previousLength = accumulatedLength;
169
+ const nextLength = accumulatedLength + node.getTextContentSize();
170
+
171
+ if (nextLength <= offset) {
172
+ const parent = node.getParent();
173
+ const previousSibling = node.getPreviousSibling();
174
+ const nextSibling = node.getNextSibling();
175
+ $unwrapNode(node);
176
+ const selection = lexical.$getSelection(); // Restore selection when the overflow children are removed
177
+
178
+ if (selection !== null && (!selection.anchor.getNode().isAttached() || !selection.focus.getNode().isAttached())) {
179
+ if (lexical.$isTextNode(previousSibling)) {
180
+ previousSibling.select();
181
+ } else if (lexical.$isTextNode(nextSibling)) {
182
+ nextSibling.select();
183
+ } else if (parent !== null) {
184
+ parent.select();
185
+ }
186
+ }
187
+
188
+ return previousNode;
189
+ } else if (previousLength < offset) {
190
+ const descendant = node.getFirstDescendant();
191
+ const descendantLength = descendant !== null ? descendant.getTextContentSize() : 0;
192
+ const previousPlusDescendantLength = previousLength + descendantLength; // For simple text we can redimension the overflow into a smaller and more accurate
193
+ // container
194
+
195
+ const firstDescendantIsSimpleText = lexical.$isTextNode(descendant) && descendant.isSimpleText();
196
+ const firstDescendantDoesNotOverflow = previousPlusDescendantLength <= offset;
197
+
198
+ if (firstDescendantIsSimpleText || firstDescendantDoesNotOverflow) {
199
+ $unwrapNode(node);
200
+ return previousNode;
201
+ }
202
+ }
203
+ } else if (lexical.$isLeafNode(node)) {
204
+ const previousAccumulatedLength = accumulatedLength;
205
+ accumulatedLength += node.getTextContentSize();
206
+
207
+ if (accumulatedLength > offset && !OverflowNode.$isOverflowNode(node.getParent())) {
208
+ const previousSelection = lexical.$getSelection();
209
+ let overflowNode; // For simple text we can improve the limit accuracy by splitting the TextNode
210
+ // on the split point
211
+
212
+ if (previousAccumulatedLength < offset && lexical.$isTextNode(node) && node.isSimpleText()) {
213
+ const [, overflowedText] = node.splitText(offset - previousAccumulatedLength);
214
+ overflowNode = $wrapNode(overflowedText);
215
+ } else {
216
+ overflowNode = $wrapNode(node);
217
+ }
218
+
219
+ if (previousSelection !== null) {
220
+ lexical.$setSelection(previousSelection);
221
+ }
222
+
223
+ mergePrevious(overflowNode);
224
+ }
225
+ }
226
+
227
+ previousNode = node;
228
+ return node;
229
+ });
230
+ }
231
+
232
+ function $wrapNode(node) {
233
+ const overflowNode = OverflowNode.$createOverflowNode();
234
+ node.insertBefore(overflowNode);
235
+ overflowNode.append(node);
236
+ return overflowNode;
237
+ }
238
+
239
+ function $unwrapNode(node) {
240
+ const children = node.getChildren();
241
+ const childrenLength = children.length;
242
+
243
+ for (let i = 0; i < childrenLength; i++) {
244
+ node.insertBefore(children[i]);
245
+ }
246
+
247
+ node.remove();
248
+ return childrenLength > 0 ? children[childrenLength - 1] : null;
249
+ }
250
+
251
+ function mergePrevious(overflowNode) {
252
+ const previousNode = overflowNode.getPreviousSibling();
253
+
254
+ if (!OverflowNode.$isOverflowNode(previousNode)) {
255
+ return;
256
+ }
257
+
258
+ const firstChild = overflowNode.getFirstChild();
259
+ const previousNodeChildren = previousNode.getChildren();
260
+ const previousNodeChildrenLength = previousNodeChildren.length;
261
+
262
+ if (firstChild === null) {
263
+ overflowNode.append(...previousNodeChildren);
264
+ } else {
265
+ for (let i = 0; i < previousNodeChildrenLength; i++) {
266
+ firstChild.insertBefore(previousNodeChildren[i]);
267
+ }
268
+ }
269
+
270
+ const selection = lexical.$getSelection();
271
+
272
+ if (selection !== null) {
273
+ const anchor = selection.anchor;
274
+ const anchorNode = anchor.getNode();
275
+ const focus = selection.focus;
276
+ const focusNode = anchor.getNode();
277
+
278
+ if (anchorNode.is(previousNode)) {
279
+ anchor.set(overflowNode.getKey(), anchor.offset, 'element');
280
+ } else if (anchorNode.is(overflowNode)) {
281
+ anchor.set(overflowNode.getKey(), previousNodeChildrenLength + anchor.offset, 'element');
282
+ }
283
+
284
+ if (focusNode.is(previousNode)) {
285
+ focus.set(overflowNode.getKey(), focus.offset, 'element');
286
+ } else if (focusNode.is(overflowNode)) {
287
+ focus.set(overflowNode.getKey(), previousNodeChildrenLength + focus.offset, 'element');
288
+ }
289
+ }
290
+
291
+ previousNode.remove();
292
+ }
293
+
294
+ /**
295
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
296
+ *
297
+ * This source code is licensed under the MIT license found in the
298
+ * LICENSE file in the root directory of this source tree.
299
+ *
300
+ *
301
+ */
302
+ const CHARACTER_LIMIT = 5;
303
+ let textEncoderInstance = null;
304
+
305
+ function textEncoder() {
306
+ if (window.TextEncoder === undefined) {
307
+ return null;
308
+ }
309
+
310
+ if (textEncoderInstance === null) {
311
+ textEncoderInstance = new window.TextEncoder();
312
+ }
313
+
314
+ return textEncoderInstance;
315
+ }
316
+
317
+ function utf8Length(text) {
318
+ const currentTextEncoder = textEncoder();
319
+
320
+ if (currentTextEncoder === null) {
321
+ // http://stackoverflow.com/a/5515960/210370
322
+ const m = encodeURIComponent(text).match(/%[89ABab]/g);
323
+ return text.length + (m ? m.length : 0);
324
+ }
325
+
326
+ return currentTextEncoder.encode(text).length;
327
+ }
328
+
329
+ function CharacterLimitPlugin({
330
+ charset = 'UTF-16'
331
+ }) {
332
+ const [editor] = LexicalComposerContext.useLexicalComposerContext();
333
+ const [remainingCharacters, setRemainingCharacters] = React.useState(0);
334
+ const characterLimitProps = React.useMemo(() => ({
335
+ remainingCharacters: setRemainingCharacters,
336
+ strlen: text => {
337
+ if (charset === 'UTF-8') {
338
+ return utf8Length(text);
339
+ } else if (charset === 'UTF-16') {
340
+ return text.length;
341
+ } else {
342
+ throw new Error('Unrecognized charset');
343
+ }
344
+ }
345
+ }), [charset]);
346
+ useCharacterLimit(editor, CHARACTER_LIMIT, characterLimitProps);
347
+ return /*#__PURE__*/React.createElement("span", {
348
+ className: `characters-limit ${remainingCharacters < 0 ? 'characters-limit-exceeded' : ''}`
349
+ }, remainingCharacters);
350
+ }
351
+
352
+ module.exports = CharacterLimitPlugin;
@@ -1,10 +1,9 @@
1
- 'use strict';var l=require("@lexical/react/LexicalComposerContext"),p=require("lexical"),q=require("react"),r=require("@lexical/react/withSubscriptions");function t(a,e){for(e(a);null!==a;){if(p.$isElementNode(a)&&0<a.getChildrenSize())a=a.getFirstChild();else{let f=null;for(;null===f&&null!==a;)f=a.getNextSibling(),a=null===f?a.getParent():f}null!==a&&(a=e(a))}}function u(){return p.$getRoot().getTextContent()}
2
- function w(a,e,f={}){const {strlen:h=c=>c.length,remainingCharacters:d=()=>{}}=f;q.useEffect(()=>a.registerNodes([x]),[a]);q.useEffect(()=>{let c=a.getEditorState().read(u),b=0;return r(a.addListener("textcontent",g=>{c=g}),a.addListener("update",({dirtyLeaves:g})=>{var k=a.isComposing();g=0<g.size;if(!k&&g){k=h(c);g=k>e||null!==b&&b>e;d(e-k);if(null===b||g){const n=y(c,e,h);a.update(()=>{p.$log("CharacterLimit");z(n)},{tag:"without-history"})}b=k}}))},[a,e,d,h])}
3
- function y(a,e,f){var h=Intl.Segmenter;let d=0;var c=0;if("function"===typeof h){a=(new h).segment(a);for(var {segment:b}of a){c+=f(b);if(c>e)break;d+=b.length}}else for(b=Array.from(a),a=b.length,h=0;h<a;h++){const g=b[h];c+=f(g);if(c>e)break;d+=g.length}return d}
4
- function z(a){const e=p.$getRoot();let f=0,h=e;t(e,d=>{if(d instanceof x){var c=f;if(f+d.getTextContentSize()<=a){var b=d.getParent();c=d.getPreviousSibling();var g=d.getNextSibling();A(d);d=p.$getSelection();null===d||d.anchor.getNode().isAttached()&&d.focus.getNode().isAttached()||(p.$isTextNode(c)?c.select():p.$isTextNode(g)?g.select():null!==b&&b.select());return h}if(c<a&&(b=d.getFirstDescendant(),g=null!==b?b.getTextContentSize():0,c+=g,b=p.$isTextNode(b)&&b.isSimpleText(),c=c<=a,b||c))return A(d),
5
- h}else if(p.$isLeafNode(d)&&(c=f,f+=d.getTextContentSize(),f>a&&!(d.getParent()instanceof x)&&(b=p.$getSelection(),c<a&&p.$isTextNode(d)&&d.isSimpleText()?([,c]=d.splitText(a-c),c=B(c)):c=B(d),null!==b&&p.$setSelection(b),b=c,g=b.getPreviousSibling(),g instanceof x))){var k=b.getFirstChild(),n=g.getChildren();c=n.length;if(null===k)b.append(...n);else for(var m=0;m<c;m++)k.insertBefore(n[m]);m=p.$getSelection();if(null!==m){k=m.anchor;n=k.getNode();m=m.focus;const v=k.getNode();n.is(g)?k.set(b.getKey(),
6
- k.offset,"element"):n.is(b)&&k.set(b.getKey(),c+k.offset,"element");v.is(g)?m.set(b.getKey(),m.offset,"element"):v.is(b)&&m.set(b.getKey(),c+m.offset,"element")}g.remove()}return h=d})}
7
- class x extends p.ElementNode{static getType(){return"overflow"}static clone(a){return new x(a.__key)}constructor(a){super(a);this.__type="overflow"}createDOM(a){const e=document.createElement("div");a=a.theme.characterLimit;"string"===typeof a&&(e.className=a);return e}updateDOM(){return!1}insertNewAfter(a){return this.getParentOrThrow().insertNewAfter(a)}excludeFromCopy(){return!0}}function B(a){const e=new x;a.insertBefore(e);e.append(a);return e}
8
- function A(a){const e=a.getChildren(),f=e.length;for(let h=0;h<f;h++)a.insertBefore(e[h]);a.remove();return 0<f?e[f-1]:null}let C=null;
9
- module.exports=function({charset:a="UTF-16"}){const [e]=l.useLexicalComposerContext(),[f,h]=q.useState(0),d=q.useMemo(()=>({remainingCharacters:h,strlen:c=>{if("UTF-8"===a){if(void 0===window.TextEncoder)var b=null;else null===C&&(C=new window.TextEncoder),b=C;null===b?(b=encodeURIComponent(c).match(/%[89ABab]/g),c=c.length+(b?b.length:0)):c=b.encode(c).length;return c}if("UTF-16"===a)return c.length;throw Error("Unrecognized charset");}}),[a]);w(e,5,d);return q.createElement("span",{className:`characters-limit ${0>
10
- f?"characters-limit-exceeded":""}`},f)};
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ 'use strict'
8
+ const LexicalCharacterLimitPlugin = process.env.NODE_ENV === 'development' ? require('./LexicalCharacterLimitPlugin.dev.js') : require('./LexicalCharacterLimitPlugin.prod.js')
9
+ module.exports = LexicalCharacterLimitPlugin;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ 'use strict';var l=require("@lexical/react/LexicalComposerContext"),p=require("react"),q=require("lexical"),r=require("@lexical/react/withSubscriptions"),t=require("lexical/OverflowNode");function u(a,e){for(e(a);null!==a;){if(q.$isElementNode(a)&&0<a.getChildrenSize())a=a.getFirstChild();else{let f=null;for(;null===f&&null!==a;)f=a.getNextSibling(),a=null===f?a.getParent():f}null!==a&&(a=e(a))}}function w(){return q.$getRoot().getTextContent()}
8
+ function x(a,e,f=Object.freeze({})){const {strlen:h=c=>c.length,remainingCharacters:d=()=>{}}=f;p.useEffect(()=>{if(!a.hasNodes([t.OverflowNode]))throw Error("useCharacterLimit: OverflowNode not registered on editor");},[a]);p.useEffect(()=>{let c=a.getEditorState().read(w),b=0;return r(a.addListener("textcontent",g=>{c=g}),a.addListener("update",({dirtyLeaves:g})=>{var k=a.isComposing();g=0<g.size;if(!k&&g){k=h(c);g=k>e||null!==b&&b>e;d(e-k);if(null===b||g){const n=y(c,e,h);a.update(()=>{q.$log("CharacterLimit");
9
+ z(n)},{tag:"without-history"})}b=k}}))},[a,e,d,h])}function y(a,e,f){var h=Intl.Segmenter;let d=0;var c=0;if("function"===typeof h){a=(new h).segment(a);for(var {segment:b}of a){c+=f(b);if(c>e)break;d+=b.length}}else for(b=Array.from(a),a=b.length,h=0;h<a;h++){const g=b[h];c+=f(g);if(c>e)break;d+=g.length}return d}
10
+ function z(a){const e=q.$getRoot();let f=0,h=e;u(e,d=>{if(t.$isOverflowNode(d)){var c=f;if(f+d.getTextContentSize()<=a){var b=d.getParent();c=d.getPreviousSibling();var g=d.getNextSibling();A(d);d=q.$getSelection();null===d||d.anchor.getNode().isAttached()&&d.focus.getNode().isAttached()||(q.$isTextNode(c)?c.select():q.$isTextNode(g)?g.select():null!==b&&b.select());return h}if(c<a&&(b=d.getFirstDescendant(),g=null!==b?b.getTextContentSize():0,c+=g,b=q.$isTextNode(b)&&b.isSimpleText(),c=c<=a,b||c))return A(d),
11
+ h}else if(q.$isLeafNode(d)&&(c=f,f+=d.getTextContentSize(),f>a&&!t.$isOverflowNode(d.getParent())&&(b=q.$getSelection(),c<a&&q.$isTextNode(d)&&d.isSimpleText()?([,c]=d.splitText(a-c),c=B(c)):c=B(d),null!==b&&q.$setSelection(b),b=c,g=b.getPreviousSibling(),t.$isOverflowNode(g)))){var k=b.getFirstChild(),n=g.getChildren();c=n.length;if(null===k)b.append(...n);else for(var m=0;m<c;m++)k.insertBefore(n[m]);m=q.$getSelection();if(null!==m){k=m.anchor;n=k.getNode();m=m.focus;const v=k.getNode();n.is(g)?
12
+ k.set(b.getKey(),k.offset,"element"):n.is(b)&&k.set(b.getKey(),c+k.offset,"element");v.is(g)?m.set(b.getKey(),m.offset,"element"):v.is(b)&&m.set(b.getKey(),c+m.offset,"element")}g.remove()}return h=d})}function B(a){const e=t.$createOverflowNode();a.insertBefore(e);e.append(a);return e}function A(a){const e=a.getChildren(),f=e.length;for(let h=0;h<f;h++)a.insertBefore(e[h]);a.remove();return 0<f?e[f-1]:null}let C=null;
13
+ module.exports=function({charset:a="UTF-16"}){const [e]=l.useLexicalComposerContext(),[f,h]=p.useState(0),d=p.useMemo(()=>({remainingCharacters:h,strlen:c=>{if("UTF-8"===a){if(void 0===window.TextEncoder)var b=null;else null===C&&(C=new window.TextEncoder),b=C;null===b?(b=encodeURIComponent(c).match(/%[89ABab]/g),c=c.length+(b?b.length:0)):c=b.encode(c).length;return c}if("UTF-16"===a)return c.length;throw Error("Unrecognized charset");}}),[a]);x(e,5,d);return p.createElement("span",{className:`characters-limit ${0>
14
+ f?"characters-limit-exceeded":""}`},f)};
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ 'use strict';
8
+
9
+ var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
10
+ var React = require('react');
11
+ var yjs = require('@lexical/yjs');
12
+ var reactDom = require('react-dom');
13
+
14
+ /**
15
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
16
+ *
17
+ * This source code is licensed under the MIT license found in the
18
+ * LICENSE file in the root directory of this source tree.
19
+ *
20
+ *
21
+ */
22
+ const EditorPriority = 0;
23
+ const BootstrapPriority = 1;
24
+ function useYjsCollaboration(editor, id, provider, docMap, name, color, shouldBootstrap) {
25
+ const binding = React.useMemo(() => yjs.createBinding(editor, provider, id, docMap), [editor, provider, id, docMap]);
26
+ const connect = React.useCallback(() => {
27
+ provider.connect();
28
+ }, [provider]);
29
+ const disconnect = React.useCallback(() => {
30
+ try {
31
+ provider.disconnect();
32
+ } catch (e) {// Do nothing
33
+ }
34
+ }, [provider]);
35
+ const isInitialized = React.useRef(false);
36
+ React.useLayoutEffect(() => {
37
+ return editor.addListener('command', type => {
38
+ if (type === 'bootstrapEditor') {
39
+ return !isInitialized.current;
40
+ }
41
+
42
+ return false;
43
+ }, BootstrapPriority);
44
+ }, [editor]);
45
+ React.useEffect(() => {
46
+ const {
47
+ root
48
+ } = binding;
49
+ const {
50
+ awareness
51
+ } = provider;
52
+
53
+ const onStatus = ({
54
+ status
55
+ }) => {
56
+ editor.execCommand('connected', status === 'connected');
57
+ };
58
+
59
+ const onSync = isSynced => {
60
+ if (shouldBootstrap && isSynced && root.isEmpty() && root._xmlText._length === 0) {
61
+ isInitialized.current = true;
62
+ editor.execCommand('bootstrapEditor');
63
+ }
64
+ };
65
+
66
+ const onAwarenessUpdate = () => {
67
+ yjs.syncCursorPositions(binding, provider);
68
+ };
69
+
70
+ const onYjsTreeChanges = (events, transaction) => {
71
+ if (transaction.origin !== binding) {
72
+ yjs.syncYjsChangesToLexical(binding, provider, events);
73
+ }
74
+ };
75
+
76
+ yjs.initLocalState(provider, name, color, document.activeElement === editor.getRootElement());
77
+ provider.on('status', onStatus);
78
+ provider.on('sync', onSync);
79
+ awareness.on('update', onAwarenessUpdate);
80
+ root.getSharedType().observeDeep(onYjsTreeChanges);
81
+ const removeListener = editor.addListener('update', ({
82
+ prevEditorState,
83
+ editorState,
84
+ dirtyLeaves,
85
+ dirtyElements,
86
+ normalizedNodes,
87
+ tags
88
+ }) => {
89
+ yjs.syncLexicalUpdateToYjs(binding, provider, prevEditorState, editorState, dirtyElements, dirtyLeaves, normalizedNodes, tags);
90
+ });
91
+ connect();
92
+ return () => {
93
+ disconnect();
94
+ provider.off('sync', onSync);
95
+ provider.off('status', onStatus);
96
+ awareness.off('update', onAwarenessUpdate);
97
+ root.getSharedType().unobserveDeep(onYjsTreeChanges);
98
+ removeListener();
99
+ };
100
+ }, [binding, color, connect, disconnect, editor, name, provider, shouldBootstrap]);
101
+ const cursorsContainer = React.useMemo(() => {
102
+ const ref = element => {
103
+ binding.cursorsContainer = element;
104
+ };
105
+
106
+ return /*#__PURE__*/reactDom.createPortal( /*#__PURE__*/React.createElement("div", {
107
+ ref: ref
108
+ }), document.body);
109
+ }, [binding]);
110
+ React.useEffect(() => {
111
+ return editor.addListener('command', (type, payload) => {
112
+ if (type === 'toggleConnect') {
113
+ if (connect !== undefined && disconnect !== undefined) {
114
+ const shouldConnect = payload;
115
+
116
+ if (shouldConnect) {
117
+ // eslint-disable-next-line no-console
118
+ console.log('Collaboration connected!');
119
+ connect();
120
+ } else {
121
+ // eslint-disable-next-line no-console
122
+ console.log('Collaboration disconnected!');
123
+ disconnect();
124
+ }
125
+ }
126
+ }
127
+
128
+ return false;
129
+ }, EditorPriority);
130
+ }, [connect, disconnect, editor]);
131
+ return [cursorsContainer, binding];
132
+ }
133
+ function useYjsFocusTracking(editor, provider) {
134
+ React.useEffect(() => {
135
+ const onBlur = () => {
136
+ yjs.setLocalStateFocus(provider, false);
137
+ };
138
+
139
+ const onFocus = () => {
140
+ yjs.setLocalStateFocus(provider, true);
141
+ };
142
+
143
+ return editor.addListener('root', (rootElement, prevRootElement) => {
144
+ // Clear our old listener if the root element changes
145
+ if (prevRootElement !== null) {
146
+ prevRootElement.removeEventListener('blur', onBlur);
147
+ prevRootElement.removeEventListener('focus', onFocus);
148
+ }
149
+
150
+ if (rootElement !== null) {
151
+ if (document.activeElement === rootElement) {
152
+ onFocus();
153
+ }
154
+
155
+ rootElement.addEventListener('blur', onBlur);
156
+ rootElement.addEventListener('focus', onFocus);
157
+ }
158
+ });
159
+ }, [editor, provider, provider.awareness]);
160
+ }
161
+ function useYjsHistory(editor, binding) {
162
+ const undoManager = React.useMemo(() => yjs.createUndoManager(binding, binding.root.getSharedType()), [binding]);
163
+ React.useEffect(() => {
164
+ const undo = () => {
165
+ undoManager.undo();
166
+ };
167
+
168
+ const redo = () => {
169
+ undoManager.redo();
170
+ };
171
+
172
+ const applyCommand = type => {
173
+ if (type === 'undo') {
174
+ undo();
175
+ return true;
176
+ }
177
+
178
+ if (type === 'redo') {
179
+ redo();
180
+ return true;
181
+ }
182
+
183
+ return false;
184
+ };
185
+
186
+ return editor.addListener('command', applyCommand, EditorPriority);
187
+ });
188
+ const clearHistory = React.useCallback(() => {
189
+ undoManager.clear();
190
+ }, [undoManager]);
191
+ return clearHistory;
192
+ }
193
+
194
+ /**
195
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
196
+ *
197
+ * This source code is licensed under the MIT license found in the
198
+ * LICENSE file in the root directory of this source tree.
199
+ *
200
+ *
201
+ */
202
+ const entries = [['Cat', '255,165,0'], ['Dog', '0,200,55'], ['Rabbit', '160,0,200'], ['Frog', '0,172,200'], ['Fox', '197,200,0'], ['Hedgehog', '31,200,0'], ['Pigeon', '200,0,0'], ['Squirrel', '200,0,148'], ['Bear', '255,235,0'], ['Tiger', '86,255,0'], ['Leopard', '0,255,208'], ['Zebra', '0,243,255'], ['Wolf', '0,102,255'], ['Owl', '147,0,255'], ['Gull', '255,0,153'], ['Squid', '0,220,255']];
203
+ const randomEntry = entries[Math.floor(Math.random() * (entries.length - 1 - 0 + 1) + 0)];
204
+ function CollaborationPlugin({
205
+ id,
206
+ providerFactory,
207
+ shouldBootstrap
208
+ }) {
209
+ const collabContext = useCollaborationContext();
210
+ const {
211
+ yjsDocMap,
212
+ name,
213
+ color
214
+ } = collabContext;
215
+ const [editor] = LexicalComposerContext.useLexicalComposerContext();
216
+ const provider = React.useMemo(() => providerFactory(id, yjsDocMap), [id, providerFactory, yjsDocMap]);
217
+ const [cursors, binding] = useYjsCollaboration(editor, id, provider, yjsDocMap, name, color, shouldBootstrap);
218
+ collabContext.clientID = binding.clientID;
219
+ useYjsHistory(editor, binding);
220
+ useYjsFocusTracking(editor, provider);
221
+ return cursors;
222
+ }
223
+ const CollaborationContext = /*#__PURE__*/React.createContext({
224
+ clientID: 0,
225
+ color: randomEntry[1],
226
+ name: randomEntry[0],
227
+ yjsDocMap: new Map()
228
+ });
229
+ function useCollaborationContext() {
230
+ return React.useContext(CollaborationContext);
231
+ }
232
+
233
+ exports.CollaborationContext = CollaborationContext;
234
+ exports.CollaborationPlugin = CollaborationPlugin;
235
+ exports.useCollaborationContext = useCollaborationContext;
@@ -1,8 +1,9 @@
1
- 'use strict';var d=require("react"),g=require("@lexical/react/LexicalComposerContext"),t=require("react-dom"),z=require("@lexical/yjs"),A=require("lexical"),B=require("lexical/ParagraphNode");function C(b){b.update(()=>{A.$log("initEditor");var c=A.$getRoot();if(null===c.getFirstChild()){const a=B.$createParagraphNode();c.append(a);c=document.activeElement;(null!==A.$getSelection()||null!==c&&c===b.getRootElement())&&a.select()}})}
2
- function D(b,c,a,e,h,l,q){const f=d.useMemo(()=>z.createBinding(b,a,c,e),[b,a,c,e]),m=d.useCallback(()=>{a.connect()},[a]),n=d.useCallback(()=>{try{a.disconnect()}catch(k){}},[a]);d.useEffect(()=>{const {root:k}=f,{awareness:r}=a,v=({status:p})=>{b.execCommand("connected","connected"===p)},w=p=>{!q&&p&&k.isEmpty()&&0===k._xmlText._length&&C(b)},x=()=>{z.syncCursorPositions(f,a)},y=(p,u)=>{u.origin!==f&&z.syncYjsChangesToLexical(f,a,p)};z.initLocalState(a,h,l,document.activeElement===b.getRootElement());
3
- a.on("status",v);a.on("sync",w);r.on("update",x);k.getSharedType().observeDeep(y);const M=b.addListener("update",({prevEditorState:p,editorState:u,dirtyLeaves:I,dirtyElements:J,normalizedNodes:K,tags:L})=>{z.syncLexicalUpdateToYjs(f,a,p,u,J,I,K,L)});m();return()=>{n();a.off("sync",w);a.off("status",v);r.off("update",x);k.getSharedType().unobserveDeep(y);M()}},[f,l,m,n,b,h,a,q]);const N=d.useMemo(()=>t.createPortal(d.createElement("div",{ref:k=>{f.cursorsContainer=k}}),document.body),[f]);d.useEffect(()=>
4
- b.addListener("command",(k,r)=>{"toggleConnect"===k&&void 0!==m&&void 0!==n&&(r?(console.log("Collaboration connected!"),m()):(console.log("Collaboration disconnected!"),n()));return!1},0),[m,n,b]);return[N,f]}
5
- function E(b,c){d.useEffect(()=>{const a=()=>{z.setLocalStateFocus(c,!1)},e=()=>{z.setLocalStateFocus(c,!0)};return b.addListener("root",(h,l)=>{null!==l&&(l.removeEventListener("blur",a),l.removeEventListener("focus",e));null!==h&&(document.activeElement===h&&z.setLocalStateFocus(c,!0),h.addEventListener("blur",a),h.addEventListener("focus",e))})},[b,c,c.awareness])}
6
- function F(b,c){const a=d.useMemo(()=>z.createUndoManager(c,c.root.getSharedType()),[c]);d.useEffect(()=>b.addListener("command",e=>"undo"===e?(a.undo(),!0):"redo"===e?(a.redo(),!0):!1,0));return d.useCallback(()=>{a.clear()},[a])}
7
- const G=[["Cat","255,165,0"],["Dog","0,200,55"],["Rabbit","160,0,200"],["Frog","0,172,200"],["Fox","197,200,0"],["Hedgehog","31,200,0"],["Pigeon","200,0,0"],["Squirrel","200,0,148"],["Bear","255,235,0"],["Tiger","86,255,0"],["Leopard","0,255,208"],["Zebra","0,243,255"],["Wolf","0,102,255"],["Owl","147,0,255"],["Gull","255,0,153"],["Squid","0,220,255"]],H=G[Math.floor(Math.random()*(G.length-1+1))],O=d.createContext({yjsDocMap:new Map,name:H[0],color:H[1]});function P(){return d.useContext(O)}
8
- exports.CollaborationContext=O;exports.CollaborationPlugin=function({id:b,providerFactory:c,skipInit:a}){const {yjsDocMap:e,name:h,color:l}=P(),[q]=g.useLexicalComposerContext(),f=d.useMemo(()=>c(b,e),[b,c,e]),[m,n]=D(q,b,f,e,h,l,a||!1);F(q,n);E(q,f);return m};exports.useCollaborationContext=P;
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ 'use strict'
8
+ const LexicalCollaborationPlugin = process.env.NODE_ENV === 'development' ? require('./LexicalCollaborationPlugin.dev.js') : require('./LexicalCollaborationPlugin.prod.js')
9
+ module.exports = LexicalCollaborationPlugin;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ 'use strict';var c=require("@lexical/react/LexicalComposerContext"),k=require("react"),z=require("@lexical/yjs"),A=require("react-dom");
8
+ function B(b,d,a,f,g,l,r){const e=k.useMemo(()=>z.createBinding(b,a,d,f),[b,a,d,f]),m=k.useCallback(()=>{a.connect()},[a]),n=k.useCallback(()=>{try{a.disconnect()}catch(h){}},[a]),q=k.useRef(!1);k.useLayoutEffect(()=>b.addListener("command",h=>"bootstrapEditor"===h?!q.current:!1,1),[b]);k.useEffect(()=>{const {root:h}=e,{awareness:t}=a,v=({status:p})=>{b.execCommand("connected","connected"===p)},w=p=>{r&&p&&h.isEmpty()&&0===h._xmlText._length&&(q.current=!0,b.execCommand("bootstrapEditor"))},x=()=>
9
+ {z.syncCursorPositions(e,a)},y=(p,u)=>{u.origin!==e&&z.syncYjsChangesToLexical(e,a,p)};z.initLocalState(a,g,l,document.activeElement===b.getRootElement());a.on("status",v);a.on("sync",w);t.on("update",x);h.getSharedType().observeDeep(y);const K=b.addListener("update",({prevEditorState:p,editorState:u,dirtyLeaves:G,dirtyElements:H,normalizedNodes:I,tags:J})=>{z.syncLexicalUpdateToYjs(e,a,p,u,H,G,I,J)});m();return()=>{n();a.off("sync",w);a.off("status",v);t.off("update",x);h.getSharedType().unobserveDeep(y);
10
+ K()}},[e,l,m,n,b,g,a,r]);const L=k.useMemo(()=>A.createPortal(k.createElement("div",{ref:h=>{e.cursorsContainer=h}}),document.body),[e]);k.useEffect(()=>b.addListener("command",(h,t)=>{"toggleConnect"===h&&void 0!==m&&void 0!==n&&(t?(console.log("Collaboration connected!"),m()):(console.log("Collaboration disconnected!"),n()));return!1},0),[m,n,b]);return[L,e]}
11
+ function C(b,d){k.useEffect(()=>{const a=()=>{z.setLocalStateFocus(d,!1)},f=()=>{z.setLocalStateFocus(d,!0)};return b.addListener("root",(g,l)=>{null!==l&&(l.removeEventListener("blur",a),l.removeEventListener("focus",f));null!==g&&(document.activeElement===g&&z.setLocalStateFocus(d,!0),g.addEventListener("blur",a),g.addEventListener("focus",f))})},[b,d,d.awareness])}
12
+ function D(b,d){const a=k.useMemo(()=>z.createUndoManager(d,d.root.getSharedType()),[d]);k.useEffect(()=>b.addListener("command",f=>"undo"===f?(a.undo(),!0):"redo"===f?(a.redo(),!0):!1,0));return k.useCallback(()=>{a.clear()},[a])}
13
+ const E=[["Cat","255,165,0"],["Dog","0,200,55"],["Rabbit","160,0,200"],["Frog","0,172,200"],["Fox","197,200,0"],["Hedgehog","31,200,0"],["Pigeon","200,0,0"],["Squirrel","200,0,148"],["Bear","255,235,0"],["Tiger","86,255,0"],["Leopard","0,255,208"],["Zebra","0,243,255"],["Wolf","0,102,255"],["Owl","147,0,255"],["Gull","255,0,153"],["Squid","0,220,255"]],F=E[Math.floor(Math.random()*(E.length-1+1))],M=k.createContext({clientID:0,color:F[1],name:F[0],yjsDocMap:new Map});
14
+ function N(){return k.useContext(M)}exports.CollaborationContext=M;exports.CollaborationPlugin=function({id:b,providerFactory:d,shouldBootstrap:a}){const f=N(),{yjsDocMap:g,name:l,color:r}=f,[e]=c.useLexicalComposerContext(),m=k.useMemo(()=>d(b,g),[b,d,g]),[n,q]=B(e,b,m,g,l,r,a);f.clientID=q.clientID;D(e,q);C(e,m);return n};exports.useCollaborationContext=N;