Files
minimax/webui/src/components/Editor.tsx
2025-10-29 20:36:09 -07:00

96 lines
2.5 KiB
TypeScript

"use client";
import { useEffect, useRef, forwardRef, useImperativeHandle, useState } from "react";
import styles from "@/styles/Editor.module.css";
// Dynamic import for CodeMirror to avoid SSR issues
let CodeMirror: any = null;
if (typeof window !== "undefined") {
import("codemirror")
.then(async (cm) => {
CodeMirror = cm.default;
await import("codemirror/mode/javascript/javascript");
await import("codemirror/addon/edit/matchbrackets");
await import("codemirror/addon/edit/closebrackets");
await import("codemirror/addon/selection/active-line");
await import("codemirror/lib/codemirror.css");
await import("codemirror/theme/monokai.css");
});
}
interface EditorProps {
initialValue?: string;
onChange?: (editor: any, changes: any) => void;
onRequestRun?: () => void;
onReady?: (editor: any) => void;
}
export const Editor = forwardRef<any, EditorProps>(function Editor(
{ initialValue = "", onChange, onRequestRun, onReady },
ref,
) {
const textareaRef = useRef<HTMLTextAreaElement>(null);
const editorRef = useRef<any>(null);
const [content, setContent] = useState(initialValue);
useImperativeHandle(ref, () => editorRef.current);
// Initialize editor only once
useEffect(() => {
if (!CodeMirror || !textareaRef.current || editorRef.current) return;
const editor = CodeMirror.fromTextArea(textareaRef.current, {
lineNumbers: true,
mode: "javascript", // Placeholder mode, will be 'rhai' when WASM is integrated
theme: "monokai",
matchBrackets: true,
autoCloseBrackets: true,
styleActiveLine: true,
extraKeys: {
"Ctrl-Enter": () => {
onRequestRun?.();
},
},
});
editor.setValue(content);
editor.on("change", (instance: any, changes: any) => {
const newContent = instance.getValue();
setContent(newContent);
onChange?.(instance, changes);
});
editorRef.current = editor;
onReady?.(editor);
return () => {
if (editorRef.current) {
editorRef.current.toTextArea();
editorRef.current = null;
}
};
}, []); // Empty dependency array - only initialize once
// Update keyboard shortcut when onRequestRun changes
useEffect(() => {
if (editorRef.current && onRequestRun) {
editorRef.current.setOption("extraKeys", {
"Ctrl-Enter": () => {
onRequestRun();
},
});
}
}, [onRequestRun]);
return (
<div className={styles.editorContainer}>
<textarea
ref={textareaRef}
defaultValue={initialValue}
placeholder="Enter your Rhai code here..."
/>
</div>
);
});