A free setting typed json and a declared object or array setting (a Switch node's rules, HTTP headers) show one line of their value; clicking opens a Monaco JSON editor in a dialog that saves only once the text parses. Declared object settings were not shown at all before. Escape in a dialog opened from a side panel no longer closes the panel too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
82 lines
3.0 KiB
TypeScript
82 lines
3.0 KiB
TypeScript
/**
|
|
* Monaco, self-hosted and themed from the design tokens.
|
|
*
|
|
* Only the base editor, the Python grammar and JSON (for settings holding JSON)
|
|
* are pulled in; the other seventy languages would triple the chunk for
|
|
* nothing. This module is imported by NodeEditor alone, which the panel loads
|
|
* lazily.
|
|
*/
|
|
import { loader } from "@monaco-editor/react"
|
|
import * as monaco from "monaco-editor/editor/editor.api"
|
|
// Only Python registers itself; `basic-languages` would pull in all seventy.
|
|
import "monaco-editor/languages/definitions/python/register"
|
|
import "monaco-editor/languages/features/json/register"
|
|
import editorWorker from "monaco-editor/editor/editor.worker?worker"
|
|
import jsonWorker from "monaco-editor/languages/features/json/json.worker?worker"
|
|
|
|
let configured = false
|
|
|
|
function defineThemes() {
|
|
const themes = [
|
|
{ id: "fluksio-light", base: "vs" as const },
|
|
{ id: "fluksio-dark", base: "vs-dark" as const },
|
|
]
|
|
|
|
for (const theme of themes) {
|
|
const dark = theme.id.endsWith("dark")
|
|
const background = dark ? "#1a1a1a" : "#ffffff"
|
|
const foreground = dark ? "#f5f5f5" : "#333232"
|
|
const muted = dark ? "#a3a3a3" : "#6b6b6b"
|
|
const accent = dark ? "#262626" : "#f5f5f5"
|
|
const primary = dark ? "#7ba3b8" : "#4a7189"
|
|
const success = dark ? "#87b596" : "#5e8b6d"
|
|
|
|
monaco.editor.defineTheme(theme.id, {
|
|
base: theme.base,
|
|
inherit: true,
|
|
rules: [
|
|
{ token: "keyword", foreground: primary.slice(1) },
|
|
{ token: "string", foreground: success.slice(1) },
|
|
{ token: "comment", foreground: muted.slice(1), fontStyle: "italic" },
|
|
{ token: "number", foreground: foreground.slice(1) },
|
|
// JSON names its tokens more specifically, so the base theme's
|
|
// colours would win over the generic ones above.
|
|
{ token: "string.key.json", foreground: foreground.slice(1) },
|
|
{ token: "string.value.json", foreground: success.slice(1) },
|
|
{ token: "keyword.json", foreground: primary.slice(1) },
|
|
],
|
|
colors: {
|
|
"editor.background": background,
|
|
"editor.foreground": foreground,
|
|
"editorLineNumber.foreground": muted,
|
|
"editorLineNumber.activeForeground": foreground,
|
|
"editor.lineHighlightBackground": accent,
|
|
"editorCursor.foreground": primary,
|
|
"editor.selectionBackground": `${primary}33`,
|
|
"editorIndentGuide.background1": accent,
|
|
"editorWidget.background": background,
|
|
"editorGutter.background": background,
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
export function setupMonaco(): typeof monaco {
|
|
if (configured) return monaco
|
|
configured = true
|
|
|
|
// Self-hosted: no CDN fetch, so the editor works on a LAN install.
|
|
self.MonacoEnvironment = {
|
|
getWorker: (_, label) =>
|
|
label === "json" ? new jsonWorker() : new editorWorker(),
|
|
}
|
|
loader.config({ monaco })
|
|
defineThemes()
|
|
return monaco
|
|
}
|
|
|
|
export const monacoFontFamily = (): string =>
|
|
getComputedStyle(document.documentElement)
|
|
.getPropertyValue("--font-mono")
|
|
.trim() || "ui-monospace, monospace"
|