UTC scales and domain helpers
Render real NOAA observations with UTC calendar ticks, numeric extents and outward domain rounding.
APIs demonstrated
Section titled “APIs demonstrated”- extent from
@pibbl/core/viz - niceUTCDomain from
@pibbl/core/viz - NumericDomain from
@pibbl/core/viz - UtcDomain from
@pibbl/core/viz - UTCScaleProps from
@pibbl/core/viz - ResolvedUtcScale from
@pibbl/core/viz - ResolvedContinuousScale from
@pibbl/core/viz
Complete example
Section titled “Complete example”Plain source. Run as a browser module after the document body exists. TSX uses jsx: "react-jsx" and jsxImportSource: "@pibbl/core".
import { Overlay, Group, Text, pibbl, useLayoutBox } from "@pibbl/core";import { Axis, LineSeries, extent, niceUTCDomain, type NumericDomain, type UtcDomain, type UTCScaleProps, type ResolvedUtcScale, type ResolvedContinuousScale, useUTCScale, UTCScale, LinearScale } from "@pibbl/core/viz";
// NOAA GML / Scripps, Mauna Loa monthly CO2 (ppm), Jan–Jun 1980.// https://gml.noaa.gov/webdata/ccgg/trends/co2/co2_mm_mlo.csv// Reused from the repository's 2026-09-28 snapshot; no runtime requests.const data = [337.9, 338.34, 340.07, 340.93, 341.45, 341.36].map((ppm, month) => ({ time: Date.UTC(1980, month, 1), ppm,}));const observed: NumericDomain = extent(data, row => row.time)!;const domain: UtcDomain = niceUTCDomain(observed, { count: 4 });const utcProps: UTCScaleProps = { id: "date", domain, range: "width" };const monthName = new Intl.DateTimeFormat("en-US", { month: "short", timeZone: "UTC" });
function Readout() { const utc: ResolvedUtcScale = useUTCScale("date").get(); const numeric: ResolvedContinuousScale = useUTCScale("date").get(); const middle = numeric.invert((numeric.range[0] + numeric.range[1]) / 2); return <Text pointerEvents="none" style={{ left: 0, top: -32, textBaseline: "alphabetic", font: "12px monospace", fill: "#64748b" }}> {`Midpoint · ${utc.formatTick(middle).slice(0, 10)} UTC`} </Text>;}function Scene() { const { width, height } = useLayoutBox(); return <> <Text style={{ left: 24, top: 32, textBaseline: "alphabetic", font: "600 22px sans-serif", fill: "#182a38" }}>A real calendar axis</Text> <Text style={{ left: 24, top: 57, textBaseline: "alphabetic", font: "13px sans-serif", fill: "#64748b" }}>Mauna Loa CO₂ · ppm · Jan–Jun 1980</Text> <Group style={{ translateX: 56, translateY: 118 }}> <Overlay style={{ width: Math.max(160, width - 94), height: Math.max(100, height - 180) }}> <UTCScale style={{ width: Math.max(160, width - 94), height: Math.max(100, height - 180) }} {...utcProps}> <LinearScale id="ppm" domain={[337, 342]} range="height" reverse> <Readout /> <Axis scale="date" position="bottom" tickCount={4} tickFormat={value => monthName.format(Number(value))} /> <Axis scale="ppm" position="left" tickValues={[337, 339, 342]} /> <LineSeries data={data} x="time" y="ppm" xScale="date" yScale="ppm" style={{ stroke: "#087f8c", strokeWidth: 3 }} /> </LinearScale> </UTCScale> </Overlay> </Group> <Text style={{ left: 24, top: height - 15, textBaseline: "alphabetic", font: "11px sans-serif", fill: "#64748b" }}>Source: NOAA GML / Scripps · static snapshot</Text> </>;}const canvas = document.createElement("canvas");canvas.style.cssText = "width:100%;height:360px";document.body.append(canvas);const app = pibbl(canvas, <Scene />, { viewport: "responsive" });window.addEventListener("pagehide", () => app.dispose(), { once: true });Usage notes
Section titled “Usage notes”Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.