-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathmarkdowneditor.component.tsx
More file actions
79 lines (68 loc) · 2.3 KB
/
markdowneditor.component.tsx
File metadata and controls
79 lines (68 loc) · 2.3 KB
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
import React from "react";
import { basicSetup, EditorView } from 'codemirror'
import { EditorState } from '@codemirror/state'
import { useEffect, useRef } from 'react'
import { markdown } from '@codemirror/lang-markdown'
import { languages } from '@codemirror/language-data'
import { tags } from '@lezer/highlight'
import { syntaxHighlighting, HighlightStyle} from '@codemirror/language'
import * as classes from './markdowneditor.styles';
const stylesEditor = HighlightStyle.define([
{ tag: tags.heading1, class: classes.headerH1},
{ tag: tags.heading2, class: classes.headerH2},
{ tag: tags.heading3, class: classes.headerH3},
]);
interface Props {
value: string
onChange?: (value: string) => void
className?: string
}
export const MarkdownEditor: React.FC<Props> = (props) => {
const refContainer = useRef(null)
const editorView = useRef<EditorView>()
useEffect(() => {
if (!refContainer.current) return
editorView.current = new EditorView({
state: EditorState.create({
doc: props.value,
extensions: [
basicSetup,
markdown({
codeLanguages: languages,
}),
syntaxHighlighting(stylesEditor),
EditorView.lineWrapping,
EditorView.updateListener.of((update) => {
props.onChange(update.state.doc.toString())
}),
EditorView.theme({
'&': {
border: '2px solid #070707',
height: '300px',
},
}),
]
}),
parent: refContainer.current
});
return () => editorView.current?.destroy()
}, []);
const scrollToEnd = () => {
if (!refContainer.current) return;
const scrollHeight = refContainer.current.scrollHeight;
const clientHeight = refContainer.current.clientHeight;
editorView.current.scrollDOM.scrollTop = scrollHeight - clientHeight;
}
useEffect(() => {
const state = editorView.current?.state
const currentValue = state?.doc.toString()
if (state && currentValue !== props.value) {
const update = state.update({
changes: { from: 0, to: state.doc.length, insert: props.value }
});
editorView.current?.update([update]);
scrollToEnd();
}
}, [props.value]);
return <div ref={refContainer} className={ props.className } />
};