-
-
Notifications
You must be signed in to change notification settings - Fork 24
/
index.tsx
107 lines (100 loc) · 2.91 KB
/
index.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
95
96
97
98
99
100
101
102
103
104
105
106
107
import React, { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
import { processHtml, htmlEncode } from './utils';
import shortcuts from './shortcuts';
import * as styles from './styles';
import './style/index.less';
export * from './SelectionText';
export interface TextareaCodeEditorProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
prefixCls?: string;
/**
* Set what programming language the code belongs to.
*/
language?: string;
/**
* Optional padding for code. Default: `10`.
*/
padding?: number;
/**
* The minimum height of the editor. Default: `16`.
*/
minHeight?: number;
onKeyDown?: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void | boolean;
}
export default React.forwardRef<HTMLTextAreaElement, TextareaCodeEditorProps>((props, ref) => {
const {
prefixCls = 'w-tc-editor',
value: _,
padding = 10,
minHeight = 16,
placeholder,
language,
className,
style,
onChange,
...other
} = props;
const [value, setValue] = useState(props.value || '');
useEffect(() => setValue(props.value || ''), [props.value]);
const textRef = useRef<HTMLTextAreaElement>(null);
useImperativeHandle<HTMLTextAreaElement, HTMLTextAreaElement>(ref, () => textRef.current!);
const contentStyle = {
paddingTop: padding,
paddingRight: padding,
paddingBottom: padding,
paddingLeft: padding,
};
const htmlStr = useMemo(
() =>
processHtml(
`<pre aria-hidden=true><code ${language ? `class="language-${language}"` : ''} >${htmlEncode(
String(value || ''),
)}</code><br /></pre>`,
),
[value, language],
);
const preView = useMemo(
() => (
<div
style={{ ...styles.editor, ...contentStyle, minHeight }}
className={`${prefixCls}-preview ${language ? `language-${language}` : ''}`}
dangerouslySetInnerHTML={{
__html: htmlStr,
}}
/>
),
// eslint-disable-next-line react-hooks/exhaustive-deps
[prefixCls, language, htmlStr],
);
return (
<div style={{ ...styles.container, ...style }} className={`${prefixCls} ${className || ''}`}>
<textarea
autoComplete="off"
autoCorrect="off"
spellCheck="false"
autoCapitalize="off"
{...other}
placeholder={placeholder}
onKeyDown={(evn) => {
if (!other.onKeyDown || other.onKeyDown(evn) !== false) {
shortcuts(evn);
}
}}
style={{
...styles.editor,
...styles.textarea,
...contentStyle,
minHeight,
...(placeholder && !value ? { WebkitTextFillColor: 'inherit' } : {}),
}}
ref={textRef}
onChange={(evn) => {
setValue(evn.target.value);
onChange && onChange(evn);
}}
className={`${prefixCls}-text`}
value={value}
/>
{preView}
</div>
);
});