Files
zui/src/components/ConfigNode.tsx
2026-03-05 23:46:12 +01:00

69 lines
2.7 KiB
TypeScript

import React from 'react'
import { Handle, Position } from 'reactflow'
import Editor, { loader } from '@monaco-editor/react'
import FlowContext from '../lib/flowContext'
// Ensure Monaco can load its web workers under Vite by pointing to a CDN
// This avoids the editor hanging while trying to locate worker scripts locally.
loader.config({ paths: { vs: 'https://unpkg.com/monaco-editor@latest/min/vs' } })
type Props = {
id: string
data: any
}
export default function ConfigNode({ id, data }: Props) {
const [value, setValue] = React.useState<string>(data?.yaml ?? "# Enter YAML here\n")
const ctx = React.useContext(FlowContext)
const setNodes = ctx?.setNodes
const storedYaml = ctx?.nodes?.find((n: any) => n.id === id)?.data?.yaml ?? ''
React.useEffect(() => {
// keep node data in sync on mount
if (setNodes) {
setNodes((nds: any[]) => nds.map((n) => (n.id === id ? { ...n, data: { ...n.data, yaml: value } } : n)))
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const onChange = React.useCallback(
(val?: string) => {
const v = val ?? ''
setValue(v)
// debug log to help trace updates
// eslint-disable-next-line no-console
console.debug('ConfigNode:onChange', id, v.substring(0, 60))
if (setNodes) {
setNodes((nds: any[]) => nds.map((n) => (n.id === id ? { ...n, data: { ...n.data, yaml: v } } : n)))
}
},
[id, setNodes]
)
return (
<div className="w-80 bg-white rounded shadow hover:shadow-md border border-gray-200">
<div className="px-3 py-2 border-b border-gray-100 flex items-center justify-between">
<div className="text-sm font-medium">Configuration</div>
<div className="text-xs text-gray-400">YAML</div>
</div>
<div style={{ height: 180 }}>
<Editor
height="100%"
defaultLanguage="yaml"
value={value}
theme="vs-light"
onChange={onChange}
options={{ minimap: { enabled: false }, fontSize: 12 }}
/>
</div>
<div className="px-3 py-2 text-xs text-gray-500 border-t border-gray-100">
Stored YAML: {storedYaml ? `${storedYaml.length} chars` : 'none'}
</div>
<Handle type="source" position={Position.Right} id="out" style={{ background: '#10B981', right: -6 }} />
<Handle type="target" position={Position.Left} id="in" style={{ background: '#F97316', left: -6 }} />
</div>
)
}