SPB Git forge

spb/rareindex

Public
54commits 1branches 0releases
7.1 MBsize
maindefault branch
10 days agolast push
TypeScript 61.9% HTML 37.2% SQL 0.7%
1.4 KB · 20 lines tsx
Raw Blame History
1/** Server-renderable sparkline (no hover; used inside dense tables and stat tiles). */2export function Sparkline({ values, width = 96, height = 24, tone = 'auto', className }: { values: number[]; width?: number; height?: number; tone?: 'auto' | 'neutral' | 'index'; className?: string }) {3  const v = values.filter((x) => Number.isFinite(x));4  if (v.length < 2) return <span className={`inline-block ${className ?? ''}`} style={{ width, height }} aria-hidden />;5  const min = Math.min(...v);6  const max = Math.max(...v);7  const pad = 2;8  const sx = (i: number) => pad + (i / (v.length - 1)) * (width - pad * 2);9  const sy = (y: number) => (max === min ? height / 2 : pad + (height - pad * 2) - ((y - min) / (max - min)) * (height - pad * 2));10  const d = v.map((y, i) => `${i === 0 ? 'M' : 'L'}${sx(i).toFixed(1)},${sy(y).toFixed(1)}`).join(' ');11  const up = v[v.length - 1]! >= v[0]!;12  const color = tone === 'neutral' ? 'var(--ri-fg-subtle)' : tone === 'index' ? 'var(--ri-index)' : up ? 'var(--ri-gain)' : 'var(--ri-loss)';13  return (14    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} className={`inline-block align-middle ${className ?? ''}`} aria-hidden>15      <path d={d} fill="none" stroke={color} strokeWidth={1.5} strokeLinejoin="round" strokeLinecap="round" />16      <circle cx={sx(v.length - 1)} cy={sy(v[v.length - 1]!)} r={2} fill={color} />17    </svg>18  );19}20