@pond-ts/process 0.59.0 → 0.61.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 +21 -16
- package/CHANGELOG.md +238 -1
- package/package.json +2 -2
package/API.md
CHANGED
|
@@ -249,17 +249,17 @@ Types: `UseSnapshotOptions`, `SnapshotSource` (structural — covers
|
|
|
249
249
|
|
|
250
250
|
### Components — layout & axes
|
|
251
251
|
|
|
252
|
-
| Component | Key props
|
|
253
|
-
| --------------------------- |
|
|
254
|
-
| `ChartContainer` | `width`, `range?`, `theme?`, `cursor?`, `panZoom?`, `bounds?`, `showAxis?`, `calendar?`, `origin?`, `maxBandWidth?`/`bandAlign?`, `onTrackerChanged?`, `onDrawStats?` | Root: shared x-scale, interactions, annotations | `packages/charts/src/ChartContainer.tsx` |
|
|
255
|
-
| `ChartRow` | `height`, `cursor?` (deprecated — mount a cursor in the row)
|
|
256
|
-
| `Layers` | children
|
|
257
|
-
| `YAxis` | `id` (req), `side?`, `scale?` (`'linear'` \| `'log'` \| `'symlog'`), `linearWindow?`, `min?`/`max?`, `format?`, `width?`, `hide?`
|
|
258
|
-
| `XAxis` | `side?`, `label?`, `format?`, `ticks?`, `transform?`, `dateStyle?`
|
|
259
|
-
| `TimeAxis` / `CategoryAxis` | (XAxis props)
|
|
260
|
-
| `Canvas` | `width`, `height`, `draw`
|
|
261
|
-
| `Selector` | `enabled?` (default `true`), `selected?` (mark \| set), `hovered?`, `onSelect?`, `onHover?`, `children?`
|
|
262
|
-
| `MultiSelector` | `enabled?`, `selected?`, `hovered?`, `sequence?`, `onSelect?`, `onHover?`, `children?`
|
|
252
|
+
| Component | Key props | Purpose | Source |
|
|
253
|
+
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
|
|
254
|
+
| `ChartContainer` | `width`, `range?`, `theme?`, `cursor?`, `panZoom?`, `xScale?`, `bounds?`, `showAxis?`, `calendar?`, `origin?`, `maxBandWidth?`/`bandAlign?`, `onTrackerChanged?`, `onDrawStats?` | Root: shared x-scale, interactions, annotations | `packages/charts/src/ChartContainer.tsx` |
|
|
255
|
+
| `ChartRow` | `height`, `cursor?` (deprecated — mount a cursor in the row) | One stacked plot band; owns its y-axes | `packages/charts/src/ChartRow.tsx` |
|
|
256
|
+
| `Layers` | children | Mandatory z-stack inside a row (back-to-front) | `packages/charts/src/Layers.tsx` |
|
|
257
|
+
| `YAxis` | `id` (req), `side?`, `scale?` (`'linear'` \| `'log'` \| `'symlog'`), `linearWindow?`, `min?`/`max?`, `format?`, `width?`, `hide?` | Y-axis gutter; layers bind via their `axis` prop | `packages/charts/src/YAxis.tsx` |
|
|
258
|
+
| `XAxis` | `side?`, `label?`, `format?`, `ticks?`, `transform?`, `dateStyle?` | Placeable x-axis strip; kind inferred from data | `packages/charts/src/XAxis.tsx` |
|
|
259
|
+
| `TimeAxis` / `CategoryAxis` | (XAxis props) | Thin `XAxis` presets | `packages/charts/src/TimeAxis.tsx`, `CategoryAxis.tsx` |
|
|
260
|
+
| `Canvas` | `width`, `height`, `draw` | Low-level DPR-aware canvas primitive | `packages/charts/src/Canvas.tsx` |
|
|
261
|
+
| `Selector` | `enabled?` (default `true`), `selected?` (mark \| set), `hovered?`, `onSelect?`, `onHover?`, `children?` | Wraps its scope; mounting enables click-select and owns the state it drives (RFC A10) | `packages/charts/src/selectors.tsx` |
|
|
262
|
+
| `MultiSelector` | `enabled?`, `selected?`, `hovered?`, `sequence?`, `onSelect?`, `onHover?`, `children?` | Sweep-select superset of `Selector`: drag sweeps marks, release reports `(hits, modifiers, spans)` — plural, one per swept layer (RFC A5.2) | `packages/charts/src/selectors.tsx` |
|
|
263
263
|
|
|
264
264
|
### Components — draw layers
|
|
265
265
|
|
|
@@ -280,7 +280,7 @@ schema columns). Because the union splits per series _kind_, a value typed as
|
|
|
280
280
|
| Component | Data props | Purpose | Source |
|
|
281
281
|
| -------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | -------------------------------------- |
|
|
282
282
|
| `LineChart` | `column`, `gaps?`, `sessionBreaks?` | Gap-aware line | `packages/charts/src/LineChart.tsx` |
|
|
283
|
-
| `AreaChart` | `column`, `baseline?`, `gaps?`
|
|
283
|
+
| `AreaChart` | `column`, `baseline?`, `gaps?`, `thresholds?`/`bandColors?` | Filled area | `packages/charts/src/AreaChart.tsx` |
|
|
284
284
|
| `BandChart` | `lower`, `upper` | Variance-band envelope | `packages/charts/src/BandChart.tsx` |
|
|
285
285
|
| `ScatterChart` | `column`, `id?` (selection), radius/color encodings | Points; data-driven size/colour | `packages/charts/src/ScatterChart.tsx` |
|
|
286
286
|
| `BarChart` | `column` \| `columns` \| `bins` \| `categories`, `orientation?`, `thresholds?`/`bandColors?` | Bars, stacked bars, histograms, categorical | `packages/charts/src/BarChart.tsx` |
|
|
@@ -328,10 +328,10 @@ label + data cells, `sortBy`/`sort`, optional per-row expander. The in-plot
|
|
|
328
328
|
histogram stays `<BarChart orientation="horizontal">` — these are the table
|
|
329
329
|
shape (react-timeseries-charts' `HorizontalBarChart`).
|
|
330
330
|
|
|
331
|
-
| Component | Data props
|
|
332
|
-
| --------- |
|
|
333
|
-
| `BarList` | `rows`, `columns` (`values` names), `sortBy?`, `before?`/`after?`, `renderExpanded?` | Ranked bar list — one proportional bar line per column per row | `packages/charts/src/BarList.tsx` |
|
|
334
|
-
| `BoxList` | `rows`, `columns` (five-number names + `value?` tick), same table props
|
|
331
|
+
| Component | Data props | Purpose | Source |
|
|
332
|
+
| --------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | --------------------------------- |
|
|
333
|
+
| `BarList` | `rows`, `columns` (`values` names), `barColors?`, `sortBy?`, `before?`/`after?`, `renderExpanded?` | Ranked bar list — one proportional bar line per column per row | `packages/charts/src/BarList.tsx` |
|
|
334
|
+
| `BoxList` | `rows`, `columns` (five-number names + `value?` tick), same table props | Distribution list — range band / q1→q3 body / median / current tick | `packages/charts/src/BoxList.tsx` |
|
|
335
335
|
|
|
336
336
|
Row/option types + readers (`packages/charts/src/list.ts`): `ListRow`,
|
|
337
337
|
`ListValue`, `ListCellSpec`, `ListMarker` (reference rule through every row,
|
|
@@ -411,12 +411,17 @@ Series shapes (same file): `ChartSeries`, `BandSeries`, `BoxSeries`,
|
|
|
411
411
|
| `SwatchSpec` / `LegendItemInput` | Legend swatch vocabulary + explicit-rows input (`<Legend items>`) | `packages/charts/src/swatch.ts` |
|
|
412
412
|
| `useChartLegend` | Headless legend hook: rows (items grouped by chart row) + `hover`/`select` verbs | `packages/charts/src/useChartLegend.ts` |
|
|
413
413
|
| `ChartLegend` / `LegendRow` / `LegendItem` | The hook's return shape (`rows` group `items`; items carry `selected`/`hovered`) | `packages/charts/src/useChartLegend.ts` |
|
|
414
|
+
| `useChartFrame` | Resolved plot geometry: plot rect, gutters, x scale, a row's y scales, band slot edges | `packages/charts/src/useChartFrame.ts` |
|
|
415
|
+
| `ChartFrame` / `ChartFrameRow` | The hook's return shape — container x half, plus a row y half that is `null` outside a `<ChartRow>` | `packages/charts/src/useChartFrame.ts` |
|
|
416
|
+
| `ChartBands` / `ChartBand` | Ordinal slot geometry on a category axis (`count`/`pitch`/`labels`/`at(i)`); `null` on time/value | `packages/charts/src/useChartFrame.ts` |
|
|
417
|
+
| `ChartXScale` | The union the container's shared x scale resolves to (time / linear / trading / band / elapsed) | `packages/charts/src/context.ts` |
|
|
414
418
|
| `LegendPlacement` | `'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right'` | `packages/charts/src/Legend.tsx` |
|
|
415
419
|
| `Curve` | Path interpolation: `'linear' \| 'monotone' \| 'natural' \| 'basis' \| 'step'` | `packages/charts/src/curve.ts` |
|
|
416
420
|
| `RadiusEncoding` / `ColorEncoding` | Data-driven scatter size/colour | `packages/charts/src/encoding.ts` |
|
|
417
421
|
| `CandleVariant` / `ColorBy` | OHLC mark shape / colouring strategy | `packages/charts/src/ohlc.ts` |
|
|
418
422
|
| `AxisFormat` / `CursorFormat` | Tick and cursor-readout formatting (d3 specifier or fn) | `packages/charts/src/format.ts` |
|
|
419
423
|
| `AxisTransform` | Monotonic `to`/`from` pair for derived-unit x-axis relabeling | `packages/charts/src/derivedTicks.ts` |
|
|
424
|
+
| `AxisMouseEvent` / `AxisMouseHandler` | Axis `onMouseEvent` payload — the mouse event, the axis's `id`, and the value/label under the pointer | `packages/charts/src/axis-events.ts` |
|
|
420
425
|
| `Orientation` | Bar growth direction | `packages/charts/src/bars.ts` |
|
|
421
426
|
|
|
422
427
|
---
|
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.61.0...HEAD
|
|
12
|
+
[0.61.0]: https://github.com/pond-ts/pond/compare/v0.60.0...v0.61.0
|
|
13
|
+
[0.60.0]: https://github.com/pond-ts/pond/compare/v0.59.0...v0.60.0
|
|
12
14
|
[0.59.0]: https://github.com/pond-ts/pond/compare/v0.58.0...v0.59.0
|
|
13
15
|
[0.58.0]: https://github.com/pond-ts/pond/compare/v0.57.0...v0.58.0
|
|
14
16
|
[0.57.0]: https://github.com/pond-ts/pond/compare/v0.56.2...v0.57.0
|
|
@@ -62,6 +64,241 @@ include new features and type-level changes; patch bumps are strictly additive.
|
|
|
62
64
|
|
|
63
65
|
## [Unreleased]
|
|
64
66
|
|
|
67
|
+
## [0.61.0] — 2026-08-16
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- `@pond-ts/charts`: **`onMouseEvent` on `<XAxis>` and `<YAxis>`** — mouse
|
|
72
|
+
events on an axis strip, carrying the **axis value under the pointer** (the
|
|
73
|
+
part a consumer can't compute, since the scale lives inside the container).
|
|
74
|
+
One handler takes every mouse event on the strip (`click`, `dblclick`,
|
|
75
|
+
`contextmenu`, `mousedown`/`mouseup`, `mousemove`, `mouseenter`/`mouseleave`)
|
|
76
|
+
— switch on `event.type`. The payload (`AxisMouseEvent`, exported) carries
|
|
77
|
+
the raw React event, `axis: 'x' | 'y'`, the axis's `id` (a `<YAxis>` has one;
|
|
78
|
+
an `<XAxis>` does not), the inverted `value`, and the `label` that axis would
|
|
79
|
+
print there — the **category name** on a category axis, whose scale inverts
|
|
80
|
+
to the nearest band centre. Nothing is attached when the prop is omitted, so
|
|
81
|
+
an axis that doesn't opt in pays nothing for the move events. Axis strips now
|
|
82
|
+
also carry `data-axis="x"` / `data-axis="y"` + `data-axis-id` hooks, so a
|
|
83
|
+
consumer can style one (`[data-axis='x'] { cursor: pointer }`) despite the
|
|
84
|
+
axes taking no `className`.
|
|
85
|
+
|
|
86
|
+
### Fixed
|
|
87
|
+
|
|
88
|
+
- `@pond-ts/charts`: the category x-axis label fit now **measures** rendered
|
|
89
|
+
label widths (offscreen-canvas `measureText` in the axis font, with a
|
|
90
|
+
per-glyph estimate fallback for SSR/test DOMs) instead of estimating by
|
|
91
|
+
character count — labels wider than their band (e.g. `SYMBOL-VENUE-TYPE`
|
|
92
|
+
keys) no longer overprint into a smear. The fit measures against the scale's
|
|
93
|
+
real band pitch (so a `maxBandWidth`-packed axis thins correctly), keeps a
|
|
94
|
+
minimum clear gap between drawn labels, truncates from the **middle**
|
|
95
|
+
(`EDGE01…EQT`) so a shared prefix or a shared tail stays distinguishable,
|
|
96
|
+
and draws **no** labels at a degenerate (collapsed / pre-layout) width
|
|
97
|
+
rather than overprinting every label at x ≈ 0. Filed from the SPARC
|
|
98
|
+
migration ([PND-CATFIT]).
|
|
99
|
+
|
|
100
|
+
**Heads-up on a deliberate visual change:** an axis whose labels previously
|
|
101
|
+
packed edge-to-edge at a borderline pitch (label within a couple of px of
|
|
102
|
+
its band) now **thins to every 2nd label** instead — clear separation
|
|
103
|
+
outranks per-band labelling at the margin. On a dense dashboard axis this
|
|
104
|
+
can read as "half the labels disappeared"; it is the fit working as
|
|
105
|
+
intended, not data loss — every band still draws its mark, and the cursor
|
|
106
|
+
readout still names every category.
|
|
107
|
+
|
|
108
|
+
## [0.60.0] — 2026-08-13
|
|
109
|
+
|
|
110
|
+
### Added
|
|
111
|
+
|
|
112
|
+
- `@pond-ts/charts`: `<AreaChart thresholds>` + `bandColors` — threshold
|
|
113
|
+
banding along the area's height ([PND-BANDAREA]), the area counterpart of
|
|
114
|
+
`<BarChart thresholds>`. `n` breakpoints (absolute data values, magnitude-
|
|
115
|
+
mirrored below zero) make `n + 1` bands; fills resolve `bandColors` → the
|
|
116
|
+
new `AreaStyle.bands` theme token (the default theme ships the same
|
|
117
|
+
teal/amber/red ladder as the bar role). One hard-stop pixel-space gradient
|
|
118
|
+
carries the ladder for the fill **and** the outline, so the value line
|
|
119
|
+
switches hue exactly at each crossing and the banded area keeps one hit
|
|
120
|
+
region, one legend row and one readout identity. Composes with `curve`,
|
|
121
|
+
`gaps` and M4 decimation unchanged; a swept window keeps the band colours
|
|
122
|
+
(no `spanColor` swap). Ladder resolution + dev warnings shared with
|
|
123
|
+
`<BarChart>` via one internal hook.
|
|
124
|
+
- **charts: `<ChartContainer xScale="log" | "symlog">` — a logarithmic value x
|
|
125
|
+
axis** ([#649]). The x counterpart of `<YAxis scale>`, for a quantity spanning
|
|
126
|
+
orders of magnitude — a power–duration curve is watts against 1s · 5s · 1m ·
|
|
127
|
+
20m · 3h, which is unreadable on a linear x.
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
<ChartContainer range={[1, 10800]} xScale="log">
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Why the container and not `<XAxis scale>`**, where the `<YAxis>` mirror would
|
|
134
|
+
put it: there is one x scale shared by every row and the container builds it,
|
|
135
|
+
while every `<XAxis>` prop is presentational (`format`, `label`, `side`,
|
|
136
|
+
`ticks`, `align`, …). `<YAxis>` is the opposite — one scale per axis per row,
|
|
137
|
+
declared by the axis, which is why `min`/`max`/`pad`/`scale` live there. It
|
|
138
|
+
sits beside `origin`, `spacing` and `calendar`, which shape the same scale.
|
|
139
|
+
|
|
140
|
+
Ignored on a time or category axis. A `'log'` domain reaching zero **falls back
|
|
141
|
+
to linear and warns** rather than silently clamping — `log(0)` is undefined;
|
|
142
|
+
use `'symlog'` for data that crosses zero.
|
|
143
|
+
|
|
144
|
+
Nothing downstream branches: d3's log scales share the continuous-scale
|
|
145
|
+
surface, so draw layers are untouched. The tick ladder is the one the y axis
|
|
146
|
+
already built (`tickValues`, renamed from `yTickValues` now that both axes use
|
|
147
|
+
it) — d3's raw `scaleLog.ticks()` is nearly a step function.
|
|
148
|
+
|
|
149
|
+
[#649]: https://github.com/pond-ts/pond/issues/649
|
|
150
|
+
|
|
151
|
+
- **charts: `<BarList barColors>` — per-row bar colour** ([#650]). The list's
|
|
152
|
+
counterpart to `<BarChart binColors>`: `barColors[i]` aligned to the rows you
|
|
153
|
+
passed, an `undefined` or short entry falling back to the column's `as` /
|
|
154
|
+
theme fill.
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
<BarList rows={zones} columns={[{ column: 'frac' }]} barColors={ZONE_RAMP} />
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
For the case `binColors` was built for and a list could not do — a zone table
|
|
161
|
+
where each row's bar carries its own step of a ramp. A `BarListColumn`'s
|
|
162
|
+
single `as` paints every row the same colour, so the ramp had to move onto the
|
|
163
|
+
row label, putting it on the wrong element: the bar is the natural carrier of
|
|
164
|
+
a magnitude.
|
|
165
|
+
|
|
166
|
+
**Colours key on the row, not its render position**, so they follow the data
|
|
167
|
+
through a `sortBy` rather than repainting the ramp onto whichever rows now sit
|
|
168
|
+
in those slots.
|
|
169
|
+
|
|
170
|
+
**A per-row colour makes the fill load-bearing, so its state treatment stands
|
|
171
|
+
down** — a coloured bar keeps its own colour while selected, and shows the
|
|
172
|
+
state in opacity instead. That is the rule a multi-metric row already
|
|
173
|
+
followed, and the one `binColors` follows on the canvas: recolouring a bar
|
|
174
|
+
that means something trades a distinction the reader needs for one the band
|
|
175
|
+
and rail already give them.
|
|
176
|
+
|
|
177
|
+
[#650]: https://github.com/pond-ts/pond/issues/650
|
|
178
|
+
|
|
179
|
+
- **charts: `<ChartContainer categories>` — the ordinal axis as a
|
|
180
|
+
container-level choice** ([PND-IGNITECAT]). Declare the slot names on the
|
|
181
|
+
container and **any value-keyed layer can live on them** — a target line, a
|
|
182
|
+
point mark or a filled envelope over categorical bars, which was previously
|
|
183
|
+
not expressible at all.
|
|
184
|
+
|
|
185
|
+
The band scale used to be reachable only _through a layer_: `<BarChart
|
|
186
|
+
categories>` and a **horizontal** heat map reported `xKind: 'category'`, every other layer
|
|
187
|
+
reported `'time'` or `'value'`, and a container throws on a mixed kind. The
|
|
188
|
+
workaround — key every layer to a synthetic integer index and hand-supply the
|
|
189
|
+
tick labels — forfeits two features the ordinal axis already implements, and
|
|
190
|
+
both came back as their own friction entries: `<XAxis>` label thinning (gated
|
|
191
|
+
on a category axis with no custom ticks) and the `maxBandWidth` / `bandAlign`
|
|
192
|
+
slot packing. Declaring the categories on the container keeps both.
|
|
193
|
+
|
|
194
|
+
The change is small because the scale was already built for it: `scaleBand`'s
|
|
195
|
+
domain is **numeric** (`[0, n]`, slot `i` at `[i, i+1]`) with a linear pixel
|
|
196
|
+
mapping, so a `ValueSeries` keyed on slot coordinates already lands where the
|
|
197
|
+
bars do. **Slot `i`'s centre is `i + 0.5`** — the same number
|
|
198
|
+
`ScaleBand.ticks()` returns and where `<XAxis>` puts the tick.
|
|
199
|
+
|
|
200
|
+
Two things error, deliberately: a **time-keyed layer** (a timestamp has no
|
|
201
|
+
slot), and a **category layer that disagrees** with the prop in content or
|
|
202
|
+
order — the prop is authoritative, and a silent mismatch would draw bars
|
|
203
|
+
under the wrong labels. The pre-existing mixed-kind error now names the prop
|
|
204
|
+
as the fix.
|
|
205
|
+
|
|
206
|
+
Declaring it has two costs, both already true of an inferred category axis
|
|
207
|
+
and now reachable from a previously-continuous container: **x pan and zoom
|
|
208
|
+
stop** (`panZoom` keeps working on y), and **`range` stops applying to x**
|
|
209
|
+
(the domain is `[0, n]` from the slot count, so an x range is a no-op).
|
|
210
|
+
|
|
211
|
+
One hazard is documented rather than enforced: **a value-keyed layer is taken
|
|
212
|
+
at its word**, so a layer whose x means something other than a slot
|
|
213
|
+
coordinate — a horizontal categorical `<BarChart>`, whose x is bar _length_ —
|
|
214
|
+
will draw in the wrong place. A guard for that case was written and removed
|
|
215
|
+
after review: it tested `binCategories`, which is the generic "my _y_ is
|
|
216
|
+
ordinal" channel that a **vertical heat map** sets for its rows, so it
|
|
217
|
+
rejected a slot-keyed grid with named columns on x — a wanted layout, since
|
|
218
|
+
ordinal rows plus ordinal columns is just a 2-D grid. Nothing distinguishes
|
|
219
|
+
"my x is a coordinate" from "my x is a magnitude", so there is no
|
|
220
|
+
contradiction to detect.
|
|
221
|
+
|
|
222
|
+
`categories={[]}` is an ordinal axis with **no slots yet**, not a fallback to
|
|
223
|
+
time — so the kind doesn't flip and rebuild every scale when data arrives.
|
|
224
|
+
|
|
225
|
+
Omitting `categories` leaves the inferred behaviour exactly as it was.
|
|
226
|
+
|
|
227
|
+
- **charts: `useChartFrame()` — the resolved plot geometry, published**
|
|
228
|
+
([PND-IGNITEFRAME]). A hook returning what the container already worked out:
|
|
229
|
+
the plot rect (`plot.x` / `plot.width`), the reserved axis `gutters`, the
|
|
230
|
+
shared `xScale` and its `xKind`, a row's `yScales` and top inset, and — on a
|
|
231
|
+
category axis — the ordinal slot edges (`bands.at(i)`, `pitch`, `labels`).
|
|
232
|
+
|
|
233
|
+
Consumers aligning DOM chrome to the plot (per-slot header tables, column
|
|
234
|
+
summary strips, cards pinned over a band, a colour ramp keyed to the plot's
|
|
235
|
+
own scale) previously had to re-derive all of it: pin every axis gutter to a
|
|
236
|
+
fixed width so it stops depending on label content, measure the outer box,
|
|
237
|
+
subtract, and re-implement the band packing. **That duplicate is not merely
|
|
238
|
+
verbose — it is wrong over time.** It holds only until the library changes
|
|
239
|
+
how a gutter is sized or how bands are packed, at which point the chrome
|
|
240
|
+
slides out of alignment with the plot it labels, with no type error and no
|
|
241
|
+
failing test.
|
|
242
|
+
|
|
243
|
+
Two shape notes. **The x/y split is the library's own** — the container owns
|
|
244
|
+
one shared x scale, rows own their y scales — so `plot` carries x and `row`
|
|
245
|
+
carries y, and `row` is `null` when the hook is called outside a
|
|
246
|
+
`<ChartRow>`. That `null` is deliberate: the common case (a header strip
|
|
247
|
+
beside the rows) genuinely has no y geometry, and reporting `height: 0`
|
|
248
|
+
instead would be the same silent misalignment the hook exists to remove.
|
|
249
|
+
**Scope follows placement**, exactly as `useChartLegend` already does.
|
|
250
|
+
|
|
251
|
+
`useChartLegend`'s `gutters` is unchanged and still the right call for a
|
|
252
|
+
legend; it now documents `useChartFrame()` as the fuller surface. It was the
|
|
253
|
+
only geometry the library published, for one consumer, on a hook named for
|
|
254
|
+
something else — which is why this exists.
|
|
255
|
+
|
|
256
|
+
- **charts: `<ChartContainer width="auto">` — fill the available width**
|
|
257
|
+
([PND-WIDTH]). `width` now accepts `'auto'`, and an omitted `width` means the
|
|
258
|
+
same; a number still skips the measure pass and paints on the first render.
|
|
259
|
+
The container renders a plain full-width box, measures it with a
|
|
260
|
+
`ResizeObserver`, and mounts the chart at that pixel width — the canvas
|
|
261
|
+
renderer needs real pixels to lay out ticks and slots, so this is measurement
|
|
262
|
+
moved inside the library rather than a percentage handed to a canvas. Nothing
|
|
263
|
+
paints until a real width exists.
|
|
264
|
+
|
|
265
|
+
This is the shipped
|
|
266
|
+
[responsive-width recipe](https://pond-ts.github.io/pond/docs/recipes/responsive-width)
|
|
267
|
+
become the implementation, and it closes that recipe's sharpest edge by
|
|
268
|
+
construction: the measured box is one the library owns, so it can never be
|
|
269
|
+
the caller's padded or bordered box (whose border-box width overflowed the
|
|
270
|
+
chart by exactly the padding, silently clipped when the box also hid
|
|
271
|
+
overflow). Style your own wrapper freely.
|
|
272
|
+
|
|
273
|
+
Two behaviours worth knowing. A container **hidden** by an ancestor's
|
|
274
|
+
`display: none` keeps the last width it measured and stays mounted, so a tab
|
|
275
|
+
switch does not discard pan/zoom position, selection or hover — writing the
|
|
276
|
+
zero measurement through would unmount and rebuild all of it. And `'auto'`
|
|
277
|
+
needs a parent with a **definite** width: a parent sized by its own content
|
|
278
|
+
(a float, an `inline-block`, a grid `auto` track, a flex child without
|
|
279
|
+
`min-width: 0`) measures 0, and the chart is the content that would have
|
|
280
|
+
given it a width, so the chart stays blank with no error.
|
|
281
|
+
|
|
282
|
+
Three independent consumers reported the explicit-pixel requirement; the
|
|
283
|
+
third was multiplying the same ~25-line measure-and-gate hook across seven
|
|
284
|
+
panes.
|
|
285
|
+
|
|
286
|
+
### Changed
|
|
287
|
+
|
|
288
|
+
- **charts: `ChartContainerProps.width` is now `number | 'auto'` and optional**
|
|
289
|
+
(was a required `number`). Strictly additive for callers passing a number.
|
|
290
|
+
|
|
291
|
+
### Fixed
|
|
292
|
+
|
|
293
|
+
- **charts: value-axis pan and zoom no longer snap to whole integers**
|
|
294
|
+
(shipped inside [#653]). `panRange`/`zoomRange` were written for a
|
|
295
|
+
millisecond axis and silently assumed every axis was one, so a value domain
|
|
296
|
+
of `[0.5, 10800]` snapped its floor to `0` and `[0.001, 1]` collapsed to
|
|
297
|
+
`[0, 1]` — fatal under a log axis, where `log(0)` is undefined. Gestures now
|
|
298
|
+
snap only on a **time** axis (`ViewportOptions.snap`), and a log x axis pans
|
|
299
|
+
by ratio and zooms in log space, keeping the value under the cursor fixed.
|
|
300
|
+
Time-axis behaviour is unchanged.
|
|
301
|
+
|
|
65
302
|
## [0.59.0] — 2026-08-11
|
|
66
303
|
|
|
67
304
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pond-ts/process",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.61.0",
|
|
4
4
|
"description": "Computations as data over pond-ts: processing graphs authored fluently or composed as JSON, resolved against a declared op vocabulary with content-addressed caching, provenance, and per-node timings. Experimental, pre-1.0.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"verify": "npm run format:check && npm run build && npm test"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"pond-ts": "^0.
|
|
45
|
+
"pond-ts": "^0.61.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"typescript": "^5.6.3",
|