69 lines
2.7 KiB
TypeScript
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>
|
|
)
|
|
}
|