@perspective-dev/viewer-charts 5.3.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) 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/cartesian/cartesian.d.ts +6 -0
  7. package/dist/esm/charts/cartesian/glyph.d.ts +2 -1
  8. package/dist/esm/charts/cartesian/glyphs/density.d.ts +2 -1
  9. package/dist/esm/charts/cartesian/glyphs/lines.d.ts +2 -1
  10. package/dist/esm/charts/cartesian/glyphs/points.d.ts +2 -1
  11. package/dist/esm/charts/cartesian/tooltip-lines.d.ts +1 -1
  12. package/dist/esm/charts/chart-base.d.ts +2 -0
  13. package/dist/esm/charts/chart.d.ts +77 -6
  14. package/dist/esm/charts/common/draw-tooltip-box.d.ts +2 -1
  15. package/dist/esm/charts/common/tree-interact.d.ts +1 -1
  16. package/dist/esm/charts/series/series-build.d.ts +7 -0
  17. package/dist/esm/charts/series/series-interact.d.ts +1 -1
  18. package/dist/esm/charts/series/series.d.ts +6 -0
  19. package/dist/esm/index.d.ts +2 -0
  20. package/dist/esm/interaction/axis-indicators.d.ts +11 -0
  21. package/dist/esm/interaction/host-sink-dom.d.ts +3 -2
  22. package/dist/esm/interaction/host-sink-message.d.ts +3 -2
  23. package/dist/esm/interaction/lazy-tooltip.d.ts +2 -2
  24. package/dist/esm/interaction/legend-controller.d.ts +246 -0
  25. package/dist/esm/interaction/tooltip-controller.d.ts +20 -95
  26. package/dist/esm/interaction/tooltip-grid.d.ts +33 -0
  27. package/dist/esm/layout/facet-grid.d.ts +6 -0
  28. package/dist/esm/layout/ticks.d.ts +1 -0
  29. package/dist/esm/map/tile-source.d.ts +77 -8
  30. package/dist/esm/perspective-viewer-charts.js +1 -2
  31. package/dist/esm/perspective-viewer-charts.js.map +4 -4
  32. package/dist/esm/plugin/charts.d.ts +2 -0
  33. package/dist/esm/plugin/format-defaults.d.ts +9 -0
  34. package/dist/esm/plugin/plugin.d.ts +20 -0
  35. package/dist/esm/theme/gradient.d.ts +1 -0
  36. package/dist/esm/transport/protocol.d.ts +45 -3
  37. package/dist/esm/transport/renderer-transport.d.ts +3 -0
  38. package/dist/esm/worker/renderer.worker.d.ts +19 -1
  39. package/package.json +6 -6
  40. package/src/css/perspective-viewer-charts.css +0 -1
  41. package/src/ts/axis/bar-axis.ts +2 -7
  42. package/src/ts/axis/legend.ts +351 -24
  43. package/src/ts/axis/map-ticks.ts +94 -0
  44. package/src/ts/axis/numeric-axis.ts +2 -9
  45. package/src/ts/charts/candlestick/candlestick-interact.ts +46 -40
  46. package/src/ts/charts/candlestick/candlestick-render.ts +73 -10
  47. package/src/ts/charts/cartesian/cartesian-interact.ts +9 -3
  48. package/src/ts/charts/cartesian/cartesian-render.ts +369 -75
  49. package/src/ts/charts/cartesian/cartesian.ts +9 -0
  50. package/src/ts/charts/cartesian/glyph.ts +6 -2
  51. package/src/ts/charts/cartesian/glyphs/density.ts +2 -2
  52. package/src/ts/charts/cartesian/glyphs/lines.ts +15 -11
  53. package/src/ts/charts/cartesian/glyphs/points.ts +9 -5
  54. package/src/ts/charts/cartesian/tooltip-lines.ts +8 -8
  55. package/src/ts/charts/chart-base.ts +34 -32
  56. package/src/ts/charts/chart.ts +106 -7
  57. package/src/ts/charts/common/draw-tooltip-box.ts +13 -30
  58. package/src/ts/charts/common/tree-chrome.ts +102 -23
  59. package/src/ts/charts/common/tree-interact.ts +18 -17
  60. package/src/ts/charts/heatmap/heatmap-interact.ts +65 -7
  61. package/src/ts/charts/heatmap/heatmap-render.ts +100 -24
  62. package/src/ts/charts/map/map.ts +3 -5
  63. package/src/ts/charts/series/series-build.ts +14 -2
  64. package/src/ts/charts/series/series-interact.ts +12 -11
  65. package/src/ts/charts/series/series-render.ts +305 -132
  66. package/src/ts/charts/series/series.ts +10 -0
  67. package/src/ts/charts/sunburst/sunburst-render.ts +7 -1
  68. package/src/ts/charts/treemap/treemap-render.ts +7 -1
  69. package/src/ts/data/view-reader.ts +1 -4
  70. package/src/ts/index.ts +2 -0
  71. package/src/ts/interaction/axis-indicators.ts +137 -0
  72. package/src/ts/interaction/host-sink-dom.ts +66 -2
  73. package/src/ts/interaction/host-sink-message.ts +8 -2
  74. package/src/ts/interaction/lazy-tooltip.ts +5 -5
  75. package/src/ts/interaction/legend-controller.ts +1084 -0
  76. package/src/ts/interaction/tooltip-controller.ts +43 -131
  77. package/src/ts/interaction/tooltip-grid.ts +187 -0
  78. package/src/ts/layout/facet-grid.ts +8 -1
  79. package/src/ts/layout/ticks.ts +12 -0
  80. package/src/ts/map/tile-loader.ts +16 -1
  81. package/src/ts/map/tile-source.ts +199 -53
  82. package/src/ts/map/tile-sources.json +18 -0
  83. package/src/ts/plugin/charts.ts +40 -6
  84. package/src/ts/plugin/format-defaults.ts +37 -0
  85. package/src/ts/plugin/plugin.ts +236 -67
  86. package/src/ts/shaders/line.vert.glsl +5 -2
  87. package/src/ts/shaders/scatter.vert.glsl +0 -7
  88. package/src/ts/theme/gradient.ts +24 -0
  89. package/src/ts/transport/protocol.ts +46 -2
  90. package/src/ts/transport/renderer-transport.ts +83 -4
  91. package/src/ts/worker/dispatch.ts +6 -2
  92. package/src/ts/worker/renderer.worker.ts +78 -2
