A bar / histogram draw layer. In its simplest form, one rectangle per event
spanning the key's [begin, end] from the axis baseline to a numeric
column's value (see below). It also draws stacked bars (a group-by
dimension → segments, columns / a Map series / bins) and horizontal
bars (orientation='horizontal', bins on the y axis) — first-class histogram
support. Registers into the enclosing Layers and renders nothing to the
DOM; the row draws it.
Data sources. A time / value TimeSeries or ValueSeries (column), a
wide series or bins array (columns), or a Map<group, TimeSeries>
(column) — the last three stack. Every shape composes from pond's own
aggregation (aggregate / byColumn / partitionBy); the histogram guide
has the recipes.
Baseline (single, vertical). Bars rest on the zero line when the axis
domain spans zero, or on the axis floor when an explicit <YAxis min> sits
above zero (see resolveBarBaseline).
Baseline (stacked). A stack is cumulative from value 0 — the segments
sum upward from the zero line, so its value axis must include 0. The
auto-fit guarantees this: stackValueExtent always returns [0, maxTotal].
An explicit <YAxis min> above 0 is therefore unsupported for a stack — it
would hide the bottom of the cumulative column; only the portion above the floor
draws (clipped cleanly at the plot floor, as any bar below an explicit floor is).
Segment values are assumed non-negative (a negative or zero segment is
skipped — diverging stacks are out of scope).
Interaction (opt-in via id). Hover lights the bar / segment under the
cursor (hit-tested by pixel rect, so it works in both orientations); click
selects it (outlined). A stacked segment's identity is (id, key = bin begin, label = group). Both channels are controllable from outside via the container
(selected/onSelect, hovered/onHover). The in-chart flag/crosshair
value cursor is single-series-vertical only.
<Layers>
<BarChart series={hourlyVolume} column="count" />
<BarChart series={byHost} column="n" colors={{ web1: '#…' }} />
<BarChart bins={powerDist} column="seconds" orientation="horizontal" ordinal />
</Layers>
Props
asstringThe single series' semantic identifier — what the data is. The theme maps
it to a BarStyle (theme.bar[as] ?? theme.bar.default). Single
series only — ignored (not an error) on a stacked chart, which colours
its segments per group instead (see colors).
axisstringWhich <YAxis> (by its id) this layer scales against — the scale (as
picks the style). Omitted ⇒ the row's default axis. For a horizontal
histogram this is the bin (band) axis; for a vertical one the value
axis.
binColorsreadonly (string | undefined)[]Per-bin colours for a single-series band chart — binColors[i] fills
bar i (aligned to the bins / bands in order), overriding the as/theme
fill. This is the way to colour heart-rate / power zones or value bands
each their own colour (the colors map above is per-group, for stacks).
An undefined/short entry falls back to the theme fill. Meant for a
single-series chart (column + bins, or a horizontal single series); on a
multi-group stack it would tint every segment of a bin alike, so it's not
the tool there.
binsreadonly BinRecordBinRecordtype@pond-ts/chartsunknownA single bin record from byColumn — its [start, end) range plus the mapped
aggregate columns (read by name via stacksFromBins). Deliberately just
the start/end shape (no index signature) so pond's
byColumn(...): Array<{ start, end } & ReduceResult> assigns to it structurally
— the aggregate fields ride along and are read out by the reader.
[]byColumn bin records — Array<{ start, end, …aggregates }> from a
value-band aggregation
(series.byColumn('power', { width: 20 }, { seconds: … })). The value-axis
alternative to series: column / columns name the aggregate field(s) to
draw. Pair with ordinal for a category (band) axis.
categoriesreadonly CategoryDatumCategoryDatuminterface@pond-ts/charts{ label: string; value: number }One category's { label, value } for a categorical bar chart — the row-read /
transpose view's (columnName, cell) pair (categorical-axis RFC, Phase 1). An
ordered list of these is the explicit categorical data source; Phase 2's
transpose reader produces the same list from a wide series' row.
[]Categorical data — an ordered { label, value }[], one bar per category
on a first-class ordinal category x-axis (the container infers
xKind:'category' and builds a band scale over the labels). The transpose
view's "columns on x": each label is a category (ticker / account / zone),
value its bar height. Provide exactly one of series / bins /
categories; categories takes no column/columns and is vertical only
(categories on x). Colour per category via binColors. (Categorical-axis RFC,
Phase 1.)
colorsReadonly<Record<string, string>>Per-group colour override for a stacked chart — { group: cssColor }.
A segment resolves colors[group] ?? theme.bar[group]?.fill ?? theme.bar.default.fill, so named roles (e.g. a crit band styled in the
theme) come from the theme while ad-hoc groups (five hosts) take a colour
here without minting a theme role. The single styling channel still holds:
this is the stack's one colour input.
columnstringName of the numeric value column for the bar height (single series). Provide
column or columns, not both.
columnsreadonly string[]Stacked-segment columns, bottom → top — one segment per name. Use with a
wide series (e.g. pivotByGroup output) or with bins. Mutually
exclusive with column, and invalid with a Map series (there the segments
are the map's groups; use column).
gapnumberPixel gap between adjacent bars / bins — the bar's key span is inset by this
total (half each side). Omitted ⇒ the theme's bar gap. A span the gap
would invert collapses to the style's minWidth.
idstringThe stable series identity for selection + hover — and it gates
interactivity (a bar layer is selectable/hoverable only when given an
id). For a stack, a clicked / hovered segment is identified by
(id, key = bin begin, label = group), so two segments in one bin don't both
light up.
ordinalbooleanFor bins: lay the bands out as uniform unit slots ([i, i+1]) instead
of their numeric [start, end] edges — an ordinal band axis where every band
reads the same width (heart-rate zones). Ignored for series.
orientationOrientationOrientationtype@pond-ts/charts'vertical' | 'horizontal'Bar growth direction — the histogram orientation. 'vertical' bars grow up
from a value baseline, bins on the x axis (the column / time-bucket look);
'horizontal' bars grow right, bins on the y axis (the band look, e.g.
heart-rate zones). The stacked geometry below transposes on this alone — the
StackedBarSeries data is identical for both.
Bar growth direction (the histogram orientation). Default 'vertical'.
'vertical'— bars grow up from a value baseline, bins on the x axis (time buckets, value bands). The column / time-histogram look.'horizontal'— bars grow right, bins on the y axis (a band axis like heart-rate zones). Label the bands with<YAxis ticks={[{ at, label }]}>.
A 'horizontal' chart puts the value on the shared x axis, so its
container's x-kind is 'value' — it cannot share a <ChartContainer> with
time-series rows (each horizontal histogram stands alone). Vertical charts
have no such constraint. The in-chart flag / crosshair value cursor is
drawn for the single-series vertical case only; stacked and horizontal
charts read out via hover / click (onHover / onSelect).
seriesTimeSeriesTimeSeriesclasspond-tsAn immutable, schema-typed, ordered collection of events — the batch
layer's core primitive. A series is constructed whole from complete data
and never mutated: every transform (filter, align, rollup, …)
returns a new TimeSeries, so the full analytical surface can sort,
scan, or index freely. Example:
new TimeSeries({ name, schema, rows }).
<S> | ValueSeriesValueSeriesclasspond-tsA value-keyed series — the closed value-axis counterpart of
TimeSeries. Its key is a monotonic non-time axis (distance, cumulative
work, …). Two doors in: project a TimeSeries onto one of its monotonic
columns (TimeSeries.byValue(axis) — a track re-keyed by cumulative
distance), or construct directly from columnar arrays
(`ValueSeries.fromC…
<VS> | ReadonlyMap<string, TimeSeriesTimeSeriesclasspond-tsAn immutable, schema-typed, ordered collection of events — the batch
layer's core primitive. A series is constructed whole from complete data
and never mutated: every transform (filter, align, rollup, …)
returns a new TimeSeries, so the full analytical surface can sort,
scan, or index freely. Example:
new TimeSeries({ name, schema, rows }).
<S>>The source series. Provide exactly one of series or bins.
- A
TimeSeries(interval / timeRange-keyed is the primary form — each event's key[begin, end]is a bar's x-span; a point-keyed series derives its width from neighbour spacing) → single-series bars viacolumn, or stacked bars from a wide series viacolumns. - A
ValueSeries(series.byValue('dist')) bars against its value axis. - A
ReadonlyMap<group, TimeSeries>— one series per stack group, all on the same bin grid, the shapeseries.partitionBy('host', { groups }).aggregate(seq, m).toMap()returns. Stacked bars,columnnames the shared value column, groups = map order.
Live charts: series.byValue(…) / .toMap() mint fresh objects each
call, so an inline series={…} re-registers this layer every render — on a
frequently re-rendering chart, memoize the projection (useMemo).