@pond-ts/charts 0.62.0 → 0.64.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/API.md +1 -1
- package/CHANGELOG.md +223 -1
- package/dist/BarChart.js +6 -6
- package/dist/ChartContainer.d.ts +72 -0
- package/dist/ChartContainer.js +151 -24
- package/dist/ChartRow.d.ts +39 -3
- package/dist/ChartRow.js +194 -7
- package/dist/Layers.js +25 -8
- package/dist/XAxis.d.ts +6 -0
- package/dist/XAxis.js +81 -3
- package/dist/YAxis.d.ts +92 -2
- package/dist/YAxis.js +268 -6
- package/dist/annotations.js +14 -7
- package/dist/bars.d.ts +21 -8
- package/dist/bars.js +38 -12
- package/dist/chip.d.ts +50 -7
- package/dist/chip.js +66 -9
- package/dist/context.d.ts +134 -7
- package/dist/cursors.js +33 -8
- package/dist/domain.d.ts +18 -0
- package/dist/domain.js +33 -0
- package/dist/select.d.ts +1 -1
- package/dist/select.js +7 -2
- package/dist/tradingTimeScale.d.ts +11 -1
- package/dist/tradingTimeScale.js +53 -7
- package/dist/use-axis-gestures.d.ts +79 -0
- package/dist/use-axis-gestures.js +257 -0
- package/package.json +3 -3
package/API.md
CHANGED
|
@@ -164,7 +164,7 @@ Deliberately small — the ordering-based slice of the algebra, no calendar ops
|
|
|
164
164
|
| Operation schemas | `RollingSchema`, `RollingAlignment`, `AlignSchema`, `DiffSchema`, `SmoothSchema`, `SmoothMethod`, `FillStrategy`, `FillMapping` | `packages/core/src/schema/index.ts` |
|
|
165
165
|
| Column/data kinds | `Column`, `KeyColumn`, `ColumnKind`, `ScalarKind`, `ScalarValue`, `ColumnValue`, `ArrayValue`, `ValidityBitmap` | `packages/core/src/columnar/` |
|
|
166
166
|
| JSON wire format | `JsonRowFormat`, `JsonRowForSchema`, `JsonObjectRowForSchema`, `JsonValueForKind`, `JsonTimestampInput`, `JsonTimeRangeInput`, `JsonIntervalInput` | `packages/core/src/schema/index.ts` |
|
|
167
|
-
| Temporal utility | `TemporalLike`, `DurationInput`, `CalendarUnit`, `TimeZoneOptions`, `KeyLike`, `BatchSampleStrategy`
|
|
167
|
+
| Temporal utility | `TemporalLike`, `DurationInput`, `CalendarUnit`, `TimeZoneOptions`, `KeyLike`, `BatchSampleStrategy`, `SequenceSample`, `SequenceCoverage` | `packages/core/src/core/`, `packages/core/src/sequence/` |
|
|
168
168
|
|
|
169
169
|
The `pond-ts/types` subpath re-exports the schema-as-contract types with zero
|
|
170
170
|
runtime (`packages/core/src/schema/public.ts`).
|
package/CHANGELOG.md
CHANGED
|
@@ -8,7 +8,9 @@ The `@pond-ts` packages — `pond-ts`, `@pond-ts/react`, `@pond-ts/charts`,
|
|
|
8
8
|
under a single `v*` tag, so this file covers them all. Pre-1.0: minor bumps may
|
|
9
9
|
include new features and type-level changes; patch bumps are strictly additive.
|
|
10
10
|
|
|
11
|
-
[Unreleased]: https://github.com/pond-ts/pond/compare/v0.
|
|
11
|
+
[Unreleased]: https://github.com/pond-ts/pond/compare/v0.64.0...HEAD
|
|
12
|
+
[0.64.0]: https://github.com/pond-ts/pond/compare/v0.63.0...v0.64.0
|
|
13
|
+
[0.63.0]: https://github.com/pond-ts/pond/compare/v0.62.0...v0.63.0
|
|
12
14
|
[0.62.0]: https://github.com/pond-ts/pond/compare/v0.61.0...v0.62.0
|
|
13
15
|
[0.61.0]: https://github.com/pond-ts/pond/compare/v0.60.0...v0.61.0
|
|
14
16
|
[0.60.0]: https://github.com/pond-ts/pond/compare/v0.59.0...v0.60.0
|
|
@@ -65,6 +67,226 @@ include new features and type-level changes; patch bumps are strictly additive.
|
|
|
65
67
|
|
|
66
68
|
## [Unreleased]
|
|
67
69
|
|
|
70
|
+
## [0.64.0] — 2026-08-28
|
|
71
|
+
|
|
72
|
+
### Added
|
|
73
|
+
|
|
74
|
+
- `pond-ts`: **`Sequence.bounded(range, { coverage })`** — chooses whether a
|
|
75
|
+
range selects buckets by their sample point (`'sample'`, the default and the
|
|
76
|
+
existing behaviour) or by their extent (`'overlap'`, every bucket the range
|
|
77
|
+
touches, including the one containing `range.begin()`). `aggregate` realizes
|
|
78
|
+
its grid with `'overlap'`; alignment keeps `'sample'`. As a side benefit
|
|
79
|
+
`bounded({ start: t, end: t }, { coverage: 'overlap' })` is a flooring
|
|
80
|
+
primitive — it returns exactly the bucket containing `t` — so consumers no
|
|
81
|
+
longer have to re-derive pond's calendar anchoring by hand to floor a
|
|
82
|
+
timestamp. New exported type `SequenceCoverage`.
|
|
83
|
+
|
|
84
|
+
- `@pond-ts/charts`: **`<YAxis zeroAnchored>`** — pins a y-axis's zoom to the
|
|
85
|
+
value-`0` gridline instead of the pointer, and drops drag-to-pan entirely.
|
|
86
|
+
For a bar chart, whose baseline must never move: a bar rests on `0` (at the
|
|
87
|
+
plot floor for all-positive data, or somewhere mid-plot for data that
|
|
88
|
+
straddles positive and negative), and an ordinary pointer-pivoted gesture
|
|
89
|
+
would slide that baseline around the plot as you scroll. With
|
|
90
|
+
`zeroAnchored`, every wheel notch scales the axis around wherever `0`
|
|
91
|
+
currently renders, so the baseline holds however far in or out you zoom.
|
|
92
|
+
One qualification: the pivot is clamped into the axis's pixel range, so once
|
|
93
|
+
`0` has been scrolled off the plot the zoom pivots about the nearer edge and
|
|
94
|
+
the baseline does creep — benign for bars, where that clamp coincides with
|
|
95
|
+
the declared floor, but not an unconditional guarantee. Still gated by the
|
|
96
|
+
container's own `axisPanZoom` opt-in — this changes what the gesture does,
|
|
97
|
+
not whether it's on.
|
|
98
|
+
|
|
99
|
+
### Changed
|
|
100
|
+
|
|
101
|
+
- `pond-ts`: **`aggregate` now emits the bucket containing the first event**,
|
|
102
|
+
where before it started at the first grid boundary _at or after_ it — so
|
|
103
|
+
every event between the two aggregated into nothing, silently. 60 daily bars
|
|
104
|
+
rolled to a calendar month came back holding 38 of them: no error, no
|
|
105
|
+
warning, no `undefined`, just a well-formed series with a third of the input
|
|
106
|
+
gone. It contradicted `aggregate`'s own documented membership rule ("point
|
|
107
|
+
events contribute to the bucket containing their timestamp") and was
|
|
108
|
+
asymmetric — the trailing partial bucket _was_ emitted. **This changes
|
|
109
|
+
results for any caller whose first event did not land exactly on a grid
|
|
110
|
+
boundary**: expect an extra leading bucket, and sums/counts that now account
|
|
111
|
+
for the previously-dropped events. Callers who worked around it by passing a
|
|
112
|
+
pre-floored explicit `range` are unaffected — the floor is now what the
|
|
113
|
+
default does. **Note what `range` does and does not bound:** it selects the
|
|
114
|
+
grid, not the event scan, so the leading bucket is filled from every event it
|
|
115
|
+
contains — including events _before_ `range.begin()` when the series has
|
|
116
|
+
them. On a window narrower than the series (a chart viewport, say) the edge
|
|
117
|
+
bucket is therefore a complete bucket rather than a clipped one, which is
|
|
118
|
+
what keeps bar heights stable under a pan; if you need the window to bound
|
|
119
|
+
the events too, narrow the series rather than the grid. `align(...)` and
|
|
120
|
+
`materialize(...)` are deliberately unchanged: their grids are _sampled_,
|
|
121
|
+
and the sample point becomes the output key. A pre-realized
|
|
122
|
+
`BoundedSequence` argument is an explicit bucket list, used as given and
|
|
123
|
+
unaffected by any of this. Reported by Tidal (#672).
|
|
124
|
+
|
|
125
|
+
- `@pond-ts/charts`: **y gutter drag now pans instead of zooming** — matching
|
|
126
|
+
the x strip's own gesture (drag pans, wheel zooms) instead of the
|
|
127
|
+
drag-to-zoom behavior it shipped with in `axisPanZoom="y"`/`"xy"`. Wheel
|
|
128
|
+
still zooms the grabbed axis about the pointer, and double-click still
|
|
129
|
+
releases it back to its fit; only the drag's own effect changed.
|
|
130
|
+
|
|
131
|
+
### Fixed
|
|
132
|
+
|
|
133
|
+
- `@pond-ts/charts`: **a trading-time date band clamped onto a labelled tick
|
|
134
|
+
keeps its segment boundary.** The F-charts-21 collision fix dropped the whole
|
|
135
|
+
`{ start, label, shaded }` entry, but `<XAxis>` spans each band
|
|
136
|
+
`[its start, the next band's start)` and takes its zebra parity from
|
|
137
|
+
`shaded` — so removing an entry deleted the _period_, not a duplicate label,
|
|
138
|
+
and the preceding band ran on to the next surviving boundary under its own
|
|
139
|
+
name and shading. (Aug 1 2026 is a Saturday, so the August band clamps onto
|
|
140
|
+
Mon Aug 3, already a day tick — August vanished and July painted across it.)
|
|
141
|
+
`bands()` entries now carry **`showLabel`**, and only the text is suppressed.
|
|
142
|
+
Found by Codex reviewing the v0.64.0 range.
|
|
143
|
+
- `@pond-ts/charts`: **a controlled y-gutter wheel zoom no longer pivots about
|
|
144
|
+
the wrong point under a plot-level y zoom.** The `zeroAnchored` pivot was
|
|
145
|
+
corrected above, but the ordinary (non-anchored) controlled wheel still fed
|
|
146
|
+
the pointer's _screen_ pixel into the pre-transform scale's pixel space, so
|
|
147
|
+
the value under the pointer slid out from under it — ~0.14 units per notch at
|
|
148
|
+
`k = 1.198`. Third and last face of one root cause: a screen-space pixel used
|
|
149
|
+
where `base`'s pixel space is meant.
|
|
150
|
+
- `@pond-ts/charts`: **a controlled y-gutter pan no longer overshoots the
|
|
151
|
+
cursor under a plot-level y zoom.** With `onBoundsChange` set, the drag
|
|
152
|
+
translated the axis's pre-transform scale by a _screen_ pixel delta. Those
|
|
153
|
+
two pixel spaces differ by the container's `yTransform`, so with the plot's
|
|
154
|
+
own y pan/zoom engaged (`panZoom="panZoomY"` / `"panZoomXY"`) the axis
|
|
155
|
+
panned `k`× too far and the grabbed value outran the pointer. Both
|
|
156
|
+
transforms are applied in pixel space, so the base↔screen relation is
|
|
157
|
+
exactly affine and the correction is a division, on `log` and `symlog` as
|
|
158
|
+
well. (The division is exact on all three; end-to-end tracking on `symlog`
|
|
159
|
+
still drifts, because its knee is re-derived from the panned domain — a
|
|
160
|
+
pre-existing property the sibling zoom test already documents.) Invisible at
|
|
161
|
+
`k === 1`.
|
|
162
|
+
- `@pond-ts/charts`: **`<YAxis zeroAnchored>` no longer lets the baseline drift
|
|
163
|
+
in the controlled path.** With `onBoundsChange` set, the zoom read `0`'s
|
|
164
|
+
pixel off the axis's _live_ scale but inverted it through `baseYScales`.
|
|
165
|
+
Those two pixel spaces differ by the container's own `yTransform`, so with
|
|
166
|
+
the plot's y pan/zoom active (`panZoom="panZoomY"` / `"panZoomXY"`) the
|
|
167
|
+
baseline crept a few pixels per wheel notch — monotonically, in exactly the
|
|
168
|
+
gesture whose purpose is to hold it still. It was invisible without a
|
|
169
|
+
plot-level y zoom, where the two spaces coincide. Found by a post-merge
|
|
170
|
+
adversarial review of #676.
|
|
171
|
+
- `@pond-ts/charts`: **a `BarChart`'s baseline no longer relocates under a y
|
|
172
|
+
gutter pan/zoom.** `resolveBarBaseline` decided whether bars rest on zero or
|
|
173
|
+
on the axis floor by reading the axis's _live, transformed_ domain — the
|
|
174
|
+
same read a pan/zoom keeps moving — so once a gesture scrolled zero out of
|
|
175
|
+
view, every bar's rendered top silently snapped to the moving floor instead
|
|
176
|
+
of its actual value. It now reads the axis's declared (pre-transform)
|
|
177
|
+
domain for that decision, so a pan/zoom can move the viewport without ever
|
|
178
|
+
relocating a bar's own baseline.
|
|
179
|
+
- `@pond-ts/charts`: **[F-charts-21] a trading-time axis's stacked date-band
|
|
180
|
+
row no longer draws a second, colliding label over a collapsed-gap seam.**
|
|
181
|
+
`scale.bands()` picked its anchors from the raw calendar (a month or day
|
|
182
|
+
start) without checking whether that instant was live, so a period
|
|
183
|
+
beginning on a collapsed weekend or holiday clamped its label onto the same
|
|
184
|
+
seam a tick (or another band) already occupied — rendering as two
|
|
185
|
+
overlapping labels (`"Aug"` over `"Aug 3"`, or worse at tight zoom, fully
|
|
186
|
+
interleaved). Bands whose raw start needed clamping now dedupe against a
|
|
187
|
+
run of other clamped starts landing on the same live instant (picking the
|
|
188
|
+
genuinely-live member as the representative when one exists) and against
|
|
189
|
+
an already-labelled tick, so a seam carries exactly one label.
|
|
190
|
+
|
|
191
|
+
## [0.63.0] — 2026-08-18
|
|
192
|
+
|
|
193
|
+
### Added
|
|
194
|
+
|
|
195
|
+
- `@pond-ts/charts`: **axis pan/zoom**, behind a new
|
|
196
|
+
**`<ChartContainer axisPanZoom>`** (`'none'` — the default — / `'x'` / `'y'` /
|
|
197
|
+
`'xy'`). Opted in, the `<XAxis>` strip and each `<YAxis>` gutter become
|
|
198
|
+
grabbable, and **double-click** puts one back (the declared `range` on x, its
|
|
199
|
+
fit on y). The cursor stays an ordinary arrow at rest and becomes directional
|
|
200
|
+
(`↕` / `↔`) only while a gesture is running.
|
|
201
|
+
|
|
202
|
+
**The opt-in is deliberately separate from `panZoom`, in both directions.** An
|
|
203
|
+
already-interactive chart does not grow axis gestures on upgrade — nothing
|
|
204
|
+
changes for any existing chart — and a chart can scale its y axes with
|
|
205
|
+
`panZoom` off entirely, which is what you want when the plot's drag belongs to
|
|
206
|
+
a selection sweep.
|
|
207
|
+
|
|
208
|
+
**The x strip is the canvas gesture, moved to the axis** — drag pans, wheel
|
|
209
|
+
zooms about the pointer — reusing the plot's own domain-space maths, so
|
|
210
|
+
`bounds` and `minDuration` still fence the view and a trading-time axis still
|
|
211
|
+
pans and floors in _trading_ time. A category axis has no continuous domain and
|
|
212
|
+
stays inert.
|
|
213
|
+
|
|
214
|
+
**A y gutter zooms, and only the axis you grabbed** — its sibling and every
|
|
215
|
+
other row hold still. That needed a new per-axis pixel transform
|
|
216
|
+
(`RowFrame.axisTransforms`, layered under the container's uniform
|
|
217
|
+
`yTransform`), since the uniform one exists precisely so a _plot_ gesture never
|
|
218
|
+
has to pick an axis; unlike it, this is not floored at `k ≥ 1`, because
|
|
219
|
+
squashing an axis you grabbed is the point.
|
|
220
|
+
|
|
221
|
+
- `@pond-ts/charts`: **`<YAxis onBoundsChange>`** — the auto-vs-manual hand-off
|
|
222
|
+
for a scaled y axis. Fires with the `[min, max]` a gutter gesture reached, and
|
|
223
|
+
with `null` when the axis is released back to auto-fit, so a UI can show the
|
|
224
|
+
bounds, badge the scale "manual", and offer a toggle back. Providing it makes
|
|
225
|
+
the axis **controlled** (the gesture only reports; `min`/`max` fed back are
|
|
226
|
+
what it draws), exactly as `onTimeRangeChange` does for the x view; omit it and
|
|
227
|
+
the axis holds the zoom itself. `ContainerFrame` also gains `seedRange` — the
|
|
228
|
+
declared view, as against the gestured `timeRange` — which is the x reset's
|
|
229
|
+
target.
|
|
230
|
+
|
|
231
|
+
- **charts: `<ChartContainer height>` + `<ChartRow flex>` — container-owned
|
|
232
|
+
vertical layout** ([PND-HEIGHT]). `height` takes a pixel number or `'auto'`
|
|
233
|
+
(measured by the same `ResizeObserver` as `width="auto"`); omitted stays the
|
|
234
|
+
classic mode where rows declare pixels. A managed container renders as a
|
|
235
|
+
**flex column** — the rows block flexes, the x-axis strip keeps its natural
|
|
236
|
+
height — and flex rows (a bare `<ChartRow>` is `flex={1}`) divide what the
|
|
237
|
+
browser says is left, then read that height back for their y-scales.
|
|
238
|
+
|
|
239
|
+
The design constraint was that **CSS does the subtraction**: the axis
|
|
240
|
+
strip's height depends on its `label`, the theme font size, the tick
|
|
241
|
+
ladder's calendar band row at the current grain, and stacked marker pills —
|
|
242
|
+
it is not a constant a caller can subtract, and every consumer who tried
|
|
243
|
+
carried a wrong one (`20` and `24` in one codebase; this site's own
|
|
244
|
+
resizable-panels recipe said `22`). It also means non-row children between
|
|
245
|
+
rows — the recipe's draggable splitter — keep taking their natural space,
|
|
246
|
+
so that recipe reduces to its drag handler: one flex row absorbing slack
|
|
247
|
+
over one fixed row the drag resizes, no `AXIS_H`, no measuring hook.
|
|
248
|
+
|
|
249
|
+
A flex row paints nothing until its first measurement, latches its last
|
|
250
|
+
non-zero height while hidden (a `display: none` tab switch keeps its
|
|
251
|
+
scales), and warns in dev when mounted in a container that never sizes it.
|
|
252
|
+
The container **warns in dev when a measured dimension stays 0** — the
|
|
253
|
+
unconstrained-parent deadlock, which for height is the _default_ (a
|
|
254
|
+
flex-column child's height is its content) rather than an edge case.
|
|
255
|
+
|
|
256
|
+
Fixed-`height` rows keep their pixels everywhere, managed or not; a
|
|
257
|
+
container with no `height` behaves exactly as before.
|
|
258
|
+
|
|
259
|
+
### Fixed
|
|
260
|
+
|
|
261
|
+
- **charts: the crosshair's value pill lands on the axis that measured the
|
|
262
|
+
value, in that axis's colour.** With two y-axes on one side, the pill was
|
|
263
|
+
placed by side alone — always against the plot edge — so a reading taken off
|
|
264
|
+
the **outer** axis appeared over the **inner** axis's ticks, in the cursor's
|
|
265
|
+
grey: a number pinned to a ruler that never measured it. The reticle picks one
|
|
266
|
+
series, so the resolved sample now carries its axis's gutter **offset** (the
|
|
267
|
+
reserved widths of the columns between it and the plot) and its
|
|
268
|
+
`<YAxis color>`, and the pill uses both — position _and_ ink say which of two
|
|
269
|
+
stacked scales the number is on. A single axis per side is unchanged (offset
|
|
270
|
+
`0`), as is an axis that sets no colour (the theme's cursor ink).
|
|
271
|
+
|
|
272
|
+
A pill placed further out is now **bridged back to the plot edge** by a 1px
|
|
273
|
+
connector in its own colour — the y-side twin of the crosshair's x-axis time
|
|
274
|
+
connector, without which a pill a column out reads as a value floating in a
|
|
275
|
+
gutter. It draws at half opacity because, unlike the time connector's empty
|
|
276
|
+
strip, it crosses another axis's tick labels; nothing is drawn on the innermost
|
|
277
|
+
axis, where the pill already meets the line.
|
|
278
|
+
|
|
279
|
+
`<YAxis color>` is now part of the axis's registered spec rather than
|
|
280
|
+
presentation-only, because the pill is drawn by the row's cursor overlay, not
|
|
281
|
+
by `<YAxis>`. `<Baseline indicator>` — the other on-axis value pill — got the
|
|
282
|
+
same placement fix and the same connector. New `Cursors/Crosshair` stories fan
|
|
283
|
+
the states out (`AxisColor`, `StackedAxes`, `StackedAxesColored`,
|
|
284
|
+
`StackedAxesLeft`, `StackedAxesBothSides`).
|
|
285
|
+
|
|
286
|
+
Not covered: `<YAxisIndicator>` still takes an explicit `side` alongside its
|
|
287
|
+
`axis`, so it can be pointed at a gutter its axis isn't in; reconciling those
|
|
288
|
+
two props is a public-API question, left for its own change.
|
|
289
|
+
|
|
68
290
|
## [0.62.0] — 2026-08-16
|
|
69
291
|
|
|
70
292
|
### Added
|
package/dist/BarChart.js
CHANGED
|
@@ -448,8 +448,8 @@ export function BarChart({ series, bins, categories, column, columns, as: semant
|
|
|
448
448
|
...(id === undefined
|
|
449
449
|
? {}
|
|
450
450
|
: {
|
|
451
|
-
hitTest: (px, py, xScale, yScale, mode) => {
|
|
452
|
-
const baseline = resolveBarBaseline(yScale);
|
|
451
|
+
hitTest: (px, py, xScale, yScale, mode, baseYScale) => {
|
|
452
|
+
const baseline = resolveBarBaseline(yScale, baseYScale);
|
|
453
453
|
// No `gapPx` — the hit region is the bar's whole slot (its
|
|
454
454
|
// interval width, full plot height), not the inset rect the
|
|
455
455
|
// gap draws. See barSlotRect.
|
|
@@ -525,7 +525,7 @@ export function BarChart({ series, bins, categories, column, columns, as: semant
|
|
|
525
525
|
},
|
|
526
526
|
}),
|
|
527
527
|
}),
|
|
528
|
-
draw: (ctx, xScale, yScale) => drawBars(ctx, bs, xScale, yScale, singleDrawStyle, resolveBarBaseline(yScale), gapPx, id, selection, hover, decimate, binColors, bandLadder, layerSpans),
|
|
528
|
+
draw: (ctx, xScale, yScale, baseYScale) => drawBars(ctx, bs, xScale, yScale, singleDrawStyle, resolveBarBaseline(yScale, baseYScale), gapPx, id, selection, hover, decimate, binColors, bandLadder, layerSpans),
|
|
529
529
|
},
|
|
530
530
|
axisId: axis,
|
|
531
531
|
index,
|
|
@@ -562,7 +562,7 @@ export function BarChart({ series, bins, categories, column, columns, as: semant
|
|
|
562
562
|
...(id === undefined
|
|
563
563
|
? {}
|
|
564
564
|
: {
|
|
565
|
-
hitTest: (px, py, xScale, yScale) => {
|
|
565
|
+
hitTest: (px, py, xScale, yScale, _mode, baseYScale) => {
|
|
566
566
|
// The cap reaches the hit rect ONLY for a real stack, where the
|
|
567
567
|
// rect is what resolves *which segment* was hit and so must be
|
|
568
568
|
// the drawn one. A single-series chart has one segment per slot
|
|
@@ -576,7 +576,7 @@ export function BarChart({ series, bins, categories, column, columns, as: semant
|
|
|
576
576
|
// the fix is to make the guarantee orientation-independent rather
|
|
577
577
|
// than to narrow the claim, since the reason for the split is
|
|
578
578
|
// segment disambiguation and that is a property of the *stack*.
|
|
579
|
-
const hit = stackAt(ss, px, py, orientation, xScale, yScale, gapPx, stackMinWidth, ss.groups.length > 1 ? maxWidthPx : undefined);
|
|
579
|
+
const hit = stackAt(ss, px, py, orientation, xScale, yScale, gapPx, stackMinWidth, ss.groups.length > 1 ? maxWidthPx : undefined, baseYScale);
|
|
580
580
|
if (hit === null)
|
|
581
581
|
return null;
|
|
582
582
|
const [bi, g, begin, name, value] = hit;
|
|
@@ -657,7 +657,7 @@ export function BarChart({ series, bins, categories, column, columns, as: semant
|
|
|
657
657
|
});
|
|
658
658
|
},
|
|
659
659
|
}),
|
|
660
|
-
draw: (ctx, xScale, yScale) => drawStacks(ctx, ss, orientation, xScale, yScale, stackStyle, gapPx, stackMinWidth, id, selection, hover, bandLadder, layerSpans),
|
|
660
|
+
draw: (ctx, xScale, yScale, baseYScale) => drawStacks(ctx, ss, orientation, xScale, yScale, stackStyle, gapPx, stackMinWidth, id, selection, hover, bandLadder, layerSpans, baseYScale),
|
|
661
661
|
},
|
|
662
662
|
axisId: axis,
|
|
663
663
|
index,
|
package/dist/ChartContainer.d.ts
CHANGED
|
@@ -294,6 +294,48 @@ export interface ChartContainerProps {
|
|
|
294
294
|
* render.
|
|
295
295
|
*/
|
|
296
296
|
width?: number | 'auto';
|
|
297
|
+
/**
|
|
298
|
+
* Total height in CSS pixels, or `'auto'` to fill the available height —
|
|
299
|
+
* **the container-owned vertical layout** ([PND-HEIGHT]). Omitted means the
|
|
300
|
+
* classic mode: rows declare pixel heights and the container's height is
|
|
301
|
+
* their sum.
|
|
302
|
+
*
|
|
303
|
+
* With a height, the container renders as a **flex column** — the rows
|
|
304
|
+
* block flexes, the x-axis strip keeps its natural height at the bottom —
|
|
305
|
+
* and `<ChartRow flex>` rows (a bare `<ChartRow>` is `flex={1}`) divide
|
|
306
|
+
* whatever the browser says is left. That "whatever the browser says" is
|
|
307
|
+
* the point: the axis strip's height depends on its `label`, the theme's
|
|
308
|
+
* font size, whether the tick ladder is showing its calendar band row at
|
|
309
|
+
* the current grain, and how many marker pills stack — it is not a constant
|
|
310
|
+
* a caller could subtract, and every consumer who tried carried a wrong
|
|
311
|
+
* number (20, 24, and the recipe's 22 were all in the wild for one strip).
|
|
312
|
+
* CSS does the subtraction, so there is no number to know.
|
|
313
|
+
*
|
|
314
|
+
* A single full-bleed chart is therefore zero arithmetic:
|
|
315
|
+
*
|
|
316
|
+
* ```tsx
|
|
317
|
+
* <ChartContainer width="auto" height="auto">
|
|
318
|
+
* <ChartRow>
|
|
319
|
+
* <YAxis id="v" />
|
|
320
|
+
* <Layers>…</Layers>
|
|
321
|
+
* </ChartRow>
|
|
322
|
+
* </ChartContainer>
|
|
323
|
+
* ```
|
|
324
|
+
*
|
|
325
|
+
* Fixed-`height` rows keep their pixels inside a managed container, and
|
|
326
|
+
* non-row children (a draggable splitter between two rows) take their
|
|
327
|
+
* natural space — so the resizable-panels shape becomes one `flex` row
|
|
328
|
+
* absorbing slack over one fixed row the drag resizes, with no reserved
|
|
329
|
+
* strip constant and no measuring hook.
|
|
330
|
+
*
|
|
331
|
+
* `'auto'` measures with the same `ResizeObserver` as `width="auto"`, gates
|
|
332
|
+
* the first paint until both needed dimensions exist, latches the last
|
|
333
|
+
* non-zero size while hidden, and — because a flex-**column** child's
|
|
334
|
+
* height defaults to its content — **warns in dev when a measured dimension
|
|
335
|
+
* stays 0**: the parent needs a definite height, or the deadlock is the
|
|
336
|
+
* default.
|
|
337
|
+
*/
|
|
338
|
+
height?: number | 'auto';
|
|
297
339
|
/** Vertical space between rows in CSS pixels (not under the axis). Default 0. */
|
|
298
340
|
rowGap?: number;
|
|
299
341
|
/**
|
|
@@ -438,8 +480,38 @@ export interface ChartContainerProps {
|
|
|
438
480
|
* The boolean form is the back-compat shorthand (`true` ⇒ `'panZoom'`,
|
|
439
481
|
* `false` ⇒ `'none'`). Bound the reachable range with {@link bounds}
|
|
440
482
|
* (zoom-out / pan extent) and {@link minDuration} (zoom-in floor).
|
|
483
|
+
*
|
|
484
|
+
* **This prop is about the plot only.** Gestures on the axis strips are a
|
|
485
|
+
* separate opt-in — see {@link axisPanZoom} — so turning pan/zoom on here does
|
|
486
|
+
* not silently make the axes grabbable.
|
|
441
487
|
*/
|
|
442
488
|
panZoom?: boolean | 'none' | 'pan' | 'panZoom' | 'panZoomX' | 'panZoomY' | 'panZoomXY';
|
|
489
|
+
/**
|
|
490
|
+
* Which **axis strips** take gestures — the opt-in for grabbing an axis, and
|
|
491
|
+
* **`'none'` by default** so no existing chart changes behaviour:
|
|
492
|
+
*
|
|
493
|
+
* - `'none'` (or `false`, the **default**) — the strips are inert chrome.
|
|
494
|
+
* - `'x'` — the `<XAxis>` strip **pans on drag and zooms on wheel**, exactly as
|
|
495
|
+
* the plot's own gestures do (same maths, same sign, same {@link bounds} /
|
|
496
|
+
* {@link minDuration} fences). Double-click returns to the declared
|
|
497
|
+
* {@link range}. A category axis has no continuous domain and stays inert.
|
|
498
|
+
* - `'y'` — each `<YAxis>` gutter **zooms that one axis** on drag or wheel,
|
|
499
|
+
* double-click releasing it back to its fit. Report it to a scale UI with
|
|
500
|
+
* {@link YAxisProps.onBoundsChange}.
|
|
501
|
+
* - `'xy'` (or `true`) — both.
|
|
502
|
+
*
|
|
503
|
+
* **Deliberately independent of {@link panZoom}**, in both directions. A chart
|
|
504
|
+
* can scale its y axes without letting the plot capture vertical drags (which
|
|
505
|
+
* would fight a selection sweep), and an interactive plot does not hand its
|
|
506
|
+
* axes gestures nobody asked for. The one thing they share is the view itself:
|
|
507
|
+
* the x strip moves the same range the plot's pan does, and reports through
|
|
508
|
+
* {@link onTimeRangeChange} the same way.
|
|
509
|
+
*
|
|
510
|
+
* The pairing to reach for on a time-series chart is
|
|
511
|
+
* `panZoom="panZoom" axisPanZoom="xy"` — drag the plot to pan, drag the x strip
|
|
512
|
+
* to pan, wheel either to zoom, and drag a y gutter to override its fit.
|
|
513
|
+
*/
|
|
514
|
+
axisPanZoom?: boolean | 'none' | 'x' | 'y' | 'xy';
|
|
443
515
|
/**
|
|
444
516
|
* **Outer pan/zoom extent** — `[min, max]` (same units as {@link range}) the
|
|
445
517
|
* view can never move outside. Panning into an edge stops there (the window
|