import { onMount, onCleanup } from "solid-js"; import { EditorView, basicSetup } from "codemirror"; import { EditorState } from "@codemirror/state"; import { oneDark } from "@codemirror/theme-one-dark"; import { vim } from "@replit/codemirror-vim"; export interface EditorProps { value: string, onUpdate(val: string): void, onRun(): void, height?: string, } export function CodeEditor(props: EditorProps) { let containerRef: HTMLDivElement | undefined; let view: EditorView; const handleKeydown = (e: KeyboardEvent) => { if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) { e.preventDefault(); e.stopImmediatePropagation(); props.onRun(); } }; onMount(() => { const themeConfig = EditorView.theme({ "&": { height: props.height || "300px" }, ".cm-scroller": { overflow: "auto" } }); const state = EditorState.create({ doc: props.value, extensions: [ basicSetup, oneDark, vim(), themeConfig, EditorView.updateListener.of((update) => { if (update.docChanged) { props.onUpdate(update.state.doc.toString()); } }), ], }); view = new EditorView({ state, parent: containerRef!, }); containerRef?.addEventListener("keydown", handleKeydown, { capture: true }); }); onCleanup(() => { containerRef?.removeEventListener("keydown", handleKeydown, { capture: true }); view.destroy() }); return (
); }