@perspective-dev/viewer-charts 4.5.2 → 5.1.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/dist/cdn/perspective-viewer-charts.js +2 -2
- package/dist/cdn/perspective-viewer-charts.js.map +3 -3
- package/dist/esm/charts/candlestick/candlestick.d.ts +8 -10
- package/dist/esm/charts/chart-base.d.ts +58 -4
- package/dist/esm/charts/chart.d.ts +45 -9
- package/dist/esm/charts/series/glyphs/draw-areas.d.ts +8 -2
- package/dist/esm/charts/series/glyphs/draw-bars.d.ts +8 -1
- package/dist/esm/charts/series/glyphs/draw-lines.d.ts +8 -2
- package/dist/esm/charts/series/glyphs/draw-scatter.d.ts +8 -2
- package/dist/esm/charts/series/series-build.d.ts +11 -0
- package/dist/esm/charts/series/series-interact.d.ts +13 -2
- package/dist/esm/charts/series/series-render.d.ts +17 -1
- package/dist/esm/charts/series/series.d.ts +104 -10
- package/dist/esm/data/view-reader.d.ts +10 -1
- package/dist/esm/event-detail.d.ts +7 -0
- package/dist/esm/layout/ticks.d.ts +5 -0
- package/dist/esm/perspective-viewer-charts.js +2 -2
- package/dist/esm/perspective-viewer-charts.js.map +3 -3
- package/dist/esm/plugin/charts.d.ts +6 -3
- package/dist/esm/plugin/plugin.d.ts +40 -2
- package/dist/esm/render/scheduler.d.ts +11 -8
- package/dist/esm/transport/protocol.d.ts +39 -2
- package/dist/esm/transport/renderer-transport.d.ts +75 -3
- package/dist/esm/webgl/instanced-attrs.d.ts +7 -1
- package/dist/esm/worker/renderer.worker.d.ts +12 -0
- package/package.json +1 -1
- package/src/ts/charts/candlestick/candlestick-render.ts +4 -1
- package/src/ts/charts/candlestick/candlestick.ts +12 -17
- package/src/ts/charts/cartesian/cartesian-render.ts +80 -63
- package/src/ts/charts/chart-base.ts +85 -5
- package/src/ts/charts/chart.ts +47 -9
- package/src/ts/charts/common/category-axis-resolver.ts +5 -1
- package/src/ts/charts/common/tree-data.ts +61 -16
- package/src/ts/charts/heatmap/heatmap-render.ts +6 -2
- package/src/ts/charts/series/glyphs/draw-areas.ts +21 -1
- package/src/ts/charts/series/glyphs/draw-bars.ts +30 -9
- package/src/ts/charts/series/glyphs/draw-lines.ts +21 -1
- package/src/ts/charts/series/glyphs/draw-scatter.ts +68 -3
- package/src/ts/charts/series/series-build.ts +21 -3
- package/src/ts/charts/series/series-interact.ts +210 -78
- package/src/ts/charts/series/series-render.ts +779 -49
- package/src/ts/charts/series/series.ts +209 -26
- package/src/ts/charts/sunburst/sunburst-interact.ts +2 -3
- package/src/ts/charts/sunburst/sunburst-render.ts +3 -1
- package/src/ts/charts/treemap/treemap-interact.ts +2 -5
- package/src/ts/charts/treemap/treemap-render.ts +3 -1
- package/src/ts/charts/treemap/treemap.ts +6 -1
- package/src/ts/data/view-reader.ts +22 -2
- package/src/ts/event-detail.ts +8 -0
- package/src/ts/index.ts +13 -7
- package/src/ts/interaction/raw-event-forwarder.ts +7 -0
- package/src/ts/interaction/zoom-controller.ts +8 -0
- package/src/ts/layout/ticks.ts +9 -0
- package/src/ts/plugin/charts.ts +20 -4
- package/src/ts/plugin/plugin.ts +99 -17
- package/src/ts/render/scheduler.ts +39 -13
- package/src/ts/transport/protocol.ts +42 -0
- package/src/ts/transport/renderer-transport.ts +198 -9
- package/src/ts/webgl/instanced-attrs.ts +15 -1
- package/src/ts/worker/dispatch.ts +4 -1
- package/src/ts/worker/renderer.worker.ts +35 -3
|
@@ -52,21 +52,19 @@ export declare class CandlestickChart extends CategoricalYChart {
|
|
|
52
52
|
max: number;
|
|
53
53
|
};
|
|
54
54
|
/**
|
|
55
|
-
* `domain_mode: "expand"`
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
55
|
+
* `domain_mode: "expand"` accumulator — the VALUE (Y) axis only.
|
|
56
|
+
* The category axis has NO accumulator on band charts (see
|
|
57
|
+
* `SeriesChart._expandedLeftDomain`): a numeric/datetime `group_by`
|
|
58
|
+
* axis always fits the current data. Cleared in
|
|
59
|
+
* `resetExpandedDomain` — wired from the worker's `resetAllZooms`
|
|
60
|
+
* and from view-config mutations on `AbstractChart`. `null`
|
|
61
|
+
* whenever the option is `"fit"` or the accumulator has just been
|
|
62
|
+
* cleared.
|
|
61
63
|
*/
|
|
62
64
|
_expandedYDomain: {
|
|
63
65
|
min: number;
|
|
64
66
|
max: number;
|
|
65
67
|
} | null;
|
|
66
|
-
_expandedCategoryDomain: {
|
|
67
|
-
min: number;
|
|
68
|
-
max: number;
|
|
69
|
-
} | null;
|
|
70
68
|
/**
|
|
71
69
|
* Numeric category-axis state (single non-string group_by).
|
|
72
70
|
*/
|
|
@@ -57,6 +57,22 @@ export declare abstract class AbstractChart implements ChartImplementation {
|
|
|
57
57
|
_glManager: WebGLContextManager | null;
|
|
58
58
|
_gridlineCanvas: HTMLCanvasElement | OffscreenCanvas | null;
|
|
59
59
|
_chromeCanvas: HTMLCanvasElement | OffscreenCanvas | null;
|
|
60
|
+
/**
|
|
61
|
+
* 2D-canvas draw closures collected during `_fullRender` (the GL
|
|
62
|
+
* pass) and flushed by {@link _flush2D} *after* the scheduler's
|
|
63
|
+
* `awaitGpuFence`. Deferring the gridline/chrome draws past the GPU
|
|
64
|
+
* fence stops the 2D placeholder canvases from pushing a resized
|
|
65
|
+
* frame to the compositor a frame ahead of the GL present — the
|
|
66
|
+
* visible GL/2D misalignment on resize.
|
|
67
|
+
*
|
|
68
|
+
* Renderers wrap their 2D drawing in {@link _defer2D}; the closures
|
|
69
|
+
* capture the exact per-frame locals (layout, ticks, theme) so no
|
|
70
|
+
* state needs to be recomputed or replayed from cache at flush time.
|
|
71
|
+
* Reset at the start of every GL pass (see {@link requestRender} /
|
|
72
|
+
* {@link renderFrameSync}) so a `_fullRender` that throws mid-way
|
|
73
|
+
* can't leak stale closures into the next frame.
|
|
74
|
+
*/
|
|
75
|
+
_deferred2D: Array<() => void>;
|
|
60
76
|
/**
|
|
61
77
|
* Host-supplied CSS-variable map. The host snapshots its DOM via
|
|
62
78
|
* `snapshotThemeVars(el)` and ships it over the control channel;
|
|
@@ -299,6 +315,17 @@ export declare abstract class AbstractChart implements ChartImplementation {
|
|
|
299
315
|
* (pivot / filter / sort changes can all reshuffle rows).
|
|
300
316
|
*/
|
|
301
317
|
setView(view: View): void;
|
|
318
|
+
/**
|
|
319
|
+
* Silently dismiss any pinned tooltip (the chart's selection visual)
|
|
320
|
+
* WITHOUT emitting `perspective-global-filter` — unlike the `setView`
|
|
321
|
+
* implicit dismiss above, the HOST initiated this (its global filter
|
|
322
|
+
* bar removed the clause this selection contributed), so an unselect
|
|
323
|
+
* emit would double-mutate the host's filter set.
|
|
324
|
+
* `TooltipController.dismiss()` posts the host-side pin teardown but
|
|
325
|
+
* never fires `onUnpin` (that emit belongs to `dispatchClick`'s
|
|
326
|
+
* click-to-unpin gesture), so this is emit-free by construction.
|
|
327
|
+
*/
|
|
328
|
+
deselect(): void;
|
|
302
329
|
/**
|
|
303
330
|
* Build the chart-specific {@link TooltipCallbacks} object — the
|
|
304
331
|
* `onHover` / `onLeave` / `onClickPre` / `onPin` / `onDblClick`
|
|
@@ -382,16 +409,43 @@ export declare abstract class AbstractChart implements ChartImplementation {
|
|
|
382
409
|
* scheduler so concurrent calls collapse to one `_fullRender` per
|
|
383
410
|
* RAF and the host blitter receives one bitmap per frame. The
|
|
384
411
|
* returned promise resolves after this chart's `awaitGpuFence` +
|
|
385
|
-
* `endFrame` chain — independent of other charts in the
|
|
386
|
-
* RAF, which run their fence waits in parallel.
|
|
412
|
+
* `render2D` + `endFrame` chain — independent of other charts in the
|
|
413
|
+
* same RAF, which run their fence waits in parallel.
|
|
414
|
+
*
|
|
415
|
+
* `_fullRender` submits the GL commands and stashes the frame's 2D
|
|
416
|
+
* draws (gridlines + chrome) via {@link _defer2D}; the scheduler
|
|
417
|
+
* flushes them with {@link _flush2D} *after* the GPU fence, so the
|
|
418
|
+
* 2D canvases don't present ahead of the GL frame. The GL pass
|
|
419
|
+
* resets `_deferred2D` first so a mid-pass throw can't leak stale
|
|
420
|
+
* closures into the next frame.
|
|
387
421
|
*
|
|
388
422
|
* Every render-triggering caller — upload chunks, zoom / pan,
|
|
389
423
|
* resize, theme invalidation, host-driven redraws — calls this.
|
|
390
|
-
* The only sanctioned bypass is `snapshotPng`, which
|
|
391
|
-
*
|
|
424
|
+
* The only sanctioned bypass is `snapshotPng`, which uses
|
|
425
|
+
* {@link renderFrameSync} to keep the GL backbuffer intact for
|
|
392
426
|
* `gl.readPixels`.
|
|
393
427
|
*/
|
|
394
428
|
requestRender(glManager: WebGLContextManager): Promise<void>;
|
|
429
|
+
/**
|
|
430
|
+
* Queue a 2D-canvas draw (gridline or chrome) to run after the
|
|
431
|
+
* GPU fence. Called from the chart renderers in place of drawing to
|
|
432
|
+
* the gridline/chrome canvases inline during the GL pass. See
|
|
433
|
+
* {@link _deferred2D}.
|
|
434
|
+
*/
|
|
435
|
+
_defer2D(fn: () => void): void;
|
|
436
|
+
/**
|
|
437
|
+
* Run and clear the queued 2D-canvas draws. Invoked by the scheduler
|
|
438
|
+
* after `awaitGpuFence` (Phase 2), and by {@link renderFrameSync}.
|
|
439
|
+
*/
|
|
440
|
+
_flush2D(): void;
|
|
441
|
+
/**
|
|
442
|
+
* Synchronous full frame (GL + 2D) for the `snapshotPng` bypass,
|
|
443
|
+
* which sits outside the scheduler and needs the gridline/chrome
|
|
444
|
+
* canvases painted before it composites them. Resets the deferred
|
|
445
|
+
* queue, runs the GL pass, then flushes the 2D draws immediately
|
|
446
|
+
* (no fence split — a snapshot isn't presented to the compositor).
|
|
447
|
+
*/
|
|
448
|
+
renderFrameSync(glManager: WebGLContextManager): void;
|
|
395
449
|
destroy(): void;
|
|
396
450
|
abstract uploadAndRender(glManager: WebGLContextManager, columns: ColumnDataMap, startRow: number, endRow: number): Promise<void>;
|
|
397
451
|
abstract _fullRender(glManager: WebGLContextManager): void;
|
|
@@ -24,12 +24,21 @@ export interface ChartImplementation {
|
|
|
24
24
|
*/
|
|
25
25
|
requestRender(glManager: WebGLContextManager): Promise<void>;
|
|
26
26
|
/**
|
|
27
|
-
* The chart-specific frame builder.
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* The chart-specific GL frame builder. Submits the GL draw commands
|
|
28
|
+
* and stashes the frame's 2D-canvas draws (gridlines + chrome) for
|
|
29
|
+
* the scheduler to flush after `awaitGpuFence`. The scheduler wraps
|
|
30
|
+
* this with fence + 2D flush + `endFrame`; callers must not invoke
|
|
31
|
+
* it directly — `snapshotPng` uses {@link renderFrameSync} instead.
|
|
31
32
|
*/
|
|
32
33
|
_fullRender(glManager: WebGLContextManager): void;
|
|
34
|
+
/**
|
|
35
|
+
* Synchronous full frame (GL + 2D) for the `snapshotPng` bypass,
|
|
36
|
+
* which sits outside the scheduler and needs the gridline/chrome
|
|
37
|
+
* canvases painted before compositing. Runs the GL pass then flushes
|
|
38
|
+
* the deferred 2D draws immediately, skipping the fence split and
|
|
39
|
+
* `endFrame` so the GL backbuffer stays intact for `gl.readPixels`.
|
|
40
|
+
*/
|
|
41
|
+
renderFrameSync(glManager: WebGLContextManager): void;
|
|
33
42
|
/**
|
|
34
43
|
* Hand the current View to the chart so it can make on-demand
|
|
35
44
|
* per-row queries (for lazy tooltip column lookups). Called on
|
|
@@ -137,6 +146,14 @@ export interface ChartImplementation {
|
|
|
137
146
|
* hook internally.
|
|
138
147
|
*/
|
|
139
148
|
resetExpandedDomain?(): void;
|
|
149
|
+
/**
|
|
150
|
+
* Silently clear any active selection state (pinned tooltip) WITHOUT
|
|
151
|
+
* emitting selection events. Driven from the host's `deselect`
|
|
152
|
+
* message — its global filter bar removed a clause this chart's
|
|
153
|
+
* selection contributed, so an unselect emit would double-mutate the
|
|
154
|
+
* host's filter set.
|
|
155
|
+
*/
|
|
156
|
+
deselect?(): void;
|
|
140
157
|
destroy(): void;
|
|
141
158
|
}
|
|
142
159
|
export interface FacetConfig {
|
|
@@ -193,8 +210,19 @@ export interface PluginConfig {
|
|
|
193
210
|
* Faceting strategy when `split_by` is non-empty.
|
|
194
211
|
*
|
|
195
212
|
* - `"grid"` — one small-multiple sub-plot per split group.
|
|
196
|
-
* - `"overlay"` — single plot
|
|
197
|
-
* color
|
|
213
|
+
* - `"overlay"` — a single plot: cartesian charts differentiate
|
|
214
|
+
* split groups by color; the categorical band pipeline (series
|
|
215
|
+
* charts) stacks splits within each aggregate's band slot.
|
|
216
|
+
* Synced into `_facetConfig.facet_mode`.
|
|
217
|
+
*
|
|
218
|
+
* The default differs by family via
|
|
219
|
+
* `ChartTypeConfig.plugin_field_defaults`: cartesian / density /
|
|
220
|
+
* map chart types default to `"grid"`, the series / financial
|
|
221
|
+
* band-pipeline types to `"overlay"` (their historical split
|
|
222
|
+
* rendering). Series charts REBUILD on a mode change — grid mode
|
|
223
|
+
* keys the stack ladder per split (`facetSplits` in
|
|
224
|
+
* `buildSeriesPipeline`) so each facet grows from its own
|
|
225
|
+
* baseline.
|
|
198
226
|
*/
|
|
199
227
|
facet_mode: "grid" | "overlay";
|
|
200
228
|
/**
|
|
@@ -226,15 +254,23 @@ export interface PluginConfig {
|
|
|
226
254
|
/**
|
|
227
255
|
* Domain accumulation policy across successive `View` updates.
|
|
228
256
|
*
|
|
229
|
-
* - `"fit"` — every update recomputes the
|
|
230
|
-
* cartesian charts, the X/Y range and color/size scales) from
|
|
257
|
+
* - `"fit"` — every update recomputes the affected domains from
|
|
231
258
|
* the current data extent. Can grow or shrink frame-to-frame.
|
|
232
|
-
* - `"expand"` — the
|
|
259
|
+
* - `"expand"` — the affected domains monotonically *grow*: each
|
|
233
260
|
* update unions the new data extent with the previously rendered
|
|
234
261
|
* extent, so once a value is in scope it stays in scope. Reset
|
|
235
262
|
* by the "Reset Zoom" button, view-config changes (group_by /
|
|
236
263
|
* split_by / column-slot / column-type), or toggling back to
|
|
237
264
|
* `"fit"`.
|
|
265
|
+
*
|
|
266
|
+
* AXIS SCOPE differs by family: cartesian charts (X/Y Scatter,
|
|
267
|
+
* X/Y Line, Density, Maps) apply it to BOTH axes plus the
|
|
268
|
+
* color/size scales (categorical string axes opt out — slot
|
|
269
|
+
* indices are frame-local); the categorical band pipeline (series
|
|
270
|
+
* / financial) applies it to the VALUE axis only — Y for the
|
|
271
|
+
* Y-family, X for X Bar — while the category axis always fits, so
|
|
272
|
+
* a streaming numeric/datetime `group_by` axis releases departed
|
|
273
|
+
* categories instead of pinning to its history.
|
|
238
274
|
*/
|
|
239
275
|
domain_mode: "fit" | "expand";
|
|
240
276
|
/**
|
|
@@ -22,9 +22,15 @@ export declare class AreaGlyph {
|
|
|
22
22
|
rebuildBuffers(chart: SeriesChart, glManager: WebGLContextManager): void;
|
|
23
23
|
/**
|
|
24
24
|
* Bind persistent strip buffers and dispatch one TRIANGLE_STRIP per
|
|
25
|
-
* series-run. Skips hidden series.
|
|
25
|
+
* series-run. Skips hidden series. `splitFilter` (faceted frames)
|
|
26
|
+
* draws only the series whose `splitIdx` matches; `aggRange` (mixed
|
|
27
|
+
* glyph-run frames) only those whose `aggIdx` lies in the inclusive
|
|
28
|
+
* run span.
|
|
26
29
|
*/
|
|
27
|
-
draw(chart: SeriesChart, gl: GL, _glManager: WebGLContextManager, projLeft: Float32Array, projRight: Float32Array, opacity: number
|
|
30
|
+
draw(chart: SeriesChart, gl: GL, _glManager: WebGLContextManager, projLeft: Float32Array, projRight: Float32Array, opacity: number, splitFilter?: number, aggRange?: {
|
|
31
|
+
start: number;
|
|
32
|
+
end: number;
|
|
33
|
+
}): void;
|
|
28
34
|
destroy(chart: SeriesChart): void;
|
|
29
35
|
}
|
|
30
36
|
export {};
|
|
@@ -10,6 +10,13 @@ type GL = WebGL2RenderingContext | WebGLRenderingContext;
|
|
|
10
10
|
/**
|
|
11
11
|
* Draw the bar-typed subset of `chart._bars` as instanced quads. Assumes
|
|
12
12
|
* the caller has already `useProgram`'d the bar shader and set uniforms.
|
|
13
|
+
*
|
|
14
|
+
* `range` draws a contiguous instance sub-range instead of the full
|
|
15
|
+
* uploaded set — the faceted renderer uploads instances split-major
|
|
16
|
+
* (see `uploadBarInstances`) and dispatches one range per facet.
|
|
13
17
|
*/
|
|
14
|
-
export declare function drawBars(chart: SeriesChart, gl: GL, glManager: WebGLContextManager
|
|
18
|
+
export declare function drawBars(chart: SeriesChart, gl: GL, glManager: WebGLContextManager, range?: {
|
|
19
|
+
start: number;
|
|
20
|
+
count: number;
|
|
21
|
+
}): void;
|
|
15
22
|
export {};
|
|
@@ -33,9 +33,15 @@ export declare class LineGlyph {
|
|
|
33
33
|
* Bind the persistent vertex buffers and dispatch one instanced draw
|
|
34
34
|
* per series. Skips hidden series via `_hiddenSeries`. Gap /
|
|
35
35
|
* transparency rendering is governed by `u_interp_alpha`, set per
|
|
36
|
-
* series.
|
|
36
|
+
* series. `splitFilter` (faceted frames) draws only the series
|
|
37
|
+
* whose `splitIdx` matches — one call per facet. `aggRange` (mixed
|
|
38
|
+
* glyph-run frames) draws only the series whose `aggIdx` lies in
|
|
39
|
+
* the inclusive run span.
|
|
37
40
|
*/
|
|
38
|
-
draw(chart: SeriesChart, gl: GL, glManager: WebGLContextManager, projLeft: Float32Array, projRight: Float32Array
|
|
41
|
+
draw(chart: SeriesChart, gl: GL, glManager: WebGLContextManager, projLeft: Float32Array, projRight: Float32Array, splitFilter?: number, aggRange?: {
|
|
42
|
+
start: number;
|
|
43
|
+
end: number;
|
|
44
|
+
}): void;
|
|
39
45
|
destroy(chart: SeriesChart): void;
|
|
40
46
|
}
|
|
41
47
|
export {};
|
|
@@ -25,9 +25,15 @@ export declare class ScatterGlyph {
|
|
|
25
25
|
rebuildBuffers(chart: SeriesChart, glManager: WebGLContextManager): void;
|
|
26
26
|
/**
|
|
27
27
|
* Bind the persistent left/right buffers and issue up to two draw
|
|
28
|
-
* calls. No per-frame allocations or buffer uploads.
|
|
28
|
+
* calls. No per-frame allocations or buffer uploads. `splitFilter`
|
|
29
|
+
* (faceted frames) and/or `aggRange` (mixed glyph-run frames)
|
|
30
|
+
* instead draw each matching series' contiguous bucket sub-range —
|
|
31
|
+
* one `drawArrays(POINTS, first, count)` per matching series.
|
|
29
32
|
*/
|
|
30
|
-
draw(chart: SeriesChart, gl: GL, glManager: WebGLContextManager, projLeft: Float32Array, projRight: Float32Array
|
|
33
|
+
draw(chart: SeriesChart, gl: GL, glManager: WebGLContextManager, projLeft: Float32Array, projRight: Float32Array, splitFilter?: number, aggRange?: {
|
|
34
|
+
start: number;
|
|
35
|
+
end: number;
|
|
36
|
+
}): void;
|
|
31
37
|
destroy(chart: SeriesChart): void;
|
|
32
38
|
}
|
|
33
39
|
export {};
|
|
@@ -168,6 +168,17 @@ export interface SeriesPipelineInput {
|
|
|
168
168
|
* variation. Maps directly to `PluginConfig.include_zero`.
|
|
169
169
|
*/
|
|
170
170
|
includeZero: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* `facet_mode: "grid"` geometry: key the stack ladder by
|
|
173
|
+
* `(catIdx, aggIdx, splitIdx)` instead of `(catIdx, aggIdx)`, so
|
|
174
|
+
* splits never stack on each other — each facet's bars / areas
|
|
175
|
+
* grow from their own zero baseline. Slot geometry (`xCenter` /
|
|
176
|
+
* `halfWidth`) is unchanged: facets separate splits by projection
|
|
177
|
+
* + scissor, not by X offset, so every split's records share the
|
|
178
|
+
* same band-slot coordinates. Value extents still accumulate
|
|
179
|
+
* across ALL splits — the facet grid renders a shared value axis.
|
|
180
|
+
*/
|
|
181
|
+
facetSplits?: boolean;
|
|
171
182
|
/**
|
|
172
183
|
* Reusable scratch — pipeline writes records into these in place
|
|
173
184
|
* and zero-fills the stack ladder. Pass the previous build's
|
|
@@ -8,14 +8,25 @@ import { type SeriesChartRecord } from "./series-build";
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function getHoveredBar(chart: SeriesChart): SeriesChartRecord | null;
|
|
10
10
|
/**
|
|
11
|
-
* Handle mouse-move across all glyph types. Tests
|
|
12
|
-
* so top glyphs win
|
|
11
|
+
* Handle mouse-move across all glyph types. Tests glyph runs in reverse
|
|
12
|
+
* paint order so top glyphs win — paint order is the `columns`
|
|
13
|
+
* declaration order (see `_glyphRuns` / `drawGlyphRuns`).
|
|
13
14
|
* Updates `_hoveredBarIdx` or `_hoveredSample` and re-renders on change.
|
|
15
|
+
*
|
|
16
|
+
* Faceted frames first resolve the cell under the cursor: that cell's
|
|
17
|
+
* layout supplies the pixel→data mapping and its index becomes the
|
|
18
|
+
* `splitFilter` — records of other splits share the same band-slot
|
|
19
|
+
* coordinates by construction, so an unfiltered hit-test would match
|
|
20
|
+
* a bar from a different facet.
|
|
14
21
|
*/
|
|
15
22
|
export declare function handleBarHover(chart: SeriesChart, mx: number, my: number): void;
|
|
16
23
|
/**
|
|
17
24
|
* Handle a click on the legend area. Returns true when the click hit a
|
|
18
25
|
* legend entry (the caller should then treat the event as consumed).
|
|
26
|
+
*
|
|
27
|
+
* An entry may own several series (facet-grid mode groups the legend
|
|
28
|
+
* by aggregate): the toggle is all-or-nothing — any visible member
|
|
29
|
+
* hides the whole group, a fully-hidden group shows every member.
|
|
19
30
|
*/
|
|
20
31
|
export declare function handleBarLegendClick(chart: SeriesChart, mx: number, my: number): boolean;
|
|
21
32
|
/**
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import type { WebGLContextManager } from "../../webgl/context-manager";
|
|
2
2
|
import { type SeriesChart } from "./series";
|
|
3
|
+
import { PlotLayout } from "../../layout/plot-layout";
|
|
3
4
|
/**
|
|
4
5
|
* Upload bar instance buffers from the columnar `_bars` storage.
|
|
6
|
+
*
|
|
7
|
+
* Overlay mode emits instances in `_bars` order. Facet-grid mode
|
|
8
|
+
* (`_facetActive`) emits them split-major via a counting sort so each
|
|
9
|
+
* facet's instances form a contiguous range — recorded on
|
|
10
|
+
* `chart._facetBarRanges` and drawn per facet with an instance-offset
|
|
11
|
+
* `drawBars` call.
|
|
5
12
|
*/
|
|
6
13
|
export declare function uploadBarInstances(chart: SeriesChart, glManager: WebGLContextManager): void;
|
|
7
14
|
/**
|
|
@@ -28,11 +35,20 @@ export declare function rebuildGlyphBuffers(chart: SeriesChart, glManager: WebGL
|
|
|
28
35
|
* Full-frame render: gridlines → WebGL bars (instanced) → chrome overlay.
|
|
29
36
|
*/
|
|
30
37
|
export declare function renderBarFrame(chart: SeriesChart, glManager: WebGLContextManager): void;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve the `PlotLayout` a record renders in: the record's facet
|
|
40
|
+
* cell in faceted frames, the single plot layout otherwise. Tooltip /
|
|
41
|
+
* pin positioning must map through this so faceted anchors land in the
|
|
42
|
+
* record's own cell.
|
|
43
|
+
*/
|
|
44
|
+
export declare function layoutForRecord(chart: SeriesChart, b: {
|
|
45
|
+
splitIdx: number;
|
|
46
|
+
}): PlotLayout | null;
|
|
31
47
|
/**
|
|
32
48
|
* Draw axes chrome + legend + tooltip onto the overlay canvas.
|
|
33
49
|
*/
|
|
34
50
|
export declare function renderBarChromeOverlay(chart: SeriesChart): void;
|
|
35
|
-
export declare function rightAxisDataToPixel(chart: SeriesChart, x: number, y: number): {
|
|
51
|
+
export declare function rightAxisDataToPixel(chart: SeriesChart, x: number, y: number, layoutOverride?: PlotLayout): {
|
|
36
52
|
px: number;
|
|
37
53
|
py: number;
|
|
38
54
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ColumnDataMap } from "../../data/view-reader";
|
|
2
2
|
import type { WebGLContextManager } from "../../webgl/context-manager";
|
|
3
3
|
import type { ZoomConfig } from "../../interaction/zoom-controller";
|
|
4
|
+
import type { FacetGrid } from "../../layout/facet-grid";
|
|
4
5
|
import { CategoricalYChart } from "../common/categorical-y-chart";
|
|
5
6
|
import { type PlotRect } from "../../layout/plot-layout";
|
|
6
7
|
import { type AxisDomain } from "../../axis/numeric-axis";
|
|
@@ -25,6 +26,15 @@ export interface SeriesAutoFitCache {
|
|
|
25
26
|
rightMax: number;
|
|
26
27
|
hasRight: boolean;
|
|
27
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* One paint pass: the contiguous span of aggregates (`columns` indices,
|
|
31
|
+
* inclusive) sharing a glyph type. See {@link SeriesChart._glyphRuns}.
|
|
32
|
+
*/
|
|
33
|
+
export interface GlyphRun {
|
|
34
|
+
chartType: SeriesInfo["chartType"];
|
|
35
|
+
aggStart: number;
|
|
36
|
+
aggEnd: number;
|
|
37
|
+
}
|
|
28
38
|
export interface CachedLocations {
|
|
29
39
|
u_proj_left: WebGLUniformLocation | null;
|
|
30
40
|
u_proj_right: WebGLUniformLocation | null;
|
|
@@ -68,6 +78,64 @@ export declare class SeriesChart extends CategoricalYChart {
|
|
|
68
78
|
_aggregates: string[];
|
|
69
79
|
_splitPrefixes: string[];
|
|
70
80
|
_series: SeriesInfo[];
|
|
81
|
+
/**
|
|
82
|
+
* Whether the CURRENT build's geometry was produced for facet-grid
|
|
83
|
+
* mode (`facet_mode: "grid"` with real splits). The render / hover
|
|
84
|
+
* paths branch on this — never on the live `_facetConfig` — so a
|
|
85
|
+
* `setPluginConfig` that flips `facet_mode` between a build and a
|
|
86
|
+
* redraw can't pair grid-mode rendering with overlay-built stack
|
|
87
|
+
* geometry (or vice versa). The host always follows a
|
|
88
|
+
* `plugin.restore` with an `update` → `loadAndRender`, so the flag
|
|
89
|
+
* catches up one build later.
|
|
90
|
+
*/
|
|
91
|
+
_facetActive: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Facet grid of the most recent faceted frame — one cell per
|
|
94
|
+
* split group. `null` in overlay / no-split frames. Read by the
|
|
95
|
+
* chrome overlay, hover hit-test, and tooltip pin to resolve the
|
|
96
|
+
* per-facet `PlotLayout`.
|
|
97
|
+
*/
|
|
98
|
+
_facetGrid: FacetGrid | null;
|
|
99
|
+
/**
|
|
100
|
+
* Per-split contiguous instance ranges in the uploaded bar
|
|
101
|
+
* buffers, indexed by `splitIdx`. Populated by
|
|
102
|
+
* `uploadBarInstances` when `_facetActive` (instances are emitted
|
|
103
|
+
* split-major); `null` in overlay mode. Each facet's draw binds
|
|
104
|
+
* the instance attributes at `start` and draws `count` instances.
|
|
105
|
+
*/
|
|
106
|
+
_facetBarRanges: {
|
|
107
|
+
start: number;
|
|
108
|
+
count: number;
|
|
109
|
+
}[] | null;
|
|
110
|
+
/**
|
|
111
|
+
* Paint order of the current build: consecutive aggregates sharing
|
|
112
|
+
* a glyph type, merged into runs, in `columns` declaration order
|
|
113
|
+
* (`aggIdx` ascending — later columns paint on top). The frame
|
|
114
|
+
* draws one pass per run; a homogeneous chart is a single run and
|
|
115
|
+
* degenerates to the legacy one-pass-per-type path. `aggEnd` is
|
|
116
|
+
* inclusive.
|
|
117
|
+
*/
|
|
118
|
+
_glyphRuns: GlyphRun[];
|
|
119
|
+
/**
|
|
120
|
+
* Per-aggregate contiguous instance ranges in the uploaded bar
|
|
121
|
+
* buffers, indexed by `aggIdx` — the overlay-mode counterpart of
|
|
122
|
+
* `_facetBarRanges`, populated by `uploadBarInstances`' aggregate
|
|
123
|
+
* counting sort. `null` until first upload.
|
|
124
|
+
*/
|
|
125
|
+
_barAggRanges: {
|
|
126
|
+
start: number;
|
|
127
|
+
count: number;
|
|
128
|
+
}[] | null;
|
|
129
|
+
/**
|
|
130
|
+
* Faceted per-(split, aggregate) instance ranges,
|
|
131
|
+
* `[splitIdx][aggIdx]` — instances are emitted split-major then
|
|
132
|
+
* aggregate-ordered, so a facet's glyph-run slice is contiguous.
|
|
133
|
+
* `null` in overlay mode.
|
|
134
|
+
*/
|
|
135
|
+
_facetBarAggRanges: {
|
|
136
|
+
start: number;
|
|
137
|
+
count: number;
|
|
138
|
+
}[][] | null;
|
|
71
139
|
/**
|
|
72
140
|
* Columnar bar/area record storage. Indexed by bar slot in
|
|
73
141
|
* `[0, _bars.count)`. Replaces the legacy `SeriesChartRecord[]` to
|
|
@@ -148,8 +216,12 @@ export declare class SeriesChart extends CategoricalYChart {
|
|
|
148
216
|
_hasRightAxis: boolean;
|
|
149
217
|
/**
|
|
150
218
|
* `domain_mode: "expand"` accumulators. Hold the running union of
|
|
151
|
-
* every prior build's
|
|
152
|
-
*
|
|
219
|
+
* every prior build's VALUE-axis extents (primary + alt) for as
|
|
220
|
+
* long as the option is active. The category axis deliberately has
|
|
221
|
+
* NO accumulator: `domain_mode` scopes to the value axis only on
|
|
222
|
+
* band charts (Y for the Y-family, X for X Bar) — a numeric or
|
|
223
|
+
* datetime `group_by` axis always fits the current data, so a
|
|
224
|
+
* streaming chart's time axis releases departed categories.
|
|
153
225
|
* Cleared in `resetExpandedDomain` — wired from the worker's
|
|
154
226
|
* `resetAllZooms` and from view-config mutations on the base
|
|
155
227
|
* class. `null` whenever the option is `"fit"` or the accumulator
|
|
@@ -163,10 +235,19 @@ export declare class SeriesChart extends CategoricalYChart {
|
|
|
163
235
|
min: number;
|
|
164
236
|
max: number;
|
|
165
237
|
} | null;
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
238
|
+
/**
|
|
239
|
+
* The axis partition (per-aggregate axis side) the expand
|
|
240
|
+
* accumulators were accumulated under. An accumulator is only
|
|
241
|
+
* meaningful for the partition that produced it: when an aggregate
|
|
242
|
+
* moves sides (`columns_config.alt_axis` pin via a config-only
|
|
243
|
+
* `update()`, or a data-driven `auto_alt_y_axis` flip), the side it
|
|
244
|
+
* LEFT would otherwise retain its extent forever — the departed
|
|
245
|
+
* column's range never leaves the primary axis. A signature
|
|
246
|
+
* mismatch resets BOTH accumulators before the union. Keyed per
|
|
247
|
+
* AGGREGATE (not per series) so split-group growth on a streaming
|
|
248
|
+
* update never spuriously resets.
|
|
249
|
+
*/
|
|
250
|
+
_expandedAxisSig: string | null;
|
|
170
251
|
/**
|
|
171
252
|
* Numeric category-axis state. Populated only when `group_by` has
|
|
172
253
|
* exactly one level and that level is `date | datetime | integer |
|
|
@@ -233,8 +314,14 @@ export declare class SeriesChart extends CategoricalYChart {
|
|
|
233
314
|
* capacity is reused across data reloads / legend toggles.
|
|
234
315
|
*/
|
|
235
316
|
_visibleBarIndices: Int32Array;
|
|
317
|
+
/**
|
|
318
|
+
* Hit-test rects for legend entries. Overlay mode: one entry per
|
|
319
|
+
* series (`seriesIds.length === 1`). Facet-grid mode: one entry
|
|
320
|
+
* per AGGREGATE, carrying every split's seriesId — a legend
|
|
321
|
+
* toggle hides/shows the aggregate across all facets at once.
|
|
322
|
+
*/
|
|
236
323
|
_legendRects: {
|
|
237
|
-
|
|
324
|
+
seriesIds: number[];
|
|
238
325
|
rect: PlotRect;
|
|
239
326
|
}[];
|
|
240
327
|
/**
|
|
@@ -318,9 +405,16 @@ export declare class SeriesChart extends CategoricalYChart {
|
|
|
318
405
|
/**
|
|
319
406
|
* Resolve the per-series palette and stamp it onto `_series[i].color`.
|
|
320
407
|
* Cached on `_paletteCache` keyed by reference identity of the theme
|
|
321
|
-
* inputs +
|
|
322
|
-
* via `invalidateTheme`) or a data load (which clears
|
|
323
|
-
* forces re-resolution.
|
|
408
|
+
* inputs + resolved color count — only `restyle()` (which clears
|
|
409
|
+
* `_paletteCache` via `invalidateTheme`) or a data load (which clears
|
|
410
|
+
* it explicitly) forces re-resolution.
|
|
411
|
+
*
|
|
412
|
+
* Facet-grid mode colors by AGGREGATE, not by (agg × split) series:
|
|
413
|
+
* the facet is the axis of splitting, so aggregate `k` renders the
|
|
414
|
+
* same color in every facet and the legend lists aggregates once.
|
|
415
|
+
* Overlay mode keeps the per-series palette (splits are distinguished
|
|
416
|
+
* by color there). `_facetActive` only changes at build time, which
|
|
417
|
+
* clears the cache, so the stamp mode can't go stale.
|
|
324
418
|
*
|
|
325
419
|
* Returns true when the cache changed (caller invalidates color upload).
|
|
326
420
|
*/
|
|
@@ -31,5 +31,14 @@ export interface TypedArrayWindowOptions {
|
|
|
31
31
|
* `Promise`, the underlying `with_typed_arrays` call awaits it before
|
|
32
32
|
* releasing the backing Arrow buffer. Callers must not retain any
|
|
33
33
|
* `ColumnData` reference past `render`'s resolution.
|
|
34
|
+
*
|
|
35
|
+
* `render` also receives the DELIVERED row count — the shortest
|
|
36
|
+
* column's length, which may be less than the requested `end_row`:
|
|
37
|
+
* the engine clamps the window to the view's size at fetch time, and
|
|
38
|
+
* on a fast-updating table with deletions that size can shrink after
|
|
39
|
+
* the caller's `num_rows()` round-trip. Build pipelines must iterate
|
|
40
|
+
* to THIS count, never the requested one — a typed array indexed past
|
|
41
|
+
* its length returns `undefined`, which no amount of validity-bitmap
|
|
42
|
+
* checking catches (the bitmap read is out-of-bounds too).
|
|
34
43
|
*/
|
|
35
|
-
export declare function viewToColumnDataMap(view: View, render: (data: ColumnDataMap) => void | Promise<void>, options?: TypedArrayWindowOptions): Promise<void>;
|
|
44
|
+
export declare function viewToColumnDataMap(view: View, render: (data: ColumnDataMap, numRows: number) => void | Promise<void>, options?: TypedArrayWindowOptions): Promise<void>;
|
|
@@ -24,5 +24,12 @@ export interface PerspectiveClickDetail {
|
|
|
24
24
|
* `[<col>, "==", <value>]` clauses.
|
|
25
25
|
*/
|
|
26
26
|
config: Partial<ViewConfig>;
|
|
27
|
+
/**
|
|
28
|
+
* The source panel's `slot` name in a multi-panel `<perspective-viewer>`,
|
|
29
|
+
* so the host can attribute the click to the originating panel. `undefined`
|
|
30
|
+
* for a lone, unslotted viewer. Mirrors `PerspectiveSelectDetail.panel` and
|
|
31
|
+
* the datagrid `PerspectiveClickDetail`.
|
|
32
|
+
*/
|
|
33
|
+
panel?: string;
|
|
27
34
|
}
|
|
28
35
|
export { PerspectiveSelectDetail } from "@perspective-dev/viewer/src/ts/extensions.js";
|
|
@@ -8,6 +8,11 @@ export declare function computeNiceTicks(min: number, max: number, targetCount:
|
|
|
8
8
|
/**
|
|
9
9
|
* Format a numeric tick value for display.
|
|
10
10
|
* Uses K/M/B suffixes for large numbers, fixed decimals for small.
|
|
11
|
+
*
|
|
12
|
+
* Total over any input: label formatters run inside render passes, so a
|
|
13
|
+
* non-finite value (or `undefined` smuggled in by an upstream
|
|
14
|
+
* out-of-bounds read) must degrade to a placeholder, never throw the
|
|
15
|
+
* frame away.
|
|
11
16
|
*/
|
|
12
17
|
export declare function formatTickValue(val: number): string;
|
|
13
18
|
/**
|