pond-ts 0.52.0 → 0.53.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 (2) hide show
  1. package/CHANGELOG.md +87 -1
  2. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -8,7 +8,8 @@ The `@pond-ts` packages — `pond-ts`, `@pond-ts/react`, `@pond-ts/charts`,
8
8
  tag, so this file covers them all. Pre-1.0: minor bumps may include new features
9
9
  and type-level changes; patch bumps are strictly additive.
10
10
 
11
- [Unreleased]: https://github.com/pond-ts/pond/compare/v0.52.0...HEAD
11
+ [Unreleased]: https://github.com/pond-ts/pond/compare/v0.53.0...HEAD
12
+ [0.53.0]: https://github.com/pond-ts/pond/compare/v0.52.0...v0.53.0
12
13
  [0.52.0]: https://github.com/pond-ts/pond/compare/v0.51.0...v0.52.0
13
14
  [0.51.0]: https://github.com/pond-ts/pond/compare/v0.50.0...v0.51.0
14
15
  [0.50.0]: https://github.com/pond-ts/pond/compare/v0.49.0...v0.50.0
@@ -52,6 +53,91 @@ and type-level changes; patch bumps are strictly additive.
52
53
 
53
54
  ## [Unreleased]
54
55
 
56
+ ## [0.53.0] — 2026-07-25
57
+
58
+ ### Changed
59
+
60
+ - **fit (breaking):** **Power bins and zones now use pond's canonical bin
61
+ edges**, so they feed `@pond-ts/charts` with no mapping step:
62
+
63
+ ```tsx
64
+ <BarChart bins={power.distribution} column="seconds" />
65
+ <BarChart bins={power.zones} column="seconds" orientation="horizontal" ordinal />
66
+ ```
67
+
68
+ Each type previously spoke its own dialect for the same concept —
69
+ `PowerBin.wattsFrom` (with **no upper edge at all**), `ZoneTime.lo`/`hi`, and
70
+ `PowerZone.minWatts`/`maxWatts` — while core's `byColumn` and charts' `BinRecord`
71
+ both use `{ start, end, …aggregates }`. Every caller had to hand-map before
72
+ drawing, even though the internals already computed the canonical shape and
73
+ discarded it.
74
+
75
+ **Migration** (pre-1.0, so the old names are gone rather than deprecated):
76
+
77
+ | Was | Now |
78
+ | --------------------- | -------------------------------------- |
79
+ | `PowerBin.wattsFrom` | `PowerBin.start` (+ new `end`) |
80
+ | `ZoneTime.lo` / `.hi` | `ZoneTime.start` / `.end`, `openEnded` |
81
+ | `PowerZone.minWatts` | `PowerZone.start` |
82
+ | `PowerZone.maxWatts` | `PowerZone.end`, `openEnded` |
83
+
84
+ Only **`PowerZone.maxWatts`** — a zone's upper edge — is affected. The
85
+ identically-named `PowerSummary.maxWatts` and the per-lap / per-section peak
86
+ power are a different concept and are unchanged.
87
+
88
+ `end` is now **always finite and always `> start`** — the guarantee core
89
+ enforces (`byColumn` throws on a zero-width bin) and charts need (an infinite
90
+ edge blows up an axis domain). The open-ended top band, which previously
91
+ carried only `Infinity`, gets a **drawable stand-in** edge: wide enough to
92
+ cover the highest value observed, and at least as wide as the band below it.
93
+ Treat it as a drawing bound rather than data, and test for the band with the
94
+ new **`openEnded`** flag rather than comparing an edge against `Infinity`
95
+ (`openEnded` is now also strictly positional — only the final band can carry
96
+ it). Rounding zone edges to whole watts no longer collapses bands at very low
97
+ FTPs.
98
+
99
+ ### Added
100
+
101
+ - **charts:** **Duration (elapsed) x axis** — `<ChartContainer origin>` labels
102
+ the shared x axis as offsets from a zero point instead of absolute values, so
103
+ a workout / lab run / load test reads `00:00 00:05 00:10` rather than
104
+ `10:35 10:40 10:45`:
105
+
106
+ ```tsx
107
+ <ChartContainer width={620} origin="data">
108
+
109
+ <XAxis label="Elapsed" />
110
+ </ChartContainer>
111
+ ```
112
+
113
+ `'data'` zeroes at the start of the data (and stays there as you pan); a
114
+ **number** sets an explicit zero point — a gun, a trigger, a lap — with ticks
115
+ before it reading negative (`-00:05`). Ticks are placed at round durations
116
+ **measured from the origin** (a ride starting at 10:33:17 ticks 10:33:17,
117
+ 10:38:17, …), off a clock ladder (…15s, 30s, 1m, 2m, 5m, …, 12h, then whole
118
+ days) rather than the 1-2-5 ladder — the part a formatter alone can't do.
119
+ Labels pick their shape from the step and the axis's magnitude
120
+ (`00:00.500` · `00:15` · `01:01:30` · `1d 12:00` · `5d`), gridlines follow the
121
+ same ticks, and the cursor / marker pills read one grain finer (`00:05:12`).
122
+
123
+ It's a **labelling** mode, not a data transform: `range`, `<Marker at>`,
124
+ `onRegionSelect`, `trackerPosition` all stay in absolute axis units. The same
125
+ prop works on a **value** x axis (distance travelled, not distance recorded).
126
+ An explicit format still wins — on a time axis a d3 _time_ specifier can only
127
+ describe an instant, so it labels the wall clock, which is the lever for
128
+ stacking a wall-clock strip under a duration strip on one shared tick set; on
129
+ a value axis a number specifier formats the offset. Ignored on a category
130
+ axis; on a trading calendar the durations are wall-clock, so ticks spanning a
131
+ collapsed session gap sit unevenly.
132
+
133
+ - **fit:** `computePower` takes an options object — **`{ binWatts }`** sets the
134
+ width of the `distribution` buckets (default `1`, unchanged). 1 W bins draw as
135
+ hairlines, so pass the width you intend to render rather than re-bucketing the
136
+ output yourself. It throws `RangeError` on a non-positive or non-finite
137
+ `binWatts`. New exported type `ComputePowerOptions`, also accepted by the
138
+ activity façade: `Activity.power(ftp, options)` and
139
+ `ProfiledActivity.power(options)`.
140
+
55
141
  ## [0.52.0] — 2026-07-23
56
142
 
57
143
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pond-ts",
3
- "version": "0.52.0",
3
+ "version": "0.53.0",
4
4
  "description": "TypeScript-first time series primitives",
5
5
  "license": "MIT",
6
6
  "repository": {