import { useCallback, useMemo, useRef, useState } from 'react'; import { useTheme } from '@vertesia/ui/core'; import { MonacoEditor, IEditorApi } from '../monacoEditor/MonacoEditor'; export interface JSONEditorProps { /** The JSON value to edit */ value: Record | undefined | null; /** Called when the user saves (value is the parsed JSON) */ onChange?: (value: Record) => void; /** Called on every valid edit (for controlled mode) */ onValidChange?: (value: Record) => void; /** If true, the editor is read-only */ readonly?: boolean; /** Editor height (default: '200px') */ height?: string; /** Placeholder text when value is empty */ placeholder?: string; /** Additional CSS class */ className?: string; } /** * Reusable JSON editor based on Monaco. * Parses and validates JSON, reports errors. */ export function JSONEditor({ value, onChange: _onChange, onValidChange, readonly = false, height = '200px', placeholder, className, }: JSONEditorProps) { const { theme } = useTheme(); const editorRef = useRef(undefined); const [error, setError] = useState(null); const jsonString = useMemo(() => { if (value === undefined || value === null) return placeholder ?? '{}'; try { return JSON.stringify(value, null, 2); } catch { return '{}'; } }, [value, placeholder]); // Validate on change const handleChange = useCallback(() => { if (!editorRef.current || readonly) return; const text = editorRef.current.getValue(); try { const parsed = JSON.parse(text); setError(null); onValidChange?.(parsed); } catch { setError('Invalid JSON'); } }, [readonly, onValidChange]); return (
{error &&

{error}

}
); } /** * Get the current parsed value from a JSONEditor ref. * Returns the parsed object or null if invalid. */ export function getJSONEditorValue(editorRef: React.RefObject): Record | null { if (!editorRef.current) return null; try { return JSON.parse(editorRef.current.getValue()); } catch { return null; } }