@pond-ts/react 0.63.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.
Files changed (3) hide show
  1. package/API.md +1 -1
  2. package/CHANGELOG.md +123 -1
  3. package/package.json +2 -2
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` | `packages/core/src/core/`, `packages/core/src/sequence/` |
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,8 @@ 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.63.0...HEAD
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
12
13
  [0.63.0]: https://github.com/pond-ts/pond/compare/v0.62.0...v0.63.0
13
14
  [0.62.0]: https://github.com/pond-ts/pond/compare/v0.61.0...v0.62.0
14
15
  [0.61.0]: https://github.com/pond-ts/pond/compare/v0.60.0...v0.61.0
@@ -66,6 +67,127 @@ include new features and type-level changes; patch bumps are strictly additive.
66
67
 
67
68
  ## [Unreleased]
68
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
+
69
191
  ## [0.63.0] — 2026-08-18
70
192
 
71
193
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pond-ts/react",
3
- "version": "0.63.0",
3
+ "version": "0.64.0",
4
4
  "description": "React hooks for pond-ts live time series",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -34,7 +34,7 @@
34
34
  "test:runtime": "vitest run"
35
35
  },
36
36
  "peerDependencies": {
37
- "pond-ts": "^0.63.0",
37
+ "pond-ts": "^0.64.0",
38
38
  "react": "^18.0.0 || ^19.0.0"
39
39
  },
40
40
  "devDependencies": {