@uiw/react-md-editor 4.0.10 → 4.1.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 (64) hide show
  1. package/README.md +39 -4
  2. package/common.d.ts +17 -0
  3. package/dist/mdeditor.css +105 -110
  4. package/dist/mdeditor.js +7122 -9557
  5. package/dist/mdeditor.min.css +1 -1
  6. package/dist/mdeditor.min.js +1 -1
  7. package/dist/mdeditor.min.js.LICENSE.txt +2 -2
  8. package/esm/Editor.common.d.ts +5 -0
  9. package/esm/Editor.common.js +7 -0
  10. package/esm/Editor.d.ts +4 -11
  11. package/esm/Editor.factory.d.ts +14 -0
  12. package/esm/Editor.factory.js +270 -0
  13. package/esm/Editor.js +5 -261
  14. package/esm/Editor.nohighlight.d.ts +4 -11
  15. package/esm/Editor.nohighlight.js +5 -261
  16. package/esm/components/TextArea/Markdown.common.d.ts +5 -0
  17. package/esm/components/TextArea/Markdown.common.js +59 -0
  18. package/esm/components/TextArea/factory.d.ts +33 -0
  19. package/esm/components/TextArea/factory.js +105 -0
  20. package/esm/components/TextArea/index.common.d.ts +3 -0
  21. package/esm/components/TextArea/index.common.js +6 -0
  22. package/esm/components/TextArea/index.d.ts +3 -27
  23. package/esm/components/TextArea/index.js +5 -100
  24. package/esm/components/TextArea/index.nohighlight.d.ts +3 -27
  25. package/esm/components/TextArea/index.nohighlight.js +2 -93
  26. package/esm/index.common.d.ts +16 -0
  27. package/esm/index.common.js +16 -0
  28. package/esm/index.css +0 -1
  29. package/esm/react-markdown-preview.common.d.ts +4 -0
  30. package/lib/Editor.common.d.ts +5 -0
  31. package/lib/Editor.common.js +15 -0
  32. package/lib/Editor.d.ts +4 -11
  33. package/lib/Editor.factory.d.ts +14 -0
  34. package/lib/Editor.factory.js +333 -0
  35. package/lib/Editor.js +4 -318
  36. package/lib/Editor.nohighlight.d.ts +4 -11
  37. package/lib/Editor.nohighlight.js +4 -318
  38. package/lib/components/TextArea/Markdown.common.d.ts +5 -0
  39. package/lib/components/TextArea/Markdown.common.js +68 -0
  40. package/lib/components/TextArea/factory.d.ts +33 -0
  41. package/lib/components/TextArea/factory.js +109 -0
  42. package/lib/components/TextArea/index.common.d.ts +3 -0
  43. package/lib/components/TextArea/index.common.js +14 -0
  44. package/lib/components/TextArea/index.d.ts +3 -27
  45. package/lib/components/TextArea/index.js +6 -98
  46. package/lib/components/TextArea/index.nohighlight.d.ts +3 -27
  47. package/lib/components/TextArea/index.nohighlight.js +3 -92
  48. package/lib/index.common.d.ts +16 -0
  49. package/lib/index.common.js +123 -0
  50. package/lib/react-markdown-preview.common.d.ts +4 -0
  51. package/markdown-editor.css +0 -1
  52. package/nohighlight.d.ts +2 -0
  53. package/package.json +8 -2
  54. package/src/Editor.common.tsx +7 -0
  55. package/src/Editor.factory.tsx +286 -0
  56. package/src/Editor.nohighlight.tsx +3 -271
  57. package/src/Editor.tsx +3 -271
  58. package/src/components/TextArea/Markdown.common.tsx +49 -0
  59. package/src/components/TextArea/factory.tsx +120 -0
  60. package/src/components/TextArea/index.common.tsx +6 -0
  61. package/src/components/TextArea/index.nohighlight.tsx +3 -108
  62. package/src/components/TextArea/index.tsx +3 -110
  63. package/src/index.common.tsx +19 -0
  64. package/src/react-markdown-preview.common.d.ts +4 -0
