Skip to content

UTC domains

Read as Markdown

Import from @pibbl/core/viz. UTC positions are numeric epoch milliseconds, not Date objects. No runtime data fetching is required.

import {
UTCScale,
Axis,
useUTCScale,
utcTickLabels,
type NumericDomain,
} from "@pibbl/core/viz";
const domain: NumericDomain = [Date.UTC(2025, 0, 1), Date.UTC(2026, 0, 1)];
declare function extent<D>(
data: readonly D[],
value: (
datum: D,
index: number,
data: readonly D[],
) => number | null | undefined,
): NumericDomain | undefined;
declare function niceUTCDomain(
domain: NumericDomain,
options?: { count?: number },
): NumericDomain;

extent calls the accessor once per row, skips null/undefined, rejects other nonfinite or nonnumeric results, and returns a frozen minimum/maximum pair. Empty/all-missing data returns undefined. Singleton data returns equal endpoints. It never sorts, mutates, subscribes, or caches.

niceUTCDomain expands epoch endpoints to enclosing UTC boundaries. Count defaults to 5 and must be an integer 2–100. It preserves descending direction. A singleton gets one millisecond padding on each side, or inward padding at Date limits. Outward rounding beyond Date range throws; it never wraps a date. With count 2, if no cadence can avoid an interior boundary (a domain straddling year zero), niceness keeps the original integral-millisecond bounds.

UTCScaleProps shares id, domain, range, reverse, style, and children with the linear scale and is provided by UTCScale. NumericDomain and UtcDomain are readonly numeric pairs. UTC domain endpoints must be distinct safe integer milliseconds inside ±8,640,000,000,000,000. Domain/range/reverse accept signals.

<UTCScale id="date" domain={domain} range="width">
<Axis
scale="date"
position="bottom"
tickCount={5}
tickFormat={(value) => new Date(Number(value)).toISOString().slice(0, 10)}
/>
</UTCScale>

useUTCScale(id) returns Signal<ResolvedUtcScale>. Snapshots are frozen; signal identity survives data/allocation changes.

UTC map/invert use linear arithmetic with no clamp. Mapping accepts finite fractional milliseconds inside Date range. A collapsed range cannot invert. ticks(count = 5) accepts 2–100 and returns original endpoints plus aligned UTC interior boundaries, using a cadence that fits the count. Axis handles counts 0 and 1. Month/year lengths are calendar-aware; weeks start Monday. The result may have fewer ticks than requested and preserves descending order.

formatTick(value) returns deterministic full ISO UTC text, independent of prior tick calls. Fractional milliseconds truncate toward zero for display only. Use an Axis formatter for compact presentation; no automatic collision solver or locale/time-zone selection is implied. Explicit Axis ticks remain numeric, bounded, unique, in-domain, and in caller order.

Lines, points, custom plots, bar value scales, ScaleAdjust and numeric hover queries accept either continuous kind. Missing-data gaps keep their existing semantics. UTC is not browser-local calendar time; DST, IANA time zones, log scales and automatic domain mutation remain separate work.

utcTickLabels(values: readonly number[], options?: UTCTickLabelOptions): readonly string[] returns frozen labels in the same order, without modifying timestamps. locale defaults to "en-US"; the calendar is Gregorian and the time zone is always UTC. Use the returned array in Axis.tickFormat={(_, index) => labels[index]} with the same tickValues array. Existing useUTCScale(id).get().formatTick(value) keeps its full-ISO contract.

The complete set determines precision: January 1 midnight ticks use years; first-of-month midnight ticks use month/year; other midnight ticks use month/day/year; sub-day ticks also include 24-hour hour/minute, adding seconds and three millisecond digits when present. Every label keeps its year and any necessary date, so collision skipping never removes essential calendar context. An era is included for all labels when any input is in year zero or earlier. UTC should still be identified in the composition’s title or units.

Empty input returns a frozen empty array. At most 100 safe-integer epoch millisecond values within the JavaScript Date range are accepted; invalid input throws RangeError. Duplicates and descending/arbitrary order are preserved. Invalid locale options retain native Intl errors; punctuation follows host Intl data. The helper accepts plain values, not signals. Read signal .get() in a component/computed value to recompute; it acquires no resources or subscriptions.

function DateAxis() {
const ticks = useUTCScale("date").get().ticks(5);
const labels = utcTickLabels(ticks);
return (
<Axis
scale="date"
position="bottom"
tickValues={ticks}
tickFormat={(_, index) => labels[index]}
labelOverlap="skip"
/>
);
}

The minimal UTC demo is runnable and editable with these labels.

Computes a finite numeric extent in source order, skipping only null and undefined.