@@ -1,7 +1,55 @@
1
- import type { Canvas2D } from "../charts/canvas-types";
1
+ import type { Canvas2D, Context2D } from "../charts/canvas-types";
2
2
  import type { PlotLayout, PlotRect } from "../layout/plot-layout";
3
+ import { LEGEND_LINE_HEIGHT, type LegendAutoFit, type LegendController } from "../interaction/legend-controller";
3
4
  import { type GradientStop } from "../theme/gradient";
4
5
  import type { Theme } from "../theme/theme";
6
+ export { LEGEND_LINE_HEIGHT };
7
+ /**
8
+ * Presentation context threaded into every legend painter. Carries the
9
+ * resolved `legend_mode` branch and the chart's {@link LegendController}
10
+ * — the painter reads its scroll offset and reports the painted
11
+ * geometry back so hit-testing always resolves against what is on
12
+ * screen. `"none"` mode never reaches a painter (call sites skip and
13
+ * `clearPainted()` instead).
14
+ */
15
+ export interface LegendPaintView {
16
+ mode: "sidebar" | "floating";
17
+ legend: LegendController;
18
+ title?: string;
19
+ sidebarGutter?: number;
20
+ /**
21
+ * Floating background-fill opacity (`plugin_config.legend_opacity`,
22
+ * default 1). Border, header text, and entries stay opaque.
23
+ */
24
+ opacity?: number;
25
+ }
26
+ export declare function legendAutoFit(canvas: Canvas2D | null | undefined, theme: Theme, entryCount: number, labels: () => Iterable<string>, opts?: {
27
+ title?: string;
28
+ leading?: number;
29
+ fontPx?: number;
30
+ }): LegendAutoFit;
31
+ export declare function gradientLegendAutoFit(canvas: Canvas2D | null | undefined, theme: Theme, colorDomain: {
32
+ min: number;
33
+ max: number;
34
+ }, formatter?: (v: number) => string, title?: string): LegendAutoFit;
35
+ /**
36
+ * Paint the floating panel's chrome — themed background, border, and
37
+ * header strip — and return the content rect inside it. The header
38
+ * carries `title` and doubles as the move grip. `opacity` applies to
39
+ * the background fill only.
40
+ */
41
+ export declare function paintFloatingLegendFrame(ctx: Context2D, box: PlotRect, theme: Theme, title: string | undefined, opacity?: number): PlotRect;
42
+ /**
43
+ * Paint the scroll thumb on the content rect's right edge. No-op when
44
+ * the content fits.
45
+ */
46
+ export declare function paintLegendScrollbar(ctx: Context2D, content: PlotRect, scroll: number, contentHeight: number, theme: Theme): void;
47
+ /**
48
+ * Clip `text` to `maxWidth` with a trailing ellipsis. Only called for
49
+ * entries inside the visible window, so the `measureText` cost is
50
+ * bounded by the box height, not the entry count.
51
+ */
52
+ export declare function truncateText(ctx: Context2D, text: string, maxWidth: number): string;
5
53
  /**
6
54
  * Render a vertical color gradient legend on the Canvas2D overlay.
7
55
  * Only call when a color column is active. When `colorDomain` crosses
@@ -15,7 +63,7 @@ export declare function renderLegend(canvas: Canvas2D, layout: PlotLayout, color
15
63
  min: number;
16
64
  max: number;
17
65
  label: string;
18
- }, stops: GradientStop[], theme: Theme, formatter?: (v: number) => string): void;
66
+ }, stops: GradientStop[], theme: Theme, formatter?: (v: number) => string, view?: LegendPaintView): void;
19
67
  /**
20
68
  * Render a gradient legend at an explicit canvas-absolute rect.
21
69
  * Used by facet grids that paint one legend for the whole grid and
@@ -25,7 +73,7 @@ export declare function renderLegendAt(canvas: Canvas2D, rect: PlotRect, colorDo
25
73
  min: number;
26
74
  max: number;
27
75
  label: string;
28
- }, stops: GradientStop[], theme: Theme, formatter?: (v: number) => string): void;
76
+ }, stops: GradientStop[], theme: Theme, formatter?: (v: number) => string, view?: LegendPaintView): void;
29
77
  /**
30
78
  * Render a categorical legend with discrete colored swatches.
31
79
  * Used when split_by or string color columns produce distinct categories.
@@ -35,10 +83,10 @@ export declare function renderLegendAt(canvas: Canvas2D, rect: PlotRect, colorDo
35
83
  * shared legend pass an explicit rect to `renderCategoricalLegendAt`
36
84
  * directly.
37
85
  */
