'use client' import { useState, useMemo } from 'react' import type { GuardrailData } from '@/lib/types' import { guardrailCreatorColor } from '@/lib/utils' import { LabLogo } from '@/components/LabLogo' type Metric = 'recall' | 'precision' | 'f1' const TABS: { key: Metric; label: string; yLabel: string }[] = [ { key: 'recall', label: 'Recall', yLabel: 'Score (Higher is Better)' }, { key: 'precision', label: 'Precision', yLabel: 'Score (Higher is Better)' }, { key: 'f1', label: 'F1 Score', yLabel: 'Score (Higher is Better)' }, ] const ML = 80 const MR = 80 const MT = 14 const BAR_H = 300 const LBL_H = 150 const VW = 1100 const VH = MT + BAR_H + LBL_H const CHART_W = VW - ML - MR const GAP = 4 const GRID = [0, 0.25, 0.5, 0.75, 1.0] export default function GuardrailBarChart({ guardrails }: { guardrails: GuardrailData[] }) { const [metric, setMetric] = useState('f1') const [activeCreators, setCreators] = useState>(new Set()) const allCreators = useMemo( () => [...new Set(guardrails.map(g => g.creator))].sort(), [guardrails], ) const toggleCreator = (c: string) => setCreators(prev => { const s = new Set(prev); s.has(c) ? s.delete(c) : s.add(c); return s }) const sorted = useMemo(() => { let list = [...guardrails] if (activeCreators.size) list = list.filter(g => activeCreators.has(g.creator)) list = list.filter(g => g[metric] !== null) return list.sort((a, b) => (b[metric] ?? 0) - (a[metric] ?? 0)) }, [guardrails, metric, activeCreators]) const n = sorted.length const bw = n > 0 ? (CHART_W - (n - 1) * GAP) / n : 0 const legendCreators = useMemo( () => [...new Set(sorted.map(g => g.creator))].sort(), [sorted], ) const tab = TABS.find(t => t.key === metric)! return (
{/* Filters row */}
{/* Creator chips */}
Provider {allCreators.map(c => { const cc = guardrailCreatorColor(c) const on = activeCreators.has(c) return ( ) })}
{/* Metric tabs */}
{TABS.map((t, i) => ( ))}
{/* Chart */}
{/* Grid lines + y-axis labels */} {GRID.map(lvl => { const y = MT + BAR_H - lvl * BAR_H return ( {`${Math.round(lvl * 100)}`} ) })} {/* Y-axis title */} {tab.yLabel} {/* Bars */} {sorted.map((g, i) => { const val = g[metric]! const barHeight = val * BAR_H const x = ML + i * (bw + GAP) const y = MT + BAR_H - barHeight const cc = guardrailCreatorColor(g.creator) return ( {barHeight > 18 && ( {`${(val * 100).toFixed(0)}%`} )} {g.guardrail} ) })} {/* Legend */}
{legendCreators.map(c => (
{c}
))}
) }