extent: <D>(data: readonly D[], value: (datum: D, index: number, data: readonly D[]) => number | null | undefined) => LinearDomain | undefined

Related API: extent, LinearDomain.

  • data — Source rows, which are never sorted or mutated.

  • value — Accessor called once per row with its index and original array.

A frozen minimum/maximum pair, or undefined when every row is missing.

niceUTCDomain

View source — packages/core/src/features/viz/lib/utc-scale.ts:118

Expands a numeric timestamp domain to enclosing UTC calendar boundaries.

niceUTCDomain: (domain: LinearDomain, options?: { readonly count?: number; }) => LinearDomain

Related API: niceUTCDomain, LinearDomain.

  • domain — Safe integer epoch-millisecond endpoints, possibly equal or descending.

  • options — Optional bounded target tick count (default 5).

A frozen outward-rounded domain preserving its direction. See LinearDomain.

UTCScale

View source — packages/core/src/features/viz/lib/utc-scale.ts:96

Numeric endpoints shared by continuous scales. See LinearDomain.

type NumericDomain = LinearDomain

Related API: NumericDomain, LinearDomain.

View source — packages/core/src/features/viz/lib/types.ts:149

UTC timestamps use numeric epoch milliseconds. See LinearDomain.

type UtcDomain = LinearDomain

Related API: UtcDomain, LinearDomain.

View source — packages/core/src/features/viz/lib/types.ts:147

Calendar-aware UTC scale inputs. See LinearScaleProps.

type UTCScaleProps = LinearScaleProps

Related API: UTCScaleProps, LinearScaleProps.

View source — packages/core/src/features/viz/lib/types.ts:151

id
readonly id: ScaleId

Related API: ScaleId.

Stable identifier of this resource or connection. See ScaleId.

View source — packages/core/src/features/viz/lib/types.ts:75

domain
readonly domain: SignalValue<LinearDomain>

Related API: SignalValue, LinearDomain.

Data values or endpoints accepted by the scale. See SignalValue, LinearDomain .

View source — packages/core/src/features/viz/lib/types.ts:80

range
readonly range: SignalValue<ScaleRange>

Related API: SignalValue, ScaleRange.

Logical output coordinates produced by the scale. See SignalValue, ScaleRange .

View source — packages/core/src/features/viz/lib/types.ts:85

reverse (optional)
readonly reverse?: SignalValue<boolean> | undefined

Related API: SignalValue.

Whether to reverse the direction of the mapping or guide. See SignalValue.

View source — packages/core/src/features/viz/lib/types.ts:87

style (optional)
Full type declaration
readonly style?: SignalValue<Readonly<{ left?: SignalValue<number | `${number}%` | undefined>; top?: SignalValue<number | `${number}%` | undefined>; width?: SignalValue<Length | undefined>; height?: SignalValue<Length | undefined>; alignSelf?: SignalValue<"auto" | "center" | "end" | "flex-end" | "flex-start" | "start" | "stretch" | undefined>; justifySelf?: SignalValue<"auto" | "center" | "end" | "start" | "stretch" | undefined>; flexBasis?: SignalValue<Length | undefined>; flexGrow?: SignalValue<number | undefined>; flexShrink?: SignalValue<number | undefined>; gridColumnStart?: SignalValue<number | undefined>; gridColumnSpan?: SignalValue<number | undefined>; gridRowStart?: SignalValue<number | undefined>; gridRowSpan?: SignalValue<number | undefined>; transition?: SignalValue<PibblTransitionBinding | undefined>; custom?: unknown; filter?: SignalValue<PibblFilter | readonly PibblFilter[] | undefined>; }>> | undefined

Related API: SignalValue, Length, PibblTransitionBinding, PibblFilter.

Declared presentation and layout properties. See SignalValue, SignalStyle, ScaleLayoutStyle.

View source — packages/core/src/features/viz/lib/types.ts:92

children (optional)
readonly children?: PibblNode

Related API: PibblNode.

Descendant content or the callback that supplies it. See PibblNode.

View source — packages/core/src/features/viz/lib/types.ts:94

UTC continuous mapping with stateless ISO formatting. See ResolvedLinearScale.

interface ResolvedUtcScale extends Omit<ResolvedLinearScale, "type">

Related API: ResolvedUtcScale, ResolvedLinearScale.

View source — packages/core/src/features/viz/lib/types.ts:227

type
readonly type: "utc"

UTC calendar scale discriminant. See UTCScaleProps.

View source — packages/core/src/features/viz/lib/types.ts:229

formatTick
formatTick: (value: number) => string

Formats a timestamp as full UTC ISO text without changing tick geometry.

  • value — Finite epoch milliseconds inside the Date range.

ISO text with millisecond precision. See ResolvedUtcScale.

