71 lines
1.6 KiB
TypeScript
71 lines
1.6 KiB
TypeScript
import { EditorView, basicSetup } from 'codemirror'
|
|
import { Shrimp } from '#/index'
|
|
|
|
import { shrimpTheme } from './theme'
|
|
import { createShrimpDiagnostics } from './diagnostics'
|
|
import { shrimpHighlighter } from './highlighter'
|
|
import { createShrimpCompletions } from './completions'
|
|
import { shrimpKeymap } from './keymap'
|
|
import { getContent, persistence } from './persistence'
|
|
|
|
type EditorProps = {
|
|
initialCode?: string
|
|
onChange?: (code: string) => void
|
|
extensions?: import('@codemirror/state').Extension[]
|
|
shrimp?: Shrimp
|
|
}
|
|
|
|
export const Editor = ({
|
|
initialCode = '',
|
|
onChange,
|
|
extensions: customExtensions = [],
|
|
shrimp = new Shrimp(),
|
|
}: EditorProps) => {
|
|
return (
|
|
<div
|
|
ref={(el: Element) => {
|
|
if (!el?.querySelector('.cm-editor'))
|
|
createEditorView(el, getContent() ?? initialCode, onChange, customExtensions, shrimp)
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
|
|
const createEditorView = (
|
|
el: Element,
|
|
initialCode: string,
|
|
onChange: ((code: string) => void) | undefined,
|
|
customExtensions: import('@codemirror/state').Extension[],
|
|
shrimp: Shrimp
|
|
) => {
|
|
const extensions = [
|
|
basicSetup,
|
|
shrimpTheme,
|
|
createShrimpDiagnostics(shrimp),
|
|
createShrimpCompletions(shrimp),
|
|
shrimpHighlighter,
|
|
shrimpKeymap,
|
|
persistence,
|
|
...customExtensions,
|
|
]
|
|
|
|
if (onChange) {
|
|
extensions.push(
|
|
EditorView.updateListener.of((update) => {
|
|
if (update.docChanged) {
|
|
onChange(update.state.doc.toString())
|
|
}
|
|
})
|
|
)
|
|
}
|
|
|
|
new EditorView({
|
|
parent: el,
|
|
doc: initialCode,
|
|
extensions,
|
|
})
|
|
|
|
// Trigger onChange with initial content
|
|
onChange?.(initialCode)
|
|
}
|