import Link from 'next/link'; import type { IndexRow } from '@/lib/queries/indices'; import { fmtNum, cn, fmtPct, deltaClass } from '@/lib/format'; /** * Live tape (§163, §194): a terminal-style ticker of the PUBLISHED indices only — value + daily change. * Indices that have not met their constituent minimum are not in the tape; they are listed in a secondary * compact "Indices in development" line with their constituent progress. Pauses on hover/focus; static under * reduced motion. */ export function IndexTape({ indices, className }: { indices: IndexRow[]; className?: string }) { if (!indices.length) return null; const published = indices.filter((i) => i.latest).sort((a, b) => Number(b.isFlagship) - Number(a.isFlagship) || a.ticker.localeCompare(b.ticker)); const developing = indices.filter((i) => !i.latest).sort((a, b) => b.pricedAssets / Math.max(1, b.minConstituents) - a.pricedAssets / Math.max(1, a.minConstituents)); const items = published.map((i) => { const up = (i.change1d ?? 0) > 0; const down = (i.change1d ?? 0) < 0; return ( {i.ticker} {fmtNum(i.latest!.value, { digits: 2 })} {up ? '▲' : down ? '▼' : '■'} {fmtPct(i.change1d)} ); }); return (
{items.length ? (
{items} {items.map((it, k) => ( {it} ))}
) : (
No index has met its publication minimum yet — see the indices in development below.
)} {developing.length ? : null}
); } /** Secondary line (§194): indices not yet published, with constituent progress. Compact, no marquee. */ function DevelopingStrip({ items }: { items: IndexRow[] }) { return (
▸ Indices in development {items.length} · publish once each has its minimum number of priced constituents Methodology →
    {items.map((i) => (
  • {i.ticker} {i.pricedAssets}/{i.minConstituents}
  • ))}
); }