@pond-ts/charts 0.48.1 → 0.50.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 +225 -1
- package/dist/AreaChart.d.ts +18 -1
- package/dist/AreaChart.js +23 -2
- package/dist/BandChart.d.ts +21 -2
- package/dist/BandChart.js +68 -9
- package/dist/BarChart.d.ts +12 -1
- package/dist/BarChart.js +34 -1
- package/dist/BoxPlot.d.ts +29 -1
- package/dist/BoxPlot.js +61 -3
- package/dist/Candlestick.d.ts +21 -1
- package/dist/Candlestick.js +42 -7
- package/dist/ChartContainer.d.ts +23 -13
- package/dist/ChartContainer.js +86 -32
- package/dist/ChartRow.js +22 -3
- package/dist/Layers.js +37 -14
- package/dist/Legend.d.ts +62 -0
- package/dist/Legend.js +169 -0
- package/dist/LineChart.d.ts +20 -1
- package/dist/LineChart.js +23 -2
- package/dist/ScatterChart.d.ts +8 -1
- package/dist/ScatterChart.js +24 -1
- package/dist/XAxis.js +9 -2
- package/dist/YAxis.d.ts +9 -1
- package/dist/YAxis.js +27 -6
- package/dist/annotations.d.ts +21 -3
- package/dist/annotations.js +36 -15
- package/dist/area.d.ts +2 -1
- package/dist/area.js +29 -4
- package/dist/band.d.ts +2 -1
- package/dist/band.js +18 -1
- package/dist/bars.js +8 -1
- package/dist/box.d.ts +15 -1
- package/dist/box.js +71 -2
- package/dist/context.d.ts +51 -4
- package/dist/culling.d.ts +165 -0
- package/dist/culling.js +286 -0
- package/dist/data.d.ts +3 -1
- package/dist/decimate.d.ts +231 -0
- package/dist/decimate.js +478 -0
- package/dist/format.d.ts +20 -11
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/line.d.ts +2 -1
- package/dist/line.js +38 -3
- package/dist/ohlc.d.ts +2 -1
- package/dist/ohlc.js +23 -2
- package/dist/scatter.js +42 -7
- package/dist/swatch.d.ts +104 -0
- package/dist/swatch.js +96 -0
- package/dist/theme.d.ts +27 -0
- package/dist/theme.js +12 -0
- package/dist/useChartLegend.d.ts +106 -0
- package/dist/useChartLegend.js +122 -0
- package/dist/yticks.d.ts +20 -0
- package/dist/yticks.js +28 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -8,7 +8,9 @@ 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.
|
|
11
|
+
[Unreleased]: https://github.com/pond-ts/pond/compare/v0.50.0...HEAD
|
|
12
|
+
[0.50.0]: https://github.com/pond-ts/pond/compare/v0.49.0...v0.50.0
|
|
13
|
+
[0.49.0]: https://github.com/pond-ts/pond/compare/v0.48.1...v0.49.0
|
|
12
14
|
[0.48.1]: https://github.com/pond-ts/pond/compare/v0.48.0...v0.48.1
|
|
13
15
|
[0.48.0]: https://github.com/pond-ts/pond/compare/v0.47.0...v0.48.0
|
|
14
16
|
[0.47.0]: https://github.com/pond-ts/pond/compare/v0.46.0...v0.47.0
|
|
@@ -48,6 +50,228 @@ and type-level changes; patch bumps are strictly additive.
|
|
|
48
50
|
|
|
49
51
|
## [Unreleased]
|
|
50
52
|
|
|
53
|
+
## [0.50.0] — 2026-07-21
|
|
54
|
+
|
|
55
|
+
### Added
|
|
56
|
+
|
|
57
|
+
- **charts:** M4 decimation extended to **`<Candlestick>`** (same auto-on
|
|
58
|
+
`decimate` prop). Dense candles are drawn as per-pixel-column **aggregate
|
|
59
|
+
candles** — `open=first`, `high=max`, `low=min`, `close=last` over the column —
|
|
60
|
+
i.e. re-bucketed to the pixel-column timeframe, the way a trading chart shows
|
|
61
|
+
fewer, wider candles as you zoom out (decimator §2.4). It is a faithful OHLC of
|
|
62
|
+
each column's span, never a distortion; the hover readout still reads the
|
|
63
|
+
**source** candle at the cursor (§2.3). Decimation gates on the **visible**
|
|
64
|
+
candle count, so a deep zoom into a large series still draws full-width
|
|
65
|
+
candles. Pass `decimate={false}` (and pre-aggregate upstream) for
|
|
66
|
+
fixed-timeframe candles.
|
|
67
|
+
- **charts:** M4 decimation extended to **`<BoxPlot>`** (same auto-on `decimate`
|
|
68
|
+
prop) — the interval-mark sibling of the candle. Dense boxes are drawn as
|
|
69
|
+
per-pixel-column **aggregate boxes**: the whiskers widen to the column's reach
|
|
70
|
+
(`min(lower)`/`max(upper)`), the body to its IQR envelope
|
|
71
|
+
(`min(q1)`/`max(q3)`), the centre line to the first box's median. Gates on the
|
|
72
|
+
**visible** box count (a deep zoom still draws full-width boxes); the
|
|
73
|
+
`hasBox`/`hasMedian` flags carry through, so a range-only box stays range-only.
|
|
74
|
+
Interaction is unaffected — hit-testing reads the source boxes (§2.3). Pass
|
|
75
|
+
`decimate={false}` to draw every box at its own slot.
|
|
76
|
+
|
|
77
|
+
## [0.49.0] — 2026-07-21
|
|
78
|
+
|
|
79
|
+
### Added
|
|
80
|
+
|
|
81
|
+
- **charts:** **Annotation theme roles** (#508 item 3, Tidal vol-surface
|
|
82
|
+
friction). `theme.annotation` gains an optional **`roles`** map (role name →
|
|
83
|
+
`{ color, fillOpacity? }`), and `<Baseline>` / `<Marker>` / `<Region>` gain a
|
|
84
|
+
**`role`** prop that recolours that mark from `roles[role]` while keeping the
|
|
85
|
+
shared depth ramp — so a smile can place a green ATM baseline, a distinct
|
|
86
|
+
reference marker, and an amber zone at once without the whole register
|
|
87
|
+
shifting together. Resolves `roles[role] ?? annotation` (an unknown/unset
|
|
88
|
+
role is the base register). **Colour stays a theme concern** — there is no
|
|
89
|
+
per-mark colour prop (the one-styling-channel discipline; consistent with the
|
|
90
|
+
per-box red/green reject). `cssVarTheme` carries the `roles` map through
|
|
91
|
+
unchanged (deep-merged). `theme.annotation.roles` is optional, so existing
|
|
92
|
+
themes are unaffected.
|
|
93
|
+
- **charts:** **`<BoxPlot id>` — box selection** (#508 item 5, Tidal
|
|
94
|
+
vol-surface friction). A `BoxPlot` with an `id` is now clickable on the same
|
|
95
|
+
id-gated contract `<BarChart>` / `<ScatterChart>` carry
|
|
96
|
+
(`selected`/`onSelect`, `hovered`/`onHover`): a click anywhere on a box —
|
|
97
|
+
body or whisker, a range-only bid→ask segment included — selects it via
|
|
98
|
+
rect-containment (`boxAt`, the interval-mark analog of `barAt`, **not** the
|
|
99
|
+
continuous nearest-point threshold), and the selected box outlines (hovered
|
|
100
|
+
fainter, reusing `theme.box.stroke`, no new token). `key` is the box's `x`
|
|
101
|
+
(its span begin). Without an `id` the box stays display-only. Independent of
|
|
102
|
+
the box's `cursorFlag` cursor opt-out — selection rides the separate
|
|
103
|
+
`hitTest` path.
|
|
104
|
+
- **charts:** **`<YAxis tickCount>` + height-derived tick density** (#508
|
|
105
|
+
item 4, Tidal vol-surface friction). The y axis's auto-tick count now
|
|
106
|
+
follows the **row height** by default — a short strip (e.g. a 72px
|
|
107
|
+
histogram lane) gets fewer ticks than a tall row instead of crushing the
|
|
108
|
+
same ~5 labels into the space (mirrors the width-derived trading-time x
|
|
109
|
+
axis). A new **`tickCount`** prop pins an explicit target; explicit
|
|
110
|
+
`ticks` still overrides both. The count is resolved once per axis on the
|
|
111
|
+
row (`resolveYTickCount`) and shared by the axis labels, the cursor-readout
|
|
112
|
+
formatter, and the row gridlines, so a label / its gridline / its readout
|
|
113
|
+
stay on the same `ticks(count)` (replaces three hardcoded `5`s that agreed
|
|
114
|
+
by convention).
|
|
115
|
+
|
|
116
|
+
- **charts:** **`<Legend>` — the series key** (#508 item 2, Tidal vol-surface
|
|
117
|
+
friction; design per the sender's sketch on the issue). Every draw layer now
|
|
118
|
+
registers its readout identity (`as ?? column`) plus its **resolved** style
|
|
119
|
+
as a `SwatchSpec` (line stroke+dash, area fill+line, band envelope, scatter
|
|
120
|
+
dot, box whisker, bar fill, candle up/down pair), and `<Legend />` renders
|
|
121
|
+
the registry as a small card anchored to a corner of the rows block
|
|
122
|
+
(`placement`, default `top-right`) — so the key can never drift from the
|
|
123
|
+
plot. Rows follow chart-row → declaration order; identities collapse
|
|
124
|
+
(`id ?? label`, as the tracker readout merges keys); a **stacked bar
|
|
125
|
+
registers one row per group** with its resolved fill. Per-layer control via
|
|
126
|
+
a new `legend` prop on all seven marks: `false` opts out, a string renames.
|
|
127
|
+
Interactions are **id-gated** (the shipped selection contract): rows whose
|
|
128
|
+
layer has an `id` echo hover into the container and toggle selection on
|
|
129
|
+
click; `onRowHover` / `onRowClick` take over when provided; series
|
|
130
|
+
show/hide deliberately stays consumer-side. **Scope follows placement:** at
|
|
131
|
+
the container level the card lists every row; placed inside a `<Layers>` it
|
|
132
|
+
scopes to that `<ChartRow>` and anchors to that row's plot (a per-row legend
|
|
133
|
+
needs no prop). `<Legend items={…}>` renders explicit rows — inside a
|
|
134
|
+
container or standalone (a dashboard-side key).
|
|
135
|
+
New optional `theme.legend` slot (background/border/text; derives from
|
|
136
|
+
`chip`/`axis` tokens when absent, so hand-built themes keep compiling).
|
|
137
|
+
**Headless variant:** `useChartLegend()` serves the entries as data —
|
|
138
|
+
`rows` (**items grouped by chart row**; each item is
|
|
139
|
+
`label` + resolved swatch + `id` + live `selected`/`hovered`; a flat list
|
|
140
|
+
is `rows.flatMap((r) => r.items)`) plus chart-synced `hover`/`select`
|
|
141
|
+
verbs, the container's axis `gutters` (for aligning a custom layout to the
|
|
142
|
+
plot), and **`cursorTime`** (the cursor's axis instant, `null` when idle) —
|
|
143
|
+
the seams for a legend that is a design of its own: horizontal chip rows,
|
|
144
|
+
ticker-compare with the secondary dimmed, and **current-or-cursor values**
|
|
145
|
+
per item (`series.nearest(cursorTime)`, else the latest sample; item
|
|
146
|
+
labels also match the tracker's sample labels, so an `onTrackerChanged`
|
|
147
|
+
merge is a label-keyed join); `<Legend>` itself renders through the same
|
|
148
|
+
core, so the two can't disagree. **Scope follows placement** for both the
|
|
149
|
+
card and the hook: inside a `<Layers>` they scope to that `<ChartRow>` and
|
|
150
|
+
the card anchors to that row's plot; container-level stays all-rows. Card
|
|
151
|
+
polish per the first design pass: plot-area-inset placement, selection
|
|
152
|
+
reads by contrast (the selected item bold, others dulled — the
|
|
153
|
+
ticker-compare treatment), a dashed line's swatch hand-renders as a
|
|
154
|
+
canonical three-dash glyph, and a bar's swatch is a centred rounded square.
|
|
155
|
+
New exports: `Legend`, `LegendProps`, `LegendPlacement`, `SwatchSpec`,
|
|
156
|
+
`LegendItemInput`, `useChartLegend`, `ChartLegend`, `LegendRow`,
|
|
157
|
+
`LegendItem`.
|
|
158
|
+
- **charts:** **`cursorFormat` reaches value axes** (#508 item 1, Tidal
|
|
159
|
+
vol-surface friction) — the container's readout channel now applies on a
|
|
160
|
+
value x axis exactly as on a time axis: a **string** is a d3 _number_
|
|
161
|
+
specifier there, a **function** receives
|
|
162
|
+
`(value, { grain: undefined, defaultText })` (no time grain to hand over;
|
|
163
|
+
`defaultText` is the axis-default text). The readout also gains its
|
|
164
|
+
documented precedence on the axis strip on **every** axis kind:
|
|
165
|
+
`cursorFormat → axis format → container`, so an explicit `<XAxis format>`
|
|
166
|
+
keeps ticks terse while `cursorFormat` makes the cursor pill / marker
|
|
167
|
+
indicators / annotation auto-labels precise (`+2.0σ` ticks, `+1.83σ` pill).
|
|
168
|
+
A `transform`ed axis is exempt (its pill speaks the derived unit); a
|
|
169
|
+
category axis reads names and ignores `cursorFormat`. Type change:
|
|
170
|
+
`CursorFormat`'s function form widens `ctx.grain` from `TimeGrain` to
|
|
171
|
+
`TimeGrain | undefined`; the frame gains an optional `formatReadout`
|
|
172
|
+
channel (see Fixed below for the `formatTime` clarification).
|
|
173
|
+
- **charts:** **M4 line decimation** (charts decimator wave, Phase 3) — the
|
|
174
|
+
`<LineChart>` now draws from the per-device-pixel-column min/max/first/last
|
|
175
|
+
(pond's `binBy(…, 'minMaxFirstLast')`) once the visible data exceeds ~2 samples
|
|
176
|
+
per pixel, so a **fully-visible** dense series (which viewport culling can't
|
|
177
|
+
help) draws from O(plot width) points instead of every sample: a 1M-point line
|
|
178
|
+
drops from ~34 ms/frame to ~3.4 ms, under the 60 fps budget. It is **visually
|
|
179
|
+
lossless** (an e2e pixel-diff bounds the decimated-vs-full difference to a thin
|
|
180
|
+
sub-pixel AA seam) and **preserves single-sample anomalies** (the min/max
|
|
181
|
+
channel keeps the spike M4 is chosen over LTTB to keep). Bucket edges are the
|
|
182
|
+
scale's pixel range inverted back to key space, so each bucket is one pixel
|
|
183
|
+
column on **any** scale, including a non-affine `TradingTimeScale`. Auto-on with
|
|
184
|
+
an opt-out / tuning prop
|
|
185
|
+
`decimate={false | { threshold }}` (new `DecimateOption` export). **All gap
|
|
186
|
+
modes** decimate: a §2.2 **gap-edge union** folds each ≥1-pixel interior gap's
|
|
187
|
+
boundaries into the bucket edges, so the gap reduces to its own empty (`NaN`)
|
|
188
|
+
bucket with exact pre/post-gap values — `'empty'` breaks precisely, `'none'`
|
|
189
|
+
bridges, and the `dashed`/`step`/`fade` connectors still draw across the gap.
|
|
190
|
+
**`sessionBreaks` decimate too** — the same union folds each trading-axis
|
|
191
|
+
session-break instant into the bucket edges so no bucket merges two sessions'
|
|
192
|
+
extremes across the discontinuity, and `sessionRuns` then splits the decimated
|
|
193
|
+
series into clean per-session subpaths (a dense intraday line on a trading-time
|
|
194
|
+
axis decimates _and_ breaks at each session open). Still gated off only a
|
|
195
|
+
non-linear `curve` (documented backlog). Interaction reads the source series
|
|
196
|
+
(§2.3), so readouts/selection are unaffected.
|
|
197
|
+
- **charts:** M4 decimation extended to **`<AreaChart>` and `<BandChart>`** (same
|
|
198
|
+
auto-on `decimate={false | { threshold }}` prop). An **area** reuses the line M4
|
|
199
|
+
on its outline (gap-edge union included) with the fill following under the
|
|
200
|
+
full-series gradient — so a dense filled area shrinks its fill + outline work to
|
|
201
|
+
O(plot width). A **band** decimates to the per-pixel-column **min(`lower`) /
|
|
202
|
+
max(`upper`)** — the widest envelope the samples span, so it can never invert
|
|
203
|
+
(§2.5) and covers the same pixels; the win is the canvas fill (≈W vertices vs
|
|
204
|
+
every sample). Both gated off a non-linear `curve`; interaction unaffected.
|
|
205
|
+
- **charts:** **Viewport culling** (charts decimator wave, Phase 2). Line, area,
|
|
206
|
+
and band layers now clip to the **visible slice** of their key column — plus
|
|
207
|
+
one entry/exit point each side so the segment crossing each plot edge still
|
|
208
|
+
draws — before any path work, so a pan/zoom repaint costs O(visible) instead
|
|
209
|
+
of O(N). On a large series zoomed in, the per-frame `drawLine` path-generation
|
|
210
|
+
cost drops from ~29 ms at 1M points (over the 16.67 ms/60 fps budget — the
|
|
211
|
+
cause of the #256 pan-FPS collapse) to ~0.06 ms; a fully-visible series is
|
|
212
|
+
unchanged (culling no-ops, keeping that draw byte-identical — the baseline the
|
|
213
|
+
Phase 3 M4 decimator addresses). Interaction is unaffected: `sampleAt` /
|
|
214
|
+
`hitTest` read the full source series, so a hover readout or selection never
|
|
215
|
+
shifts when the window resizes (the decimator RFC §2.3 invariant). Culling is
|
|
216
|
+
automatic and internal — no API change.
|
|
217
|
+
- **charts:** Viewport culling extended to the **per-mark** layers — scatter,
|
|
218
|
+
bars, candles, and boxes. These loop over independent marks with index-keyed
|
|
219
|
+
accessors (a scatter's `colorAt(i)`, a bar's `begin[i]` selection match), so
|
|
220
|
+
rather than a subarray view they cull by **restricting the draw loop to the
|
|
221
|
+
visible index range** (the original `i` is preserved, so every accessor and
|
|
222
|
+
selection/hover match stays correct). Point marks (scatter) use the same
|
|
223
|
+
entry/exit window as lines; interval marks (bars / candles / boxes) use a
|
|
224
|
+
span-overlap window that keeps a wide mark crossing a plot edge. Same
|
|
225
|
+
automatic, internal, interaction-safe behaviour — a 500k-bar chart zoomed in
|
|
226
|
+
drops from ~23 ms/frame to ~0.16 ms.
|
|
227
|
+
- **charts:** Scatter culling is now **radius-aware**. The per-mark index margin
|
|
228
|
+
above measures neighbours in sample count, but a scatter mark's disc has a
|
|
229
|
+
pixel radius independent of sample spacing — so a dense scatter of fat marks
|
|
230
|
+
could drop an edge bubble whose _centre_ sits several samples off-screen while
|
|
231
|
+
its _disc_ still overlaps the plot edge (a subtle flicker under pan). The
|
|
232
|
+
scatter draw now widens the visible window by its max drawn radius (converted
|
|
233
|
+
px→data through the scale, plus any `offsetPx` nudge) before culling, so every
|
|
234
|
+
mark that can paint into the plot is kept. Small-radius scatters are unaffected
|
|
235
|
+
(they re-expand by a few pixels — usually the same window). Interval marks
|
|
236
|
+
(bars / candles / boxes) don't need this — their width _is_ their x-span.
|
|
237
|
+
|
|
238
|
+
### Changed
|
|
239
|
+
|
|
240
|
+
- **charts:** **Tracker labels key on `as` across the multi-value marks**
|
|
241
|
+
(F-charts-8 §3, the `<Legend>` label-source prerequisite). With a semantic
|
|
242
|
+
`as`, a `<BandChart>`'s edge samples now read `"<as> lower"` / `"<as>
|
|
243
|
+
upper"` and a `<Candlestick showOHLC>`'s quote pills read `"<as> high"` /
|
|
244
|
+
`"<as> open"` / … — the series-name + role convention `<BoxPlot>` already
|
|
245
|
+
shipped (`iv upper`) — so readout/legend merge keys are the series
|
|
246
|
+
identity, not raw column names or bare role words. Without an `as`,
|
|
247
|
+
labels are unchanged (column names / role words). Consumers keying
|
|
248
|
+
`onTrackerChanged` readouts on the old labels while setting `as` should
|
|
249
|
+
key on the new `"<as> <role>"` form.
|
|
250
|
+
|
|
251
|
+
### Fixed
|
|
252
|
+
|
|
253
|
+
- **charts:** **`cursorFormat` no longer leaks into tick labels** — setting
|
|
254
|
+
`timeFormat` _and_ `cursorFormat` together on a time axis rendered the
|
|
255
|
+
**tick labels** with `cursorFormat` (the ladder was disqualified by
|
|
256
|
+
`timeFormat`, and the tick fallback read the merged readout formatter).
|
|
257
|
+
The frame now carries two channels: `formatTime` is the label channel
|
|
258
|
+
(`timeFormat`-shaped, never `cursorFormat` — restoring its documented
|
|
259
|
+
meaning), and the new optional `formatReadout` carries `cursorFormat` to
|
|
260
|
+
the readout consumers (crosshair pill + in-plot cursor time, marker
|
|
261
|
+
indicators, annotation auto-labels). Frame consumers that read
|
|
262
|
+
`ContainerFrame.formatTime` for a readout should use
|
|
263
|
+
`formatReadout ?? formatTime`.
|
|
264
|
+
- **charts:** **Region drag-select no longer races the pointer stream**
|
|
265
|
+
(#508 item 7) — the drag anchor was container **state** read back through
|
|
266
|
+
the rendered frame at `pointerup`, so a batched/untrusted pointer stream
|
|
267
|
+
(automation, jsdom — plausibly a very fast flick under load) could deliver
|
|
268
|
+
`down→up` before the anchor committed: the select was **silently dropped**
|
|
269
|
+
and the late-committing anchor **leaked**, leaving the band stuck.
|
|
270
|
+
Human-paced trusted input hid this (React flushes trusted discrete events
|
|
271
|
+
synchronously). Gesture logic now reads a ref (the same ref+state
|
|
272
|
+
discipline the annotation-create drag already used); the state stays
|
|
273
|
+
paint-only. Deterministic regression tests cover both pacings.
|
|
274
|
+
|
|
51
275
|
## [0.48.1] — 2026-07-19
|
|
52
276
|
|
|
53
277
|
### Fixed
|
package/dist/AreaChart.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ValueSeries } from 'pond-ts';
|
|
2
2
|
import type { SeriesSchema, TimeSeries, ValueSeriesSchema } from 'pond-ts';
|
|
3
|
+
import type { DecimateOption } from './decimate.js';
|
|
3
4
|
import { type Curve } from './curve.js';
|
|
4
5
|
import { type GapMode } from './gaps.js';
|
|
5
6
|
export interface AreaChartProps<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema> {
|
|
@@ -65,6 +66,22 @@ export interface AreaChartProps<S extends SeriesSchema = SeriesSchema, VS extend
|
|
|
65
66
|
* `'dashed'` / `'step'` connector faintness is the theme's `gap.connectorOpacity`.)
|
|
66
67
|
*/
|
|
67
68
|
gaps?: GapMode;
|
|
69
|
+
/**
|
|
70
|
+
* **M4 viewport decimation** (charts decimator wave). **Omitted ⇒ `true`**:
|
|
71
|
+
* once the visible data is denser than ~2 samples per device pixel, the fill +
|
|
72
|
+
* outline are drawn from the per-pixel-column M4 buckets (a visually-lossless
|
|
73
|
+
* polyline of O(plot width) points) instead of every sample. Applies with a
|
|
74
|
+
* linear `curve`; pass `false` to always draw every point, or `{ threshold }`
|
|
75
|
+
* to tune the samples-per-pixel factor. Shares {@link LineChart}'s
|
|
76
|
+
* `DecimateOption`.
|
|
77
|
+
*/
|
|
78
|
+
decimate?: DecimateOption;
|
|
79
|
+
/**
|
|
80
|
+
* This layer's `<Legend>` row: `false` ⇒ no row (opt out), a string ⇒ the
|
|
81
|
+
* row's display name. **Omitted ⇒ a row named by the layer's readout
|
|
82
|
+
* identity** (`as` ?? `column`). The swatch is the resolved area style.
|
|
83
|
+
*/
|
|
84
|
+
legend?: boolean | string;
|
|
68
85
|
/**
|
|
69
86
|
* @internal Declaration position among the `<Layers>` children, injected by
|
|
70
87
|
* `Layers` so z-order follows JSX order. Do not set.
|
|
@@ -91,5 +108,5 @@ export interface AreaChartProps<S extends SeriesSchema = SeriesSchema, VS extend
|
|
|
91
108
|
* </Layers>
|
|
92
109
|
* ```
|
|
93
110
|
*/
|
|
94
|
-
export declare function AreaChart<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema>({ series, column, as: semantic, axis, baseline, curve, gaps, index, }: AreaChartProps<S, VS>): null;
|
|
111
|
+
export declare function AreaChart<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema>({ series, column, as: semantic, axis, baseline, curve, gaps, decimate, legend, index, }: AreaChartProps<S, VS>): null;
|
|
95
112
|
//# sourceMappingURL=AreaChart.d.ts.map
|
package/dist/AreaChart.js
CHANGED
|
@@ -5,6 +5,7 @@ import { areaExtent, drawArea } from './area.js';
|
|
|
5
5
|
import { resolveCurve } from './curve.js';
|
|
6
6
|
import { DEFAULT_GAP_MODE, DEFAULT_GAP_CONNECTOR_OPACITY, } from './gaps.js';
|
|
7
7
|
import { ContainerContext, LayersContext } from './context.js';
|
|
8
|
+
import { legendLabelFor, useLegendItems, } from './swatch.js';
|
|
8
9
|
import { useSlotKey } from './use-slot-key.js';
|
|
9
10
|
/** Read a d3 linear scale's domain lower bound (the axis floor) from the plain
|
|
10
11
|
* `(value) => pixel` function the row hands to `draw`. The runtime object is a
|
|
@@ -35,7 +36,7 @@ function domainFloor(yScale) {
|
|
|
35
36
|
* </Layers>
|
|
36
37
|
* ```
|
|
37
38
|
*/
|
|
38
|
-
export function AreaChart({ series, column, as: semantic, axis, baseline, curve, gaps = DEFAULT_GAP_MODE, index = 0, }) {
|
|
39
|
+
export function AreaChart({ series, column, as: semantic, axis, baseline, curve, gaps = DEFAULT_GAP_MODE, decimate = true, legend, index = 0, }) {
|
|
39
40
|
const container = useContext(ContainerContext);
|
|
40
41
|
if (container === null) {
|
|
41
42
|
throw new Error('<AreaChart> must be rendered inside a <ChartContainer>');
|
|
@@ -96,7 +97,7 @@ export function AreaChart({ series, column, as: semantic, axis, baseline, curve,
|
|
|
96
97
|
// Omitted baseline rests on the axis floor (resolved late from the
|
|
97
98
|
// scale, so it tracks the auto-fit domain); a fixed baseline is used
|
|
98
99
|
// verbatim.
|
|
99
|
-
baseline ?? domainFloor(yScale), curveFactory, gaps, gapConnectorOpacity),
|
|
100
|
+
baseline ?? domainFloor(yScale), curveFactory, gaps, gapConnectorOpacity, decimate),
|
|
100
101
|
},
|
|
101
102
|
axisId: axis,
|
|
102
103
|
index,
|
|
@@ -110,6 +111,7 @@ export function AreaChart({ series, column, as: semantic, axis, baseline, curve,
|
|
|
110
111
|
curveFactory,
|
|
111
112
|
gaps,
|
|
112
113
|
gapConnectorOpacity,
|
|
114
|
+
decimate,
|
|
113
115
|
axis,
|
|
114
116
|
index,
|
|
115
117
|
]);
|
|
@@ -127,6 +129,25 @@ export function AreaChart({ series, column, as: semantic, axis, baseline, curve,
|
|
|
127
129
|
useEffect(() => {
|
|
128
130
|
registerTrackerSource(slot, entry.layer);
|
|
129
131
|
}, [registerTrackerSource, slot, entry.layer]);
|
|
132
|
+
// And a legend row: the readout identity + the resolved area style (top line
|
|
133
|
+
// over the translucent fill), so a `<Legend>` swatch can never drift.
|
|
134
|
+
const legendRows = useMemo(() => {
|
|
135
|
+
const name = legendLabelFor(legend, label);
|
|
136
|
+
return name === null
|
|
137
|
+
? null
|
|
138
|
+
: [
|
|
139
|
+
{
|
|
140
|
+
label: name,
|
|
141
|
+
swatch: {
|
|
142
|
+
kind: 'area',
|
|
143
|
+
line: style.color,
|
|
144
|
+
fill: style.fill,
|
|
145
|
+
fillOpacity: style.fillOpacity,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
}, [legend, label, style]);
|
|
150
|
+
useLegendItems(container, slot, index, legendRows);
|
|
130
151
|
return null;
|
|
131
152
|
}
|
|
132
153
|
//# sourceMappingURL=AreaChart.js.map
|
package/dist/BandChart.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ValueSeries } from 'pond-ts';
|
|
2
2
|
import type { SeriesSchema, TimeSeries, ValueSeriesSchema } from 'pond-ts';
|
|
3
3
|
import { type Curve } from './curve.js';
|
|
4
|
+
import type { DecimateOption } from './decimate.js';
|
|
4
5
|
export interface BandChartProps<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema> {
|
|
5
6
|
/**
|
|
6
7
|
* The source series. A `TimeSeries` fills the envelope against the time axis;
|
|
@@ -23,7 +24,9 @@ export interface BandChartProps<S extends SeriesSchema = SeriesSchema, VS extend
|
|
|
23
24
|
* p5/p95 envelope, `inner` for p25/p75). The theme maps it to a
|
|
24
25
|
* {@link BandStyle} (`theme.band[as] ?? theme.band.default`). **Omitted ⇒ the
|
|
25
26
|
* `default` band style** — no per-component fill/opacity override (restyle via
|
|
26
|
-
* the theme, the single styling channel).
|
|
27
|
+
* the theme, the single styling channel). It's also the series identity for
|
|
28
|
+
* the tracker readout: with an `as`, the edge samples read `"<as> lower"` /
|
|
29
|
+
* `"<as> upper"` (else the raw column names).
|
|
27
30
|
*/
|
|
28
31
|
as?: string;
|
|
29
32
|
/**
|
|
@@ -39,6 +42,22 @@ export interface BandChartProps<S extends SeriesSchema = SeriesSchema, VS extend
|
|
|
39
42
|
* Denoise the underlying values with `smooth()`, not this.
|
|
40
43
|
*/
|
|
41
44
|
curve?: Curve;
|
|
45
|
+
/**
|
|
46
|
+
* **M4 viewport decimation** (charts decimator wave). **Omitted ⇒ `true`**:
|
|
47
|
+
* once the visible envelope is denser than ~2 samples per device pixel, it is
|
|
48
|
+
* drawn from the per-pixel-column **min(lower) / max(upper)** — the widest band
|
|
49
|
+
* the samples span, so it covers the same pixels from O(plot width) points.
|
|
50
|
+
* Applies with a linear `curve`; pass `false` to always fill every sample, or
|
|
51
|
+
* `{ threshold }` to tune. Shares {@link LineChart}'s `DecimateOption`.
|
|
52
|
+
*/
|
|
53
|
+
decimate?: DecimateOption;
|
|
54
|
+
/**
|
|
55
|
+
* This layer's `<Legend>` row: `false` ⇒ no row (opt out), a string ⇒ the
|
|
56
|
+
* row's display name. **Omitted ⇒ a row named by the layer's readout
|
|
57
|
+
* identity** (`as`, else `"<lower>–<upper>"`). The swatch is the resolved
|
|
58
|
+
* band fill.
|
|
59
|
+
*/
|
|
60
|
+
legend?: boolean | string;
|
|
42
61
|
/**
|
|
43
62
|
* @internal Declaration position among the `<Layers>` children, injected by
|
|
44
63
|
* `Layers` so z-order follows JSX order. Do not set.
|
|
@@ -62,5 +81,5 @@ export interface BandChartProps<S extends SeriesSchema = SeriesSchema, VS extend
|
|
|
62
81
|
* </Layers>
|
|
63
82
|
* ```
|
|
64
83
|
*/
|
|
65
|
-
export declare function BandChart<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema>({ series, lower, upper, as: semantic, axis, curve, index, }: BandChartProps<S, VS>): null;
|
|
84
|
+
export declare function BandChart<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema>({ series, lower, upper, as: semantic, axis, curve, decimate, legend, index, }: BandChartProps<S, VS>): null;
|
|
66
85
|
//# sourceMappingURL=BandChart.d.ts.map
|
package/dist/BandChart.js
CHANGED
|
@@ -4,6 +4,7 @@ import { bandFromTimeSeries, bandFromValueSeries } from './data.js';
|
|
|
4
4
|
import { bandExtent, drawBand } from './band.js';
|
|
5
5
|
import { resolveCurve } from './curve.js';
|
|
6
6
|
import { ContainerContext, LayersContext } from './context.js';
|
|
7
|
+
import { legendLabelFor, useLegendItems, } from './swatch.js';
|
|
7
8
|
import { useSlotKey } from './use-slot-key.js';
|
|
8
9
|
/**
|
|
9
10
|
* A variance-band draw layer: fills the envelope between the `lower` and `upper`
|
|
@@ -22,7 +23,7 @@ import { useSlotKey } from './use-slot-key.js';
|
|
|
22
23
|
* </Layers>
|
|
23
24
|
* ```
|
|
24
25
|
*/
|
|
25
|
-
export function BandChart({ series, lower, upper, as: semantic, axis, curve, index = 0, }) {
|
|
26
|
+
export function BandChart({ series, lower, upper, as: semantic, axis, curve, decimate = true, legend, index = 0, }) {
|
|
26
27
|
const container = useContext(ContainerContext);
|
|
27
28
|
if (container === null) {
|
|
28
29
|
throw new Error('<BandChart> must be rendered inside a <ChartContainer>');
|
|
@@ -38,6 +39,14 @@ export function BandChart({ series, lower, upper, as: semantic, axis, curve, ind
|
|
|
38
39
|
const { band } = container.theme;
|
|
39
40
|
const style = (semantic !== undefined ? band[semantic] : undefined) ?? band.default;
|
|
40
41
|
const curveFactory = resolveCurve(curve);
|
|
42
|
+
// Readout label per edge: with a semantic `as`, an edge reads under the series
|
|
43
|
+
// name + role (`iv lower`, `iv upper`) — the `as ?? column` convention Line /
|
|
44
|
+
// Scatter use and the exact shape BoxPlot's qLabel ships — so two bands (or a
|
|
45
|
+
// band and its centre line) merge readout keys by series, not by raw column
|
|
46
|
+
// names (F-charts-8 §3). With no `as`, the column name stands (self-evident).
|
|
47
|
+
const edgeLabel = useMemo(() => {
|
|
48
|
+
return (col, role) => semantic !== undefined ? `${semantic} ${role}` : col;
|
|
49
|
+
}, [semantic]);
|
|
41
50
|
const entry = useMemo(() => ({
|
|
42
51
|
layer: {
|
|
43
52
|
yExtent: () => bandExtent(bs),
|
|
@@ -62,8 +71,18 @@ export function BandChart({ series, lower, upper, as: semantic, axis, curve, ind
|
|
|
62
71
|
if (!Number.isFinite(lo) || !Number.isFinite(hi))
|
|
63
72
|
return [];
|
|
64
73
|
return [
|
|
65
|
-
{
|
|
66
|
-
|
|
74
|
+
{
|
|
75
|
+
x: bs.x[i],
|
|
76
|
+
value: lo,
|
|
77
|
+
color: style.fill,
|
|
78
|
+
label: edgeLabel(lower, 'lower'),
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
x: bs.x[i],
|
|
82
|
+
value: hi,
|
|
83
|
+
color: style.fill,
|
|
84
|
+
label: edgeLabel(upper, 'upper'),
|
|
85
|
+
},
|
|
67
86
|
];
|
|
68
87
|
}
|
|
69
88
|
const e = series.nearest(x);
|
|
@@ -80,18 +99,40 @@ export function BandChart({ series, lower, upper, as: semantic, axis, curve, ind
|
|
|
80
99
|
!Number.isFinite(hi)) {
|
|
81
100
|
return [];
|
|
82
101
|
}
|
|
83
|
-
// Both edges, labelled by
|
|
84
|
-
//
|
|
102
|
+
// Both edges, labelled by series + role under an `as` (else by their
|
|
103
|
+
// column, e.g. p25 / p75), in the band's fill colour. A gap on either
|
|
104
|
+
// edge yields no readout (like the fill).
|
|
85
105
|
return [
|
|
86
|
-
{
|
|
87
|
-
|
|
106
|
+
{
|
|
107
|
+
x: e.begin(),
|
|
108
|
+
value: lo,
|
|
109
|
+
color: style.fill,
|
|
110
|
+
label: edgeLabel(lower, 'lower'),
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
x: e.begin(),
|
|
114
|
+
value: hi,
|
|
115
|
+
color: style.fill,
|
|
116
|
+
label: edgeLabel(upper, 'upper'),
|
|
117
|
+
},
|
|
88
118
|
];
|
|
89
119
|
},
|
|
90
|
-
draw: (ctx, xScale, yScale) => drawBand(ctx, bs, xScale, yScale, style, curveFactory),
|
|
120
|
+
draw: (ctx, xScale, yScale) => drawBand(ctx, bs, xScale, yScale, style, curveFactory, decimate),
|
|
91
121
|
},
|
|
92
122
|
axisId: axis,
|
|
93
123
|
index,
|
|
94
|
-
}), [
|
|
124
|
+
}), [
|
|
125
|
+
bs,
|
|
126
|
+
series,
|
|
127
|
+
lower,
|
|
128
|
+
upper,
|
|
129
|
+
style,
|
|
130
|
+
curveFactory,
|
|
131
|
+
decimate,
|
|
132
|
+
axis,
|
|
133
|
+
index,
|
|
134
|
+
edgeLabel,
|
|
135
|
+
]);
|
|
95
136
|
// Stable per-instance slot (see useSlotKey): keeps this band's z-position +
|
|
96
137
|
// identity across prop updates; the injected index drives the sort.
|
|
97
138
|
const slot = useSlotKey();
|
|
@@ -106,6 +147,24 @@ export function BandChart({ series, lower, upper, as: semantic, axis, curve, ind
|
|
|
106
147
|
useEffect(() => {
|
|
107
148
|
registerTrackerSource(slot, entry.layer);
|
|
108
149
|
}, [registerTrackerSource, slot, entry.layer]);
|
|
150
|
+
// And a legend row: the series identity (`as`, else the edge columns as a
|
|
151
|
+
// span) + the resolved band fill, so a `<Legend>` swatch can never drift.
|
|
152
|
+
const legendRows = useMemo(() => {
|
|
153
|
+
const name = legendLabelFor(legend, semantic ?? `${lower}–${upper}`);
|
|
154
|
+
return name === null
|
|
155
|
+
? null
|
|
156
|
+
: [
|
|
157
|
+
{
|
|
158
|
+
label: name,
|
|
159
|
+
swatch: {
|
|
160
|
+
kind: 'band',
|
|
161
|
+
fill: style.fill,
|
|
162
|
+
opacity: style.opacity,
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
];
|
|
166
|
+
}, [legend, semantic, lower, upper, style]);
|
|
167
|
+
useLegendItems(container, slot, index, legendRows);
|
|
109
168
|
return null;
|
|
110
169
|
}
|
|
111
170
|
//# sourceMappingURL=BandChart.js.map
|
package/dist/BarChart.d.ts
CHANGED
|
@@ -120,6 +120,17 @@ export interface BarChartProps<S extends SeriesSchema = SeriesSchema, VS extends
|
|
|
120
120
|
* would invert collapses to the style's `minWidth`.
|
|
121
121
|
*/
|
|
122
122
|
gap?: number;
|
|
123
|
+
/**
|
|
124
|
+
* This layer's `<Legend>` row(s): `false` ⇒ none (opt out), a string ⇒ the
|
|
125
|
+
* display name of a **one-row** layer. **Omitted ⇒** the single path (and a
|
|
126
|
+
* one-group stack) registers one row named by the layer identity
|
|
127
|
+
* (`as` ?? `column` ?? `id`); a **multi-group stack registers one row per
|
|
128
|
+
* group** (stack order, each group's resolved fill), where a rename string
|
|
129
|
+
* is ignored — group names come from the data. A per-bin-coloured histogram
|
|
130
|
+
* (`binColors`) is one series: its single row's swatch shows the group's
|
|
131
|
+
* base fill, not the per-bin palette.
|
|
132
|
+
*/
|
|
133
|
+
legend?: boolean | string;
|
|
123
134
|
/**
|
|
124
135
|
* @internal Declaration position among the `<Layers>` children, injected by
|
|
125
136
|
* `Layers` so z-order follows JSX order. Do not set.
|
|
@@ -169,5 +180,5 @@ export interface BarChartProps<S extends SeriesSchema = SeriesSchema, VS extends
|
|
|
169
180
|
* </Layers>
|
|
170
181
|
* ```
|
|
171
182
|
*/
|
|
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;
|
|
183
|
+
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, legend, index, }: BarChartProps<S, VS>): null;
|
|
173
184
|
//# sourceMappingURL=BarChart.d.ts.map
|
package/dist/BarChart.js
CHANGED
|
@@ -3,6 +3,7 @@ import { Interval, ValueSeries } from 'pond-ts';
|
|
|
3
3
|
import { barsFromTimeSeries, barsFromValueSeries, categoryStack, stacksFromBins, stacksFromColumns, stacksFromGroups, } from './data.js';
|
|
4
4
|
import { barAt, barExtent, barIndexAtTime, drawBars, drawStacks, resolveBarBaseline, stackAt, stackBinExtent, stackValueExtent, } from './bars.js';
|
|
5
5
|
import { ContainerContext, LayersContext, } from './context.js';
|
|
6
|
+
import { legendLabelFor, useLegendItems, } from './swatch.js';
|
|
6
7
|
import { useSlotKey } from './use-slot-key.js';
|
|
7
8
|
/**
|
|
8
9
|
* A bar / histogram draw layer. In its simplest form, one rectangle per event
|
|
@@ -47,7 +48,7 @@ import { useSlotKey } from './use-slot-key.js';
|
|
|
47
48
|
* </Layers>
|
|
48
49
|
* ```
|
|
49
50
|
*/
|
|
50
|
-
export function BarChart({ series, bins, categories, column, columns, as: semantic, colors, binColors, orientation = 'vertical', ordinal = false, id, axis, gap, index = 0, }) {
|
|
51
|
+
export function BarChart({ series, bins, categories, column, columns, as: semantic, colors, binColors, orientation = 'vertical', ordinal = false, id, axis, gap, legend, index = 0, }) {
|
|
51
52
|
const container = useContext(ContainerContext);
|
|
52
53
|
if (container === null) {
|
|
53
54
|
throw new Error('<BarChart> must be rendered inside a <ChartContainer>');
|
|
@@ -364,6 +365,38 @@ export function BarChart({ series, bins, categories, column, columns, as: semant
|
|
|
364
365
|
registerSelectable(slot);
|
|
365
366
|
return () => unregisterSelectable(slot);
|
|
366
367
|
}, [registerSelectable, unregisterSelectable, slot, id]);
|
|
368
|
+
// Legend rows: a genuinely multi-group layer (a stack) registers **one row
|
|
369
|
+
// per group** in stack order, each with the same per-group fill resolution
|
|
370
|
+
// the canvas draws with; everything else — the single path, a one-group
|
|
371
|
+
// stack (horizontal single, categorical) — registers one row under the
|
|
372
|
+
// layer's identity. A `legend` string renames only a one-row layer (a
|
|
373
|
+
// multi-group layer has no single name to give); `legend={false}` opts all
|
|
374
|
+
// out. The layer's `id` rides every row (selection identity is the layer).
|
|
375
|
+
const legendRows = useMemo(() => {
|
|
376
|
+
if (legend === false)
|
|
377
|
+
return null;
|
|
378
|
+
if (groups !== undefined && groups.length > 1) {
|
|
379
|
+
return groups.map((g, i) => ({
|
|
380
|
+
label: g,
|
|
381
|
+
id,
|
|
382
|
+
swatch: { kind: 'bar', fill: stackStyle.fills[i] },
|
|
383
|
+
}));
|
|
384
|
+
}
|
|
385
|
+
const name = legendLabelFor(legend, label);
|
|
386
|
+
return name === null
|
|
387
|
+
? null
|
|
388
|
+
: [
|
|
389
|
+
{
|
|
390
|
+
label: name,
|
|
391
|
+
id,
|
|
392
|
+
swatch: {
|
|
393
|
+
kind: 'bar',
|
|
394
|
+
fill: groups !== undefined ? stackStyle.fills[0] : singleStyle.fill,
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
];
|
|
398
|
+
}, [legend, groups, stackStyle, label, id, singleStyle]);
|
|
399
|
+
useLegendItems(container, slot, index, legendRows);
|
|
367
400
|
return null;
|
|
368
401
|
}
|
|
369
402
|
//# sourceMappingURL=BarChart.js.map
|
package/dist/BoxPlot.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ValueSeries } from 'pond-ts';
|
|
2
2
|
import type { SeriesSchema, TimeSeries, ValueSeriesSchema } from 'pond-ts';
|
|
3
3
|
import { type BoxShape } from './box.js';
|
|
4
|
+
import type { DecimateOption } from './decimate.js';
|
|
4
5
|
export interface BoxPlotProps<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema> {
|
|
5
6
|
/**
|
|
6
7
|
* The source series. A `TimeSeries` plots against the time axis; a `ValueSeries`
|
|
@@ -88,6 +89,33 @@ export interface BoxPlotProps<S extends SeriesSchema = SeriesSchema, VS extends
|
|
|
88
89
|
* `'whisker'` shape (`'solid'`/`'none'` have no caps).
|
|
89
90
|
*/
|
|
90
91
|
capWidth?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Stable series identity — **gates selection + hover**, the same id-gated
|
|
94
|
+
* contract `<BarChart>` / `<ScatterChart>` carry. With an `id`, a click on a
|
|
95
|
+
* box (body or whisker — a range-only bid→ask segment included) selects it
|
|
96
|
+
* (`selected`/`onSelect`) and pointer-over lights it (`hovered`/`onHover`);
|
|
97
|
+
* the box matching the selection's `(id, key)` outlines. **Omitted ⇒
|
|
98
|
+
* display-only** (a click resolves to empty space). `key` is the box's `x`
|
|
99
|
+
* (its `begin`).
|
|
100
|
+
*/
|
|
101
|
+
id?: string;
|
|
102
|
+
/**
|
|
103
|
+
* **M4 viewport decimation** (charts decimator wave). **Omitted ⇒ `true`**:
|
|
104
|
+
* once the visible boxes are denser than ~2 per device pixel, they are drawn as
|
|
105
|
+
* per-pixel-column **aggregate boxes** — whiskers widen to the column's reach
|
|
106
|
+
* (`min(lower)`/`max(upper)`), the body to its IQR envelope
|
|
107
|
+
* (`min(q1)`/`max(q3)`), the centre line to the first box's median. Pass `false`
|
|
108
|
+
* to draw every box at its own slot. Interaction is unaffected (hit-testing
|
|
109
|
+
* reads the source boxes). Shares {@link LineChart}'s `DecimateOption`.
|
|
110
|
+
*/
|
|
111
|
+
decimate?: DecimateOption;
|
|
112
|
+
/**
|
|
113
|
+
* This layer's `<Legend>` row: `false` ⇒ no row (opt out), a string ⇒ the
|
|
114
|
+
* row's display name. **Omitted ⇒ a row named by the layer's readout
|
|
115
|
+
* identity** (`as`, else `"<lower>–<upper>"`). The swatch is the resolved
|
|
116
|
+
* whisker style.
|
|
117
|
+
*/
|
|
118
|
+
legend?: boolean | string;
|
|
91
119
|
/**
|
|
92
120
|
* @internal Declaration position among the `<Layers>` children, injected by
|
|
93
121
|
* `Layers` so z-order follows JSX order. Do not set.
|
|
@@ -125,5 +153,5 @@ export interface BoxPlotProps<S extends SeriesSchema = SeriesSchema, VS extends
|
|
|
125
153
|
* </Layers>
|
|
126
154
|
* ```
|
|
127
155
|
*/
|
|
128
|
-
export declare function BoxPlot<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema>({ series, lower, q1, median, q3, upper, as: semantic, axis, gap, shape, showMedian, offset, capWidth, index, }: BoxPlotProps<S, VS>): null;
|
|
156
|
+
export declare function BoxPlot<S extends SeriesSchema = SeriesSchema, VS extends ValueSeriesSchema = ValueSeriesSchema>({ series, lower, q1, median, q3, upper, as: semantic, axis, gap, shape, showMedian, offset, capWidth, id, decimate, legend, index, }: BoxPlotProps<S, VS>): null;
|
|
129
157
|
//# sourceMappingURL=BoxPlot.d.ts.map
|