@perspective-dev/viewer-charts 5.2.0 → 5.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dist/cdn/perspective-viewer-charts.js +1 -2
  2. package/dist/cdn/perspective-viewer-charts.js.map +4 -4
  3. package/dist/esm/axis/legend.d.ts +53 -5
  4. package/dist/esm/axis/map-ticks.d.ts +15 -0
  5. package/dist/esm/charts/candlestick/candlestick-interact.d.ts +2 -6
  6. package/dist/esm/charts/candlestick/candlestick-render.d.ts +3 -0
  7. package/dist/esm/charts/cartesian/cartesian.d.ts +7 -0
  8. package/dist/esm/charts/cartesian/glyph.d.ts +2 -1
  9. package/dist/esm/charts/cartesian/glyphs/density.d.ts +2 -1
  10. package/dist/esm/charts/cartesian/glyphs/lines.d.ts +2 -1
  11. package/dist/esm/charts/cartesian/glyphs/points.d.ts +2 -1
  12. package/dist/esm/charts/cartesian/tooltip-lines.d.ts +1 -1
  13. package/dist/esm/charts/chart-base.d.ts +24 -9
  14. package/dist/esm/charts/chart.d.ts +81 -6
  15. package/dist/esm/charts/common/category-axis-resolver.d.ts +1 -1
  16. package/dist/esm/charts/common/draw-tooltip-box.d.ts +2 -1
  17. package/dist/esm/charts/common/tree-chart.d.ts +1 -0
  18. package/dist/esm/charts/common/tree-interact.d.ts +1 -1
  19. package/dist/esm/charts/heatmap/heatmap.d.ts +1 -0
  20. package/dist/esm/charts/series/series-build.d.ts +7 -0
  21. package/dist/esm/charts/series/series-interact.d.ts +1 -1
  22. package/dist/esm/charts/series/series-type.d.ts +18 -0
  23. package/dist/esm/charts/series/series.d.ts +10 -1
  24. package/dist/esm/charts/sunburst/sunburst-render.d.ts +4 -0
  25. package/dist/esm/index.d.ts +2 -0
  26. package/dist/esm/interaction/axis-indicators.d.ts +11 -0
  27. package/dist/esm/interaction/host-sink-dom.d.ts +3 -2
  28. package/dist/esm/interaction/host-sink-message.d.ts +3 -2
  29. package/dist/esm/interaction/lazy-tooltip.d.ts +2 -2
  30. package/dist/esm/interaction/legend-controller.d.ts +246 -0
  31. package/dist/esm/interaction/tooltip-controller.d.ts +20 -95
  32. package/dist/esm/interaction/tooltip-grid.d.ts +33 -0
  33. package/dist/esm/layout/facet-grid.d.ts +6 -0
  34. package/dist/esm/layout/ticks.d.ts +1 -0
  35. package/dist/esm/map/tile-source.d.ts +77 -8
  36. package/dist/esm/perspective-viewer-charts.js +1 -2
  37. package/dist/esm/perspective-viewer-charts.js.map +4 -4
  38. package/dist/esm/plugin/charts.d.ts +2 -0
  39. package/dist/esm/plugin/format-defaults.d.ts +9 -0
  40. package/dist/esm/plugin/plugin.d.ts +28 -1
  41. package/dist/esm/theme/gradient.d.ts +32 -0
  42. package/dist/esm/theme/overrides.d.ts +19 -0
  43. package/dist/esm/transport/protocol.d.ts +58 -5
  44. package/dist/esm/transport/renderer-transport.d.ts +3 -0
  45. package/dist/esm/utils/css.d.ts +4 -0
  46. package/dist/esm/worker/renderer.worker.d.ts +46 -1
  47. package/package.json +1 -1
  48. package/src/css/perspective-viewer-charts.css +0 -1
  49. package/src/ts/axis/bar-axis.ts +2 -7
  50. package/src/ts/axis/legend.ts +351 -24
  51. package/src/ts/axis/map-ticks.ts +94 -0
  52. package/src/ts/axis/numeric-axis.ts +2 -9
  53. package/src/ts/charts/candlestick/candlestick-build.ts +1 -0
  54. package/src/ts/charts/candlestick/candlestick-interact.ts +46 -40
  55. package/src/ts/charts/candlestick/candlestick-render.ts +81 -10
  56. package/src/ts/charts/candlestick/candlestick.ts +4 -3
  57. package/src/ts/charts/cartesian/cartesian-interact.ts +9 -3
  58. package/src/ts/charts/cartesian/cartesian-render.ts +374 -75
  59. package/src/ts/charts/cartesian/cartesian.ts +13 -0
  60. package/src/ts/charts/cartesian/glyph.ts +6 -2
  61. package/src/ts/charts/cartesian/glyphs/density.ts +2 -2
  62. package/src/ts/charts/cartesian/glyphs/lines.ts +15 -11
  63. package/src/ts/charts/cartesian/glyphs/points.ts +9 -5
  64. package/src/ts/charts/cartesian/tooltip-lines.ts +8 -8
  65. package/src/ts/charts/chart-base.ts +76 -42
  66. package/src/ts/charts/chart.ts +111 -7
  67. package/src/ts/charts/common/category-axis-resolver.ts +44 -5
  68. package/src/ts/charts/common/draw-tooltip-box.ts +13 -30
  69. package/src/ts/charts/common/tree-chart.ts +4 -0
  70. package/src/ts/charts/common/tree-chrome.ts +102 -23
  71. package/src/ts/charts/common/tree-interact.ts +18 -17
  72. package/src/ts/charts/heatmap/heatmap-build.ts +7 -1
  73. package/src/ts/charts/heatmap/heatmap-interact.ts +75 -8
  74. package/src/ts/charts/heatmap/heatmap-render.ts +105 -24
  75. package/src/ts/charts/heatmap/heatmap.ts +8 -3
  76. package/src/ts/charts/map/map.ts +3 -5
  77. package/src/ts/charts/series/series-build.ts +15 -2
  78. package/src/ts/charts/series/series-interact.ts +14 -24
  79. package/src/ts/charts/series/series-render.ts +310 -132
  80. package/src/ts/charts/series/series-type.ts +65 -0
  81. package/src/ts/charts/series/series.ts +31 -8
  82. package/src/ts/charts/sunburst/sunburst-render.ts +16 -1
  83. package/src/ts/charts/treemap/treemap-render.ts +12 -1
  84. package/src/ts/data/view-reader.ts +1 -4
  85. package/src/ts/index.ts +2 -0
  86. package/src/ts/interaction/axis-indicators.ts +137 -0
  87. package/src/ts/interaction/host-sink-dom.ts +66 -2
  88. package/src/ts/interaction/host-sink-message.ts +8 -2
  89. package/src/ts/interaction/lazy-tooltip.ts +5 -5
  90. package/src/ts/interaction/legend-controller.ts +1084 -0
  91. package/src/ts/interaction/tooltip-controller.ts +43 -131
  92. package/src/ts/interaction/tooltip-grid.ts +187 -0
  93. package/src/ts/layout/facet-grid.ts +8 -1
  94. package/src/ts/layout/ticks.ts +48 -12
  95. package/src/ts/map/tile-loader.ts +16 -1
  96. package/src/ts/map/tile-source.ts +199 -53
  97. package/src/ts/map/tile-sources.json +18 -0
  98. package/src/ts/plugin/charts.ts +40 -6
  99. package/src/ts/plugin/format-defaults.ts +37 -0
  100. package/src/ts/plugin/plugin.ts +330 -76
  101. package/src/ts/shaders/line.vert.glsl +5 -2
  102. package/src/ts/shaders/scatter.vert.glsl +0 -7
  103. package/src/ts/theme/gradient.ts +265 -1
  104. package/src/ts/theme/overrides.ts +76 -0
  105. package/src/ts/transport/protocol.ts +60 -4
  106. package/src/ts/transport/renderer-transport.ts +107 -14
  107. package/src/ts/utils/css.ts +12 -0
  108. package/src/ts/worker/dispatch.ts +6 -2
  109. package/src/ts/worker/renderer.worker.ts +191 -7
