"use client"; import { useEffect, useState } from "react"; import { ChevronDown, ChevronRight, Trash2 } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Badge } from "@/components/ui/badge"; import { lookup } from "@/lib/node-catalog"; import type { PipelineNode } from "@/lib/pipeline-graph"; import { NodeForm, hasTypedForm } from "./node-form"; interface InspectorProps { node: PipelineNode | null; onChange: (next: PipelineNode) => void; onDelete: (id: string) => void; onClose: () => void; } export function Inspector({ node, onChange, onDelete, onClose }: InspectorProps) { const [name, setName] = useState(""); const [paramsText, setParamsText] = useState("{}"); const [paramsErr, setParamsErr] = useState(null); const [showJSON, setShowJSON] = useState(false); useEffect(() => { if (!node) return; setName(node.name); setParamsText(JSON.stringify(node.parameters ?? {}, null, 2)); setParamsErr(null); setShowJSON(false); }, [node?.id]); // eslint-disable-line react-hooks/exhaustive-deps // Keep the JSON textarea in sync when typed-form edits change parameters. useEffect(() => { if (!node) return; setParamsText(JSON.stringify(node.parameters ?? {}, null, 2)); }, [node?.parameters]); // eslint-disable-line react-hooks/exhaustive-deps if (!node) { return ( ); } const entry = lookup(node.type); const typed = hasTypedForm(node.type); function commitName(next: string) { if (!node) return; onChange({ ...node, name: next }); } function commitParams(text: string) { if (!node) return; try { const parsed = JSON.parse(text || "{}"); if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) { throw new Error("parameters must be a JSON object"); } setParamsErr(null); onChange({ ...node, parameters: parsed as Record }); } catch (e) { setParamsErr(e instanceof Error ? e.message : "invalid JSON"); } } return (