"use client"; import { Node, mergeAttributes } from "@tiptap/core"; import { ReactNodeViewRenderer, NodeViewWrapper, type ReactNodeViewProps } from "@tiptap/react"; import { useState, useCallback } from "react"; import type { ReportConfig } from "../../components/charts/types"; // Lazy-load ReportCard to keep bundle light import dynamic from "next/dynamic"; const ReportCard = dynamic( () => import("../../components/charts/report-card").then((m) => ({ default: m.ReportCard, })), { ssr: false, loading: () => (
), }, ); // --- React NodeView Component --- function ReportBlockView({ node, updateAttributes, deleteNode, selected, }: ReactNodeViewProps) { const configAttr = node.attrs.config as string; const [showSource, setShowSource] = useState(false); const [editValue, setEditValue] = useState(configAttr); let parsedConfig: ReportConfig | null = null; let parseError: string | null = null; try { const parsed = JSON.parse(configAttr); if (parsed?.panels && Array.isArray(parsed.panels)) { parsedConfig = parsed as ReportConfig; } else { parseError = "Invalid report config: missing panels array"; } } catch { parseError = "Invalid JSON in report block"; } const handleSaveSource = useCallback(() => { try { JSON.parse(editValue); // validate updateAttributes({ config: editValue }); setShowSource(false); } catch { // Don't close if invalid JSON } }, [editValue, updateAttributes]); return ( {/* Overlay toolbar */}
{showSource ? ( /* JSON source editor */
report-json