@pond-ts/charts 0.41.0 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,12 +3,14 @@
3
3
  All notable changes to this project are documented here.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
- The `@pond-ts` packages — `pond-ts`, `@pond-ts/react`, `@pond-ts/charts`, and
7
- `@pond-ts/fit` — release together under a single `v*` tag, so this file covers
8
- them all. Pre-1.0: minor bumps may include new features and type-level changes;
9
- patch bumps are strictly additive.
10
-
11
- [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.41.0...HEAD
6
+ The `@pond-ts` packages — `pond-ts`, `@pond-ts/react`, `@pond-ts/charts`,
7
+ `@pond-ts/fit`, and `@pond-ts/financial` — release together under a single `v*`
8
+ tag, so this file covers them all. Pre-1.0: minor bumps may include new features
9
+ and type-level changes; patch bumps are strictly additive.
10
+
11
+ [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.43.0...HEAD
12
+ [0.43.0]: https://github.com/pjm17971/pond-ts/compare/v0.42.0...v0.43.0
13
+ [0.42.0]: https://github.com/pjm17971/pond-ts/compare/v0.41.0...v0.42.0
12
14
  [0.41.0]: https://github.com/pjm17971/pond-ts/compare/v0.40.0...v0.41.0
13
15
  [0.40.0]: https://github.com/pjm17971/pond-ts/compare/v0.39.0...v0.40.0
14
16
  [0.39.0]: https://github.com/pjm17971/pond-ts/compare/v0.38.0...v0.39.0
@@ -39,6 +41,155 @@ patch bumps are strictly additive.
39
41
 
40
42
  ## [Unreleased]
41
43
 
44
+ ## [0.43.0] — 2026-07-11
45
+
46
+ The **categorical x-axis** release: a first-class ordinal band scale (ticker /
47
+ account / expiry on x — the transpose view of a time series), plus the charts
48
+ **interaction** wave that landed after v0.42.0 was cut — the region cursor and
49
+ its drag-to-select gesture, per-bin band colour, and annotation edges that snap
50
+ to session boundaries.
51
+
52
+ ### Added
53
+
54
+ - **`@pond-ts/charts`: a first-class categorical x-axis.** `<BarChart
55
+ categories={[{ label, value }]}>` draws one bar per category on an ordinal
56
+ **band scale** (the transpose view's "columns on x" — ticker / account / zone
57
+ on x). The container infers `xKind:'category'` and builds a `scaleBand` over the
58
+ labels; `<CategoryAxis>` ticks once per category. Colour per category via
59
+ `binColors`; selection reports the category name. **Negative** category values
60
+ draw below the baseline (the P&L / delta case) — a single-series category bar
61
+ honours its sign. New exports `scaleBand` / `ScaleBand`, `CategoryAxis`,
62
+ `categoryStack` / `CategoryDatum`. Additive — a new x-kind alongside time /
63
+ value; existing charts are unchanged. First slice of the categorical-axis RFC
64
+ (`docs/rfcs/categorical-axis.md`, Phase 1).
65
+ - **`@pond-ts/charts`: `transposeRow`** — read one **row** of a wide `TimeSeries`
66
+ **across** into `{ label, value }[]` for `<BarChart categories>`: the schema's
67
+ numeric columns (a `pivotByGroup` output's per-group columns, a term
68
+ structure's per-expiry columns) become the categories at one instant. Pick the
69
+ row with `at` (`'last'` — the head/live row — by default; `'first'`, an index,
70
+ or `{ time }`); bound / order the set with `columns`.
71
+ - **`@pond-ts/charts`: stable per-column selection identity.** `SelectInfo` gains
72
+ an optional **`mark`** — a stable per-mark identity within a layer. A categorical
73
+ bar reports its **column name** as `mark`, and a controlled `selected` echo /
74
+ the highlight match key on `(id, mark)`, so a pinned selection survives a column
75
+ reorder (the slot index doesn't; the name does). Additive — `mark` is
76
+ `undefined` for a time / value bar (whose sample `key` is already its identity).
77
+ Plus a category-axis **label policy**: a dense axis thins (keeps every k-th) and
78
+ ellipsis-truncates its labels so they stay legible while every bar draws.
79
+ - **`@pond-ts/charts`: region cursor (`cursor="region"`).** A shaded **band**
80
+ highlights the bucket under the pointer, bucketed by a new **`cursorSequence`**
81
+ prop — a `Sequence` (`Sequence.every('15m')`, `Sequence.calendar('week')`)
82
+ realized over the view, or a `BoundedSequence` (a `TradingCalendar`'s
83
+ `sessionSequence()` / `barSequence()`) used as-is. The band maps through the x
84
+ scale, so on a trading-time axis the closed part of a bucket collapses (crops
85
+ to live sessions). Time-axis only (a no-op on a value axis). (#409, #413)
86
+ - **`@pond-ts/charts`: draggable region cursor → one-shot select.** Opt-in
87
+ **`onRegionSelect?: (range: TimeRange) => void`** makes the region cursor
88
+ draggable: the band extends bucket by bucket and fires **once** on release
89
+ with the selected `[start, end)` `TimeRange` (the cursor doesn't keep it —
90
+ typical use is to zoom the view). With **no `cursorSequence`** it degenerates
91
+ to a hover **line** + **freeform** drag. **`regionSelectModifier="shift"`**
92
+ resolves the gesture conflict with `panZoom` (plain drag pans, shift-drag
93
+ selects); omitted, a region-drag preempts pan. (#416)
94
+ - **`@pond-ts/charts`: `binColors` — per-bin colour for single-series bars.**
95
+ `<BarChart binColors={[...]}>` colours each bar/band segment individually (one
96
+ colour per bin, in order), the single-series analog of the stacked `colors`
97
+ prop — used by the category axis (colour per category) and any single-series
98
+ band chart. (#408)
99
+ - **`@pond-ts/charts`: annotation edges snap to session boundaries.** When a
100
+ `<ChartContainer>` carries a trading calendar (disjoint x axis), dragging a
101
+ `<Region>` edge (or creating one) snaps to the nearest **session boundary**
102
+ rather than raw wall-clock, so a drawn span aligns with real market sessions.
103
+ (#410)
104
+
105
+ ### Fixed
106
+
107
+ - **`@pond-ts/charts`: region body-move no longer distorts across a session
108
+ boundary.** On a trading-time (discontinuous) axis, dragging a `<Region>`
109
+ annotation by its body now translates it rigidly in pixel space, so the box
110
+ keeps its width as it crosses a collapsed gap (it previously applied one
111
+ value-delta to both edges, which stretched the box in the different
112
+ rate-contexts either side of a session boundary). No-op on a continuous axis.
113
+ (#405)
114
+
115
+ ## [0.42.0] — 2026-07-10
116
+
117
+ The **trading-calendar** release: a new `@pond-ts/financial` package (its first
118
+ publish) and a discontinuous **trading-time x axis** in `@pond-ts/charts` that
119
+ collapses closed-market time (weekends, holidays, overnight, lunch breaks).
120
+
121
+ ### Added
122
+
123
+ - **`@pond-ts/financial` — new package (first release).** A calendar/analytics
124
+ layer on `pond-ts` (peer dep; ESM, no React; `@js-temporal/polyfill` for
125
+ DST-correct session generation):
126
+ - **`TradingCalendar`** — `fromSessions` (explicit schedule) and `fromRules`
127
+ (weekmask / holidays / early-closes / breaks, DST-correct via Temporal);
128
+ query surface (`sessionOn`, `sessionContaining`, `isOpen`, `sessionsInRange`,
129
+ `nextSession`, `previousSession`).
130
+ - **Bucketing seam** — `sessionSequence()` / `barSequence(period)` return a
131
+ `BoundedSequence` that flows straight through `aggregate` / `materialize`,
132
+ so every bucket is a real trading session/bar (no weekend/holiday buckets,
133
+ no bucket spanning a closure). Zero core edits.
134
+ - **`tagSessions(series, { column?, stamped? })`** — appends a session-id
135
+ column (`number | undefined`) for `partitionBy` so stateful ops don't bridge
136
+ a session boundary. `stamped: 'close'` bins a bar stamped at its close into
137
+ the closing session (`(open, close]`) for OHLC feeds.
138
+ - **`DiscontinuityProvider`** — the d3fc-style 5-method provider
139
+ (`clampUp`/`clampDown`/`distance`/`offset`/`copy` + optional `boundaries`);
140
+ `identityDiscontinuity`, `weekendSkip` (bundled reference), and
141
+ `segmentDiscontinuity(segments, { spacing })`.
142
+ - **`TradingCalendar.discontinuities({ range?, spacing?, period? })`** — the
143
+ chart-ready provider; `spacing: 'proportional'` (default, true-time) or
144
+ `'uniform'` (equal-width per session/bar, the TradingView ordinal look).
145
+ - **`@pond-ts/charts`: trading-time x axis.** Pass a `@pond-ts/financial`
146
+ provider (structurally — charts never imports that package) to collapse
147
+ closed-market gaps:
148
+ - **`ChartContainer` `discontinuities` prop** (low-level) and **`calendar` +
149
+ `spacing` props** (high-level sugar; `calendar` is a structural
150
+ `TradingCalendarLike`, `spacing` defaults to proportional).
151
+ - **`scaleTradingTime`** — a d3-scale-shaped discontinuous time scale; ticks
152
+ coarsen to a **calendar grain** (week/month/quarter/year starts) with
153
+ date/year labels, and **session dividers** draw at the collapse points
154
+ (`theme.axis.sessionDivider`), aligned with the labels.
155
+ - `Charts/TradingTimeAxis` stories (weekend/holiday/half-day/intraday,
156
+ continuous-vs-trading, daily-months, proportional-vs-uniform).
157
+ - **`@pond-ts/charts`: first-class histograms.** `<BarChart>` gains **stacking**
158
+ — a group-by dimension → stacked segments, from a wide series (`columns`), a
159
+ `Map<group, TimeSeries>` (the `partitionBy().aggregate().toMap()` shape), or a
160
+ `byColumn` `bins` array; per-group colour via `colors` or theme roles — and an
161
+ **`orientation`** prop (`'vertical'` default | `'horizontal'`, bars grow right
162
+ with the bins on a y band axis). New readers `stacksFromGroups` /
163
+ `stacksFromColumns` / `stacksFromBins` plus `StackedBarSeries` / `BinRecord` /
164
+ `Orientation` types. All data generation composes from existing operators
165
+ (`aggregate` / `byColumn` / `partitionBy`); no core changes. Guide: How-to
166
+ guides → Histograms. (#401)
167
+ - **`@pond-ts/charts`:** selection now has a stable series identity. `SelectInfo`
168
+ carries an `id`, and `BarChart` / `ScatterChart` take an optional `id` prop —
169
+ the series identity used for selection + hover. An `id` **gates interactivity**:
170
+ a layer is selectable/hoverable only when given one (a layer with no `id`
171
+ renders and reads out but can't be selected). A dev-warning fires when
172
+ `selected`/`onSelect` is wired but no layer carries an `id`. First slice of the
173
+ selection RFC (`docs/rfcs/selection.md`, Amendments 2–3).
174
+ - **`pond-ts`: `bin(W, 'minMaxFirstLast')`** — the four-channel M4 downsampling
175
+ reducer (per-bin min/max/first/last, validity-aware, chunked-delegating); the
176
+ foundation for the charts decimator wave.
177
+ - **`pond-ts`: `binBy`** — key-domain bucketed reduction (the M4 gappy-data
178
+ decimation path).
179
+
180
+ ### Changed
181
+
182
+ - **BREAKING (`@pond-ts/charts`):** `SelectInfo` gained a required `id` field
183
+ (`{ id, key, value, color, label }`) — `id` is the selection identity, `key` /
184
+ `value` are now click provenance. Code that constructs a `SelectInfo` by hand
185
+ must add `id`, and selection equality/dedup now keys on `id`, not the sample
186
+ `begin`.
187
+ - **BREAKING (`@pond-ts/charts`):** `BarChart` / `ScatterChart` selection now
188
+ requires an explicit `id` prop — the previous implicit `as ?? column` selection
189
+ identity is gone. A selectable bar/scatter layer must add `id` (e.g.
190
+ `<BarChart series={s} column="v" id="v" />`); without it the layer is
191
+ display-only.
192
+
42
193
  ## [0.41.0] — 2026-07-06
43
194
 
44
195
  ### Added
@@ -1,42 +1,123 @@
1
1
  import { ValueSeries } from 'pond-ts';
2
2
  import type { SeriesSchema, TimeSeries, ValueSeriesSchema } from 'pond-ts';
3
+ import { type BinRecord, type CategoryDatum } from './data.js';
4
+ import { type Orientation } from './bars.js';
3
5
  export interface BarChartProps<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema> {
4
6
  /**
5
- * The source series. **Interval / timeRange-keyed** `TimeSeries` is the primary
6
- * form — each event's key `[begin, end]` is a bar's x-span. A **point-keyed**
7
- * (`time`) series is supported too: each bar's width is derived from neighbour
8
- * spacing (see {@link barsFromTimeSeries}). A **`ValueSeries`**
9
- * (`series.byValue('dist')`) bars against its value axis — also point-keyed, so
10
- * the same neighbour-spacing span applies (see {@link barsFromValueSeries}); the
11
- * container infers the x-kind from the data, no axis-type prop (mirrors the
12
- * other layers).
7
+ * The source series. Provide **exactly one** of `series` or `bins`.
13
8
  *
14
- * **Live charts:** `series.byValue(…)` mints a *fresh* projection each call, so
15
- * an inline `series={s.byValue('dist')}` re-registers this layer every render —
16
- * on a frequently re-rendering chart, memoize the projection (`useMemo`).
9
+ * - A **`TimeSeries`** (interval / timeRange-keyed is the primary form — each
10
+ * event's key `[begin, end]` is a bar's x-span; a point-keyed series derives
11
+ * its width from neighbour spacing) single-series bars via `column`, or
12
+ * stacked bars from a **wide** series via `columns`.
13
+ * - A **`ValueSeries`** (`series.byValue('dist')`) bars against its value axis.
14
+ * - A **`ReadonlyMap<group, TimeSeries>`** — one series per stack group, all on
15
+ * the same bin grid, the shape
16
+ * `series.partitionBy('host', { groups }).aggregate(seq, m).toMap()` returns.
17
+ * Stacked bars, `column` names the shared value column, groups = map order.
18
+ *
19
+ * **Live charts:** `series.byValue(…)` / `.toMap()` mint fresh objects each
20
+ * call, so an inline `series={…}` re-registers this layer every render — on a
21
+ * frequently re-rendering chart, memoize the projection (`useMemo`).
22
+ */
23
+ series?: TimeSeries<S> | ValueSeries<VS> | ReadonlyMap<string, TimeSeries<S>>;
24
+ /**
25
+ * `byColumn` **bin records** — `Array<{ start, end, …aggregates }>` from a
26
+ * value-band aggregation
27
+ * (`series.byColumn('power', { width: 20 }, { seconds: … })`). The value-axis
28
+ * alternative to `series`: `column` / `columns` name the aggregate field(s) to
29
+ * draw. Pair with `ordinal` for a category (band) axis.
30
+ */
31
+ bins?: readonly BinRecord[];
32
+ /**
33
+ * **Categorical** data — an ordered `{ label, value }[]`, one bar per category
34
+ * on a first-class **ordinal category x-axis** (the container infers
35
+ * `xKind:'category'` and builds a band scale over the labels). The transpose
36
+ * view's "columns on x": each `label` is a category (ticker / account / zone),
37
+ * `value` its bar height. Provide **exactly one** of `series` / `bins` /
38
+ * `categories`; `categories` takes no `column`/`columns` and is **vertical only**
39
+ * (categories on x). Colour per category via `binColors`. (Categorical-axis RFC,
40
+ * Phase 1.)
17
41
  */
18
- series: TimeSeries<S> | ValueSeries<VS>;
19
- /** Name of the numeric value column for the bar height. */
20
- column: string;
42
+ categories?: readonly CategoryDatum[];
43
+ /** Name of the numeric value column for the bar height (single series). Provide
44
+ * `column` **or** `columns`, not both. */
45
+ column?: string;
21
46
  /**
22
- * The series' semantic identifierwhat the data _is_ / how it should read.
23
- * The theme maps it to a {@link BarStyle} (`theme.bar[as] ?? theme.bar.default`).
24
- * **Omitted the `default` style** `column` is the data, `as` is the
25
- * identity, and there's no per-component colour override (the single styling
26
- * channel; restyle via the theme).
47
+ * Stacked-segment columns, **bottom top** one segment per name. Use with a
48
+ * **wide** `series` (e.g. `pivotByGroup` output) or with `bins`. Mutually
49
+ * exclusive with `column`, and invalid with a `Map` series (there the segments
50
+ * are the map's groups; use `column`).
51
+ */
52
+ columns?: readonly string[];
53
+ /**
54
+ * The single series' semantic identifier — what the data _is_. The theme maps
55
+ * it to a {@link BarStyle} (`theme.bar[as] ?? theme.bar.default`). **Single
56
+ * series only** — **ignored** (not an error) on a stacked chart, which colours
57
+ * its segments per group instead (see `colors`).
27
58
  */
28
59
  as?: string;
29
60
  /**
30
- * Which `<YAxis>` (by its `id`) this bar scales against picks the *scale*,
31
- * where `as` picks the *style* (separate concerns). **Omitted ⇒ the row's
32
- * default axis.**
61
+ * Per-group colour override for a **stacked** chart `{ group: cssColor }`.
62
+ * A segment resolves `colors[group] ?? theme.bar[group]?.fill ??
63
+ * theme.bar.default.fill`, so named roles (e.g. a `crit` band styled in the
64
+ * theme) come from the theme while ad-hoc groups (five hosts) take a colour
65
+ * here without minting a theme role. The single styling channel still holds:
66
+ * this is the stack's one colour input.
67
+ */
68
+ colors?: Readonly<Record<string, string>>;
69
+ /**
70
+ * **Per-bin** colours for a single-series band chart — `binColors[i]` fills
71
+ * bar `i` (aligned to the bins / bands in order), overriding the `as`/theme
72
+ * fill. This is the way to colour heart-rate / power **zones** or value bands
73
+ * each their own colour (the `colors` map above is per-**group**, for stacks).
74
+ * An `undefined`/short entry falls back to the theme fill. Meant for a
75
+ * single-series chart (`column` + `bins`, or a horizontal single series); on a
76
+ * multi-group stack it would tint every segment of a bin alike, so it's not
77
+ * the tool there.
78
+ */
79
+ binColors?: readonly (string | undefined)[];
80
+ /**
81
+ * Bar growth direction (the histogram orientation). **Default `'vertical'`.**
82
+ *
83
+ * - `'vertical'` — bars grow **up** from a value baseline, bins on the **x**
84
+ * axis (time buckets, value bands). The column / time-histogram look.
85
+ * - `'horizontal'` — bars grow **right**, bins on the **y** axis (a band axis
86
+ * like heart-rate zones). Label the bands with `<YAxis ticks={[{ at, label }]}>`.
87
+ *
88
+ * A `'horizontal'` chart puts the **value** on the shared x axis, so its
89
+ * container's x-kind is `'value'` — it cannot share a `<ChartContainer>` with
90
+ * time-series rows (each horizontal histogram stands alone). Vertical charts
91
+ * have no such constraint. The in-chart `flag` / `crosshair` value cursor is
92
+ * drawn for the **single-series vertical** case only; stacked and horizontal
93
+ * charts read out via hover / click (`onHover` / `onSelect`).
94
+ */
95
+ orientation?: Orientation;
96
+ /**
97
+ * For `bins`: lay the bands out as uniform **unit slots** (`[i, i+1]`) instead
98
+ * of their numeric `[start, end]` edges — an ordinal band axis where every band
99
+ * reads the same width (heart-rate zones). Ignored for `series`.
100
+ */
101
+ ordinal?: boolean;
102
+ /**
103
+ * The **stable series identity** for selection + hover — and it **gates
104
+ * interactivity** (a bar layer is selectable/hoverable only when given an
105
+ * `id`). For a stack, a clicked / hovered **segment** is identified by
106
+ * `(id, key = bin begin, label = group)`, so two segments in one bin don't both
107
+ * light up.
108
+ */
109
+ id?: string;
110
+ /**
111
+ * Which `<YAxis>` (by its `id`) this layer scales against — the *scale* (`as`
112
+ * picks the *style*). **Omitted ⇒ the row's default axis.** For a horizontal
113
+ * histogram this is the **bin (band) axis**; for a vertical one the **value**
114
+ * axis.
33
115
  */
34
116
  axis?: string;
35
117
  /**
36
- * Pixel gap between adjacent bars — each bar's key span is inset by this total
37
- * (half each side), so neighbours breathe. **Omitted ⇒ the theme's
38
- * `bar[as].gap`.** A span the gap would invert collapses to the style's
39
- * `minWidth`, so a too-thin bucket stays visible.
118
+ * Pixel gap between adjacent bars / bins the bar's key span is inset by this
119
+ * total (half each side). **Omitted ⇒ the theme's `bar` `gap`.** A span the gap
120
+ * would invert collapses to the style's `minWidth`.
40
121
  */
41
122
  gap?: number;
42
123
  /**
@@ -46,43 +127,47 @@ export interface BarChartProps<S extends SeriesSchema = SeriesSchema, VS extends
46
127
  index?: number;
47
128
  }
48
129
  /**
49
- * A bar draw layer: one rectangle per event, spanning the key's `[begin, end]`
50
- * (inset by `gap`) from the axis baseline to a numeric `column`'s value. Reads
51
- * the key endpoints + column into a {@link BarSeries}, registers into the
52
- * enclosing {@link Layers} (scaling against its `axis`), and renders nothing to
53
- * the DOM the row draws it. A gap (missing value) is skipped (no bar).
130
+ * A bar / histogram draw layer. In its simplest form, one rectangle per event
131
+ * spanning the key's `[begin, end]` from the axis baseline to a numeric
132
+ * `column`'s value (see below). It also draws **stacked** bars (a group-by
133
+ * dimension segments, `columns` / a `Map` series / `bins`) and **horizontal**
134
+ * bars (`orientation='horizontal'`, bins on the y axis) first-class histogram
135
+ * support. Registers into the enclosing {@link Layers} and renders nothing to the
136
+ * DOM; the row draws it.
54
137
  *
55
- * **Baseline.** Bars rest on the zero line when the axis domain spans zero (the
56
- * common all-positive auto-fit case {@link barExtent} pulls `0` into the
57
- * domain), or on the axis floor when an explicit `<YAxis min={…}>` sits above
58
- * zero (see {@link resolveBarBaseline}).
138
+ * **Data sources.** A time / value `TimeSeries` or `ValueSeries` (`column`), a
139
+ * wide series or `bins` array (`columns`), or a `Map<group, TimeSeries>`
140
+ * (`column`) the last three stack. Every shape composes from pond's own
141
+ * aggregation (`aggregate` / `byColumn` / `partitionBy`); the histogram guide
142
+ * has the recipes.
59
143
  *
60
- * **Interaction.** Hover joins the tracker (`sampleAt` the value of the bar
61
- * **under the cursor**) and lights that bar (hover-highlight). Click selects the
62
- * hit bar (`hitTest`); the matching bar — same key **and** this series' `label`,
63
- * so two series sharing a timestamp don't both light up — draws highlighted
64
- * (outlined for the committed select, fill-only for the transient hover). Both
65
- * resolve by **containment**: the tracker by the bar's `[begin, end]` time span
66
- * (`barIndexAtTime`), the click by the bar's pixel rect (`barAt`) — so the
67
- * readout reads the same bar you click, even across a wide bucket (they differ
68
- * only by the `gap` inset, where the pixel rect is narrower than the span).
144
+ * **Baseline (single, vertical).** Bars rest on the zero line when the axis
145
+ * domain spans zero, or on the axis floor when an explicit `<YAxis min>` sits
146
+ * above zero (see {@link resolveBarBaseline}).
69
147
  *
70
- * Both channels are also **controllable from outside** the chart via the
71
- * container: `selected`/`onSelect` (committed) and `hovered`/`onHover` (transient)
72
- * pass either to pin the lit/selected bar from a legend or list row, and read
73
- * the callback to mirror a bar-originated hover/click out-of-band. Symmetric pair,
74
- * keyed by the same {@link SelectInfo} identity.
148
+ * **Baseline (stacked).** A stack is **cumulative from value 0** the segments
149
+ * sum upward from the zero line, so its value axis **must include 0**. The
150
+ * auto-fit guarantees this: {@link stackValueExtent} always returns `[0, maxTotal]`.
151
+ * An explicit `<YAxis min>` **above** 0 is therefore unsupported for a stack — it
152
+ * would hide the bottom of the cumulative column; only the portion above the floor
153
+ * draws (clipped cleanly at the plot floor, as any bar below an explicit floor is).
154
+ * Segment values are assumed **non-negative** (a negative or zero segment is
155
+ * skipped — diverging stacks are out of scope).
75
156
  *
76
- * **Value axis** bars also scale on a value axis when fed a `ValueSeries`
77
- * (`series.byValue('dist')`): estela's distance-domain splits/laps, one bar per
78
- * segment over a monotonic axis. A `ValueSeries` is point-keyed, so the span is
79
- * neighbour-derived like a point `TimeSeries` (see {@link barsFromValueSeries}).
157
+ * **Interaction (opt-in via `id`).** Hover lights the bar / segment under the
158
+ * cursor (hit-tested by pixel rect, so it works in both orientations); click
159
+ * selects it (outlined). A stacked segment's identity is `(id, key = bin begin,
160
+ * label = group)`. Both channels are controllable from outside via the container
161
+ * (`selected`/`onSelect`, `hovered`/`onHover`). The in-chart `flag`/`crosshair`
162
+ * value cursor is single-series-vertical only.
80
163
  *
81
164
  * ```tsx
82
165
  * <Layers>
83
166
  * <BarChart series={hourlyVolume} column="count" />
167
+ * <BarChart series={byHost} column="n" colors={{ web1: '#…' }} />
168
+ * <BarChart bins={powerDist} column="seconds" orientation="horizontal" ordinal />
84
169
  * </Layers>
85
170
  * ```
86
171
  */
87
- export declare function BarChart<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema>({ series, column, as: semantic, axis, gap, index, }: BarChartProps<S, VS>): null;
172
+ export declare function BarChart<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema>({ series, bins, categories, column, columns, as: semantic, colors, binColors, orientation, ordinal, id, axis, gap, index, }: BarChartProps<S, VS>): null;
88
173
  //# sourceMappingURL=BarChart.d.ts.map