"use client"; import { useEffect, useRef, useState, type ReactNode } from "react"; import s from "../compare.module.css"; /** measure a container so charts render at real pixels (no viewBox distortion) */ export function useSize() { const ref = useRef(null); const [size, setSize] = useState({ w: 0, h: 0 }); useEffect(() => { const el = ref.current; if (!el) return; const ro = new ResizeObserver(([e]) => setSize({ w: Math.round(e.contentRect.width), h: Math.round(e.contentRect.height) })); ro.observe(el); return () => ro.disconnect(); }, []); return [ref, size] as const; } /** honest empty state for any chart — never a blank axis pretending to have data */ export function ChartEmpty({ title, msg, tier }: { title: string; msg: string; tier?: "telemetry" | "derived" }) { return (
{title} {tier && {tier === "telemetry" ? "FEED" : "DERIVED"}}

{msg}

); } /** panel chrome shared by the SVG charts: title + tier chip + a measured plot area */ export function ChartPanel({ title, tier, note, children, }: { title: string; tier: "telemetry" | "derived"; note?: string; children: (w: number, h: number) => ReactNode; }) { const [ref, { w, h }] = useSize(); return (
{title} {note && {note}} {tier === "telemetry" ? "FEED" : "DERIVED"}
{w > 0 && h > 0 ? children(w, h) : null}
); }