Chart spec
A ChartSpec is a plain-JSON description of a chart, discriminated on
type and versioned (version: 1). <Chart spec={spec} rows={rows} />
renders it. Nothing in a spec is a function or JSX, so specs can be stored,
transmitted, diffed, and built by end users at runtime.
import Chart, {type ChartSpec} from '@zuilib/charts'
const spec: ChartSpec = {
version: 1,
type: 'bar',
title: 'Revenue by region',
xKey: 'region',
series: [{field: 'revenue', label: 'Revenue', format: 'currency:USD'}],
yAxis: {format: 'compact'},
}
Series and colors
Cartesian specs (line, area, bar, composed, radar) declare
series: each entry names a row field, an optional label, an optional
palette slot (paletteSlot: 1–8, assigned in declaration order when
left out — fixed order, never cycled), an optional axis: 'secondary'
for a secondary value axis, and stacking via stackId or the spec-level
stacked: true | 'percent'.
Category specs (pie, donut, radial-bar, funnel, treemap) declare
nameKey + valueKey/sizeKey; categories take palette slots in data
order. Scatter declares xKey/yKey and an optional groupKey that
splits points into colored groups — at most three concurrently, the
palette subset validated for every-pair discrimination.
A dual axis is supported but discouraged: two measures of different scale
read better as two charts or an indexed series. Keep axis: 'secondary' for
the genuinely paired cases (a count and a rate over the same buckets).
Format tokens
Formats are named, not passed: 'number', 'compact', 'percent'
(0–1 fraction), 'currency:USD' (any ISO code), 'date:short|medium|long',
'datetime:short|medium', 'none'. All are Intl-backed and honor the
locale prop. A custom format keeps the spec serializable — the spec names
a token and the function arrives as a prop:
<Chart
spec={{...spec, yAxis: {format: 'sla-ms'}}}
rows={rows}
formats={{'sla-ms': (v) => `${v} ms`}}
/>
A factory receives the part after the colon, so one entry can serve a family of tokens:
<Chart spec={spec} rows={rows} formats={{unit: (arg) => (v) => `${v} ${arg}`}} />
// the spec may now name 'unit:req/s', 'unit:GB', …
Interaction
tooltip(default on) renders the themed tooltip.legenddefaults to on for two or more entries, off for one; a single series needs no legend — the title names it.interactiondecides what a mark click does inside aCrossFilterProvider:'filter'(default) toggles the category into the shared filters (shift-click accumulates),'highlight'only sets the shared highlight,'none'does nothing. Every click also reports throughonMarkClick.brush: trueadds a range brush under a cartesian plot.referenceLinesdraw targets and thresholds:{axis: 'y', value: 90000, label: 'Target'}.
Gallery
Every chart type, each rendered live from the spec shown below it.