38
- export declare function renderCategoricalLegend(canvas: Canvas2D, layout: PlotLayout, labels: Map<string, number>, palette: [number, number, number][], theme: Theme): void;
86
+ export declare function renderCategoricalLegend(canvas: Canvas2D, layout: PlotLayout, labels: Map<string, number>, palette: [number, number, number][], theme: Theme, view?: LegendPaintView): void;
39
87
  /**
40
88
  * Render a categorical legend at an explicit canvas-absolute rect.
41
89
  * Used by facet grids that paint one legend for the whole grid and by
42
90
  * single-plot charts through {@link renderCategoricalLegend}.
43
91
  */
44
- export declare function renderCategoricalLegendAt(canvas: Canvas2D, rect: PlotRect, labels: Map<string, number>, palette: [number, number, number][], theme: Theme): void;
92
+ export declare function renderCategoricalLegendAt(canvas: Canvas2D, rect: PlotRect, labels: Map<string, number>, palette: [number, number, number][], theme: Theme, view?: LegendPaintView): void;
@@ -0,0 +1,15 @@
1
+ import type { PlotLayout } from "../layout/plot-layout";
2
+ export interface MapDegreeTicks {
3
+ xTicks: number[];
4
+ yTicks: number[];
5
+ formatX: (meters: number) => string;
6
+ formatY: (meters: number) => string;
7
+ }
8
+ /**
9
+ * Compute "nice" longitude/latitude ticks for the visible window of a
10
+ * map layout. Must be called AFTER `buildProjectionMatrix` has seeded
11
+ * the layout's padded-domain fields — the ticks are derived from the
12
+ * exact meter domain the projection maps, or labels would misalign
13
+ * with glyphs.
14
+ */
15
+ export declare function computeMapDegreeTicks(layout: PlotLayout): MapDegreeTicks;
@@ -2,9 +2,5 @@ import type { CandlestickChart } from "./candlestick";
2
2
  export declare function handleCandlestickHover(chart: CandlestickChart, mx: number, my: number): void;
