const { useState: useStateP, useMemo: useMemoP, useRef: useRefP } = React; function PollingSection({ lang = "en" }) { const data = window.POLLING_DATA; const t = (en, fr) => (lang === "fr" ? fr : en); const [mode, setMode] = useStateP("parties"); // 'parties' | 'approval' const [hoverIdx, setHoverIdx] = useStateP(null); return (
{t("Public Support · Rolling aggregate", "Appui public · Moyenne mobile")}

{mode === "parties" ? t(<>Federal vote intention since the 2025 election., <>Intentions de vote depuis les élections de 2025.) : t(<>Carney approval, Angus Reid., <>Approbation de Carney, Angus Reid.)}

{mode === "parties" ? : }
{data.meta.note}
); } /* ────────────────────────────────────────────────────────── Shared chart geometry ────────────────────────────────────────────────────────── */ const W = 1180, H = 320, PL = 44, PR = 56, PT = 24, PB = 36; const innerW = W - PL - PR; const innerH = H - PT - PB; function ticksY(min, max, step) { const ticks = []; for (let v = min; v <= max + 0.0001; v += step) ticks.push(v); return ticks; } function fmtMonth(d) { const [y, m] = d.split("-"); return new Date(Number(y), Number(m) - 1, 1) .toLocaleDateString("en-CA", { month: "short" }) + (m === "01" ? ` ${y.slice(2)}` : ""); } /* ────────────────────────────────────────────────────────── Parties chart — multi-line with hover crosshair ────────────────────────────────────────────────────────── */ function PartiesChart({ data, hoverIdx, setHoverIdx }) { const svgRef = useRefP(null); const yMin = 0, yMax = 50; const yTicks = ticksY(yMin, yMax, 10); const N = data.series.length; const x = (i) => PL + (i / (N - 1)) * innerW; const y = (v) => PT + innerH - ((v - yMin) / (yMax - yMin)) * innerH; const handleMove = (e) => { const rect = svgRef.current.getBoundingClientRect(); const px = ((e.clientX - rect.left) / rect.width) * W; const i = Math.round(((px - PL) / innerW) * (N - 1)); setHoverIdx(Math.max(0, Math.min(N - 1, i))); }; const lastRow = data.series[N - 1]; return (
setHoverIdx(null)} > {/* Y gridlines + labels */} {yTicks.map(v => ( {v}% ))} {/* X labels */} {data.series.map((row, i) => { if (i % 2 !== 0 && i !== N - 1) return null; return ( {fmtMonth(row.date)} ); })} {/* Hover crosshair */} {hoverIdx != null && ( )} {/* Party lines */} {data.parties.map(p => { const pts = data.series.map((row, i) => `${x(i)},${y(row[p.id])}`).join(" "); return ( {/* End-of-line label */} {p.name} {lastRow[p.id].toFixed(1)}% ); })} {/* Hover dots */} {hoverIdx != null && data.parties.map(p => ( ))} {/* Hover readout */} {hoverIdx != null && (
{fmtMonth(data.series[hoverIdx].date)}
{data.parties.map(p => (
{p.name} {data.series[hoverIdx][p.id].toFixed(1)}%
))}
)}
); } /* ────────────────────────────────────────────────────────── Approval chart — single area + line ────────────────────────────────────────────────────────── */ function ApprovalChart({ data, hoverIdx, setHoverIdx, lang = "en" }) { const t = (en, fr) => (lang === "fr" ? fr : en); const loc = lang === "fr" ? "fr-CA" : "en-CA"; const svgRef = useRefP(null); const yMin = 30, yMax = 70; const yTicks = ticksY(yMin, yMax, 10); const N = data.length; const x = (i) => PL + (i / (N - 1)) * innerW; const y = (v) => PT + innerH - ((v - yMin) / (yMax - yMin)) * innerH; const handleMove = (e) => { const rect = svgRef.current.getBoundingClientRect(); const px = ((e.clientX - rect.left) / rect.width) * W; const i = Math.round(((px - PL) / innerW) * (N - 1)); setHoverIdx(Math.max(0, Math.min(N - 1, i))); }; const pts = data.map((row, i) => `${x(i)},${y(row.value)}`).join(" "); const areaPath = `M ${PL},${y(yMin)} L ${data.map((r, i) => `${x(i)},${y(r.value)}`).join(" L ")} L ${x(N-1)},${y(yMin)} Z`; const last = data[N - 1]; const first = data[0]; const delta = last.value - first.value; const peak = data.reduce((a, b) => (b.value > a.value ? b : a)); const monthYear = (d) => { const [y, m] = d.split("-"); return new Date(+y, +m - 1, 1).toLocaleDateString(loc, { month: "short", year: "numeric" }); }; const monthApos = (d) => { const [y, m] = d.split("-"); return new Date(+y, +m - 1, 1).toLocaleDateString(loc, { month: "short" }) + " '" + y.slice(2); }; return (
setHoverIdx(null)} > {yTicks.map(v => ( {v}% ))} {data.map((row, i) => { if (i % 2 !== 0 && i !== N - 1) return null; return {fmtMonth(row.date)}; })} {/* 50% reference line */} 50% {hoverIdx != null && ( <> )} {/* End label */} {t("Now", "Auj.")} {last.value}%
{t("Approval", "Approbation")}, {monthYear(last.date)}
{last.value}%
{t("Since taking office", "Depuis l'entrée en fonction")}
{delta > 0 ? "+" : ""}{delta} pts
{t("Peak", "Sommet")}
{peak.value}% {monthApos(peak.date)}
{hoverIdx != null && (
{fmtMonth(data[hoverIdx].date)}
Approval {data[hoverIdx].value}%
)}
); } window.PollingSection = PollingSection;