scrowl/src/ui/CodeEditor.tsx

67 lines
1.5 KiB
TypeScript

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 (
<div
ref={containerRef}
class="editor-frame"
/>
);
}