@@ -0,0 +1,286 @@
1
+ import React, { useEffect, useReducer, useMemo, useRef, useImperativeHandle } from 'react';
2
+ import { ToolbarVisibility } from './components/Toolbar/';
3
+ import DragBar from './components/DragBar/';
4
+ import { getCommands, getExtraCommands, type ICommand, type TextState, TextAreaCommandOrchestrator } from './commands/';
5
+ import { reducer, EditorContext, type ContextStore } from './Context';
6
+ import type { MDEditorProps } from './Types';
7
+
8
+ function setGroupPopFalse(data: Record<string, boolean> = {}) {
9
+ Object.keys(data).forEach((keyname) => {
10
+ data[keyname] = false;
11
+ });
12
+ return data;
13
+ }
14
+
15
+ export interface RefMDEditor extends ContextStore {}
16
+
17
+ type PreviewComponent = React.ComponentType<any>;
18
+ type TextAreaComponent = React.ComponentType<any>;
19
+
20
+ export function createMDEditor<
21
+ TMarkdownPreview extends PreviewComponent,
22
+ TTextArea extends TextAreaComponent,
23
+ >(options: { MarkdownPreview: TMarkdownPreview; TextArea: TTextArea }) {
24
+ const { MarkdownPreview, TextArea } = options;
25
+ const PreviewComponent = MarkdownPreview as React.ComponentType<any>;
26
+ const TextAreaComponent = TextArea as React.ComponentType<any>;
27
+
28
+ const InternalMDEditor = React.forwardRef<RefMDEditor, MDEditorProps>(
29
+ (props: MDEditorProps, ref: React.ForwardedRef<RefMDEditor>) => {
30
+ const {
31
+ prefixCls = 'w-md-editor',
32
+ className,
33
+ value: propsValue,
34
+ commands = getCommands(),
35
+ commandsFilter,
36
+ direction,
37
+ extraCommands = getExtraCommands(),
38
+ height = 200,
39
+ enableScroll = true,
40
+ visibleDragbar = typeof props.visiableDragbar === 'boolean' ? props.visiableDragbar : true,
41
+ highlightEnable = true,
42
+ preview: previewType = 'live',
43
+ fullscreen = false,
44
+ overflow = true,
45
+ previewOptions = {},
46
+ textareaProps,
47
+ maxHeight = 1200,
48
+ minHeight = 100,
49
+ autoFocus,
50
+ autoFocusEnd = false,
51
+ tabSize = 2,
52
+ defaultTabEnable = false,
53
+ onChange,
54
+ onStatistics,
55
+ onHeightChange,
56
+ hideToolbar,
57
+ toolbarBottom = false,
58
+ components,
59
+ renderTextarea,
60
+ ...other
61
+ } = props || {};
62
+ const cmds = commands
63
+ .map((item) => (commandsFilter ? commandsFilter(item, false) : item))
64
+ .filter(Boolean) as ICommand[];
65
+ const extraCmds = extraCommands
66
+ .map((item) => (commandsFilter ? commandsFilter(item, true) : item))
67
+ .filter(Boolean) as ICommand[];
68
+ let [state, dispatch] = useReducer(reducer, {
69
+ markdown: propsValue,
70
+ preview: previewType,
71
+ components,
72
+ height,
73
+ minHeight,
74
+ highlightEnable,
75
+ tabSize,
76
+ defaultTabEnable,
77
+ scrollTop: 0,
78
+ scrollTopPreview: 0,
79
+ commands: cmds,
80
+ extraCommands: extraCmds,
81
+ fullscreen,
82
+ barPopup: {},
83
+ });
84
+ const container = useRef<HTMLDivElement>(null);
85
+ const previewRef = useRef<HTMLDivElement>(null);
86
+ const enableScrollRef = useRef(enableScroll);
87
+
88
+ useImperativeHandle(ref, () => ({ ...state, container: container.current, dispatch }));
89
+ useMemo(() => (enableScrollRef.current = enableScroll), [enableScroll]);
90
+ useEffect(() => {
91
+ const stateInit: ContextStore = {};
92
+ if (container.current) {
93
+ stateInit.container = container.current || undefined;
94
+ }
95
+ stateInit.markdown = propsValue || '';
96
+ stateInit.barPopup = {};
97
+ if (dispatch) {
98
+ dispatch({ ...state, ...stateInit });
99
+ }
100
+ // eslint-disable-next-line react-hooks/exhaustive-deps
101
+ }, []);
102
+
103
+ const cls = [
104
+ className,
105
+ 'wmde-markdown-var',
106
+ direction ? `${prefixCls}-${direction}` : null,
107
+ prefixCls,
108
+ state.preview ? `${prefixCls}-show-${state.preview}` : null,
109
+ state.fullscreen ? `${prefixCls}-fullscreen` : null,
110
+ ]
111
+ .filter(Boolean)
112
+ .join(' ')
113
+ .trim();
114
+
115
+ useMemo(
116
+ () => propsValue !== state.markdown && dispatch({ markdown: propsValue || '' }),
117
+ [propsValue, state.markdown],
118
+ );
119
+ // eslint-disable-next-line react-hooks/exhaustive-deps
120
+ useMemo(() => previewType !== state.preview && dispatch({ preview: previewType }), [previewType]);
121
+ // eslint-disable-next-line react-hooks/exhaustive-deps
122
+ useMemo(() => tabSize !== state.tabSize && dispatch({ tabSize }), [tabSize]);
123
+ useMemo(
124
+ () => highlightEnable !== state.highlightEnable && dispatch({ highlightEnable }),
125
+ // eslint-disable-next-line react-hooks/exhaustive-deps
126
+ [highlightEnable],
127
+ );
128
+ // eslint-disable-next-line react-hooks/exhaustive-deps
129
+ useMemo(() => autoFocus !== state.autoFocus && dispatch({ autoFocus: autoFocus }), [autoFocus]);
130
+ useMemo(() => autoFocusEnd !== state.autoFocusEnd && dispatch({ autoFocusEnd: autoFocusEnd }), [autoFocusEnd]);
131
+ useMemo(
132
+ () => fullscreen !== state.fullscreen && dispatch({ fullscreen: fullscreen }),
133
+ // eslint-disable-next-line react-hooks/exhaustive-deps
134
+ [fullscreen],
135
+ );
136
+ // eslint-disable-next-line react-hooks/exhaustive-deps
137
+ useMemo(() => height !== state.height && dispatch({ height: height }), [height]);
138
+ useMemo(
139
+ () => height !== state.height && onHeightChange && onHeightChange(state.height, height, state),
140
+ [height, onHeightChange, state],
141
+ );
142
+ // eslint-disable-next-line react-hooks/exhaustive-deps
143
+ useMemo(() => commands !== state.commands && dispatch({ commands: cmds }), [props.commands]);
144
+ // eslint-disable-next-line react-hooks/exhaustive-deps
145
+ useMemo(
146
+ () => extraCommands !== state.extraCommands && dispatch({ extraCommands: extraCmds }),
147
+ [props.extraCommands],
148
+ );
149
+
150
+ const textareaDomRef = useRef<HTMLDivElement>();
151
+ const active = useRef<'text' | 'preview'>('preview');
152
+ const initScroll = useRef(false);
153
+
154
+ useMemo(() => {
155
+ textareaDomRef.current = state.textareaWarp;
156
+ if (state.textareaWarp) {
157
+ state.textareaWarp.addEventListener('mouseover', () => {
158
+ active.current = 'text';
159
+ });
160
+ state.textareaWarp.addEventListener('mouseleave', () => {
161
+ active.current = 'preview';
162
+ });
163
+ }
164
+ }, [state.textareaWarp]);
165
+
166
+ const handleScroll = (e: React.UIEvent<HTMLDivElement>, type: 'text' | 'preview') => {
167
+ if (!enableScrollRef.current) return;
168
+ const textareaDom = textareaDomRef.current;
169
+ const previewDom = previewRef.current ? previewRef.current : undefined;
170
+ if (!initScroll.current) {
171
+ active.current = type;
172
+ initScroll.current = true;
173
+ }
174
+ if (textareaDom && previewDom) {
175
+ const scale =
176
+ (textareaDom.scrollHeight - textareaDom.offsetHeight) / (previewDom.scrollHeight - previewDom.offsetHeight);
177
+ if (e.target === textareaDom && active.current === 'text') {
178
+ previewDom.scrollTop = textareaDom.scrollTop / scale;
179
+ }
180
+ if (e.target === previewDom && active.current === 'preview') {
181
+ textareaDom.scrollTop = previewDom.scrollTop * scale;
182
+ }
183
+ let scrollTop = 0;
184
+ if (active.current === 'text') {
185
+ scrollTop = textareaDom.scrollTop || 0;
186
+ } else if (active.current === 'preview') {
187
+ scrollTop = previewDom.scrollTop || 0;
188
+ }
189
+ dispatch({ scrollTop });
190
+ }
191
+ };
192
+
193
+ const previewClassName = `${prefixCls}-preview ${previewOptions.className || ''}`;
194
+ const handlePreviewScroll = (e: React.UIEvent<HTMLDivElement, UIEvent>) => handleScroll(e, 'preview');
195
+ let mdPreview = useMemo(
196
+ () => (
197
+ <div ref={previewRef} className={previewClassName}>
198
+ <PreviewComponent {...previewOptions} onScroll={handlePreviewScroll} source={state.markdown || ''} />
199
+ </div>
200
+ ),
201
+ [previewClassName, previewOptions, state.markdown],
202
+ );
203
+ const preview = components?.preview && components?.preview(state.markdown || '', state, dispatch);
204
+ if (preview && React.isValidElement(preview)) {
205
+ mdPreview = (
206
+ <div className={previewClassName} ref={previewRef} onScroll={handlePreviewScroll}>
207
+ {preview}
208
+ </div>
209
+ );
210
+ }
211
+
212
+ const containerStyle = { ...other.style, height: state.height || '100%' };
213
+ const containerClick = () => dispatch({ barPopup: { ...setGroupPopFalse(state.barPopup) } });
214
+ const dragBarChange = (newHeight: number) => dispatch({ height: newHeight });
215
+
216
+ const changeHandle = (evn: React.ChangeEvent<HTMLTextAreaElement>) => {
217
+ onChange && onChange(evn.target.value, evn, state);
218
+ if (textareaProps && textareaProps.onChange) {
219
+ textareaProps.onChange(evn);
220
+ }
221
+ if (state.textarea && state.textarea instanceof HTMLTextAreaElement && onStatistics) {
222
+ const obj = new TextAreaCommandOrchestrator(state.textarea!);
223
+ const objState = (obj.getState() || {}) as TextState;
224
+ onStatistics({
225
+ ...objState,
226
+ lineCount: evn.target.value.split('\n').length,
227
+ length: evn.target.value.length,
228
+ });
229
+ }
230
+ };
231
+ return (
232
+ <EditorContext.Provider value={{ ...state, dispatch }}>
233
+ <div ref={container} className={cls} {...other} onClick={containerClick} style={containerStyle}>
234
+ <ToolbarVisibility
235
+ hideToolbar={hideToolbar}
236
+ toolbarBottom={toolbarBottom}
237
+ prefixCls={prefixCls}
238
+ overflow={overflow}
239
+ placement="top"
240
+ />
241
+ <div className={`${prefixCls}-content`}>
242
+ {/(edit|live)/.test(state.preview || '') && (
243
+ <TextAreaComponent
244
+ className={`${prefixCls}-input`}
245
+ prefixCls={prefixCls}
246
+ autoFocus={autoFocus}
247
+ {...textareaProps}
248
+ onChange={changeHandle}
249
+ renderTextarea={components?.textarea || renderTextarea}
250
+ onScroll={(e: React.UIEvent<HTMLDivElement>) => handleScroll(e, 'text')}
251
+ />
252
+ )}
253
+ {/(live|preview)/.test(state.preview || '') && mdPreview}
254
+ </div>
255
+ {visibleDragbar && !state.fullscreen && (
256
+ <DragBar
257
+ prefixCls={prefixCls}
258
+ height={state.height as number}
259
+ maxHeight={maxHeight!}
260
+ minHeight={minHeight!}
261
+ onChange={dragBarChange}
262
+ />
263
+ )}
264
+ <ToolbarVisibility
265
+ hideToolbar={hideToolbar}
266
+ toolbarBottom={toolbarBottom}
267
+ prefixCls={prefixCls}
268
+ overflow={overflow}
269
+ placement="bottom"
270
+ />
271
+ </div>
272
+ </EditorContext.Provider>
273
+ );
274
+ },
275
+ );
276
+
277
+ type EditorComponent = typeof InternalMDEditor & {
278
+ Markdown: TMarkdownPreview;
279
+ };
280
+
281
+ const Editor = InternalMDEditor as EditorComponent;
282
+ Editor.Markdown = MarkdownPreview;
283
+ Editor.displayName = 'MDEditor';
284
+
285
+ return Editor;
286
+ }
@@ -1,275 +1,7 @@
1
- import React, { useEffect, useReducer, useMemo, useRef, useImperativeHandle } from 'react';
2
1
  import MarkdownPreview from '@uiw/react-markdown-preview/nohighlight';
