@lexical/react 0.5.0 → 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.
- package/DEPRECATED_useLexicalDecorators.d.ts +2 -1
- package/DEPRECATED_useLexicalDecorators.dev.js +125 -10
- package/DEPRECATED_useLexicalDecorators.js.flow +8 -0
- package/DEPRECATED_useLexicalDecorators.prod.js +6 -2
- package/LexicalAutoEmbedPlugin.d.ts +3 -11
- package/LexicalAutoEmbedPlugin.dev.js +3 -18
- package/LexicalAutoEmbedPlugin.js.flow +3 -11
- package/LexicalAutoEmbedPlugin.prod.js +4 -5
- package/LexicalAutoLinkPlugin.dev.js +49 -46
- package/LexicalAutoLinkPlugin.prod.js +6 -6
- package/LexicalHorizontalRuleNode.dev.js +1 -1
- package/LexicalHorizontalRuleNode.prod.js +1 -1
- package/LexicalPlainTextPlugin.d.ts +3 -1
- package/LexicalPlainTextPlugin.dev.js +121 -5
- package/LexicalPlainTextPlugin.js.flow +3 -0
- package/LexicalPlainTextPlugin.prod.js +6 -4
- package/LexicalRichTextPlugin.d.ts +3 -1
- package/LexicalRichTextPlugin.dev.js +121 -5
- package/LexicalRichTextPlugin.js.flow +3 -0
- package/LexicalRichTextPlugin.prod.js +6 -4
- package/LexicalTreeView.dev.js +24 -9
- package/LexicalTreeView.prod.js +14 -13
- package/LexicalTypeaheadMenuPlugin.d.ts +20 -11
- package/LexicalTypeaheadMenuPlugin.dev.js +199 -59
- package/LexicalTypeaheadMenuPlugin.js.flow +19 -21
- package/LexicalTypeaheadMenuPlugin.prod.js +20 -16
- package/package.json +19 -19
- package/shared/ReactErrorBoundary.d.ts +63 -0
- package/shared/useDecorators.d.ts +8 -1
|
@@ -14,6 +14,103 @@ var reactDom = require('react-dom');
|
|
|
14
14
|
var dragon = require('@lexical/dragon');
|
|
15
15
|
var plainText = require('@lexical/plain-text');
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
19
|
+
*
|
|
20
|
+
* This source code is licensed under the MIT license found in the
|
|
21
|
+
* LICENSE file in the root directory of this source tree.
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
|
|
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();
|
|
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
|
+
}
|
|
111
|
+
|
|
112
|
+
}
|
|
113
|
+
|
|
17
114
|
/**
|
|
18
115
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
19
116
|
*
|
|
@@ -71,7 +168,14 @@ function useCanShowPlaceholder(editor) {
|
|
|
71
168
|
* LICENSE file in the root directory of this source tree.
|
|
72
169
|
*
|
|
73
170
|
*/
|
|
74
|
-
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)) {
|
|
75
179
|
const [decorators, setDecorators] = React.useState(() => editor.getDecorators()); // Subscribe to changes
|
|
76
180
|
|
|
77
181
|
useLayoutEffect(() => {
|
|
@@ -94,7 +198,11 @@ function useDecorators(editor) {
|
|
|
94
198
|
|
|
95
199
|
for (let i = 0; i < decoratorKeys.length; i++) {
|
|
96
200
|
const nodeKey = decoratorKeys[i];
|
|
97
|
-
const reactDecorator =
|
|
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]));
|
|
98
206
|
const element = editor.getElementByKey(nodeKey);
|
|
99
207
|
|
|
100
208
|
if (element !== null) {
|
|
@@ -103,7 +211,7 @@ function useDecorators(editor) {
|
|
|
103
211
|
}
|
|
104
212
|
|
|
105
213
|
return decoratedPortals;
|
|
106
|
-
}, [decorators, editor]);
|
|
214
|
+
}, [ErrorBoundary$1, decorators, editor]);
|
|
107
215
|
}
|
|
108
216
|
|
|
109
217
|
/**
|
|
@@ -129,11 +237,19 @@ function usePlainTextSetup(editor) {
|
|
|
129
237
|
*/
|
|
130
238
|
function PlainTextPlugin({
|
|
131
239
|
contentEditable,
|
|
132
|
-
placeholder
|
|
240
|
+
placeholder,
|
|
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)
|
|
133
249
|
}) {
|
|
134
250
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
135
251
|
const showPlaceholder = useCanShowPlaceholder(editor);
|
|
136
|
-
const decorators = useDecorators(editor);
|
|
252
|
+
const decorators = useDecorators(editor, ErrorBoundary$1);
|
|
137
253
|
usePlainTextSetup(editor);
|
|
138
254
|
return /*#__PURE__*/React.createElement(React.Fragment, null, contentEditable, showPlaceholder && placeholder, decorators);
|
|
139
255
|
}
|
|
@@ -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 =
|
|
@@ -18,4 +19,6 @@ type InitialEditorStateType =
|
|
|
18
19
|
declare export function PlainTextPlugin({
|
|
19
20
|
contentEditable: React$Node,
|
|
20
21
|
placeholder: React$Node,
|
|
22
|
+
// TODO 0.6 Make non-optional non-default
|
|
23
|
+
ErrorBoundary?: ErrorBoundaryType,
|
|
21
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
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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,7 +5,9 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
import { ErrorBoundaryType } from './shared/useDecorators';
|
|
9
|
+
export declare function RichTextPlugin({ contentEditable, placeholder, ErrorBoundary, }: Readonly<{
|
|
9
10
|
contentEditable: JSX.Element;
|
|
10
11
|
placeholder: JSX.Element | string;
|
|
12
|
+
ErrorBoundary?: ErrorBoundaryType;
|
|
11
13
|
}>): JSX.Element;
|
|
@@ -14,6 +14,103 @@ var reactDom = require('react-dom');
|
|
|
14
14
|
var dragon = require('@lexical/dragon');
|
|
15
15
|
var richText = require('@lexical/rich-text');
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
19
|
+
*
|
|
20
|
+
* This source code is licensed under the MIT license found in the
|
|
21
|
+
* LICENSE file in the root directory of this source tree.
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
|
|
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();
|
|
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
|
+
}
|
|
111
|
+
|
|
112
|
+
}
|
|
113
|
+
|
|
17
114
|
/**
|
|
18
115
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
19
116
|
*
|
|
@@ -71,7 +168,14 @@ function useCanShowPlaceholder(editor) {
|
|
|
71
168
|
* LICENSE file in the root directory of this source tree.
|
|
72
169
|
*
|
|
73
170
|
*/
|
|
74
|
-
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)) {
|
|
75
179
|
const [decorators, setDecorators] = React.useState(() => editor.getDecorators()); // Subscribe to changes
|
|
76
180
|
|
|
77
181
|
useLayoutEffect(() => {
|
|
@@ -94,7 +198,11 @@ function useDecorators(editor) {
|
|
|
94
198
|
|
|
95
199
|
for (let i = 0; i < decoratorKeys.length; i++) {
|
|
96
200
|
const nodeKey = decoratorKeys[i];
|
|
97
|
-
const reactDecorator =
|
|
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]));
|
|
98
206
|
const element = editor.getElementByKey(nodeKey);
|
|
99
207
|
|
|
100
208
|
if (element !== null) {
|
|
@@ -103,7 +211,7 @@ function useDecorators(editor) {
|
|
|
103
211
|
}
|
|
104
212
|
|
|
105
213
|
return decoratedPortals;
|
|
106
|
-
}, [decorators, editor]);
|
|
214
|
+
}, [ErrorBoundary$1, decorators, editor]);
|
|
107
215
|
}
|
|
108
216
|
|
|
109
217
|
/**
|
|
@@ -129,11 +237,19 @@ function useRichTextSetup(editor) {
|
|
|
129
237
|
*/
|
|
130
238
|
function RichTextPlugin({
|
|
131
239
|
contentEditable,
|
|
132
|
-
placeholder
|
|
240
|
+
placeholder,
|
|
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)
|
|
133
249
|
}) {
|
|
134
250
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
135
251
|
const showPlaceholder = useCanShowPlaceholder(editor);
|
|
136
|
-
const decorators = useDecorators(editor);
|
|
252
|
+
const decorators = useDecorators(editor, ErrorBoundary$1);
|
|
137
253
|
useRichTextSetup(editor);
|
|
138
254
|
return /*#__PURE__*/React.createElement(React.Fragment, null, contentEditable, showPlaceholder && placeholder, decorators);
|
|
139
255
|
}
|
|
@@ -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 =
|
|
@@ -18,4 +19,6 @@ type InitialEditorStateType =
|
|
|
18
19
|
declare export function RichTextPlugin({
|
|
19
20
|
contentEditable: React$Node,
|
|
20
21
|
placeholder: React$Node,
|
|
22
|
+
// TODO 0.6 Make non-optional non-default
|
|
23
|
+
ErrorBoundary?: ErrorBoundaryType,
|
|
21
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
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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)}
|
package/LexicalTreeView.dev.js
CHANGED
|
@@ -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
|
|
55
|
-
|
|
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();
|
|
@@ -215,7 +221,16 @@ function generateContent(editorState) {
|
|
|
215
221
|
});
|
|
216
222
|
return selection === null ? ': null' : lexical.$isRangeSelection(selection) ? printRangeSelection(selection) : lexical.DEPRECATED_$isGridSelection(selection) ? printGridSelection(selection) : printObjectSelection(selection);
|
|
217
223
|
});
|
|
218
|
-
|
|
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 = []) {
|
package/LexicalTreeView.prod.js
CHANGED
|
@@ -4,17 +4,18 @@
|
|
|
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
|
|
8
|
-
function H(a){let
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
`: node\n \u2514 [${Array.from(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
function
|
|
15
|
-
|
|
7
|
+
'use strict';var k=require("@lexical/link"),r=require("@lexical/mark"),v=require("@lexical/utils"),C=require("lexical"),D=require("react");let E=Object.freeze({"\t":"\\t","\n":"\\n"}),F=new RegExp(Object.keys(E).join("|"),"g"),G=Object.freeze({ancestorHasNextSibling:"|",ancestorIsLastChild:" ",hasNextSibling:"\u251c",isLastChild:"\u2514",selectedChar:"^",selectedLine:">"});
|
|
8
|
+
function H(a){let c="",e=K(a),l=a.anchor;a=a.focus;let f=l.offset,b=a.offset;c=c+`: range ${""!==e?`{ ${e} }`:""}`+`\n \u251c anchor { key: ${l.key}, offset: ${null===f?"null":f}, type: ${l.type} }`;return c+=`\n \u2514 focus { key: ${a.key}, offset: ${null===b?"null":b}, type: ${a.type} }`}
|
|
9
|
+
function L(a,c,e,l){let f=" root\n";a=a.read(()=>{const b=C.$getSelection();M(C.$getRoot(),(d,n)=>{const x=`(${d.getKey()})`,t=d.getType()||"",q=d.isSelected(),z=r.$isMarkNode(d)?` id: [ ${d.getIDs().join(", ")} ] `:"";var m=f,w=q?G.selectedLine:" ",A=n.join(" ");if(C.$isTextNode(d)){var h=d.getTextContent();var p=0===h.length?"(empty)":`"${N(h)}"`;h=[K(d),O(d),P(d)].filter(Boolean).join(", ");h=[p,0!==h.length?`{ ${h} }`:null].filter(Boolean).join(" ").trim()}else if(k.$isLinkNode(d)){h=d.getURL();
|
|
10
|
+
h=0===h.length?"(empty)":`"${N(h)}"`;p=d.getTarget();null!=p&&(p="target: "+p);var y=Boolean;let g=d.getRel();null!=g&&(g="rel: "+g);p=[p,g].filter(y).join(", ");h=[h,0!==p.length?`{ ${p} }`:null].filter(Boolean).join(" ").trim()}else h="";f=m+`${w} ${A} ${x} ${t} ${z} ${h}\n`;f+=Q({indent:n,isSelected:q,node:d,nodeKeyDisplay:x,selection:b,typeDisplay:t})});return null===b?": null":C.$isRangeSelection(b)?H(b):C.DEPRECATED_$isGridSelection(b)?`: grid\n \u2514 { grid: ${b.gridKey}, anchorCell: ${b.anchor.key}, focusCell: ${b.focus.key} }`:
|
|
11
|
+
`: node\n \u2514 [${Array.from(b._nodes).join(", ")}]`});f+="\n selection"+a;f+="\n\n editor:";f+=`\n \u2514 namespace ${c.namespace}`;null!==e&&(f+=`\n \u2514 compositionKey ${e}`);return f+=`\n \u2514 editable ${String(l)}`}function M(a,c,e=[]){a=a.getChildren();let l=a.length;a.forEach((f,b)=>{c(f,e.concat(b===l-1?G.isLastChild:G.hasNextSibling));C.$isElementNode(f)&&M(f,c,e.concat(b===l-1?G.ancestorIsLastChild:G.ancestorHasNextSibling))})}
|
|
12
|
+
function N(a){return Object.entries(E).reduce((c,[e,l])=>c.replace(new RegExp(e,"g"),String(l)),a)}
|
|
13
|
+
let R=[a=>a.hasFormat("bold")&&"Bold",a=>a.hasFormat("code")&&"Code",a=>a.hasFormat("italic")&&"Italic",a=>a.hasFormat("strikethrough")&&"Strikethrough",a=>a.hasFormat("subscript")&&"Subscript",a=>a.hasFormat("superscript")&&"Superscript",a=>a.hasFormat("underline")&&"Underline"],S=[a=>a.isDirectionless()&&"Directionless",a=>a.isUnmergeable()&&"Unmergeable"],T=[a=>a.isToken()&&"Token",a=>a.isSegmented()&&"Segmented"];
|
|
14
|
+
function O(a){let c=S.map(e=>e(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==c&&(c="detail: "+c);return c}function P(a){let c=T.map(e=>e(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==c&&(c="mode: "+c);return c}function K(a){let c=R.map(e=>e(a)).filter(Boolean).join(", ").toLocaleLowerCase();""!==c&&(c="format: "+c);return c}
|
|
15
|
+
function Q({indent:a,isSelected:c,node:e,nodeKeyDisplay:l,selection:f,typeDisplay:b}){if(!C.$isTextNode(e)||!C.$isRangeSelection(f)||!c||C.$isElementNode(e))return"";c=f.anchor;var d=f.focus;if(""===e.getTextContent()||c.getNode()===f.focus.getNode()&&c.offset===d.offset)return"";d=f.anchor;let n=f.focus,x=e.getTextContent(),t=x.length;c=f=-1;if("text"===d.type&&"text"===n.type){let m=d.getNode(),w=n.getNode();m===w&&e===m&&d.offset!==n.offset?[f,c]=d.offset<n.offset?[d.offset,n.offset]:[n.offset,
|
|
16
|
+
d.offset]:e===m?[f,c]=m.isBefore(w)?[d.offset,t]:[0,d.offset]:e===w?[f,c]=w.isBefore(m)?[n.offset,t]:[0,n.offset]:[f,c]=[0,t]}e=(x.slice(0,f).match(F)||[]).length;d=(x.slice(f,c).match(F)||[]).length;let [q,z]=[f+e,c+e+d];if(q===z)return"";e=a[a.length-1]===G.hasNextSibling?G.ancestorHasNextSibling:G.ancestorIsLastChild;a=[...a.slice(0,a.length-1),e];e=Array(q+1).fill(" ");f=Array(z-q).fill(G.selectedChar);l=Array(l.length+(b.length+3)).fill(" ");return[G.selectedLine,a.join(" "),[...l,...e,...f].join("")].join(" ")+
|
|
16
17
|
"\n"}
|
|
17
|
-
exports.TreeView=function({timeTravelButtonClassName:a,timeTravelPanelSliderClassName:
|
|
18
|
-
n(B=>[...B,[Date.now(),
|
|
19
|
-
{let
|
|
20
|
-
{
|
|
18
|
+
exports.TreeView=function({timeTravelButtonClassName:a,timeTravelPanelSliderClassName:c,timeTravelPanelButtonClassName:e,viewClassName:l,timeTravelPanelClassName:f,editor:b}){let [d,n]=D.useState([]),[x,t]=D.useState(""),[q,z]=D.useState(!1),m=D.useRef(0),w=D.useRef(null),A=D.useRef(null),[h,p]=D.useState(!1);D.useEffect(()=>{t(L(b.getEditorState(),b._config,b._compositionKey,b._editable));return v.mergeRegister(b.registerUpdateListener(({editorState:g})=>{let u=L(b.getEditorState(),b._config,b._compositionKey,
|
|
19
|
+
b._editable);t(u);q||n(B=>[...B,[Date.now(),g]])}),b.registerEditableListener(()=>{let g=L(b.getEditorState(),b._config,b._compositionKey,b._editable);t(g)}))},[q,b]);let y=d.length;D.useEffect(()=>{if(h){let g,u=()=>{const B=m.current;B===y-1?p(!1):g=setTimeout(()=>{m.current++;const I=m.current,J=A.current;null!==J&&(J.value=String(I));b.setEditorState(d[I][1]);u()},d[B+1][0]-d[B][0])};u();return()=>{clearTimeout(g)}}},[d,h,b,y]);D.useEffect(()=>{let g=w.current;if(null!==g)return g.__lexicalEditor=
|
|
20
|
+
b,()=>{g.__lexicalEditor=null}},[b]);return D.createElement("div",{className:l},!q&&2<y&&D.createElement("button",{onClick:()=>{let g=b.getRootElement();null!==g&&(g.contentEditable="false",m.current=y-1,z(!0))},className:a,type:"button"},"Time Travel"),D.createElement("pre",{ref:w},x),q&&D.createElement("div",{className:f},D.createElement("button",{className:e,onClick:()=>{m.current===y-1&&(m.current=1);p(!h)},type:"button"},h?"Pause":"Play"),D.createElement("input",{className:c,ref:A,onChange:g=>
|
|
21
|
+
{g=Number(g.target.value);let u=d[g];u&&(m.current=g,b.setEditorState(u[1]))},type:"range",min:"1",max:y-1}),D.createElement("button",{className:e,onClick:()=>{var g=b.getRootElement();if(null!==g){g.contentEditable="true";g=d.length-1;b.setEditorState(d[g][1]);let u=A.current;null!==u&&(u.value=String(g));z(!1);p(!1)}},type:"button"},"Exit")))}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
import { LexicalEditor, NodeKey, TextNode } from 'lexical';
|
|
8
|
+
import { LexicalCommand, LexicalEditor, NodeKey, TextNode } from 'lexical';
|
|
9
9
|
import { MutableRefObject, ReactPortal } from 'react';
|
|
10
10
|
export declare type QueryMatch = {
|
|
11
11
|
leadOffset: number;
|
|
@@ -14,8 +14,7 @@ export declare type QueryMatch = {
|
|
|
14
14
|
};
|
|
15
15
|
export declare type Resolution = {
|
|
16
16
|
match: QueryMatch;
|
|
17
|
-
|
|
18
|
-
getRect: () => ClientRect;
|
|
17
|
+
getRect: () => DOMRect;
|
|
19
18
|
};
|
|
20
19
|
export declare const PUNCTUATION = "\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%'\"~=<>_:;";
|
|
21
20
|
export declare class TypeaheadOption {
|
|
@@ -24,32 +23,42 @@ export declare class TypeaheadOption {
|
|
|
24
23
|
constructor(key: string);
|
|
25
24
|
setRefElement(element: HTMLElement | null): void;
|
|
26
25
|
}
|
|
27
|
-
export declare type MenuRenderFn<TOption extends TypeaheadOption> = (
|
|
26
|
+
export declare type MenuRenderFn<TOption extends TypeaheadOption> = (anchorElementRef: MutableRefObject<HTMLElement | null>, itemProps: {
|
|
28
27
|
selectedIndex: number | null;
|
|
29
28
|
selectOptionAndCleanUp: (option: TOption) => void;
|
|
30
29
|
setHighlightedIndex: (index: number) => void;
|
|
30
|
+
options: Array<TOption>;
|
|
31
31
|
}, matchingString: string) => ReactPortal | JSX.Element | null;
|
|
32
|
+
export declare function getScrollParent(element: HTMLElement, includeHidden: boolean): HTMLElement | HTMLBodyElement;
|
|
33
|
+
export declare function useDynamicPositioning(resolution: Resolution | null, targetElement: HTMLElement | null, onReposition: () => void, onVisibilityChange?: (isInView: boolean) => void): void;
|
|
34
|
+
export declare const SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND: LexicalCommand<{
|
|
35
|
+
index: number;
|
|
36
|
+
option: TypeaheadOption;
|
|
37
|
+
}>;
|
|
32
38
|
export declare function useBasicTypeaheadTriggerMatch(trigger: string, { minLength, maxLength }: {
|
|
33
39
|
minLength?: number;
|
|
34
40
|
maxLength?: number;
|
|
35
41
|
}): TriggerFn;
|
|
36
|
-
export declare type
|
|
42
|
+
export declare type TypeaheadMenuPluginProps<TOption extends TypeaheadOption> = {
|
|
37
43
|
onQueryChange: (matchingString: string | null) => void;
|
|
38
44
|
onSelectOption: (option: TOption, textNodeContainingQuery: TextNode | null, closeMenu: () => void, matchingString: string) => void;
|
|
39
45
|
options: Array<TOption>;
|
|
40
46
|
menuRenderFn: MenuRenderFn<TOption>;
|
|
41
47
|
triggerFn: TriggerFn;
|
|
42
|
-
|
|
48
|
+
onOpen?: (resolution: Resolution) => void;
|
|
49
|
+
onClose?: () => void;
|
|
50
|
+
anchorClassName?: string;
|
|
43
51
|
};
|
|
44
52
|
export declare type TriggerFn = (text: string, editor: LexicalEditor) => QueryMatch | null;
|
|
45
|
-
export declare function LexicalTypeaheadMenuPlugin<TOption extends TypeaheadOption>({ options, onQueryChange, onSelectOption, menuRenderFn, triggerFn,
|
|
46
|
-
declare type
|
|
53
|
+
export declare function LexicalTypeaheadMenuPlugin<TOption extends TypeaheadOption>({ options, onQueryChange, onSelectOption, onOpen, onClose, menuRenderFn, triggerFn, anchorClassName, }: TypeaheadMenuPluginProps<TOption>): JSX.Element | null;
|
|
54
|
+
declare type NodeMenuPluginProps<TOption extends TypeaheadOption> = {
|
|
47
55
|
onSelectOption: (option: TOption, textNodeContainingQuery: TextNode | null, closeMenu: () => void, matchingString: string) => void;
|
|
48
56
|
options: Array<TOption>;
|
|
49
57
|
nodeKey: NodeKey | null;
|
|
50
|
-
onClose
|
|
51
|
-
|
|
58
|
+
onClose?: () => void;
|
|
59
|
+
onOpen?: (resolution: Resolution) => void;
|
|
52
60
|
menuRenderFn: MenuRenderFn<TOption>;
|
|
61
|
+
anchorClassName?: string;
|
|
53
62
|
};
|
|
54
|
-
export declare function LexicalNodeMenuPlugin<TOption extends TypeaheadOption>({ options, nodeKey,
|
|
63
|
+
export declare function LexicalNodeMenuPlugin<TOption extends TypeaheadOption>({ options, nodeKey, onClose, onOpen, onSelectOption, menuRenderFn, anchorClassName, }: NodeMenuPluginProps<TOption>): JSX.Element | null;
|
|
55
64
|
export {};
|