Skip to content

Commit c3f8d11

Browse files
committed
chore(deps): update dependency @uiw/react-codemirror to v4
1 parent 6325652 commit c3f8d11

File tree

6 files changed

+62
-71
lines changed

6 files changed

+62
-71
lines changed

README.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,6 @@ interface CodePreviewProps extends SplitProps {
6161
* To specify a CSS class, use the className attribute.
6262
*/
6363
className?: string;
64-
/**
65-
* string|object. The mode to use. When not given, this will default to the first mode that was loaded.
66-
* It may be a string, which either simply names the mode or is a MIME type associated with the mode.
67-
* Alternatively, it may be an object containing configuration options for the mode,
68-
* with a name property that names the mode (for example `{name: "javascript", json: true}` ).
69-
*/
70-
language?: string | { name: string, json: boolean };
7164
/**
7265
* Whether to display the border.
7366
*/
@@ -99,7 +92,7 @@ interface CodePreviewProps extends SplitProps {
9992
/**
10093
* Modify ReactCodemirror props.
10194
*/
102-
editProps?: IReactCodemirror;
95+
editProps?: ReactCodeMirrorProps;
10396
/**
10497
* Dependent component
10598
*/

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@
6868
"@babel/runtime": "7.15.3",
6969
"@babel/standalone": "7.12.18",
7070
"@uiw/copy-to-clipboard": "1.0.12",
71-
"@uiw/react-codemirror": "3.2.1",
71+
"@uiw/react-codemirror": "4.0.0-rc.10",
72+
"@codemirror/lang-javascript": "0.19.1",
7273
"@uiw/react-split": "5.8.1",
7374
"@uiw/react-codesandbox": "1.1.0",
7475
"@uiw/react-codepen": "1.0.1",

src/ErrorMessage.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { useMemo } from "react";
2+
3+
interface ErrorMessageProps {
4+
message?: string;
5+
}
6+
7+
export function ErrorMessage(props: ErrorMessageProps) {
8+
const { message } = props;
9+
return useMemo(() => {
10+
if (!message) return null;
11+
return (
12+
<pre>
13+
<code>{message}</code>
14+
</pre>
15+
)
16+
}, [message]);
17+
}

src/index.less

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
right: 0 !important;
2727
height: 100% !important;
2828
max-height: 100% !important;
29-
z-index: 99;
29+
z-index: 99999;
3030
}
3131
&-demo-source {
3232
input {

src/index.tsx

Lines changed: 36 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import React from 'react';
22
import ReactDOM from 'react-dom';
3-
import CodeMirror, { IReactCodemirror } from '@uiw/react-codemirror';
3+
import CodeMirror, { ReactCodeMirrorProps, ReactCodeMirrorRef, ViewUpdate } from '@uiw/react-codemirror';
44
import copyTextToClipboard from '@uiw/copy-to-clipboard';
5+
import { javascript } from '@codemirror/lang-javascript';
56
import { CodeSandboxProps } from '@uiw/react-codesandbox';
67
import { CodepenProps } from '@uiw/react-codepen';
78
import Split, { SplitProps } from '@uiw/react-split';
89
import ThirdPartyButton from './ThirdPartyButton';
910
import * as icon from './icon';
1011
import { BabelTransform } from './transform';
12+
import { ErrorMessage } from './ErrorMessage';
1113
import './monokai.css';
1214
import './index.less';
1315

@@ -18,13 +20,6 @@ export interface CodePreviewProps extends SplitProps {
1820
* To specify a CSS class, use the className attribute.
1921
*/
2022
className?: string;
21-
/**
22-
* string|object. The mode to use. When not given, this will default to the first mode that was loaded.
23-
* It may be a string, which either simply names the mode or is a MIME type associated with the mode.
24-
* Alternatively, it may be an object containing configuration options for the mode,
25-
* with a name property that names the mode (for example `{name: "javascript", json: true}` ).
26-
*/
27-
language?: string | { name: string, json: boolean };
2823
/**
2924
* Whether to display the border.
3025
*/
@@ -56,7 +51,7 @@ export interface CodePreviewProps extends SplitProps {
5651
/**
5752
* Modify ReactCodemirror props.
5853
*/
59-
editProps?: IReactCodemirror;
54+
editProps?: ReactCodeMirrorProps;
6055
/**
6156
* Dependent component
6257
*/
@@ -75,24 +70,21 @@ export interface CodePreviewProps extends SplitProps {
7570
btnHideText?: string;
7671
}
7772

78-
export interface ICodePreviewState {
73+
export interface CodePreviewState {
7974
errorMessage: string;
8075
fullScreen: boolean;
8176
width: number | string;
8277
copied: boolean;
8378
showEdit: boolean;
8479
}
8580

86-
export default class CodePreview extends React.PureComponent<CodePreviewProps, ICodePreviewState> {
81+
export default class CodePreview extends React.PureComponent<CodePreviewProps, CodePreviewState> {
8782
public demoDom = React.createRef<HTMLDivElement>();
88-
// @ts-ignore
89-
public editor = React.createRef<CodeMirror>();
90-
public language: string = '';
83+
public editor = React.createRef<ReactCodeMirrorRef>();
9184
public initHeight: number = 3;
9285
public playerId: string = `${parseInt(String(Math.random() * 1e9), 10).toString(36)}`;
9386
public static defaultProps: CodePreviewProps = {
9487
prefixCls: 'w-code-preview',
95-
language: 'jsx',
9688
code: '',
9789
btnText: 'Code',
9890
btnHideText: 'Hide Editor',
@@ -104,36 +96,32 @@ export default class CodePreview extends React.PureComponent<CodePreviewProps, I
10496
noPreview: false,
10597
bordered: true,
10698
}
107-
public state: ICodePreviewState = {
108-
errorMessage: '',
109-
fullScreen: false,
110-
copied: false,
111-
showEdit: false,
112-
width: 1,
99+
constructor(props: CodePreviewProps) {
100+
super(props);
101+
this.state = {
102+
errorMessage: '',
103+
fullScreen: false,
104+
copied: false,
105+
showEdit: false,
106+
width: 1,
107+
}
113108
}
114109
componentDidMount() {
115-
const { language } = this.props;
116-
this.language = typeof language === 'string' ? language : (language ? (language.name || ''): '');
117110
if (!this.props.noPreview) {
118111
this.executeCode(this.props.code!);
119112
}
120-
window.addEventListener("popstate", function(e) {
113+
window.addEventListener("popstate", (e) => {
121114
document.body.style.overflow = 'inherit';
122115
}, false);
123116
}
124117
componentDidUpdate(prevProps: CodePreviewProps) {
125-
const { language } = this.props;
126-
this.language = typeof language === 'string' ? language : (language ? (language.name || ''): '');
127118
if (prevProps.noPreview !== this.props.noPreview) {
128-
this.executeCode(this.props.code!);
119+
this.executeCode(prevProps.code!);
129120
}
130121
}
131122
async executeCode(codeStr: string) {
132123
const { dependencies = {} } = this.props;
133-
const { React: _React, ReactDOM: _ReactDOM, ...otherDeps } = dependencies
134-
if (!/(jsx|js)/.test(this.language)) {
135-
return;
136-
}
124+
const { React: _React, ReactDOM: _ReactDOM, ...otherDeps } = dependencies;
137125
try {
138126
const deps = {
139127
context: this,
@@ -153,11 +141,11 @@ export default class CodePreview extends React.PureComponent<CodePreviewProps, I
153141
const input = `${codeStr}`;
154142
const { code } = BabelTransform(input);
155143
args.push(code || '');
144+
// console.log('code:', argv)
156145
// eslint-disable-next-line no-new-func
157146
new Function(...args).apply(null, argv);
158147
this.setState({ errorMessage: '' });
159-
160-
} catch (err) {
148+
} catch (err: any) {
161149
let message = '';
162150
if (err && err.message) {
163151
message = err.message;
@@ -197,6 +185,13 @@ export default class CodePreview extends React.PureComponent<CodePreviewProps, I
197185
this.initHeight = demo.clientHeight;
198186
}
199187
}
188+
handleChange(value: string, viewUpdate: ViewUpdate) {
189+
const { editProps } = this.props;
190+
this.executeCode(value);
191+
if (editProps && editProps.onChange) {
192+
editProps.onChange(value, viewUpdate);
193+
}
194+
}
200195
/**
201196
* onSwitchSource
202197
*/
@@ -206,14 +201,10 @@ export default class CodePreview extends React.PureComponent<CodePreviewProps, I
206201
this.setState({
207202
width: width === 1 ? '50%' : 1,
208203
showEdit: true,
209-
}, () => {
210-
if (this.editor && this.editor.current && this.editor.current.editor) {
211-
this.editor.current.editor.setSize('100%', width !== 1 ? this.initHeight : '100%');
212-
}
213204
});
214205
}
215206
public render() {
216-
const { style, prefixCls, language, className, editProps, codePenOption, codeSandboxOption, code, dependencies, btnText, btnHideText, onlyEdit, bordered, noCode, noPreview, noScroll, bgWhite, ...otherProps } = this.props;
207+
const { style, prefixCls, className, editProps, codePenOption, codeSandboxOption, code, dependencies, btnText, btnHideText, onlyEdit, bordered, noCode, noPreview, noScroll, bgWhite, ...otherProps } = this.props;
217208
const isOneItem = (!noCode && !noPreview) ? false : (!noCode || !noPreview);
218209
let visiable = this.state.width === 1 ? false : [isOneItem ? 1 : 2];
219210
return (
@@ -242,31 +233,21 @@ export default class CodePreview extends React.PureComponent<CodePreviewProps, I
242233
...(this.state.width === 1 ? { width: '100%'} : {})
243234
}}
244235
>
245-
{this.state.errorMessage && (
246-
<pre>
247-
<code>{this.state.errorMessage}</code>
248-
</pre>
249-
)}
236+
<ErrorMessage message={this.state.errorMessage} />
250237
<div className={[`${prefixCls}-demo-source`, this.state.errorMessage ? 'error' : null].filter(Boolean).join(' ').trim()} id={this.playerId} />
251238
</div>
252239
)}
253240
{(!noCode || onlyEdit) && (
254-
<div style={{ overflow: 'hidden', width: onlyEdit ? '100%' : this.state.width, }}>
241+
<div style={{ overflow: 'hidden', width: onlyEdit ? '100%' : this.state.width }}>
255242
{(this.state.showEdit || onlyEdit) && (
256243
<CodeMirror
257-
value={(code || '').replace(/\n$/, '')}
244+
value={(this.props.code || '').replace(/\n$/, '')}
258245
ref={this.editor}
259-
options={{
260-
theme: 'monokai',
261-
mode: language,
262-
}}
246+
extensions={[javascript({ jsx: true })]}
263247
{...editProps}
264-
onChange={(editor, change) => {
265-
this.executeCode(editor.getValue());
266-
if (editProps && editProps.onChange) {
267-
editProps.onChange(editor, change)
268-
}
269-
}}
248+
style={{ height: '100%' }}
249+
height="100%"
250+
onChange={this.handleChange.bind(this)}
270251
/>
271252
)}
272253
</div>

website/Example.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ReactDOM.render(
1919
);`;
2020

2121
const Example = () => {
22-
const [code, setCode] = useState(defaultCode);
22+
const [code] = useState(defaultCode);
2323
const [state, setState] = useState({
2424
bgWhite: false,
2525
noCode: false,
@@ -94,29 +94,28 @@ const Example = () => {
9494
return (
9595
<Fragment>
9696
<CodePreview
97-
code={code}
97+
code={defaultCode}
9898
dependencies={{ ...UIW }}
9999
bordered={state.bordered}
100100
noScroll={state.noScroll}
101101
bgWhite={state.bgWhite}
102102
noCode={state.noCode}
103103
editProps={{
104-
onChange: (editor) => {
105-
setCode(editor.getValue())
104+
onChange: (value) => {
106105
setState({
107106
...state,
108107
codeSandbox: {
109108
...state.codeSandbox,
110109
files: {
111110
...state.codeSandbox.files,
112111
"src/index.js": {
113-
content: editor.getValue()
112+
content: value
114113
},
115114
}
116115
},
117116
codePen: {
118117
...state.codePen,
119-
js: editor.getValue()
118+
js: value
120119
}
121120
})
122121
}

0 commit comments

Comments
 (0)