View source — packages/core/src/features/viz/lib/types.ts:235

domain
readonly domain: LinearDomain

Related API: LinearDomain.

Data values or endpoints accepted by the scale. See LinearDomain.

View source — packages/core/src/features/viz/lib/types.ts:193

range
readonly range: readonly [number, number]

Logical output coordinates produced by the scale. See ResolvedLinearScale.

View source — packages/core/src/features/viz/lib/types.ts:195

frame
readonly frame: Readonly<LayoutBox>

Related API: LayoutBox.

Resolved layout frame containing the scale. See LayoutBox.

View source — packages/core/src/features/viz/lib/types.ts:197

map
map: (value: number) => number

Maps a numeric domain value to a logical range coordinate. See ResolvedLinearScale.

  • value — Numeric domain coordinate.

The corresponding range coordinate.

View source — packages/core/src/features/viz/lib/types.ts:203

invert
invert: (pixel: number) => number

Related API: invert.

Maps a logical range coordinate back into the numeric domain. See ResolvedLinearScale .

  • pixel — Coordinate in the scale’s pixel range.

The corresponding numeric domain value.

View source — packages/core/src/features/viz/lib/types.ts:210

ticks
ticks: (count?: number) => readonly number[]

Returns representative numeric tick values for the requested count. See ResolvedLinearScale.

  • count — Suggested number of ticks.

Tick values in domain coordinates.

View source — packages/core/src/features/viz/lib/types.ts:217

Any supported numeric mapping. See ResolvedUtcScale.

type ResolvedContinuousScale = | ResolvedLinearScale
| ResolvedUtcScale
| ResolvedLogScale
| ResolvedSymlogScale

Related API: ResolvedContinuousScale, ResolvedLinearScale, ResolvedUtcScale, ResolvedLogScale, ResolvedSymlogScale.

View source — packages/core/src/features/viz/lib/types.ts:238

type
readonly type: "linear" | "log" | "symlog" | "utc"

The literal “linear” identifying this variant. See ResolvedLinearScale. Logarithmic mapping discriminant. See LogScaleProps. Signed logarithmic discriminant. See SymlogScaleProps. UTC calendar scale discriminant. See UTCScaleProps.

View source — packages/core/src/features/viz/lib/types.ts:191

domain
readonly domain: LinearDomain

Related API: LinearDomain.

Data values or endpoints accepted by the scale. See LinearDomain.

View source — packages/core/src/features/viz/lib/types.ts:193

range
readonly range: readonly [number, number]

Logical output coordinates produced by the scale. See ResolvedLinearScale.

View source — packages/core/src/features/viz/lib/types.ts:195

frame
readonly frame: Readonly<LayoutBox>

Related API: LayoutBox.

Resolved layout frame containing the scale. See LayoutBox.

View source — packages/core/src/features/viz/lib/types.ts:197

map
map: (value: number) => number

Maps a numeric domain value to a logical range coordinate. See ResolvedLinearScale.

  • value — Numeric domain coordinate.

The corresponding range coordinate.

View source — packages/core/src/features/viz/lib/types.ts:203

invert
invert: (pixel: number) => number

Related API: invert.

Maps a logical range coordinate back into the numeric domain. See ResolvedLinearScale .

  • pixel — Coordinate in the scale’s pixel range.

The corresponding numeric domain value.

View source — packages/core/src/features/viz/lib/types.ts:210

ticks
ticks: (count?: number) => readonly number[]

Returns representative numeric tick values for the requested count. See ResolvedLinearScale.

  • count — Suggested number of ticks.

Tick values in domain coordinates.

View source — packages/core/src/features/viz/lib/types.ts:217

Creates compact labels with calendar context retained on every tick.

utcTickLabels: (values: readonly number[], options?: UTCTickLabelOptions) => readonly string[]

Related API: utcTickLabels, UTCTickLabelOptions.

  • values — At most 100 safe integer epoch milliseconds within Date range, in any order.

  • options — Explicit locale; default en-US.

Frozen labels in input order. No geometry or scale state changes. See UTCTickLabelOptions.

View source — packages/core/src/features/viz/lib/utc-labels.ts:12

Locale used for compact UTC tick text. See utcTickLabels.

interface UTCTickLabelOptions

Related API: UTCTickLabelOptions.

View source — packages/core/src/features/viz/lib/utc-labels.ts:2

locale (optional)
readonly locale?: string | undefined

BCP 47 locale, default en-US. Calendar is always Gregorian; time zone is UTC.

View source — packages/core/src/features/viz/lib/utc-labels.ts:4

Read the Data visualization companion for ownership, adaptation, failure modes, and verification. Agent start provides the version-selection workflow.

Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.