spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1"use client";23import { ColumnChart } from "@/components/ui/charts";4import { fmtInt, fmtMw } from "@/lib/format";56/** Facilities opened per published opening year; MW in the tooltip only when published for that year. */7export function OpeningTimeline({ data }: { data: Array<{ year: number; opened: number; openedMw: number | null }> }) {8 const rows = [...data].filter((d) => Number.isFinite(d.year)).sort((a, b) => a.year - b.year);9 const first = rows[0]!.year;10 const last = Math.max(rows[rows.length - 1]!.year, new Date().getUTCFullYear());11 const byYear = new Map(rows.map((r) => [r.year, r]));12 const span = last - first + 1;13 const filled: Array<{ label: string; value: number; secondary: number | null }> = [];14 for (let y = first; y <= last; y++) {15 const r = byYear.get(y);16 filled.push({ label: String(y), value: r?.opened ?? 0, secondary: r?.openedMw ?? null });17 }18 const data2 = span > 30 ? rows.map((r) => ({ label: String(r.year), value: r.opened, secondary: r.openedMw })) : filled;19 const mwYears = rows.filter((r) => r.openedMw !== null).length;20 return (21 <div>22 <ColumnChart data={data2} height={150} format={(v) => fmtInt(v)} color="var(--st-operational)" ariaLabel="Facilities opened per year" />23 <ul className="mt-2 flex flex-wrap gap-x-3 gap-y-1 text-[11.5px] text-ink-3">24 {rows.slice(-6).map((r) => (25 <li key={r.year} className="figure">26 {r.year}: {fmtInt(r.opened)} opened{r.openedMw !== null ? ` · ${fmtMw(r.openedMw)}` : ""}27 </li>28 ))}29 </ul>30 <p className="mt-1.5 text-[11px] text-ink-4">{mwYears ? `${mwYears} of ${rows.length} years carry a published MW figure.` : "No opening year carries a published MW figure."} Facilities without a published opening date are not charted.</p>31 </div>32 );33}34