@lexical/react 0.4.1 → 0.5.1-next.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.
Files changed (66) hide show
  1. package/DEPRECATED_useLexical.js.flow +0 -1
  2. package/DEPRECATED_useLexicalDecorators.d.ts +2 -1
  3. package/DEPRECATED_useLexicalDecorators.dev.js +125 -10
  4. package/DEPRECATED_useLexicalDecorators.js.flow +8 -0
  5. package/DEPRECATED_useLexicalDecorators.prod.js +6 -2
  6. package/DEPRECATED_useLexicalPlainText.d.ts +2 -2
  7. package/DEPRECATED_useLexicalPlainText.dev.js +4 -4
  8. package/DEPRECATED_useLexicalPlainText.js.flow +0 -1
  9. package/DEPRECATED_useLexicalPlainText.prod.js +2 -2
  10. package/DEPRECATED_useLexicalRichText.d.ts +2 -2
  11. package/DEPRECATED_useLexicalRichText.dev.js +4 -4
  12. package/DEPRECATED_useLexicalRichText.js.flow +0 -1
  13. package/DEPRECATED_useLexicalRichText.prod.js +2 -2
  14. package/LexicalAutoEmbedPlugin.d.ts +3 -13
  15. package/LexicalAutoEmbedPlugin.dev.js +3 -19
  16. package/LexicalAutoEmbedPlugin.js.flow +3 -11
  17. package/LexicalAutoEmbedPlugin.prod.js +4 -5
  18. package/LexicalAutoLinkPlugin.dev.js +49 -45
  19. package/LexicalAutoLinkPlugin.prod.js +6 -6
  20. package/LexicalBlockWithAlignableContents.dev.js +1 -1
  21. package/LexicalBlockWithAlignableContents.prod.js +1 -1
  22. package/LexicalCollaborationPlugin.d.ts +5 -1
  23. package/LexicalCollaborationPlugin.dev.js +54 -16
  24. package/LexicalCollaborationPlugin.js.flow +1 -0
  25. package/LexicalCollaborationPlugin.prod.js +9 -9
  26. package/LexicalComposer.d.ts +1 -2
  27. package/LexicalComposer.dev.js +15 -1
  28. package/LexicalComposer.js.flow +14 -7
  29. package/LexicalComposer.prod.js +3 -3
  30. package/LexicalContentEditable.dev.js +1 -1
  31. package/LexicalContentEditable.prod.js +1 -1
  32. package/LexicalHorizontalRuleNode.d.ts +4 -2
  33. package/LexicalHorizontalRuleNode.dev.js +25 -3
  34. package/LexicalHorizontalRuleNode.js.flow +0 -1
  35. package/LexicalHorizontalRuleNode.prod.js +5 -5
  36. package/LexicalNestedComposer.d.ts +4 -2
  37. package/LexicalNestedComposer.dev.js +25 -3
  38. package/LexicalNestedComposer.js.flow +1 -0
  39. package/LexicalNestedComposer.prod.js +3 -3
  40. package/LexicalOnChangePlugin.d.ts +1 -2
  41. package/LexicalOnChangePlugin.dev.js +3 -9
  42. package/LexicalOnChangePlugin.js.flow +0 -2
  43. package/LexicalOnChangePlugin.prod.js +2 -2
  44. package/LexicalPlainTextPlugin.d.ts +3 -3
  45. package/LexicalPlainTextPlugin.dev.js +111 -20
  46. package/LexicalPlainTextPlugin.js.flow +3 -1
  47. package/LexicalPlainTextPlugin.prod.js +6 -4
  48. package/LexicalRichTextPlugin.d.ts +3 -3
  49. package/LexicalRichTextPlugin.dev.js +111 -20
  50. package/LexicalRichTextPlugin.js.flow +3 -1
  51. package/LexicalRichTextPlugin.prod.js +6 -4
  52. package/LexicalTableOfContents__EXPERIMENTAL.js.flow +1 -1
  53. package/LexicalTablePlugin.dev.js +1 -1
  54. package/LexicalTablePlugin.prod.js +1 -1
  55. package/LexicalTreeView.dev.js +28 -13
  56. package/LexicalTreeView.prod.js +14 -13
  57. package/LexicalTypeaheadMenuPlugin.d.ts +20 -8
  58. package/LexicalTypeaheadMenuPlugin.dev.js +200 -57
  59. package/LexicalTypeaheadMenuPlugin.js.flow +19 -21
  60. package/LexicalTypeaheadMenuPlugin.prod.js +18 -14
  61. package/package.json +19 -19
  62. package/shared/ReactErrorBoundary.d.ts +63 -0
  63. package/shared/useDecorators.d.ts +8 -1
  64. package/shared/usePlainTextSetup.d.ts +1 -2
  65. package/shared/useRichTextSetup.d.ts +1 -2
  66. package/shared/useYjsCollaboration.d.ts +4 -1
@@ -5,9 +5,9 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
7
  */
