/
Editor.tsx
94 lines (83 loc) · 2.54 KB
/
Editor.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Styled, { JssInjectedProps } from 'rsg-components/Styled';
import SimpleEditor from 'react-simple-code-editor';
import { highlight as prismHighlight, languages } from 'prismjs';
import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-markup';
import 'prismjs/components/prism-javascript';
import { Styles } from 'jss';
import 'prismjs/components/prism-jsx';
import { space } from '../../styles/theme';
import prismTheme from '../../styles/prismTheme';
import * as Rsg from '../../../typings';
const highlight = (code: string) => prismHighlight(code, languages.jsx, 'jsx');
const styles = ({ fontFamily, fontSize, color, borderRadius }: Rsg.Theme): Styles => ({
root: {
fontFamily: fontFamily.monospace,
fontSize: fontSize.small,
background: color.codeBackground,
borderRadius,
'& textarea': {
isolate: false,
transition: 'all ease-in-out .1s',
// important to override inline styles in react-simple-code-editor
border: `1px ${color.border} solid !important`,
borderRadius,
},
'& textarea:focus': {
isolate: false,
outline: 0,
borderColor: `${color.link} !important`,
boxShadow: [[0, 0, 0, 2, color.focus]],
},
...prismTheme({ color }),
},
});
export interface EditorProps extends JssInjectedProps {
code: string;
onChange: (code: string) => void;
}
interface EditorState {
code: string;
prevCode: string;
}
export class Editor extends Component<EditorProps> {
public static propTypes = {
code: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
classes: PropTypes.objectOf(PropTypes.string.isRequired).isRequired,
};
public state = { code: this.props.code, prevCode: this.props.code };
public static getDerivedStateFromProps(nextProps: EditorProps, prevState: EditorState) {
const { code } = nextProps;
if (prevState.prevCode !== code) {
return {
prevCode: code,
code,
};
}
return null;
}
public shouldComponentUpdate(nextProps: EditorProps, nextState: EditorState) {
return nextState.code !== this.state.code;
}
private handleChange = (code: string) => {
this.setState({ code });
this.props.onChange(code);
};
public render() {
return (
<SimpleEditor
className={this.props.classes.root}
value={this.state.code}
onValueChange={this.handleChange}
highlight={highlight}
// Padding should be passed via a prop (not CSS) for a proper
// cursor position calculation
padding={space[2]}
/>
);
}
}
export default Styled<EditorProps>(styles)(Editor);