shrimp/src/editor/editor.tsx
2026-01-05 11:30:32 -08:00

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)
}