Skip to content

Commit 60142a0

Browse files
authored
Add code editor support
This pull request enhances the schema_form component by adding automatic code editor support for fields that are likely to contain code. It detects such fields based on their name or schema format and renders a Monaco code editor with dynamic theming that responds to light/dark mode changes. The main changes are:
2 parents c233d45 + bca3c32 commit 60142a0

1 file changed

Lines changed: 53 additions & 1 deletion

File tree

components/ui/schema_form.cl.jac

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
Handles: string, number, integer, boolean, array (simple), object (nested keys).
44
"""
55

6-
cl import from "react" { useState }
6+
cl import from "react" { useState, useEffect }
77
cl import from .primitives { Input, Btn, Textarea, Select }
8+
cl import from "@monaco-editor/react" { default as MonacoEditor }
89

910
def RenderFieldForSchema(schema: Any, path: Any, value: Any, onChange: Any) -> Any {
1011
safeSchema = schema or {};
@@ -98,6 +99,57 @@ def RenderFieldForSchema(schema: Any, path: Any, value: Any, onChange: Any) -> A
9899
</div>;
99100
}
100101

102+
# Code editor: detect by field name or schema format
103+
codeFieldNames = ["code", "source", "source_code", "jac_code", "python_code", "script", "snippet"];
104+
lowerPath = path.toLowerCase();
105+
isCodeField = codeFieldNames.includes(lowerPath) or safeSchema.format == "code";
106+
107+
if isCodeField {
108+
has editorTheme: Any = "vs-dark";
109+
110+
useEffect(lambda -> Any {
111+
`root = document.documentElement;
112+
isDark = `root.classList.contains("dark");
113+
editorTheme = "vs-dark" if isDark else "vs";
114+
115+
observer = Reflect.construct(MutationObserver, [lambda(mutations: Any) -> None {
116+
editorTheme = "vs-dark" if document.documentElement.classList.contains("dark") else "vs";
117+
}]);
118+
observer.observe(`root, {"attributes": True, "attributeFilter": ["class"]});
119+
120+
return lambda -> None { observer.disconnect(); };
121+
}, []);
122+
123+
def handleEditorChange(val: Any) -> None {
124+
onChange(path, val or "");
125+
}
126+
127+
return <div className="monaco-container">
128+
<MonacoEditor
129+
height="300px"
130+
defaultLanguage="python"
131+
theme={editorTheme}
132+
value={value or ""}
133+
onChange={handleEditorChange}
134+
options={{
135+
"minimap": {"enabled": False},
136+
"fontSize": 13,
137+
"lineNumbers": "on",
138+
"scrollBeyondLastLine": False,
139+
"wordWrap": "on",
140+
"tabSize": 4,
141+
"insertSpaces": True,
142+
"automaticLayout": True,
143+
"padding": {"top": 12, "bottom": 12},
144+
"renderLineHighlight": "line",
145+
"scrollbar": {"verticalScrollbarSize": 6, "horizontalScrollbarSize": 6},
146+
"overviewRulerBorder": False,
147+
"hideCursorInOverviewRuler": True
148+
}}
149+
/>
150+
</div>;
151+
}
152+
101153
# Default: string (use textarea for long strings)
102154
if safeSchema.format == "textarea" or (description and len(description) > 50) {
103155
return <Textarea

0 commit comments

Comments
 (0)