'use client'; import 'uplot/dist/uPlot.min.css'; import uPlot from 'uplot'; import { useApp } from '@/lib/context'; import { resolveName } from '@/lib/localization'; import { CardShell } from './CardShell'; import { makeYScale, makeAnnotationHooks, makeSignalsSeries, makeSignalsAxes, CURSOR_NO_DRAG } from './plotHelpers'; import { buildSeriesData } from './seriesData'; import { usePlot } from './usePlot'; import type { AlertConfig, ChartConfig, SessionBoundary, SignalRow } from '@/lib/types'; import type { TimeMode } from '@/lib/types'; interface Props { config: ChartConfig; rows: SignalRow[]; sessions: SessionBoundary[]; alerts: AlertConfig[]; timeMode: TimeMode; onEdit: () => void; onDelete: () => void; } export default function SignalsChart({ config, rows, sessions, alerts, timeMode, onEdit, onDelete }: Props) { const { localeMap } = useApp(); const { containerRef, legendRef } = usePlot( (el, w, h, lRef) => { const data = buildSeriesData(rows, config.signal_type, timeMode); if (!data) return null; const { keys, allXs, data: seriesData } = data; const sessionXs = sessions.map(s => timeMode === 'tick' ? s.game_tick : new Date(s.real_time).getTime() / 1000); const alertThresholds = alerts .filter(a => config.signal_type === 'both' || config.signal_type === a.signal_type) .map(a => a.threshold); return new uPlot({ width: w, height: h, cursor: CURSOR_NO_DRAG, legend: { mount: (_u, legendEl) => { if (lRef.current) lRef.current.appendChild(legendEl); }, }, series: makeSignalsSeries(keys, timeMode, key => resolveName(key, localeMap)), axes: makeSignalsAxes(timeMode), scales: { x: { time: false }, y: makeYScale(config.y_min ?? null, config.y_max ?? null, config.y_scale), }, hooks: makeAnnotationHooks(sessionXs, alertThresholds), }, [allXs, ...seriesData], el); }, [rows, sessions, alerts, config, timeMode, localeMap], ); return (
} className="w-full h-full" /> ); }