@@ -63,5 +63,7 @@ export interface ChartTypeConfig {
63
63
  */
64
64
  plugin_field_defaults?: Partial<PluginConfig>;
65
65
  }
66
+ export declare const LEGEND_FIELDS: readonly PluginConfigField[];
67
+ export declare const TOOLTIP_FIELDS: readonly PluginConfigField[];
66
68
  declare const CHARTS: ChartTypeConfig[];
67
69
  export default CHARTS;
@@ -0,0 +1,9 @@
1
+ import type { DateFormatConfig, NumberFormatConfig } from "@perspective-dev/viewer/src/ts/column-format.js";
2
+ /**
3
+ * The chart plugin's default per-column formats, declared to the viewer in
4
+ * `column_config_schema()` and applied by the render path under sparse or
5
+ * absent configs.
6
+ */
7
+ export declare const CHART_NUMBER_DEFAULTS: NumberFormatConfig;
8
+ export declare const CHART_DATETIME_DEFAULTS: DateFormatConfig;
9
+ export declare const CHART_DATE_DEFAULTS: DateFormatConfig;
@@ -1,6 +1,24 @@
1
1
  import type { View } from "@perspective-dev/client";
2
2
  import type { IPerspectiveViewerPlugin, PluginStaticConfig } from "@perspective-dev/viewer";
