spb/satelliteindex
Public
TypeScript 66.5%
Python 30.9%
JavaScript 1.4%
CSS 0.7%
1import { Bars, StackedBars } from '@/components/charts/charts';2import { fmtInt, num } from '@/lib/format';3import type { LaunchTimeline } from '@/lib/types';45const REGION_LABELS = { us: 'United States', russia_cis: 'Russia / Kazakhstan', china: 'China', other: 'Other / unknown site' };67/** Launches per year by launch-site region + monthly cadence for the last 36 months. Server-rendered SVG. */8export function LaunchTimelineCharts({ timeline }: { timeline: LaunchTimeline }) {9 const years = timeline.years.map((y) => ({ x: String(y.year), us: num(y.us) ?? 0, russia_cis: num(y.russia_cis) ?? 0, china: num(y.china) ?? 0, other: num(y.other) ?? 0 }));10 const months = timeline.months.map((m) => ({ x: m.month.slice(0, 7), y: num(m.launches) ?? 0 }));11 const lastYear = timeline.years[timeline.years.length - 1];12 const totalLaunches = timeline.years.reduce((s, y) => s + (num(y.launches) ?? 0), 0);13 const totalPayloads = timeline.years.reduce((s, y) => s + (num(y.payloads) ?? 0), 0);14 return (15 <div className="grid gap-8 lg:grid-cols-[minmax(0,3fr)_minmax(0,2fr)]">16 <div className="min-w-0">17 <div className="mb-2 flex items-baseline justify-between gap-3">18 <p className="eyebrow">Launches per year by launch-site region</p>19 <p className="tnum text-xs text-ink-3">{fmtInt(totalLaunches)} launches · {fmtInt(totalPayloads)} payloads since {timeline.years[0]?.year ?? '—'}</p>20 </div>21 <StackedBars data={years} keys={['us', 'russia_cis', 'china', 'other']} labels={REGION_LABELS} title="Orbital launches per year by launch-site region" height={220} xTicks={10} />22 </div>23 <div className="min-w-0">24 <div className="mb-2 flex items-baseline justify-between gap-3">25 <p className="eyebrow">Monthly cadence · last 36 months</p>26 {lastYear && <p className="tnum text-xs text-ink-3">{fmtInt(lastYear.launches)} launches in {lastYear.year}</p>}27 </div>28 <Bars data={months} title="Launches per month over the last 36 months" height={220} xTicks={6} highlightLast color="var(--series-2)" />29 <p className="mt-1 text-2xs text-ink-3">The last bar is the current month (partial).</p>30 </div>31 </div>32 );33}34