|
3 | 3 | Handles: string, number, integer, boolean, array (simple), object (nested keys). |
4 | 4 | """ |
5 | 5 |
|
6 | | -cl import from "react" { useState } |
| 6 | +cl import from "react" { useState, useEffect } |
7 | 7 | cl import from .primitives { Input, Btn, Textarea, Select } |
| 8 | +cl import from "@monaco-editor/react" { default as MonacoEditor } |
8 | 9 |
|
9 | 10 | def RenderFieldForSchema(schema: Any, path: Any, value: Any, onChange: Any) -> Any { |
10 | 11 | safeSchema = schema or {}; |
@@ -98,6 +99,57 @@ def RenderFieldForSchema(schema: Any, path: Any, value: Any, onChange: Any) -> A |
98 | 99 | </div>; |
99 | 100 | } |
100 | 101 |
|
| 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 | + |
101 | 153 | # Default: string (use textarea for long strings) |
102 | 154 | if safeSchema.format == "textarea" or (description and len(description) > 50) { |
103 | 155 | return <Textarea |
|
0 commit comments