3
3
  import { ChartTypeConfig } from "./charts";
4
+ import { type TileSourceSpec } from "../map/tile-source";
5
+ /**
6
+ * Register a raster XYZ tile provider at runtime. The provider joins
7
+ * the bundled [map/tile-sources.json] entries in the settings panel's
8
+ * `map_tile_provider` enum and resolves on any map chart from its next
9
+ * config forward onward — the resolved spec rides every outgoing
10
+ * `setPluginConfig` / `init` message alongside the config that names
11
+ * it, so no separate registry-sync operation exists. Re-registering an
12
+ * id replaces it (a changed template drops cached tiles via the
13
+ * content-derived cache identity); a chart currently displaying that
14
+ * id picks the replacement up on its next `restore()`. Throws
15
+ * `TypeError` on a malformed spec. Returns the normalized spec.
16
+ *
17
+ * A key-gated provider is registered with the key embedded in its
18
+ * `template` — keys never enter `plugin_config`, so they never appear
19
+ * in `save()` output.
20
+ */
21
+ export declare function registerTileSource(spec: unknown): TileSourceSpec;
4
22
  export declare class HTMLPerspectiveViewerWebGLPluginElement extends HTMLElement implements IPerspectiveViewerPlugin {
5
23
  _chartType: ChartTypeConfig;
6
24
  private _initialized;
@@ -86,9 +104,13 @@ export declare class HTMLPerspectiveViewerWebGLPluginElement extends HTMLElement
86
104
  * contexts ([webgl/context-pool.ts]), so a page can exceed the cap.
87
105
  */
88
106
  static setBlitMode(mode: "direct" | "blit"): void;
107
+ static registerTileSource(spec: unknown): TileSourceSpec;
108
+ static tileSources(): readonly TileSourceSpec[];
89
109
  get_static_config(): PluginStaticConfig;
90
- column_config_schema(column_type: string, _group: string | undefined, _column_name: string, current_value: Record<string, unknown> | null, _viewer_config?: {
110
+ column_config_schema(column_type: string, group: string | undefined, column_name: string, current_value: Record<string, unknown> | null, viewer_config?: {
111
+ columns?: (string | null)[];
91
112
  group_by?: string[];
113
+ split_by?: string[];
92
114
  group_rollup_mode?: string;
93
115
  }): {
94
116
  fields: (Record<string, unknown> & {
@@ -103,6 +125,11 @@ export declare class HTMLPerspectiveViewerWebGLPluginElement extends HTMLElement
103
125
  kind: string;
104
126
  })[];
105
127
  };
128
+ private _resolvedTheme;
129
+ private static readonly GRADIENT_PALETTE_FALLBACK_COUNT;
130
+ private _themeSeriesPaletteHex;
131
+ private _themeSeriesColorHex;
132
+ private _themeGradientStopsSpec;
106
133
  draw(view: View): Promise<void>;
107
134
  update(view: View): Promise<void>;
108
135
  /**
@@ -15,6 +15,37 @@ export interface GradientStop {
15
15
  * that never set the gradient still produce sane output.
16
16
  */
17
17
  export declare function parseCssGradient(src: string | null | undefined): GradientStop[];
18
+ /**
19
+ * A color literal — `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()` or
20
+ * `rgba()` — as a `[0, 1]` RGB triple, or `null` for anything else.
21
+ */
22
+ export declare function parseCssColorStrict(src: string): [number, number, number] | null;
23
+ /**
24
+ * The shared `linear-gradient(...)` tokenizer of the viewer's CSS-valued
25
+ * config grammar.
26
+ */
27
+ export declare function tokenizeLinearGradient(src: string): Array<[[number, number, number], number | null]> | null;
28
+ /**
29
+ * Strict gradient reader: a `linear-gradient(...)` with ≥ 2 stops,
30
+ * positions optional, offsets clamped to `[0, 1]` and sorted, or `null`
31
+ * on malformed input.
32
+ */
33
+ export declare function parseCssGradientStrict(src: string): GradientStop[] | null;
34
+ /**
35
+ * Strict palette reader: a `linear-gradient(...)` of ≥ 1 colors with no
36
+ * positions, or `null` on malformed input.
37
+ */
38
+ export declare function parseCssColorList(src: string): Array<[number, number, number]> | null;
39
+ /**
40
+ * The viewer's canonical gradient string for `stops`: `linear-gradient(to
41
+ * right, #rrggbb P%, …)`, sorted, positions at 0.1% resolution.
42
+ */
43
+ export declare function stopsToCss(stops: GradientStop[]): string;
44
+ /**
45
+ * The viewer's canonical palette string for `colors`: the same frame
46
+ * with bare `#rrggbb` entries and no positions.
47
+ */
48
+ export declare function colorsToCss(colors: Array<[number, number, number]>): string;
18
49
  /**
19
50
  * Piecewise-linear color sample at `t ∈ [0, 1]`. Returns RGBA in [0, 1].
20
51
  * Clamps `t` to the gradient's first/last stop outside `[0, 1]`.
@@ -29,6 +60,7 @@ export declare function sampleGradient(stops: GradientStop[], t: number): [numbe
29
60
  * - degenerate → 0.5 (single colour at the midpoint).
30
61
  */
31
62
  export declare function colorValueToT(value: number, colorMin: number, colorMax: number): number;
63
+ export declare function colorRangePivot(colorMin: number, colorMax: number): [number, number];
32
64
  /**
33
65
  * Convert a discrete series palette (from `--psp-charts--series-N--color`)
34
66
  * into a `GradientStop[]` with stops at `i / (N - 1)`. The resulting
@@ -0,0 +1,19 @@
1
+ import { type GradientStop } from "./gradient";
2
+ import type { Theme } from "./theme";
3
+ import type { Vec3 } from "./palette";
4
+ /**
5
+ * Per-column color-scale overrides from the viewer's `columns_config`,
6
+ * patched into the resolved `Theme`'s `seriesPalette` / `gradientStops`
7
+ * fields.
8
+ */
9
+ export declare function applyColumnColorOverrides(theme: Theme, columnsConfig: Record<string, any> | undefined, colorColumn: string | null): Theme;
10
+ /**
11
+ * Parse a stored `palette` value into the `seriesPalette` shape, or
12
+ * `null` on anything malformed.
13
+ */
14
+ export declare function parsePaletteOverride(raw: unknown): Vec3[] | null;
15
+ /**
16
+ * Parse a stored `gradient` value into sorted `GradientStop[]`, or
17
+ * `null` on malformed input or fewer than 2 stops.
18
+ */
19
+ export declare function parseGradientOverride(raw: unknown): GradientStop[] | null;
@@ -1,6 +1,7 @@
1
1
  import type { FacetConfig, PluginConfig } from "../charts/chart";
2
2
  import type { PerspectiveClickDetail } from "../event-detail";
3
3
  import type { ThemeSnapshot } from "../theme/theme";
4
+ import type { TileSourceSpec } from "../map/tile-source";
4
5
  import type { ViewConfig } from "@perspective-dev/client";
5
6
  export type { ThemeSnapshot };
6
7
  /**
@@ -10,7 +11,7 @@ export type { ThemeSnapshot };
10
11
  * chart's own renderer control plane.
11
12
  */
12
13
  export type ControlMsg = InitMsg | SetViewByNameMsg | SetColumnsConfigMsg | SetPluginConfigMsg | SetBufferMaxCapacityMsg | LoadAndRenderMsg | RedrawMsg | DeselectMsg | ResizeMsg | ClearMsg | InvalidateThemeMsg | RestoreZoomMsg | ResetAllZoomsMsg | ResetExpandedDomainMsg | SaveZoomReqMsg | SnapshotPngReqMsg | InteractionMsg | DestroyMsg;
13
- export type WorkerMsg = ReadyMsg | ZoomChangedMsg | SaveZoomReplyMsg | SnapshotPngReplyMsg | PinTooltipMsg | DismissTooltipMsg | SetCursorMsg | UserClickMsg | UserSelectMsg | LoadAndRenderAckMsg | ResizeAckMsg | FrameBitmapMsg | ErrorMsg;
14
+ export type WorkerMsg = ReadyMsg | ZoomChangedMsg | SaveZoomReplyMsg | SnapshotPngReplyMsg | PinTooltipMsg | DismissTooltipMsg | SetCursorMsg | UserClickMsg | UserSelectMsg | PluginConfigDeltaMsg | LoadAndRenderAckMsg | ResizeAckMsg | FrameBitmapMsg | ErrorMsg;
14
15
  /**
15
16
  * Session-tagged envelopes for the shared-worker transport. Every
16
17
  * message between the host and the shared `Worker` carries a numeric
@@ -49,8 +50,19 @@ export interface InitMsg {
49
50
  * `dpr` and there is no host-side GL drawing buffer.
50
51
  */
51
52
  glCanvas?: OffscreenCanvas;
52
- gridlinesCanvas: OffscreenCanvas;
53
- chromeCanvas: OffscreenCanvas;
53
+ /**
54
+ * The gridlines (bottom) and chrome/axes (top) 2D layers.
55
+ * Transferred via `transferControlToOffscreen` on the host, present
56
+ * iff `renderMode === "direct"` — their pixels reach the screen
57
+ * through the compositor. In blit mode the renderer allocates
58
+ * worker-local surfaces instead and composites both layers into the
59
+ * shipped `FrameBitmapMsg`, so every layer of the frame rides the
60
+ * host's staged-present hold (a transferred canvas presents on the
61
+ * compositor's own schedule, unsynchronized with the host's layout
62
+ * commits — the one-frame axes warp on anticipated resizes).
63
+ */
64
+ gridlinesCanvas?: OffscreenCanvas;
65
+ chromeCanvas?: OffscreenCanvas;
54
66
  /**
55
67
  * `MessagePort` to the host's `ProxySession`. Worker mode only —
56
68
  * the worker bootstraps a fresh `Client` and bridges it through
@@ -113,6 +125,16 @@ export interface InitMsg {
113
125
  */
114
126
  columnsConfig?: Record<string, any>;
115
127
  defaultChartType?: string;
128
+ /**
129
+ * Resolved spec for `pluginConfig.map_tile_provider`, when the
130
+ * plugin realm's registry knows the id — see
131
+ * {@link SetPluginConfigMsg.tileSource} for the invariant. Applied
132
+ * to the worker realm's registry before the chart impl is
133
+ * constructed. Bundled [map/tile-sources.json] entries ship inside
134
+ * the worker bundle, so this matters only for runtime-registered
135
+ * providers.
136
+ */
137
+ tileSource?: TileSourceSpec;
116
138
  /**
117
139
  * Pre-resolved CSS-variable theme snapshot from the host.
118
140
  */
@@ -191,6 +213,17 @@ export interface SetColumnsConfigMsg {
191
213
  export interface SetPluginConfigMsg {
192
214
  kind: "setPluginConfig";
193
215
  cfg: PluginConfig;
216
+ /**
217
+ * Resolved spec for `cfg.map_tile_provider`, when the plugin
218
+ * realm's registry knows the id. Riding the config keeps the two
219
+ * realms' registries convergent with NO eager mirroring: the
220
+ * worker registers this spec before applying `cfg`, so it can
221
+ * never hold a config whose provider it cannot resolve —
222
+ * regardless of when `registerTileSource` ran relative to
223
+ * renderer construction. Absent for unknown ids (the worker falls
224
+ * back to the default basemap).
225
+ */
226
+ tileSource?: TileSourceSpec;
194
227
  }
195
228
  export interface SetBufferMaxCapacityMsg {
196
229
  kind: "setBufferMaxCapacity";
@@ -234,6 +267,7 @@ export interface LoadAndRenderMsg {
234
267
  export interface LoadAndRenderAckMsg {
235
268
  kind: "loadAndRenderAck";
236
269
  msgId: number;
270
+ error?: string;
237
271
  }
238
272
  export interface RedrawMsg {
239
273
  kind: "redraw";
@@ -321,7 +355,8 @@ export interface SnapshotPngReqMsg {
321
355
  export interface SnapshotPngReplyMsg {
322
356
  kind: "snapshotPngReply";
323
357
  requestId: number;
324
- blob: Blob;
358
+ blob?: Blob;
359
+ error?: string;
325
360
  }
326
361
  export interface DestroyMsg {
327
362
  kind: "destroy";
@@ -396,7 +431,11 @@ export interface ErrorMsg {
396
431
  */
397
432
  export interface PinTooltipMsg {
398
433
  kind: "pinTooltip";
399
- lines: string[];
434
+ grid: string[][];
435
+ style: {
436
+ opacity: number;
437
+ maxColumnPx: number;
438
+ };
400
439
  pos: {
401
440
  px: number;
402
441
  py: number;
@@ -419,6 +458,20 @@ export interface SetCursorMsg {
419
458
  kind: "setCursor";
420
459
  cursor: string;
421
460
  }
461
+ /**
462
+ * Renderer → host: a completed legend gesture (sidebar width drag,
463
+ * floating move / resize) produced new values for the legend's
464
+ * `plugin_config` fields. Posted ONCE per gesture, at pointerup — never
465
+ * per pointermove — with only the fields the gesture changed. The host
466
+ * plugin persists them through the viewer's public `restore` surface
467
+ * (a user-gesture echo), which merges the host bucket, refreshes the
468
+ * settings form, and echoes one `setPluginConfig` back with the same
469
+ * values (a no-op by the worker's legend-field equality guard).
470
+ */
471
+ export interface PluginConfigDeltaMsg {
472
+ kind: "pluginConfigDelta";
473
+ fields: Record<string, string | number | boolean>;
474
+ }
422
475
  /**
423
476
  * Renderer → host: a user click landed on a chart glyph. Host
424
477
  * re-dispatches as `CustomEvent<PerspectiveClickDetail>` on the
@@ -58,6 +58,7 @@ export declare class RendererTransport {
58
58
  private _pending;
59
59
  private _pendingCounter;
60
60
  private _onZoomChanged;
61
+ private _onPluginConfigDelta;
61
62
  /**
62
63
  * Cached zoom-default flag pushed by the renderer after each zoom
63
64
  * mutation. Surfaced sync via `allZoomsDefault()`; updates between
@@ -126,6 +127,7 @@ export declare class RendererTransport {
126
127
  maxCells: number;
127
128
  precompileShaders?: boolean;
128
129
  onZoomChanged?: (isDefault: boolean) => void;
130
+ onPluginConfigDelta?: (fields: Record<string, string | number | boolean>) => void;
129
131
  });
130
132
  init(opts: {
131
133
  gl: HTMLCanvasElement;
@@ -245,6 +247,7 @@ export declare class RendererTransport {
245
247
  * worth catching at the worker side.
246
248
  */
247
249
  private _resolvePending;
250
+ private _rejectPending;
248
251
  /**
249
252
  * Blit-mode handler: draw a renderer-emitted frame into the
250
253
  * visible 2D-context display canvas, then close the bitmap so its
@@ -1 +1,5 @@
1
1
  export declare function parseCSSColorToVec3(colorStr: string): [number, number, number];
2
+ /**
3
+ * Format a `[0, 1]`-range RGB triple as a plain `#rrggbb` string.
4
+ */
5
+ export declare function vec3ToHexColor(c: [number, number, number]): string;
@@ -1,9 +1,10 @@
1
1
  import "./boot";
2
2
  import type { Client, Table, View } from "@perspective-dev/client";
3
3
  import { WebGLContextManager } from "../webgl/context-manager";
4
- import { ChartImplementation } from "../charts/chart";
4
+ import { ChartImplementation, type PluginConfig } from "../charts/chart";
5
5
  import { ZoomController } from "../interaction/zoom-controller";
6
6
  import type { InitMsg, InteractionEvent, LoadAndRenderMsg, WorkerMsg } from "../transport/protocol";
7
+ import { type TileSourceSpec } from "../map/tile-source";
7
8
  export declare class WorkerRenderer {
8
9
  chartImpl: ChartImplementation;
9
10
  glManager: WebGLContextManager;
@@ -13,6 +14,17 @@ export declare class WorkerRenderer {
13
14
  cssWidth: number;
14
15
  cssHeight: number;
15
16
  dpr: number;
17
+ /**
18
+ * Blit-mode compose surface: gridlines + GL frame + chrome are
19
+ * drawn here each `endFrame` and shipped as ONE `ImageBitmap`, so
20
+ * every layer rides the host's staged-present hold (see
21
+ * `InitMsg.gridlinesCanvas`). `null` in direct mode.
22
+ */
23
+ private _composeCanvas;
24
+ private _composeCtx;
25
+ private _lastPlot;
26
+ private _frameSerial;
27
+ private _overlayPresentQueued;
16
28
  client: Client;
17
29
  view: View;
18
30
  /**
@@ -42,6 +54,13 @@ export declare class WorkerRenderer {
42
54
  private _lastDragY;
43
55
  constructor(msg: InitMsg, client: Client, view: View, table: Table | null, controlPort: MessagePort, ImplClass: new () => ChartImplementation);
44
56
  setViewByName(name: string): void;
57
+ /**
58
+ * Registry write precedes the config apply — `cfg` may name the
59
+ * spec riding alongside it (see `SetPluginConfigMsg.tileSource`),
60
+ * and a replaced template must be registered first so the map
61
+ * chart's rebind sees the new content-derived cache id.
62
+ */
63
+ setPluginConfig(cfg: PluginConfig, tileSource?: TileSourceSpec): void;
45
64
  /**
46
65
  * Full data-fetch + render pipeline. Owns every `Client`/`Table`/
47
66
  * `View` await on the render path:
@@ -97,13 +116,39 @@ export declare class WorkerRenderer {
97
116
  * facet grid and controllers, so the resolution runs here.
98
117
  */
99
118
  private _resolveTarget;
119
+ /**
120
+ * Legend-first interaction routing. The chart's `LegendController`
121
+ * sees every forwarded event BEFORE the zoom / tooltip paths, so
122
+ * legend gestures (scroll, width drag, floating move / resize)
123
+ * structurally preempt plot pan / zoom / hover — a wheel over the
124
+ * legend can never zoom the plot under it, and a floating-panel
125
+ * drag can never start a pan.
126
+ */
127
+ private _legendInteraction;
100
128
  onInteraction(event: InteractionEvent): void;
129
+ private _routeInteraction;
101
130
  /**
102
131
  * Read the chart impl's `TooltipController`. Charts that don't use
103
132
  * one (no `attachTooltip` override) yield `null` and the
104
133
  * mouse-event branches fall through.
105
134
  */
106
135
  private _tooltip;
136
+ /**
137
+ * Blit-mode frame composite: draw the gridlines (bottom), the GL
138
+ * plot bitmap (middle) and the chrome/axes (top) into the compose
139
+ * surface and transfer the result — the single `ImageBitmap` the
140
+ * host blits, and the unit the staged-present hold stages. Runs in
141
+ * `endFrame`, which the scheduler orders after `render2D`'s 2D
142
+ * flush, so both layers hold this frame's content.
143
+ *
144
+ * A layer whose buffer differs from the plot's dimensions is
145
+ * skipped rather than scaled: its content is a stale-sized frame
146
+ * mid-resize (the 2D draws re-size their canvas to `css × dpr` on
147
+ * the next flush), and scaling it would re-introduce exactly the
148
+ * warp this composite exists to prevent.
149
+ */
150
+ private _composeFrame;
151
+ private _presentOverlay;
107
152
  /**
108
153
  * Composite the three layers into a single PNG `Blob`.
109
154
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perspective-dev/viewer-charts",
3
- "version": "5.2.0",
3
+ "version": "5.3.1",
4
4
  "description": "Perspective.js WebGL Plugin",
5
5
  "unpkg": "./dist/cdn/perspective-viewer-charts.js",
6
6
  "jsdelivr": "./dist/cdn/perspective-viewer-charts.js",
@@ -89,7 +89,6 @@
89
89
  border-radius: 3px;
90
90
  padding: 3px;
91
91
  overflow-y: auto;
92
- white-space: pre;
93
92
  z-index: 10;
94
93
  line-height: 16px;
95
94
  }
@@ -12,7 +12,7 @@
12
12
 
13
13
  import type { Canvas2D, Context2D } from "../charts/canvas-types";
14
14
  import { PlotLayout } from "../layout/plot-layout";
15
- import { formatTickValue, formatDateTickValue } from "../layout/ticks";
15
+ import { stepTickFormatter } from "../layout/ticks";
16
16
  import { initCanvas } from "./canvas";
17
17
  import {
18
18
  renderCategoricalXTicks,
@@ -37,12 +37,7 @@ function tickFormatter(
37
37
  return override;
38
38
  }
39
39
 
40
- if (!domain.isDate) {
41
- return formatTickValue;
42
- }
43
-
44
- const step = ticks.length > 1 ? ticks[1] - ticks[0] : 0;
45
- return (v: number) => formatDateTickValue(v, step);
40
+ return stepTickFormatter(domain.isDate, ticks);
46
41
  }
47
42
 
48
43
  /**