export function MetricCard({ item, loading = false, onClick }) { const Icon = item.icon; const UnitIcon = item.unitIcon; const clickable = Boolean(onClick); if (loading) { return (
{Icon ?
: null}
); } return (
{ if (event.key === "Enter" || event.key === " ") { event.preventDefault(); onClick(); } } : undefined} >
{Icon ? : null} {item.label} {UnitIcon ? : null} {item.unit ? {item.unit} : null}
{Array.isArray(item.subMetrics) && item.subMetrics.length ? : }
); } function MetricMainValue({ item }) { return ( <> {item.value} ); } function MetricSubValues({ items }) { return (
{items.map((subItem) => (
{subItem.label} {subItem.value}
))}
); } function MetricDelta({ compact = false, item }) { const tone = item.deltaTone || (String(item.delta || "").trim().startsWith("-") ? "down" : "up"); return (
{item.caption} {item.delta ? `${tone === "down" ? "↓" : "↑"} ${item.delta.replace(/^[-+]/, "")}` : "--"}
); } function MetricSparkline({ series }) { const lines = Array.isArray(series) ? series.filter((item) => Array.isArray(item.data) && item.data.length > 1) : []; if (!lines.length) { return ; } const values = lines.flatMap((line) => line.data.map((point) => Number(point.value) || 0)); const min = Math.min(...values); const max = Math.max(...values); return ( ); } function sparklinePoints(points, min, max) { const width = 100; const height = 24; const count = points.length; return points.map((point, index) => { const x = count <= 1 ? width : (index / (count - 1)) * width; const normalized = max <= min ? 0.5 : ((Number(point.value) || 0) - min) / (max - min); const y = height - normalized * 18 - 3; return `${x.toFixed(2)},${y.toFixed(2)}`; }).join(" "); }