8
- import { InitialEditorStateType } from '@lexical/plain-text';
9
- export declare function PlainTextPlugin({ contentEditable, placeholder, initialEditorState, }: {
8
+ import { ErrorBoundaryType } from './shared/useDecorators';
9
+ export declare function PlainTextPlugin({ contentEditable, placeholder, ErrorBoundary, }: {
10
10
  contentEditable: JSX.Element;
11
- initialEditorState?: InitialEditorStateType;
12
11
  placeholder: JSX.Element | string;
12
+ ErrorBoundary?: ErrorBoundaryType;
13
13
  }): JSX.Element;
@@ -21,16 +21,94 @@ var plainText = require('@lexical/plain-text');
21
21
  * LICENSE file in the root directory of this source tree.
22
22
  *
23
23
  */
24
- function warnOnlyOnce(message) {
25
24
 
26
- let run = false;
27
- return () => {
28
- if (!run) {
29
- console.warn(message);
25
+ const changedArray = (a = [], b = []) => a.length !== b.length || a.some((item, index) => !Object.is(item, b[index]));
26
+
27
+ const initialState = {
28
+ error: null
29
+ };
30
+
31
+ class ErrorBoundary extends React.Component {
32
+ constructor(props) {
33
+ super(props);
34
+ this.state = initialState;
35
+ this.resetErrorBoundary = this.resetErrorBoundary.bind(this);
36
+ }
37
+
38
+ static getDerivedStateFromError(error) {
39
+ return {
40
+ error
41
+ };
42
+ }
43
+
44
+ resetErrorBoundary(...args) {
45
+ // @ts-ignore
46
+ // eslint-disable-next-line no-unused-expressions
47
+ this.props.onReset && this.props.onReset(...args);
48
+ this.reset();
49
+ }
50
+
51
+ reset() {
52
+ this.setState(initialState);
53
+ }
54
+
55
+ componentDidCatch(error, info) {
56
+ // @ts-ignore
57
+ // eslint-disable-next-line no-unused-expressions
58
+ this.props.onError && this.props.onError(error, info);
59
+ }
60
+
61
+ componentDidUpdate(prevProps, prevState) {
62
+ const {
63
+ error
64
+ } = this.state;
65
+ const {
66
+ resetKeys
67
+ } = this.props; // There's an edge case where if the thing that triggered the error
68
+ // happens to *also* be in the resetKeys array, we'd end up resetting
69
+ // the error boundary immediately. This would likely trigger a second
70
+ // error to be thrown.
71
+ // So we make sure that we don't check the resetKeys on the first call
72
+ // of cDU after the error is set
73
+
74
+ if (error !== null && prevState.error !== null && changedArray(prevProps.resetKeys, resetKeys)) {
75
+ // @ts-ignore
76
+ // eslint-disable-next-line no-unused-expressions
77
+ this.props.onResetKeysChange && this.props.onResetKeysChange(prevProps.resetKeys, resetKeys);
78
+ this.reset();
30
79
  }
80
+ }
81
+
82
+ render() {
83
+ const {
84
+ error
85
+ } = this.state;
86
+ const {
87
+ fallbackRender,
88
+ FallbackComponent,
89
+ fallback
90
+ } = this.props;
91
+
92
+ if (error !== null) {
93
+ const props = {
94
+ error,
95
+ resetErrorBoundary: this.resetErrorBoundary
96
+ };
97
+
98
+ if ( /*#__PURE__*/React.isValidElement(fallback)) {
99
+ return fallback;
100
+ } else if (typeof fallbackRender === 'function') {
101
+ return fallbackRender(props);
102
+ } else if (FallbackComponent) {
103
+ return /*#__PURE__*/React.createElement(FallbackComponent, props);
104
+ } else {
105
+ throw new Error('react-error-boundary requires either a fallback, fallbackRender, or FallbackComponent prop');
106
+ }
107
+ }
108
+
109
+ return this.props.children;
110
+ }
31
111
 
32
- run = true;
33
- };
34
112
  }
35
113
 
36
114
  /**
@@ -90,7 +168,14 @@ function useCanShowPlaceholder(editor) {
90
168
  * LICENSE file in the root directory of this source tree.
91
169
  *
92
170
  */
93
- function useDecorators(editor) {
171
+ function useDecorators(editor, // TODO 0.6 Make non-optional non-default
172
+ ErrorBoundary$1 = ({
173
+ children,
174
+ onError
175
+ }) => /*#__PURE__*/React.createElement(ErrorBoundary, {
176
+ fallback: null,
177
+ onError: onError
178
+ }, children)) {
94
179
  const [decorators, setDecorators] = React.useState(() => editor.getDecorators()); // Subscribe to changes
95
180
 
96
181
  useLayoutEffect(() => {
@@ -113,7 +198,11 @@ function useDecorators(editor) {
113
198
 
114
199
  for (let i = 0; i < decoratorKeys.length; i++) {
115
200
  const nodeKey = decoratorKeys[i];
116
- const reactDecorator = decorators[nodeKey];
201
+ const reactDecorator = /*#__PURE__*/React.createElement(ErrorBoundary$1, {
202
+ onError: e => editor._onError(e)
203
+ }, /*#__PURE__*/React.createElement(React.Suspense, {
204
+ fallback: null
205
+ }, decorators[nodeKey]));
117
206
  const element = editor.getElementByKey(nodeKey);
118
207
 
119
208
  if (element !== null) {
@@ -122,7 +211,7 @@ function useDecorators(editor) {
122
211
  }
123
212
 
124
213
  return decoratedPortals;
125
- }, [decorators, editor]);
214
+ }, [ErrorBoundary$1, decorators, editor]);
126
215
  }
127
216
 
128
217
  /**
@@ -132,9 +221,9 @@ function useDecorators(editor) {
132
221
  * LICENSE file in the root directory of this source tree.
133
222
  *
134
223
  */
135
- function usePlainTextSetup(editor, initialEditorState) {
224
+ function usePlainTextSetup(editor) {
136
225
  useLayoutEffect(() => {
137
- return utils.mergeRegister(plainText.registerPlainText(editor, initialEditorState), dragon.registerDragonSupport(editor)); // We only do this for init
226
+ return utils.mergeRegister(plainText.registerPlainText(editor), dragon.registerDragonSupport(editor)); // We only do this for init
138
227
  // eslint-disable-next-line react-hooks/exhaustive-deps
139
228
  }, [editor]);
140
229
  }
@@ -146,20 +235,22 @@ function usePlainTextSetup(editor, initialEditorState) {
146
235
  * LICENSE file in the root directory of this source tree.
147
236
  *
148
237
  */
149
- const deprecatedInitialEditorStateWarning = warnOnlyOnce('`initialEditorState` on `PlainTextPlugin` is deprecated and will be removed soon. Use the `initialConfig.editorState` prop on the `LexicalComposer` instead.');
150
238
  function PlainTextPlugin({
151
239
  contentEditable,
152
240
  placeholder,
153
- initialEditorState
241
+ // TODO 0.6 Make non-optional non-default
242
+ ErrorBoundary: ErrorBoundary$1 = ({
243
+ children,
244
+ onError
245
+ }) => /*#__PURE__*/React.createElement(ErrorBoundary, {
246
+ fallback: null,
247
+ onError: onError
248
+ }, children)
154
249
  }) {
155
- if (deprecatedInitialEditorStateWarning && initialEditorState !== undefined) {
156
- deprecatedInitialEditorStateWarning();
157
- }
158
-
159
250
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
160
251
  const showPlaceholder = useCanShowPlaceholder(editor);
161
- const decorators = useDecorators(editor);
162
- usePlainTextSetup(editor, initialEditorState);
252
+ const decorators = useDecorators(editor, ErrorBoundary$1);
253
+ usePlainTextSetup(editor);
163
254
  return /*#__PURE__*/React.createElement(React.Fragment, null, contentEditable, showPlaceholder && placeholder, decorators);
164
255
  }
165
256
 
@@ -7,6 +7,7 @@
7
7
  * @flow strict
8
8
  */
9
9
 
10
+ import type {ErrorBoundaryType} from './DEPRECATED_useLexicalDecorators';
10
11
  import type {EditorState, LexicalEditor} from 'lexical';
11
12
 
12
13
  type InitialEditorStateType =
@@ -17,6 +18,7 @@ type InitialEditorStateType =
17
18
 
18
19
  declare export function PlainTextPlugin({
19
20
  contentEditable: React$Node,
20
- initialEditorState?: InitialEditorStateType,
21
21
  placeholder: React$Node,
22
+ // TODO 0.6 Make non-optional non-default
23
+ ErrorBoundary?: ErrorBoundaryType,
22
24
  }): React$Node;
@@ -4,7 +4,9 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- 'use strict';var d=require("@lexical/react/LexicalComposerContext"),h=require("react"),l=require("@lexical/text"),m=require("@lexical/utils"),n=require("react-dom"),p=require("@lexical/dragon"),q=require("@lexical/plain-text"),r="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?h.useLayoutEffect:h.useEffect;function t(a){return a.getEditorState().read(l.$canShowPlaceholderCurry(a.isComposing(),a.isEditable()))}
8
- function u(a){let [c,f]=h.useState(()=>t(a));r(()=>{function b(){let g=t(a);f(g)}b();return m.mergeRegister(a.registerUpdateListener(()=>{b()}),a.registerEditableListener(()=>{b()}))},[a]);return c}
9
- function v(a){let [c,f]=h.useState(()=>a.getDecorators());r(()=>a.registerDecoratorListener(b=>{n.flushSync(()=>{f(b)})}),[a]);h.useEffect(()=>{f(a.getDecorators())},[a]);return h.useMemo(()=>{let b=[],g=Object.keys(c);for(let k=0;k<g.length;k++){var e=g[k];let w=c[e];e=a.getElementByKey(e);null!==e&&b.push(n.createPortal(w,e))}return b},[c,a])}function x(a,c){r(()=>m.mergeRegister(q.registerPlainText(a,c),p.registerDragonSupport(a)),[a])}
10
- exports.PlainTextPlugin=function({contentEditable:a,placeholder:c,initialEditorState:f}){let [b]=d.useLexicalComposerContext(),g=u(b),e=v(b);x(b,f);return h.createElement(h.Fragment,null,a,g&&c,e)}
7
+ 'use strict';var d=require("@lexical/react/LexicalComposerContext"),h=require("react"),l=require("@lexical/text"),m=require("@lexical/utils"),n=require("react-dom"),p=require("@lexical/dragon"),q=require("@lexical/plain-text");let t=(a=[],e=[])=>a.length!==e.length||a.some((c,b)=>!Object.is(c,e[b])),u={error:null};
8
+ class v extends h.Component{constructor(a){super(a);this.state=u;this.resetErrorBoundary=this.resetErrorBoundary.bind(this)}static getDerivedStateFromError(a){return{error:a}}resetErrorBoundary(...a){this.props.onReset&&this.props.onReset(...a);this.reset()}reset(){this.setState(u)}componentDidCatch(a,e){this.props.onError&&this.props.onError(a,e)}componentDidUpdate(a,e){let {error:c}=this.state,{resetKeys:b}=this.props;null!==c&&null!==e.error&&t(a.resetKeys,b)&&(this.props.onResetKeysChange&&this.props.onResetKeysChange(a.resetKeys,
9
+ b),this.reset())}render(){var {error:a}=this.state;let {fallbackRender:e,FallbackComponent:c,fallback:b}=this.props;if(null!==a){a={error:a,resetErrorBoundary:this.resetErrorBoundary};if(h.isValidElement(b))return b;if("function"===typeof e)return e(a);if(c)return h.createElement(c,a);throw Error("react-error-boundary requires either a fallback, fallbackRender, or FallbackComponent prop");}return this.props.children}}
10
+ var w="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?h.useLayoutEffect:h.useEffect;function x(a){return a.getEditorState().read(l.$canShowPlaceholderCurry(a.isComposing(),a.isEditable()))}function y(a){let [e,c]=h.useState(()=>x(a));w(()=>{function b(){let f=x(a);c(f)}b();return m.mergeRegister(a.registerUpdateListener(()=>{b()}),a.registerEditableListener(()=>{b()}))},[a]);return e}
11
+ function z(a,e=({children:c,onError:b})=>h.createElement(v,{fallback:null,onError:b},c)){let [c,b]=h.useState(()=>a.getDecorators());w(()=>a.registerDecoratorListener(f=>{n.flushSync(()=>{b(f)})}),[a]);h.useEffect(()=>{b(a.getDecorators())},[a]);return h.useMemo(()=>{let f=[],r=Object.keys(c);for(let k=0;k<r.length;k++){var g=r[k];let B=h.createElement(e,{onError:A=>a._onError(A)},h.createElement(h.Suspense,{fallback:null},c[g]));g=a.getElementByKey(g);null!==g&&f.push(n.createPortal(B,g))}return f},
12
+ [e,c,a])}function C(a){w(()=>m.mergeRegister(q.registerPlainText(a),p.registerDragonSupport(a)),[a])}exports.PlainTextPlugin=function({contentEditable:a,placeholder:e,ErrorBoundary:c=({children:b,onError:f})=>h.createElement(v,{fallback:null,onError:f},b)}){let [b]=d.useLexicalComposerContext(),f=y(b);c=z(b,c);C(b);return h.createElement(h.Fragment,null,a,f&&e,c)}
@@ -5,9 +5,9 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
7
  */
8
- import { InitialEditorStateType } from '@lexical/rich-text';
9
- export declare function RichTextPlugin({ contentEditable, placeholder, initialEditorState, }: Readonly<{
8
+ import { ErrorBoundaryType } from './shared/useDecorators';
9
+ export declare function RichTextPlugin({ contentEditable, placeholder, ErrorBoundary, }: Readonly<{
10
10
  contentEditable: JSX.Element;
11
- initialEditorState?: InitialEditorStateType;
12
11
  placeholder: JSX.Element | string;
12
+ ErrorBoundary?: ErrorBoundaryType;
13
13
  }>): JSX.Element;
@@ -21,16 +21,94 @@ var richText = require('@lexical/rich-text');
21
21
  * LICENSE file in the root directory of this source tree.
22
22
  *
23
23
  */
24
- function warnOnlyOnce(message) {
25
24
 
26
- let run = false;
27
- return () => {
28
- if (!run) {
29
- console.warn(message);
25
+ const changedArray = (a = [], b = []) => a.length !== b.length || a.some((item, index) => !Object.is(item, b[index]));
26
+
27
+ const initialState = {
28
+ error: null
29
+ };
30
+
31
+ class ErrorBoundary extends React.Component {
32
+ constructor(props) {
33
+ super(props);
34
+ this.state = initialState;
35
+ this.resetErrorBoundary = this.resetErrorBoundary.bind(this);
36
+ }
37
+
38
+ static getDerivedStateFromError(error) {
39
+ return {
40
+ error
41
+ };
42
+ }
43
+
44
+ resetErrorBoundary(...args) {
45
+ // @ts-ignore
46
+ // eslint-disable-next-line no-unused-expressions
47
+ this.props.onReset && this.props.onReset(...args);
48
+ this.reset();
49
+ }
50
+
51
+ reset() {
52
+ this.setState(initialState);
53
+ }
54
+
55
+ componentDidCatch(error, info) {
56
+ // @ts-ignore
57
+ // eslint-disable-next-line no-unused-expressions
58
+ this.props.onError && this.props.onError(error, info);
59
+ }
60
+
61
+ componentDidUpdate(prevProps, prevState) {
62
+ const {
63
+ error
64
+ } = this.state;
65
+ const {
66
+ resetKeys
67
+ } = this.props; // There's an edge case where if the thing that triggered the error
68
+ // happens to *also* be in the resetKeys array, we'd end up resetting
69
+ // the error boundary immediately. This would likely trigger a second
70
+ // error to be thrown.
71
+ // So we make sure that we don't check the resetKeys on the first call
72
+ // of cDU after the error is set
73
+
74
+ if (error !== null && prevState.error !== null && changedArray(prevProps.resetKeys, resetKeys)) {
75
+ // @ts-ignore
76
+ // eslint-disable-next-line no-unused-expressions
77
+ this.props.onResetKeysChange && this.props.onResetKeysChange(prevProps.resetKeys, resetKeys);
78
+ this.reset();
30
79
  }
80
+ }
81
+
82
+ render() {
83
+ const {
84
+ error
85
+ } = this.state;
86
+ const {
87
+ fallbackRender,
88
+ FallbackComponent,
89
+ fallback
90
+ } = this.props;
91
+
92
+ if (error !== null) {
93
+ const props = {
94
+ error,
95
+ resetErrorBoundary: this.resetErrorBoundary
96
+ };
97
+
98
+ if ( /*#__PURE__*/React.isValidElement(fallback)) {
99
+ return fallback;
100
+ } else if (typeof fallbackRender === 'function') {
101
+ return fallbackRender(props);
102
+ } else if (FallbackComponent) {
103
+ return /*#__PURE__*/React.createElement(FallbackComponent, props);
104
+ } else {
105
+ throw new Error('react-error-boundary requires either a fallback, fallbackRender, or FallbackComponent prop');
106
+ }
107
+ }
108
+
109
+ return this.props.children;
110
+ }
31
111
 
32
- run = true;
33
- };
34
112
  }
35
113
 
36
114
  /**
@@ -90,7 +168,14 @@ function useCanShowPlaceholder(editor) {
90
168
  * LICENSE file in the root directory of this source tree.
91
169
  *
92
170
  */
93
- function useDecorators(editor) {
171
+ function useDecorators(editor, // TODO 0.6 Make non-optional non-default
172
+ ErrorBoundary$1 = ({
173
+ children,
174
+ onError
175
+ }) => /*#__PURE__*/React.createElement(ErrorBoundary, {
176
+ fallback: null,
177
+ onError: onError
178
+ }, children)) {
94
179
  const [decorators, setDecorators] = React.useState(() => editor.getDecorators()); // Subscribe to changes
95
180
 
96
181
  useLayoutEffect(() => {
@@ -113,7 +198,11 @@ function useDecorators(editor) {
113
198
 
114
199
  for (let i = 0; i < decoratorKeys.length; i++) {
115
200
  const nodeKey = decoratorKeys[i];
116
- const reactDecorator = decorators[nodeKey];
201
+ const reactDecorator = /*#__PURE__*/React.createElement(ErrorBoundary$1, {
202
+ onError: e => editor._onError(e)
203
+ }, /*#__PURE__*/React.createElement(React.Suspense, {
204
+ fallback: null
205
+ }, decorators[nodeKey]));
117
206
  const element = editor.getElementByKey(nodeKey);
118
207
 
119
208
  if (element !== null) {
@@ -122,7 +211,7 @@ function useDecorators(editor) {
122
211
  }
123
212
 
124
213
  return decoratedPortals;
125
- }, [decorators, editor]);
214
+ }, [ErrorBoundary$1, decorators, editor]);
126
215
  }
127
216
 
128
217
  /**
@@ -132,9 +221,9 @@ function useDecorators(editor) {
132
221
  * LICENSE file in the root directory of this source tree.
133
222
  *
134
223
  */
135
- function useRichTextSetup(editor, initialEditorState) {
224
+ function useRichTextSetup(editor) {
136
225
  useLayoutEffect(() => {
137
- return utils.mergeRegister(richText.registerRichText(editor, initialEditorState), dragon.registerDragonSupport(editor)); // We only do this for init
226
+ return utils.mergeRegister(richText.registerRichText(editor), dragon.registerDragonSupport(editor)); // We only do this for init
138
227
  // eslint-disable-next-line react-hooks/exhaustive-deps
139
228
  }, [editor]);
140
229
  }
@@ -146,20 +235,22 @@ function useRichTextSetup(editor, initialEditorState) {
146
235
  * LICENSE file in the root directory of this source tree.
147
236
  *
148
237
  */
149
- const deprecatedInitialEditorStateWarning = warnOnlyOnce('`initialEditorState` on `RichTextPlugin` is deprecated and will be removed soon. Use the `initialConfig.editorState` prop on the `LexicalComposer` instead.');
150
238
  function RichTextPlugin({
151
239
  contentEditable,
152
240
  placeholder,
153
- initialEditorState
241
+ // TODO 0.6 Make non-optional non-default
242
+ ErrorBoundary: ErrorBoundary$1 = ({
243
+ children,
244
+ onError
245
+ }) => /*#__PURE__*/React.createElement(ErrorBoundary, {
246
+ fallback: null,
247
+ onError: onError
248
+ }, children)
154
249
  }) {
155
- if (deprecatedInitialEditorStateWarning && initialEditorState !== undefined) {
156
- deprecatedInitialEditorStateWarning();
157
- }
158
-
159
250
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
160
251
  const showPlaceholder = useCanShowPlaceholder(editor);
161
- const decorators = useDecorators(editor);
162
- useRichTextSetup(editor, initialEditorState);
252
+ const decorators = useDecorators(editor, ErrorBoundary$1);
253
+ useRichTextSetup(editor);
163
254
  return /*#__PURE__*/React.createElement(React.Fragment, null, contentEditable, showPlaceholder && placeholder, decorators);
164
255
  }
165
256
 
@@ -7,6 +7,7 @@
7
7
  * @flow strict
8
8
  */
9
9
 
10
+ import type {ErrorBoundaryType} from './DEPRECATED_useLexicalDecorators';
10
11
  import type {EditorState, LexicalEditor} from 'lexical';
11
12
 
12
13
  type InitialEditorStateType =
@@ -17,6 +18,7 @@ type InitialEditorStateType =
17
18
 
18
19
  declare export function RichTextPlugin({
19
20
  contentEditable: React$Node,
20
- initialEditorState?: InitialEditorStateType,
21
21
  placeholder: React$Node,
22
+ // TODO 0.6 Make non-optional non-default
23
+ ErrorBoundary?: ErrorBoundaryType,
22
24
  }): React$Node;
@@ -4,7 +4,9 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- 'use strict';var d=require("@lexical/react/LexicalComposerContext"),h=require("react"),l=require("@lexical/text"),m=require("@lexical/utils"),n=require("react-dom"),p=require("@lexical/dragon"),q=require("@lexical/rich-text"),r="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?h.useLayoutEffect:h.useEffect;function t(a){return a.getEditorState().read(l.$canShowPlaceholderCurry(a.isComposing(),a.isEditable()))}
8
- function u(a){let [c,f]=h.useState(()=>t(a));r(()=>{function b(){let g=t(a);f(g)}b();return m.mergeRegister(a.registerUpdateListener(()=>{b()}),a.registerEditableListener(()=>{b()}))},[a]);return c}
9
- function v(a){let [c,f]=h.useState(()=>a.getDecorators());r(()=>a.registerDecoratorListener(b=>{n.flushSync(()=>{f(b)})}),[a]);h.useEffect(()=>{f(a.getDecorators())},[a]);return h.useMemo(()=>{let b=[],g=Object.keys(c);for(let k=0;k<g.length;k++){var e=g[k];let w=c[e];e=a.getElementByKey(e);null!==e&&b.push(n.createPortal(w,e))}return b},[c,a])}function x(a,c){r(()=>m.mergeRegister(q.registerRichText(a,c),p.registerDragonSupport(a)),[a])}
10
- exports.RichTextPlugin=function({contentEditable:a,placeholder:c,initialEditorState:f}){let [b]=d.useLexicalComposerContext(),g=u(b),e=v(b);x(b,f);return h.createElement(h.Fragment,null,a,g&&c,e)}
7
+ 'use strict';var d=require("@lexical/react/LexicalComposerContext"),h=require("react"),l=require("@lexical/text"),m=require("@lexical/utils"),n=require("react-dom"),p=require("@lexical/dragon"),q=require("@lexical/rich-text");let t=(a=[],e=[])=>a.length!==e.length||a.some((c,b)=>!Object.is(c,e[b])),u={error:null};
8
+ class v extends h.Component{constructor(a){super(a);this.state=u;this.resetErrorBoundary=this.resetErrorBoundary.bind(this)}static getDerivedStateFromError(a){return{error:a}}resetErrorBoundary(...a){this.props.onReset&&this.props.onReset(...a);this.reset()}reset(){this.setState(u)}componentDidCatch(a,e){this.props.onError&&this.props.onError(a,e)}componentDidUpdate(a,e){let {error:c}=this.state,{resetKeys:b}=this.props;null!==c&&null!==e.error&&t(a.resetKeys,b)&&(this.props.onResetKeysChange&&this.props.onResetKeysChange(a.resetKeys,
9
+ b),this.reset())}render(){var {error:a}=this.state;let {fallbackRender:e,FallbackComponent:c,fallback:b}=this.props;if(null!==a){a={error:a,resetErrorBoundary:this.resetErrorBoundary};if(h.isValidElement(b))return b;if("function"===typeof e)return e(a);if(c)return h.createElement(c,a);throw Error("react-error-boundary requires either a fallback, fallbackRender, or FallbackComponent prop");}return this.props.children}}
10
+ var w="undefined"!==typeof window&&"undefined"!==typeof window.document&&"undefined"!==typeof window.document.createElement?h.useLayoutEffect:h.useEffect;function x(a){return a.getEditorState().read(l.$canShowPlaceholderCurry(a.isComposing(),a.isEditable()))}function y(a){let [e,c]=h.useState(()=>x(a));w(()=>{function b(){let f=x(a);c(f)}b();return m.mergeRegister(a.registerUpdateListener(()=>{b()}),a.registerEditableListener(()=>{b()}))},[a]);return e}
11
+ function z(a,e=({children:c,onError:b})=>h.createElement(v,{fallback:null,onError:b},c)){let [c,b]=h.useState(()=>a.getDecorators());w(()=>a.registerDecoratorListener(f=>{n.flushSync(()=>{b(f)})}),[a]);h.useEffect(()=>{b(a.getDecorators())},[a]);return h.useMemo(()=>{let f=[],r=Object.keys(c);for(let k=0;k<r.length;k++){var g=r[k];let B=h.createElement(e,{onError:A=>a._onError(A)},h.createElement(h.Suspense,{fallback:null},c[g]));g=a.getElementByKey(g);null!==g&&f.push(n.createPortal(B,g))}return f},
12
+ [e,c,a])}function C(a){w(()=>m.mergeRegister(q.registerRichText(a),p.registerDragonSupport(a)),[a])}exports.RichTextPlugin=function({contentEditable:a,placeholder:e,ErrorBoundary:c=({children:b,onError:f})=>h.createElement(v,{fallback:null,onError:f},b)}){let [b]=d.useLexicalComposerContext(),f=y(b);c=z(b,c);C(b);return h.createElement(h.Fragment,null,a,f&&e,c)}
@@ -10,7 +10,7 @@
10
10
  import type {HeadingTagType} from '@lexical/rich-text';
11
11
  import type {NodeKey} from 'lexical';
12
12
 
13
- declare export function LexicalTableOfContentsPlugin({
13
+ declare export default function LexicalTableOfContentsPlugin({
14
14
  children: (
15
15
  tableOfContents: Array<[NodeKey, string, HeadingTagType]>,
16
16
  ) => React$Node,
@@ -44,7 +44,7 @@ function TablePlugin() {
44
44
  if (focusNode !== null) {
45
45
  const tableNode = table.$createTableNodeWithDimensions(Number(rows), Number(columns), includeHeaders);
46
46
 
47
- if (lexical.$isRootNode(focusNode)) {
47
+ if (lexical.$isRootOrShadowRoot(focusNode)) {
48
48
  const target = focusNode.getChildAtIndex(focus.offset);
49
49
 
50
50
  if (target !== null) {
@@ -6,5 +6,5 @@
6
6
  */
7
7
  'use strict';var e=require("@lexical/react/LexicalComposerContext"),f=require("@lexical/table"),k=require("lexical"),m=require("react");
8
8
  exports.TablePlugin=function(){let [d]=e.useLexicalComposerContext();m.useEffect(()=>{if(!d.hasNodes([f.TableNode,f.TableCellNode,f.TableRowNode]))throw Error("Minified Lexical error #10; visit https://lexical.dev/docs/error?code=10 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.");return d.registerCommand(f.INSERT_TABLE_COMMAND,({columns:a,rows:c,includeHeaders:g})=>{var b=k.$getSelection();if(!k.$isRangeSelection(b))return!0;let h=b.focus;
9
- b=h.getNode();null!==b&&(a=f.$createTableNodeWithDimensions(Number(c),Number(a),g),k.$isRootNode(b)?(c=b.getChildAtIndex(h.offset),null!==c?c.insertBefore(a):b.append(a),a.insertBefore(k.$createParagraphNode())):b.getTopLevelElementOrThrow().insertAfter(a),a.insertAfter(k.$createParagraphNode()),a.getFirstChildOrThrow().getFirstChildOrThrow().select());return!0},k.COMMAND_PRIORITY_EDITOR)},[d]);m.useEffect(()=>{let a=new Map;return d.registerMutationListener(f.TableNode,c=>{for(let [g,b]of c)"created"===
9
+ b=h.getNode();null!==b&&(a=f.$createTableNodeWithDimensions(Number(c),Number(a),g),k.$isRootOrShadowRoot(b)?(c=b.getChildAtIndex(h.offset),null!==c?c.insertBefore(a):b.append(a),a.insertBefore(k.$createParagraphNode())):b.getTopLevelElementOrThrow().insertAfter(a),a.insertAfter(k.$createParagraphNode()),a.getFirstChildOrThrow().getFirstChildOrThrow().select());return!0},k.COMMAND_PRIORITY_EDITOR)},[d]);m.useEffect(()=>{let a=new Map;return d.registerMutationListener(f.TableNode,c=>{for(let [g,b]of c)"created"===
10
10
  b?d.update(()=>{var h=d.getElementByKey(g);let l=k.$getNodeByKey(g);h&&l&&(h=f.applyTableHandlers(l,h,d),a.set(g,h))}):"destroyed"===b&&(c=a.get(g),void 0!==c&&(c.removeListeners(),a.delete(g)))})},[d]);return null}
@@ -8,6 +8,7 @@
8
8
 
9
9
  var link = require('@lexical/link');
10
10
  var mark = require('@lexical/mark');
11
+ var utils = require('@lexical/utils');
11
12
  var lexical = require('lexical');
12
13
  var React = require('react');
13
14
 
@@ -47,19 +48,20 @@ function TreeView({
47
48
  const inputRef = React.useRef(null);
48
49
  const [isPlaying, setIsPlaying] = React.useState(false);
49
50
  React.useEffect(() => {
50
- setContent(generateContent(editor.getEditorState()));
51
- return editor.registerUpdateListener(({
51
+ setContent(generateContent(editor.getEditorState(), editor._config, editor._compositionKey, editor._editable));
52
+ return utils.mergeRegister(editor.registerUpdateListener(({
52
53
  editorState
53
54
  }) => {
54
- const compositionKey = editor._compositionKey;
55
- const treeText = generateContent(editor.getEditorState());
56
- const compositionText = compositionKey !== null && `Composition key: ${compositionKey}`;
57
- setContent([treeText, compositionText].filter(Boolean).join('\n\n'));
55
+ const treeText = generateContent(editor.getEditorState(), editor._config, editor._compositionKey, editor._editable);
56
+ setContent(treeText);
58
57
 
59
58
  if (!timeTravelEnabled) {
60
59
  setTimeStampedEditorStates(currentEditorStates => [...currentEditorStates, [Date.now(), editorState]]);
61
60
  }
62
- });
61
+ }), editor.registerEditableListener(() => {
62
+ const treeText = generateContent(editor.getEditorState(), editor._config, editor._compositionKey, editor._editable);
63
+ setContent(treeText);
64
+ }));
63
65
  }, [timeTravelEnabled, editor]);
64
66
  const totalEditorStates = timeStampedEditorStates.length;
65
67
  React.useEffect(() => {
@@ -130,6 +132,10 @@ function TreeView({
130
132
  }, /*#__PURE__*/React.createElement("button", {
131
133
  className: timeTravelPanelButtonClassName,
132
134
  onClick: () => {
135
+ if (playingIndexRef.current === totalEditorStates - 1) {
136
+ playingIndexRef.current = 1;
137
+ }
138
+
133
139
  setIsPlaying(!isPlaying);
134
140
  },
135
141
  type: "button"
@@ -193,7 +199,7 @@ function printGridSelection(selection) {
193
199
  return `: grid\n └ { grid: ${selection.gridKey}, anchorCell: ${selection.anchor.key}, focusCell: ${selection.focus.key} }`;
194
200
  }
195
201
 
196
- function generateContent(editorState) {
202
+ function generateContent(editorState, editorConfig, compositionKey, editable) {
197
203
  let res = ' root\n';
198
204
  const selectionString = editorState.read(() => {
199
205
  const selection = lexical.$getSelection();
@@ -213,9 +219,18 @@ function generateContent(editorState) {
213
219
  typeDisplay
214
220
  });
215
221
  });
216
- return selection === null ? ': null' : lexical.$isRangeSelection(selection) ? printRangeSelection(selection) : lexical.$isGridSelection(selection) ? printGridSelection(selection) : printObjectSelection(selection);
222
+ return selection === null ? ': null' : lexical.$isRangeSelection(selection) ? printRangeSelection(selection) : lexical.DEPRECATED_$isGridSelection(selection) ? printGridSelection(selection) : printObjectSelection(selection);
217
223
  });
218
- return res + '\n selection' + selectionString;
224
+ res += '\n selection' + selectionString;
225
+ res += '\n\n editor:';
226
+ res += `\n └ namespace ${editorConfig.namespace}`;
227
+
228
+ if (compositionKey !== null) {
229
+ res += `\n └ compositionKey ${compositionKey}`;
230
+ }
231
+
232
+ res += `\n └ editable ${String(editable)}`;
233
+ return res;
219
234
  }
220
235
 
221
236
  function visitTree(currentNode, visitor, indent = []) {
@@ -237,7 +252,7 @@ function normalize(text) {
237
252
 
238
253
  function printNode(node) {
239
254
  if (lexical.$isTextNode(node)) {
240
- const text = node.getTextContent(true);
255
+ const text = node.getTextContent();
241
256
  const title = text.length === 0 ? '(empty)' : `"${normalize(text)}"`;
242
257
  const properties = printAllTextNodeProperties(node);
243
258
  return [title, properties.length !== 0 ? `{ ${properties} }` : null].filter(Boolean).join(' ').trim();
@@ -253,7 +268,7 @@ function printNode(node) {
253
268
 
254
269
  const FORMAT_PREDICATES = [node => node.hasFormat('bold') && 'Bold', node => node.hasFormat('code') && 'Code', node => node.hasFormat('italic') && 'Italic', node => node.hasFormat('strikethrough') && 'Strikethrough', node => node.hasFormat('subscript') && 'Subscript', node => node.hasFormat('superscript') && 'Superscript', node => node.hasFormat('underline') && 'Underline'];
255
270
  const DETAIL_PREDICATES = [node => node.isDirectionless() && 'Directionless', node => node.isUnmergeable() && 'Unmergeable'];
256
- const MODE_PREDICATES = [node => node.isToken() && 'Token', node => node.isSegmented() && 'Segmented', node => node.isInert() && 'Inert'];
271
+ const MODE_PREDICATES = [node => node.isToken() && 'Token', node => node.isSegmented() && 'Segmented'];
257
272
 
258
273
  function printAllTextNodeProperties(node) {
259
274
  return [printFormatProperties(node), printDetailProperties(node), printModeProperties(node)].filter(Boolean).join(', ');
@@ -353,7 +368,7 @@ function printSelectedCharsLine({
353
368
  function $getSelectionStartEnd(node, selection) {
354
369
  const anchor = selection.anchor;
355
370
  const focus = selection.focus;
356
- const textContent = node.getTextContent(true);
371
+ const textContent = node.getTextContent();
357
372
  const textLength = textContent.length;
358
373
  let start = -1;
359
374
  let end = -1; // Only one node is being selected.