3
3
  export declare function showCandlestickPinnedTooltip(chart: CandlestickChart, idx: number): void;
4
4
  export declare function dismissCandlestickPinnedTooltip(chart: CandlestickChart): void;
5
- /**
6
- * Build tooltip lines for candle at index `idx` in the columnar
7
- * storage. Indexed access avoids materializing a `CandleRecord` POJO
8
- * on the hot tooltip path.
9
- */
10
- export declare function buildCandlestickTooltipLines(chart: CandlestickChart, idx: number): string[];
5
+ export declare function buildCandlestickTooltipLines(chart: CandlestickChart, idx: number): string[][];
6
+ export declare function candleCategoryText(chart: CandlestickChart, catIdx: number): string;
@@ -30,6 +30,12 @@ export declare class CartesianChart extends AbstractChart {
30
30
  readonly glyph: Glyph;
31
31
  constructor(glyph: Glyph);
32
32
  protected colorScaleColumn(): string | null;
33
+ /**
34
+ * Chrome-only repaint for legend scroll / floating-legend drag —
35
+ * the same lightweight path hover updates use. No GL pass; the
36
+ * composite re-presents over the retained plot bitmap.
37
+ */
38
+ repaintChrome(): void;
33
39
  /**
34
40
  * Rendering pipeline selector. `"cartesian"` is the default —
35
41
  * draws axes, gridlines, and ticks via the chrome canvas.
@@ -38,13 +38,14 @@ export interface Glyph {
38
38
  * Glyphs whose tooltip is geometry-only (e.g. `LineGlyph`) return
39
39
  * a microtask-resolved promise.
40
40
  */
41
- buildTooltipLines(chart: CartesianChart, flatIdx: number): Promise<string[]>;
41
+ buildTooltipLines(chart: CartesianChart, flatIdx: number): Promise<string[][]>;
42
42
  /**
43
43
  * Hover-overlay options (crosshair, highlight radius).
44
44
  */
45
45
  tooltipOptions(): {
46
46
  crosshair: boolean;
47
47
  highlightRadius: number;
48
+ axisIndicators: boolean;
48
49
  };
49
50
  /**
50
51
  * Release GL resources created by `ensureProgram`.
@@ -26,10 +26,11 @@ export declare class DensityGlyph implements Glyph {
26
26
  ensureProgram(chart: CartesianChart, glManager: WebGLContextManager): void;
27
27
  draw(chart: CartesianChart, glManager: WebGLContextManager, projection: Float32Array): void;
28
28
  drawSeries(chart: CartesianChart, glManager: WebGLContextManager, projection: Float32Array, seriesIdx: number): void;
29
- buildTooltipLines(chart: CartesianChart, flatIdx: number): Promise<string[]>;
29
+ buildTooltipLines(chart: CartesianChart, flatIdx: number): Promise<string[][]>;
30
30
  tooltipOptions(): {
31
31
  crosshair: boolean;
32
32
  highlightRadius: number;
33
+ axisIndicators: boolean;
33
34
  };
34
35
  destroy(chart: CartesianChart): void;
35
36
  /**
@@ -14,10 +14,11 @@ export declare class LineGlyph implements Glyph {
14
14
  ensureProgram(_chart: CartesianChart, glManager: WebGLContextManager): void;
15
15
  draw(chart: CartesianChart, glManager: WebGLContextManager, projection: Float32Array): void;
16
16
  drawSeries(chart: CartesianChart, glManager: WebGLContextManager, projection: Float32Array, seriesIdx: number): void;
17
- buildTooltipLines(chart: CartesianChart, flatIdx: number): Promise<string[]>;
17
+ buildTooltipLines(chart: CartesianChart, flatIdx: number): Promise<string[][]>;
18
18
  tooltipOptions(): {
19
19
  crosshair: boolean;
20
20
  highlightRadius: number;
21
+ axisIndicators: boolean;
21
22
  };
22
23
  destroy(chart: CartesianChart): void;
23
24
  }
@@ -15,10 +15,11 @@ export declare class PointGlyph implements Glyph {
15
15
  ensureProgram(_chart: CartesianChart, glManager: WebGLContextManager): void;
16
16
  draw(chart: CartesianChart, glManager: WebGLContextManager, projection: Float32Array): void;
17
17
  drawSeries(chart: CartesianChart, glManager: WebGLContextManager, projection: Float32Array, seriesIdx: number): void;
18
- buildTooltipLines(chart: CartesianChart, flatIdx: number): Promise<string[]>;
18
+ buildTooltipLines(chart: CartesianChart, flatIdx: number): Promise<string[][]>;
19
19
  tooltipOptions(): {
20
20
  crosshair: boolean;
21
21
  highlightRadius: number;
22
+ axisIndicators: boolean;
22
23
  };
23
24
  destroy(_chart: CartesianChart): void;
24
25
  }
@@ -8,4 +8,4 @@ import type { CartesianChart } from "./cartesian";
8
8
  * Returns `[]` when the chart has no row-index mirror or no fetcher;
9
9
  * callers should fall back to a geometry-only tooltip in that case.
10
10
  */
11
- export declare function buildPointRowTooltipLines(chart: CartesianChart, flatIdx: number): Promise<string[]>;
11
+ export declare function buildPointRowTooltipLines(chart: CartesianChart, flatIdx: number): Promise<string[][]>;
@@ -5,6 +5,7 @@ import type { WebGLContextManager } from "../webgl/context-manager";
5
5
  import { ZoomController, type ZoomConfig } from "../interaction/zoom-controller";
6
6
  import { type ChartImplementation, type FacetConfig, type PluginConfig } from "./chart";
7
7
  import { TooltipController, type HostSink, type TooltipCallbacks } from "../interaction/tooltip-controller";
8
+ import { LegendController } from "../interaction/legend-controller";
8
9
  import type { PerspectiveClickDetail } from "../event-detail";
9
10
  import type { ViewConfig } from "@perspective-dev/client";
10
11
  import { type Theme } from "../theme/theme";
@@ -144,6 +145,7 @@ export declare abstract class AbstractChart implements ChartImplementation {
144
145
  * the pre-refactor output.
145
146
  */
146
147
  _pluginConfig: PluginConfig;
148
+ _legend: LegendController;
147
149
  _tooltip: TooltipController;
148
150
  /**
149
151
  * Reference to the active host sink, captured in {@link attachTooltip}.
@@ -158,6 +158,7 @@ export interface ChartImplementation {
158
158
  * host's filter set.
159
159
  */
160
160
  deselect?(): void;
161
+ repaintChrome?(): void;
161
162
  destroy(): void;
162
163
  }
163
164
  export interface FacetConfig {
@@ -360,13 +361,15 @@ export interface PluginConfig {
360
361
  */
361
362
  gradient_color_mode: "mean" | "density" | "extreme" | "signed";
362
363
  /**
363
- * Map basemap tile provider. Applies only to map plugin tags
364
- * (`map-scatter`, `map-line`, `map-density`). Cartesian charts
365
- * ignore the field. Surfaced as an enum on the settings panel so
366
- * users can switch light/dark/voyager without writing custom
367
- * tile-source code.
364
+ * Map basemap tile provider — a `TileSourceSpec` id from the
365
+ * tile-source registry ([map/tile-sources.json] entries plus any
366
+ * runtime `registerTileSource` additions). Applies only to map
367
+ * plugin tags (`map-scatter`, `map-line`, `map-density`); other
368
+ * charts ignore the field. The default is the JSON's FIRST entry
369
+ * (reordering the file changes the default), and unknown ids fall
370
+ * back to that same entry rather than blanking the map.
368
371
  */
369
- map_tile_provider: "carto-positron" | "carto-dark-matter" | "carto-voyager";
372
+ map_tile_provider: string;
370
373
  /**
371
374
  * Map basemap alpha (0..1). Pre-multiplied into the tile fragment
372
375
  * shader's output so the chart's glyph layer composites over a
@@ -374,5 +377,73 @@ export interface PluginConfig {
374
377
  * shows the tiles at full opacity.
375
378
  */
376
379
  map_tile_alpha: number;
380
+ /**
381
+ * Map plugins only. `true` (default): standard numeric axes in the
382
+ * usual cartesian gutters, with tick labels in degrees
383
+ * longitude/latitude (`122.4°W`) rather than Mercator meters.
384
+ * `false`: no axes, and the plot is full-bleed — the basemap fills
385
+ * the entire canvas, minus only the sidebar legend gutter when a
386
+ * legend is actually shown. Gridlines are never drawn in map mode
387
+ * — the gridline canvas composites BELOW the GL layer, so opaque
388
+ * basemap tiles would hide them.
389
+ */
390
+ numeric_axes: boolean;
391
+ /**
392
+ * Legend presentation mode. `"auto"` (default) resolves per frame
393
+ * to `"floating"` when every entry fits the default floating panel
394
+ * without scrolling (≤ 7 entries; continuous gradient legends
395
+ * always qualify) and to `"sidebar"` otherwise — see
396
+ * `resolveLegendMode`. Treemap overrides the default to
397
+ * `"sidebar"` (a floating panel over edge-to-edge tiles always
398
+ * occludes data).
399
+ */
400
+ legend_mode: "auto" | "sidebar" | "none" | "floating";
401
+ /**
402
+ * Floating-panel sizing regime. `"auto"` (default) sizes the panel
403
+ * to its CONTENT every frame — the height hugs the entry rows
404
+ * exactly, and the width hugs the widest entry label (measured on
405
+ * the chrome canvas). `"fixed"` uses the saved `legend_width_px` /
406
+ * `legend_height_px` verbatim.
407
+ *
408
+ * Applies to `legend_mode: "floating"` ONLY; the sidebar gutter is
409
+ * always `legend_width_px` (its height is the plot's). Dragging a
410
+ * resize handle switches an auto panel to `"fixed"` — otherwise
411
+ * the gesture would be undone by the next paint — and
412
+ * double-clicking a resize handle switches it back.
413
+ */
414
+ legend_size_mode: LegendSizeMode;
415
+ /**
416
+ * Legend width in CSS pixels. `0` (default) = automatic — each
417
+ * chart family keeps its historical gutter width (80–96px). In
418
+ * `"sidebar"` mode this is the full right-gutter width; in
419
+ * `"floating"` mode it is the panel width. Clamped at paint time
420
+ * to at most half the canvas width so a saved wide legend cannot
421
+ * crush a small panel. Ignored by a floating panel in
422
+ * `legend_size_mode: "auto"`.
423
+ */
424
+ legend_width_px: number;
425
+ /**
426
+ * Floating-legend panel height in CSS pixels. Ignored in
427
+ * `"sidebar"` mode (the legend spans the plot height) and by a
428
+ * floating panel in `legend_size_mode: "auto"`. Clamped at paint
429
+ * time to the canvas height.
430
+ */
431
+ legend_height_px: number;
432
+ /**
433
+ * Canvas corner that `legend_x` / `legend_y` are measured FROM.
434
+ * Floating mode only. The panel keeps its distance to this corner
435
+ * across panel resizes — anchor `"bottom-right"` with small
436
+ * offsets stays glued to the bottom-right.
437
+ */
438
+ legend_anchor: LegendAnchor;
439
+ legend_x: number;
440
+ legend_y: number;
441
+ legend_opacity: number;
442
+ /** Per-column width cap for tooltip grid cells, in CSS pixels. */
443
+ tooltip_max_column_px: number;
444
+ /** Tooltip background/border alpha (0..1). */
445
+ tooltip_opacity: number;
377
446
  }
447
+ export type LegendAnchor = "top-left" | "top-right" | "bottom-left" | "bottom-right";
448
+ export type LegendSizeMode = "auto" | "fixed";
378
449
  export declare const DEFAULT_PLUGIN_CONFIG: PluginConfig;
@@ -1,9 +1,10 @@
1
1
  import type { Context2D } from "../canvas-types";
2
2
  import type { Theme } from "../../theme/theme";
3
+ import { type TooltipContent, type TooltipStyle } from "../../interaction/tooltip-grid";
3
4
  /**
4
5
  * Draw a freestanding tooltip box anchored near (cx, cy), measuring
5
6
  * lines, sizing/clamping the box, painting bg/border, and laying out
6
7
  * text rows. Shared by sunburst + treemap which need a non-PlotLayout
7
8
  * anchor.
8
9
  */
9
- export declare function drawTooltipBox(ctx: Context2D, theme: Theme, lines: string[], cx: number, cy: number, cssWidth: number, cssHeight: number, fontFamily: string): void;
10
+ export declare function drawTooltipBox(ctx: Context2D, theme: Theme, grid: TooltipContent, cx: number, cy: number, cssWidth: number, cssHeight: number, fontFamily: string, style?: TooltipStyle): void;
@@ -26,7 +26,7 @@ export declare function emitTreeNodeEvent(chart: TreeInteractChart, nodeId: numb
26
26
  * fetch; branch nodes have no underlying row so they emit a Children
27
27
  * count instead.
28
28
  */
29
- export declare function buildTreeTooltipLines(chart: TreeInteractChart, nodeId: number): Promise<string[]>;
29
+ export declare function buildTreeTooltipLines(chart: TreeInteractChart, nodeId: number): Promise<string[][]>;
30
30
  /**
31
31
  * Pin a tooltip at the chart-supplied anchor. Lines are fetched lazily;
32
32
  * the `_pinnedNodeId` check on resolve discards stale results from a
@@ -213,6 +213,13 @@ export interface SeriesPipelineResult {
213
213
  * is the position. Indexed by `catIdx` (0..numCategories-1).
214
214
  */
215
215
  categoryPositions: Float64Array | null;
216
+ /**
217
+ * One entry per (aggregate × split), in `k * P + p` order. INVARIANT:
218
+ * `series.length === aggregates.length * splitPrefixes.length` —
219
+ * consumers index `series[k * P]` directly (glyph runs, the
220
+ * `domain_mode: "expand"` axis signature), so an empty `series` MUST
221
+ * be paired with empty `aggregates` / `splitPrefixes`.
222
+ */
216
223
  series: SeriesInfo[];
217
224
  /**
218
225
  * Columnar bar/area records, one per (catIdx, agg, split) for series
@@ -32,7 +32,7 @@ export declare function handleBarLegendClick(chart: SeriesChart, mx: number, my:
32
32
  /**
33
33
  * Build the per-bar tooltip content lines.
34
34
  */
35
- export declare function buildBarTooltipLines(chart: SeriesChart, b: SeriesChartRecord): string[];
35
+ export declare function buildBarTooltipLines(chart: SeriesChart, b: SeriesChartRecord): string[][];
36
36
  /**
37
37
  * Format the hierarchical path label for a given category index. Used by
38
38
  * the tooltip — the axis uses per-level text directly instead.
@@ -74,6 +74,12 @@ export declare class SeriesChart extends CategoricalYChart {
74
74
  * always present. The value axis stays freely zoomable.
75
75
  */
76
76
  protected getZoomConfig(): ZoomConfig;
77
+ /**
78
+ * Chrome-only repaint for legend scroll / floating-legend drag —
79
+ * the same lightweight path hover updates use. No GL pass; the
80
+ * composite re-presents over the retained plot bitmap.
81
+ */
82
+ repaintChrome(): void;
77
83
  _locations: CachedLocations | null;
78
84
  _aggregates: string[];
79
85
  _splitPrefixes: string[];
@@ -1,3 +1,5 @@
1
1
  export type { PerspectiveClickDetail } from "./event-detail";
2
2
  export { PerspectiveSelectDetail } from "./event-detail";
3
+ export { registerTileSource } from "./plugin/plugin";
4
+ export { tileSources, type TileSourceSpec } from "./map/tile-source";
3
5
  export declare function register(...plugin_names: string[]): void;
@@ -0,0 +1,11 @@
1
+ import type { Canvas2D } from "../charts/canvas-types";
2
+ import type { PlotLayout } from "../layout/plot-layout";
3
+ import type { Theme } from "../theme/theme";
4
+ export type AxisSide = "bottom" | "left" | "right";
5
+ export interface AxisIndicator {
6
+ side: AxisSide;
7
+ px: number;
8
+ py: number;
9
+ text: string;
10
+ }
11
+ export declare function renderAxisHoverIndicators(canvas: Canvas2D | null, layout: PlotLayout, theme: Theme, dpr: number, indicators: AxisIndicator[], opacity?: number): void;
@@ -1,4 +1,5 @@
1
1
  import type { CssBounds, HostSink } from "./tooltip-controller";
2
+ import { type TooltipContent, type TooltipStyle } from "./tooltip-grid";
2
3
  /**
3
4
  * Host-side `HostSink` that materializes pinned tooltips as a `<div>`
4
5
  * next to the GL canvas, and applies cursor changes to the canvas's
@@ -10,10 +11,10 @@ export declare class DomHostSink implements HostSink {
10
11
  private _parent;
11
12
  private _div;
12
13
  constructor(glCanvas: HTMLCanvasElement, parent: HTMLElement);
13
- pin(lines: string[], pos: {
14
+ pin(grid: TooltipContent, pos: {
14
15
  px: number;
15
16
  py: number;
16
- }, bounds: CssBounds): void;
17
+ }, bounds: CssBounds, style?: TooltipStyle): void;
17
18
  dismiss(): void;
18
19
  setCursor(cursor: string): void;
19
20
  }
@@ -1,5 +1,6 @@
1
1
  import type { DismissTooltipMsg, PinTooltipMsg, SetCursorMsg, UserClickMsg, UserSelectMsg } from "../transport/protocol";
2
2
  import type { CssBounds, HostSink, UserClickPayload, UserSelectPayload } from "./tooltip-controller";
3
+ import { type TooltipContent, type TooltipStyle } from "./tooltip-grid";
3
4
  /**
4
5
  * The subset of `WorkerMsg`s that flow chart → host through a
5
6
  * `MessageHostSink`. Identical to the worker-side post payloads so the
@@ -17,10 +18,10 @@ export type HostSinkEnvelope = PinTooltipMsg | DismissTooltipMsg | SetCursorMsg
17
18
  export declare class MessageHostSink implements HostSink {
18
19
  private _send;
19
20
  constructor(send: (msg: HostSinkEnvelope) => void);
20
- pin(lines: string[], pos: {
21
+ pin(grid: TooltipContent, pos: {
21
22
  px: number;
22
23
  py: number;
23
- }, bounds: CssBounds): void;
24
+ }, bounds: CssBounds, style?: TooltipStyle): void;
24
25
  dismiss(): void;
25
26
  setCursor(cursor: string): void;
26
27
  emitUserClick(payload: UserClickPayload): void;
@@ -20,7 +20,7 @@ export declare class LazyTooltip<Target> {
20
20
  /**
21
21
  * Cached lines for the latest committed hover, or `null`.
22
22
  */
23
- lines: string[] | null;
23
+ grid: string[][] | null;
24
24
  /**
25
25
  * Identity of the entity `lines` describe. `null` when cleared.
26
26
  */
@@ -40,7 +40,7 @@ export declare class LazyTooltip<Target> {
40
40
  * when the write happened (caller should repaint), false when the
41
41
  * serial was stale.
42
42
  */
43
- commitHover(serial: number, lines: string[]): boolean;
43
+ commitHover(serial: number, grid: string[][]): boolean;
44
44
  /**
45
45
  * Clear hover state (mouse left, view changed, etc.).
46
46
  */