3
2
  import TextArea from './components/TextArea/index.nohighlight';
4
- import { ToolbarVisibility } from './components/Toolbar/';
5
- import DragBar from './components/DragBar/';
6
- import { getCommands, getExtraCommands, type ICommand, type TextState, TextAreaCommandOrchestrator } from './commands/';
7
- import { reducer, EditorContext, type ContextStore } from './Context';
8
- import type { MDEditorProps } from './Types';
3
+ import { createMDEditor } from './Editor.factory';
9
4
 
10
- function setGroupPopFalse(data: Record<string, boolean> = {}) {
11
- Object.keys(data).forEach((keyname) => {
12
- data[keyname] = false;
13
- });
14
- return data;
15
- }
5
+ export type { RefMDEditor } from './Editor.factory';
16
6
 
17
- export interface RefMDEditor extends ContextStore {}
18
-
19
- const InternalMDEditor = React.forwardRef<RefMDEditor, MDEditorProps>(
20
- (props: MDEditorProps, ref: React.ForwardedRef<RefMDEditor>) => {
21
- const {
22
- prefixCls = 'w-md-editor',
23
- className,
24
- value: propsValue,
25
- commands = getCommands(),
26
- commandsFilter,
27
- direction,
28
- extraCommands = getExtraCommands(),
29
- height = 200,
30
- enableScroll = true,
31
- visibleDragbar = typeof props.visiableDragbar === 'boolean' ? props.visiableDragbar : true,
32
- highlightEnable = true,
33
- preview: previewType = 'live',
34
- fullscreen = false,
35
- overflow = true,
36
- previewOptions = {},
37
- textareaProps,
38
- maxHeight = 1200,
39
- minHeight = 100,
40
- autoFocus,
41
- autoFocusEnd = false,
42
- tabSize = 2,
43
- defaultTabEnable = false,
44
- onChange,
45
- onStatistics,
46
- onHeightChange,
47
- hideToolbar,
48
- toolbarBottom = false,
49
- components,
50
- renderTextarea,
51
- ...other
52
- } = props || {};
53
- const cmds = commands
54
- .map((item) => (commandsFilter ? commandsFilter(item, false) : item))
55
- .filter(Boolean) as ICommand[];
56
- const extraCmds = extraCommands
57
- .map((item) => (commandsFilter ? commandsFilter(item, true) : item))
58
- .filter(Boolean) as ICommand[];
59
- let [state, dispatch] = useReducer(reducer, {
60
- markdown: propsValue,
61
- preview: previewType,
62
- components,
63
- height,
64
- minHeight,
65
- highlightEnable,
66
- tabSize,
67
- defaultTabEnable,
68
- scrollTop: 0,
69
- scrollTopPreview: 0,
70
- commands: cmds,
71
- extraCommands: extraCmds,
72
- fullscreen,
73
- barPopup: {},
74
- });
75
- const container = useRef<HTMLDivElement>(null);
76
- const previewRef = useRef<HTMLDivElement>(null);
77
- const enableScrollRef = useRef(enableScroll);
78
-
79
- useImperativeHandle(ref, () => ({ ...state, container: container.current, dispatch }));
80
- useMemo(() => (enableScrollRef.current = enableScroll), [enableScroll]);
81
- useEffect(() => {
82
- const stateInit: ContextStore = {};
83
- if (container.current) {
84
- stateInit.container = container.current || undefined;
85
- }
86
- stateInit.markdown = propsValue || '';
87
- stateInit.barPopup = {};
88
- if (dispatch) {
89
- dispatch({ ...state, ...stateInit });
90
- }
91
- // eslint-disable-next-line react-hooks/exhaustive-deps
92
- }, []);
93
-
94
- const cls = [
95
- className,
96
- 'wmde-markdown-var',
97
- direction ? `${prefixCls}-${direction}` : null,
98
- prefixCls,
99
- state.preview ? `${prefixCls}-show-${state.preview}` : null,
100
- state.fullscreen ? `${prefixCls}-fullscreen` : null,
101
- ]
102
- .filter(Boolean)
103
- .join(' ')
104
- .trim();
105
-
106
- useMemo(
107
- () => propsValue !== state.markdown && dispatch({ markdown: propsValue || '' }),
108
- [propsValue, state.markdown],
109
- );
110
- // eslint-disable-next-line react-hooks/exhaustive-deps
111
- useMemo(() => previewType !== state.preview && dispatch({ preview: previewType }), [previewType]);
112
- // eslint-disable-next-line react-hooks/exhaustive-deps
113
- useMemo(() => tabSize !== state.tabSize && dispatch({ tabSize }), [tabSize]);
114
- useMemo(
115
- () => highlightEnable !== state.highlightEnable && dispatch({ highlightEnable }),
116
- // eslint-disable-next-line react-hooks/exhaustive-deps
117
- [highlightEnable],
118
- );
119
- // eslint-disable-next-line react-hooks/exhaustive-deps
120
- useMemo(() => autoFocus !== state.autoFocus && dispatch({ autoFocus: autoFocus }), [autoFocus]);
121
- useMemo(() => autoFocusEnd !== state.autoFocusEnd && dispatch({ autoFocusEnd: autoFocusEnd }), [autoFocusEnd]);
122
- useMemo(
123
- () => fullscreen !== state.fullscreen && dispatch({ fullscreen: fullscreen }),
124
- // eslint-disable-next-line react-hooks/exhaustive-deps
125
- [fullscreen],
126
- );
127
- // eslint-disable-next-line react-hooks/exhaustive-deps
128
- useMemo(() => height !== state.height && dispatch({ height: height }), [height]);
129
- useMemo(
130
- () => height !== state.height && onHeightChange && onHeightChange(state.height, height, state),
131
- [height, onHeightChange, state],
132
- );
133
- // eslint-disable-next-line react-hooks/exhaustive-deps
134
- useMemo(() => commands !== state.commands && dispatch({ commands: cmds }), [props.commands]);
135
- // eslint-disable-next-line react-hooks/exhaustive-deps
136
- useMemo(
137
- () => extraCommands !== state.extraCommands && dispatch({ extraCommands: extraCmds }),
138
- [props.extraCommands],
139
- );
140
-
141
- const textareaDomRef = useRef<HTMLDivElement>();
142
- const active = useRef<'text' | 'preview'>('preview');
143
- const initScroll = useRef(false);
144
-
145
- useMemo(() => {
146
- textareaDomRef.current = state.textareaWarp;
147
- if (state.textareaWarp) {
148
- state.textareaWarp.addEventListener('mouseover', () => {
149
- active.current = 'text';
150
- });
151
- state.textareaWarp.addEventListener('mouseleave', () => {
152
- active.current = 'preview';
153
- });
154
- }
155
- }, [state.textareaWarp]);
156
-
157
- const handleScroll = (e: React.UIEvent<HTMLDivElement>, type: 'text' | 'preview') => {
158
- if (!enableScrollRef.current) return;
159
- const textareaDom = textareaDomRef.current;
160
- const previewDom = previewRef.current ? previewRef.current : undefined;
161
- if (!initScroll.current) {
162
- active.current = type;
163
- initScroll.current = true;
164
- }
165
- if (textareaDom && previewDom) {
166
- const scale =
167
- (textareaDom.scrollHeight - textareaDom.offsetHeight) / (previewDom.scrollHeight - previewDom.offsetHeight);
168
- if (e.target === textareaDom && active.current === 'text') {
169
- previewDom.scrollTop = textareaDom.scrollTop / scale;
170
- }
171
- if (e.target === previewDom && active.current === 'preview') {
172
- textareaDom.scrollTop = previewDom.scrollTop * scale;
173
- }
174
- let scrollTop = 0;
175
- if (active.current === 'text') {
176
- scrollTop = textareaDom.scrollTop || 0;
177
- } else if (active.current === 'preview') {
178
- scrollTop = previewDom.scrollTop || 0;
179
- }
180
- dispatch({ scrollTop });
181
- }
182
- };
183
-
184
- const previewClassName = `${prefixCls}-preview ${previewOptions.className || ''}`;
185
- const handlePreviewScroll = (e: React.UIEvent<HTMLDivElement, UIEvent>) => handleScroll(e, 'preview');
186
- let mdPreview = useMemo(
187
- () => (
188
- <div ref={previewRef} className={previewClassName}>
189
- <MarkdownPreview {...previewOptions} onScroll={handlePreviewScroll} source={state.markdown || ''} />
190
- </div>
191
- ),
192
- [previewClassName, previewOptions, state.markdown],
193
- );
194
- const preview = components?.preview && components?.preview(state.markdown || '', state, dispatch);
195
- if (preview && React.isValidElement(preview)) {
196
- mdPreview = (
197
- <div className={previewClassName} ref={previewRef} onScroll={handlePreviewScroll}>
198
- {preview}
199
- </div>
200
- );
201
- }
202
-
203
- const containerStyle = { ...other.style, height: state.height || '100%' };
204
- const containerClick = () => dispatch({ barPopup: { ...setGroupPopFalse(state.barPopup) } });
205
- const dragBarChange = (newHeight: number) => dispatch({ height: newHeight });
206
-
207
- const changeHandle = (evn: React.ChangeEvent<HTMLTextAreaElement>) => {
208
- onChange && onChange(evn.target.value, evn, state);
209
- if (textareaProps && textareaProps.onChange) {
210
- textareaProps.onChange(evn);
211
- }
212
- if (state.textarea && state.textarea instanceof HTMLTextAreaElement && onStatistics) {
213
- const obj = new TextAreaCommandOrchestrator(state.textarea!);
214
- const objState = (obj.getState() || {}) as TextState;
215
- onStatistics({
216
- ...objState,
217
- lineCount: evn.target.value.split('\n').length,
218
- length: evn.target.value.length,
219
- });
220
- }
221
- };
222
- return (
223
- <EditorContext.Provider value={{ ...state, dispatch }}>
224
- <div ref={container} className={cls} {...other} onClick={containerClick} style={containerStyle}>
225
- <ToolbarVisibility
226
- hideToolbar={hideToolbar}
227
- toolbarBottom={toolbarBottom}
228
- prefixCls={prefixCls}
229
- overflow={overflow}
230
- placement="top"
231
- />
232
- <div className={`${prefixCls}-content`}>
233
- {/(edit|live)/.test(state.preview || '') && (
234
- <TextArea
235
- className={`${prefixCls}-input`}
236
- prefixCls={prefixCls}
237
- autoFocus={autoFocus}
238
- {...textareaProps}
239
- onChange={changeHandle}
240
- renderTextarea={components?.textarea || renderTextarea}
241
- onScroll={(e) => handleScroll(e, 'text')}
242
- />
243
- )}
244
- {/(live|preview)/.test(state.preview || '') && mdPreview}
245
- </div>
246
- {visibleDragbar && !state.fullscreen && (
247
- <DragBar
248
- prefixCls={prefixCls}
249
- height={state.height as number}
250
- maxHeight={maxHeight!}
251
- minHeight={minHeight!}
252
- onChange={dragBarChange}
253
- />
254
- )}
255
- <ToolbarVisibility
256
- hideToolbar={hideToolbar}
257
- toolbarBottom={toolbarBottom}
258
- prefixCls={prefixCls}
259
- overflow={overflow}
260
- placement="bottom"
261
- />
262
- </div>
263
- </EditorContext.Provider>
264
- );
265
- },
266
- );
267
-
268
- type EditorComponent = typeof InternalMDEditor & {
269
- Markdown: typeof MarkdownPreview;
270
- };
271
-
272
- const Editor = InternalMDEditor as EditorComponent;
273
- Editor.Markdown = MarkdownPreview;
274
-
275
- export default Editor;
7
+ export default createMDEditor({ MarkdownPreview, TextArea });