@perspective-dev/viewer-charts 4.3.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 (258) hide show
  1. package/LICENSE.md +193 -0
  2. package/dist/cdn/perspective-viewer-charts.js +3 -0
  3. package/dist/cdn/perspective-viewer-charts.js.map +7 -0
  4. package/dist/esm/axis/axis-primitives.d.ts +24 -0
  5. package/dist/esm/axis/bar-axis.d.ts +51 -0
  6. package/dist/esm/axis/canvas.d.ts +24 -0
  7. package/dist/esm/axis/categorical-axis-core.d.ts +42 -0
  8. package/dist/esm/axis/categorical-axis.d.ts +27 -0
  9. package/dist/esm/axis/facet-chrome.d.ts +13 -0
  10. package/dist/esm/axis/label-geometry.d.ts +41 -0
  11. package/dist/esm/axis/legend.d.ts +44 -0
  12. package/dist/esm/axis/numeric-axis.d.ts +20 -0
  13. package/dist/esm/charts/candlestick/candlestick-build.d.ts +129 -0
  14. package/dist/esm/charts/candlestick/candlestick-interact.d.ts +10 -0
  15. package/dist/esm/charts/candlestick/candlestick-render.d.ts +24 -0
  16. package/dist/esm/charts/candlestick/candlestick.d.ts +144 -0
  17. package/dist/esm/charts/candlestick/glyphs/draw-candlesticks.d.ts +36 -0
  18. package/dist/esm/charts/candlestick/glyphs/draw-ohlc.d.ts +33 -0
  19. package/dist/esm/charts/canvas-types.d.ts +15 -0
  20. package/dist/esm/charts/cartesian/cartesian-build.d.ts +14 -0
  21. package/dist/esm/charts/cartesian/cartesian-interact.d.ts +20 -0
  22. package/dist/esm/charts/cartesian/cartesian-render.d.ts +26 -0
  23. package/dist/esm/charts/cartesian/cartesian.d.ts +239 -0
  24. package/dist/esm/charts/cartesian/glyph.d.ts +53 -0
  25. package/dist/esm/charts/cartesian/glyphs/density.d.ts +142 -0
  26. package/dist/esm/charts/cartesian/glyphs/lines.d.ts +23 -0
  27. package/dist/esm/charts/cartesian/glyphs/points.d.ts +24 -0
  28. package/dist/esm/charts/cartesian/label-interner.d.ts +21 -0
  29. package/dist/esm/charts/cartesian/tooltip-lines.d.ts +11 -0
  30. package/dist/esm/charts/chart-base.d.ts +402 -0
  31. package/dist/esm/charts/chart.d.ts +338 -0
  32. package/dist/esm/charts/common/band-layout.d.ts +32 -0
  33. package/dist/esm/charts/common/categorical-y-chart.d.ts +53 -0
  34. package/dist/esm/charts/common/category-axis-resolver.d.ts +90 -0
  35. package/dist/esm/charts/common/chrome-cache.d.ts +18 -0
  36. package/dist/esm/charts/common/draw-tooltip-box.d.ts +9 -0
  37. package/dist/esm/charts/common/leaf-color.d.ts +33 -0
  38. package/dist/esm/charts/common/node-store.d.ts +81 -0
  39. package/dist/esm/charts/common/tree-chart.d.ts +48 -0
  40. package/dist/esm/charts/common/tree-chrome.d.ts +31 -0
  41. package/dist/esm/charts/common/tree-data.d.ts +54 -0
  42. package/dist/esm/charts/common/visible-extent.d.ts +51 -0
  43. package/dist/esm/charts/heatmap/heatmap-build.d.ts +86 -0
  44. package/dist/esm/charts/heatmap/heatmap-interact.d.ts +19 -0
  45. package/dist/esm/charts/heatmap/heatmap-render.d.ts +19 -0
  46. package/dist/esm/charts/heatmap/heatmap-y-axis.d.ts +46 -0
  47. package/dist/esm/charts/heatmap/heatmap.d.ts +117 -0
  48. package/dist/esm/charts/map/map.d.ts +67 -0
  49. package/dist/esm/charts/registry.d.ts +14 -0
  50. package/dist/esm/charts/series/glyphs/draw-areas.d.ts +30 -0
  51. package/dist/esm/charts/series/glyphs/draw-bars.d.ts +15 -0
  52. package/dist/esm/charts/series/glyphs/draw-lines.d.ts +34 -0
  53. package/dist/esm/charts/series/glyphs/draw-scatter.d.ts +33 -0
  54. package/dist/esm/charts/series/series-build.d.ts +228 -0
  55. package/dist/esm/charts/series/series-interact.d.ts +35 -0
  56. package/dist/esm/charts/series/series-render.d.ts +41 -0
  57. package/dist/esm/charts/series/series-type.d.ts +49 -0
  58. package/dist/esm/charts/series/series.d.ts +317 -0
  59. package/dist/esm/charts/sunburst/sunburst-interact.d.ts +7 -0
  60. package/dist/esm/charts/sunburst/sunburst-layout.d.ts +33 -0
  61. package/dist/esm/charts/sunburst/sunburst-render.d.ts +22 -0
  62. package/dist/esm/charts/sunburst/sunburst.d.ts +85 -0
  63. package/dist/esm/charts/treemap/treemap-interact.d.ts +12 -0
  64. package/dist/esm/charts/treemap/treemap-layout.d.ts +28 -0
  65. package/dist/esm/charts/treemap/treemap-render.d.ts +18 -0
  66. package/dist/esm/charts/treemap/treemap.d.ts +74 -0
  67. package/dist/esm/config.d.ts +27 -0
  68. package/dist/esm/data/lazy-row.d.ts +32 -0
  69. package/dist/esm/data/split-groups.d.ts +20 -0
  70. package/dist/esm/data/view-reader.d.ts +35 -0
  71. package/dist/esm/event-detail.d.ts +28 -0
  72. package/dist/esm/index.d.ts +3 -0
  73. package/dist/esm/interaction/hit-test.d.ts +30 -0
  74. package/dist/esm/interaction/host-sink-dom.d.ts +19 -0
  75. package/dist/esm/interaction/host-sink-message.d.ts +46 -0
  76. package/dist/esm/interaction/lazy-tooltip.d.ts +61 -0
  77. package/dist/esm/interaction/raw-event-forwarder.d.ts +27 -0
  78. package/dist/esm/interaction/spatial-grid.d.ts +15 -0
  79. package/dist/esm/interaction/tooltip-controller.d.ts +193 -0
  80. package/dist/esm/interaction/zoom-controller.d.ts +106 -0
  81. package/dist/esm/interaction/zoom-router.d.ts +48 -0
  82. package/dist/esm/layout/facet-grid.d.ts +126 -0
  83. package/dist/esm/layout/plot-layout.d.ts +104 -0
  84. package/dist/esm/layout/ticks.d.ts +17 -0
  85. package/dist/esm/map/mercator.d.ts +102 -0
  86. package/dist/esm/map/tile-cache.d.ts +38 -0
  87. package/dist/esm/map/tile-layer.d.ts +66 -0
  88. package/dist/esm/map/tile-loader.d.ts +52 -0
  89. package/dist/esm/map/tile-source.d.ts +66 -0
  90. package/dist/esm/perspective-viewer-charts.js +3 -0
  91. package/dist/esm/perspective-viewer-charts.js.map +7 -0
  92. package/dist/esm/plugin/charts.d.ts +40 -0
  93. package/dist/esm/plugin/plugin.d.ts +95 -0
  94. package/dist/esm/render/scheduler.d.ts +41 -0
  95. package/dist/esm/theme/gradient.d.ts +48 -0
  96. package/dist/esm/theme/palette.d.ts +13 -0
  97. package/dist/esm/theme/theme-snapshot.d.ts +7 -0
  98. package/dist/esm/theme/theme.d.ts +53 -0
  99. package/dist/esm/transport/protocol.d.ts +430 -0
  100. package/dist/esm/transport/renderer-transport.d.ts +201 -0
  101. package/dist/esm/utils/css.d.ts +1 -0
  102. package/dist/esm/utils/font-snapshot.d.ts +50 -0
  103. package/dist/esm/webgl/buffer-pool.d.ts +62 -0
  104. package/dist/esm/webgl/context-manager.d.ts +184 -0
  105. package/dist/esm/webgl/gradient-texture.d.ts +17 -0
  106. package/dist/esm/webgl/instanced-attrs.d.ts +44 -0
  107. package/dist/esm/webgl/plot-frame.d.ts +39 -0
  108. package/dist/esm/webgl/program-cache.d.ts +13 -0
  109. package/dist/esm/webgl/shader-manifest.d.ts +53 -0
  110. package/dist/esm/webgl/shader-registry.d.ts +22 -0
  111. package/dist/esm/worker/boot.d.ts +0 -0
  112. package/dist/esm/worker/dispatch.d.ts +9 -0
  113. package/dist/esm/worker/font-loader.d.ts +2 -0
  114. package/dist/esm/worker/renderer.worker.d.ts +115 -0
  115. package/dist/esm/worker/session-host.d.ts +26 -0
  116. package/package.json +47 -0
  117. package/src/css/perspective-viewer-charts.css +95 -0
  118. package/src/ts/axis/axis-primitives.ts +125 -0
  119. package/src/ts/axis/bar-axis.ts +345 -0
  120. package/src/ts/axis/canvas.ts +64 -0
  121. package/src/ts/axis/categorical-axis-core.ts +125 -0
  122. package/src/ts/axis/categorical-axis.ts +716 -0
  123. package/src/ts/axis/facet-chrome.ts +42 -0
  124. package/src/ts/axis/label-geometry.ts +188 -0
  125. package/src/ts/axis/legend.ts +218 -0
  126. package/src/ts/axis/numeric-axis.ts +353 -0
  127. package/src/ts/charts/candlestick/candlestick-build.ts +516 -0
  128. package/src/ts/charts/candlestick/candlestick-interact.ts +256 -0
  129. package/src/ts/charts/candlestick/candlestick-render.ts +387 -0
  130. package/src/ts/charts/candlestick/candlestick.ts +367 -0
  131. package/src/ts/charts/candlestick/glyphs/draw-candlesticks.ts +432 -0
  132. package/src/ts/charts/candlestick/glyphs/draw-ohlc.ts +317 -0
  133. package/src/ts/charts/canvas-types.ts +30 -0
  134. package/src/ts/charts/cartesian/cartesian-build.ts +616 -0
  135. package/src/ts/charts/cartesian/cartesian-interact.ts +355 -0
  136. package/src/ts/charts/cartesian/cartesian-render.ts +948 -0
  137. package/src/ts/charts/cartesian/cartesian.ts +469 -0
  138. package/src/ts/charts/cartesian/glyph.ts +81 -0
  139. package/src/ts/charts/cartesian/glyphs/density.ts +1263 -0
  140. package/src/ts/charts/cartesian/glyphs/lines.ts +320 -0
  141. package/src/ts/charts/cartesian/glyphs/points.ts +239 -0
  142. package/src/ts/charts/cartesian/label-interner.ts +56 -0
  143. package/src/ts/charts/cartesian/tooltip-lines.ts +80 -0
  144. package/src/ts/charts/chart-base.ts +840 -0
  145. package/src/ts/charts/chart.ts +427 -0
  146. package/src/ts/charts/common/band-layout.ts +63 -0
  147. package/src/ts/charts/common/categorical-y-chart.ts +81 -0
  148. package/src/ts/charts/common/category-axis-resolver.ts +314 -0
  149. package/src/ts/charts/common/chrome-cache.ts +79 -0
  150. package/src/ts/charts/common/draw-tooltip-box.ts +84 -0
  151. package/src/ts/charts/common/leaf-color.ts +92 -0
  152. package/src/ts/charts/common/node-store.ts +235 -0
  153. package/src/ts/charts/common/tree-chart.ts +76 -0
  154. package/src/ts/charts/common/tree-chrome.ts +123 -0
  155. package/src/ts/charts/common/tree-data.ts +623 -0
  156. package/src/ts/charts/common/visible-extent.ts +112 -0
  157. package/src/ts/charts/heatmap/heatmap-build.ts +426 -0
  158. package/src/ts/charts/heatmap/heatmap-interact.ts +274 -0
  159. package/src/ts/charts/heatmap/heatmap-render.ts +815 -0
  160. package/src/ts/charts/heatmap/heatmap-y-axis.ts +351 -0
  161. package/src/ts/charts/heatmap/heatmap.ts +368 -0
  162. package/src/ts/charts/map/map.ts +201 -0
  163. package/src/ts/charts/registry.ts +65 -0
  164. package/src/ts/charts/series/glyphs/draw-areas.ts +331 -0
  165. package/src/ts/charts/series/glyphs/draw-bars.ts +113 -0
  166. package/src/ts/charts/series/glyphs/draw-lines.ts +320 -0
  167. package/src/ts/charts/series/glyphs/draw-scatter.ts +328 -0
  168. package/src/ts/charts/series/series-build.ts +848 -0
  169. package/src/ts/charts/series/series-interact.ts +604 -0
  170. package/src/ts/charts/series/series-render.ts +1109 -0
  171. package/src/ts/charts/series/series-type.ts +99 -0
  172. package/src/ts/charts/series/series.ts +794 -0
  173. package/src/ts/charts/sunburst/sunburst-interact.ts +460 -0
  174. package/src/ts/charts/sunburst/sunburst-layout.ts +238 -0
  175. package/src/ts/charts/sunburst/sunburst-render.ts +887 -0
  176. package/src/ts/charts/sunburst/sunburst.ts +248 -0
  177. package/src/ts/charts/treemap/treemap-interact.ts +445 -0
  178. package/src/ts/charts/treemap/treemap-layout.ts +328 -0
  179. package/src/ts/charts/treemap/treemap-render.ts +886 -0
  180. package/src/ts/charts/treemap/treemap.ts +247 -0
  181. package/src/ts/config.ts +41 -0
  182. package/src/ts/data/lazy-row.ts +140 -0
  183. package/src/ts/data/split-groups.ts +97 -0
  184. package/src/ts/data/view-reader.ts +107 -0
  185. package/src/ts/event-detail.ts +44 -0
  186. package/src/ts/index.ts +53 -0
  187. package/src/ts/interaction/hit-test.ts +106 -0
  188. package/src/ts/interaction/host-sink-dom.ts +85 -0
  189. package/src/ts/interaction/host-sink-message.ts +75 -0
  190. package/src/ts/interaction/lazy-tooltip.ts +102 -0
  191. package/src/ts/interaction/raw-event-forwarder.ts +175 -0
  192. package/src/ts/interaction/spatial-grid.ts +100 -0
  193. package/src/ts/interaction/tooltip-controller.ts +407 -0
  194. package/src/ts/interaction/zoom-controller.ts +468 -0
  195. package/src/ts/interaction/zoom-router.ts +230 -0
  196. package/src/ts/layout/facet-grid.ts +346 -0
  197. package/src/ts/layout/plot-layout.ts +277 -0
  198. package/src/ts/layout/ticks.ts +168 -0
  199. package/src/ts/map/mercator.ts +204 -0
  200. package/src/ts/map/tile-cache.ts +96 -0
  201. package/src/ts/map/tile-layer.ts +382 -0
  202. package/src/ts/map/tile-loader.ts +143 -0
  203. package/src/ts/map/tile-source.ts +156 -0
  204. package/src/ts/plugin/charts.ts +286 -0
  205. package/src/ts/plugin/plugin.ts +668 -0
  206. package/src/ts/render/scheduler.ts +339 -0
  207. package/src/ts/shaders/area.frag.glsl +20 -0
  208. package/src/ts/shaders/area.vert.glsl +19 -0
  209. package/src/ts/shaders/bar.frag.glsl +25 -0
  210. package/src/ts/shaders/bar.vert.glsl +60 -0
  211. package/src/ts/shaders/candlestick-body.frag.glsl +19 -0
  212. package/src/ts/shaders/candlestick-body.vert.glsl +34 -0
  213. package/src/ts/shaders/density-extreme.frag.glsl +30 -0
  214. package/src/ts/shaders/density-mrt.frag.glsl +44 -0
  215. package/src/ts/shaders/density-mrt.vert.glsl +48 -0
  216. package/src/ts/shaders/density-resolve.frag.glsl +89 -0
  217. package/src/ts/shaders/density-resolve.vert.glsl +23 -0
  218. package/src/ts/shaders/density-splat.frag.glsl +34 -0
  219. package/src/ts/shaders/density-splat.vert.glsl +52 -0
  220. package/src/ts/shaders/gridline.frag.glsl +18 -0
  221. package/src/ts/shaders/gridline.vert.glsl +18 -0
  222. package/src/ts/shaders/heatmap.frag.glsl +23 -0
  223. package/src/ts/shaders/heatmap.vert.glsl +42 -0
  224. package/src/ts/shaders/line-uniform.frag.glsl +26 -0
  225. package/src/ts/shaders/line-uniform.vert.glsl +54 -0
  226. package/src/ts/shaders/line.frag.glsl +28 -0
  227. package/src/ts/shaders/line.vert.glsl +87 -0
  228. package/src/ts/shaders/scatter.frag.glsl +39 -0
  229. package/src/ts/shaders/scatter.vert.glsl +67 -0
  230. package/src/ts/shaders/sunburst-arc.frag.glsl +19 -0
  231. package/src/ts/shaders/sunburst-arc.vert.glsl +79 -0
  232. package/src/ts/shaders/tile.frag.glsl +27 -0
  233. package/src/ts/shaders/tile.vert.glsl +35 -0
  234. package/src/ts/shaders/treemap.frag.glsl +19 -0
  235. package/src/ts/shaders/treemap.vert.glsl +25 -0
  236. package/src/ts/shaders/y-scatter.frag.glsl +30 -0
  237. package/src/ts/shaders/y-scatter.vert.glsl +31 -0
  238. package/src/ts/theme/gradient.ts +312 -0
  239. package/src/ts/theme/palette.ts +64 -0
  240. package/src/ts/theme/theme-snapshot.ts +66 -0
  241. package/src/ts/theme/theme.ts +166 -0
  242. package/src/ts/transport/protocol.ts +497 -0
  243. package/src/ts/transport/renderer-transport.ts +788 -0
  244. package/src/ts/utils/css.ts +36 -0
  245. package/src/ts/utils/font-snapshot.ts +159 -0
  246. package/src/ts/webgl/buffer-pool.ts +163 -0
  247. package/src/ts/webgl/context-manager.ts +414 -0
  248. package/src/ts/webgl/gradient-texture.ts +84 -0
  249. package/src/ts/webgl/instanced-attrs.ts +139 -0
  250. package/src/ts/webgl/plot-frame.ts +91 -0
  251. package/src/ts/webgl/program-cache.ts +46 -0
  252. package/src/ts/webgl/shader-manifest.ts +148 -0
  253. package/src/ts/webgl/shader-registry.ts +97 -0
  254. package/src/ts/worker/boot.ts +22 -0
  255. package/src/ts/worker/dispatch.ts +99 -0
  256. package/src/ts/worker/font-loader.ts +89 -0
  257. package/src/ts/worker/renderer.worker.ts +734 -0
  258. package/src/ts/worker/session-host.ts +118 -0
@@ -0,0 +1,402 @@
1
+ import type { View } from "@perspective-dev/client";
2
+ import type { ColumnDataMap } from "../data/view-reader";
3
+ import { LazyRowFetcher } from "../data/lazy-row";
4
+ import type { WebGLContextManager } from "../webgl/context-manager";
5
+ import { ZoomController, type ZoomConfig } from "../interaction/zoom-controller";
6
+ import { type ChartImplementation, type FacetConfig, type PluginConfig } from "./chart";
7
+ import { TooltipController, type HostSink, type TooltipCallbacks } from "../interaction/tooltip-controller";
8
+ import type { PerspectiveClickDetail } from "../event-detail";
9
+ import type { ViewConfig } from "@perspective-dev/client";
10
+ import { type Theme } from "../theme/theme";
11
+ /**
12
+ * Base class for WebGL chart implementations. Owns the common lifecycle
13
+ * plumbing (canvas wiring, viewer config setters, tooltip controller)
14
+ * so each concrete chart only implements data pipeline, rendering, and
15
+ * destruction hooks.
16
+ *
17
+ * ## Frame lifecycle (three phases)
18
+ *
19
+ * Every render of a chart passes through three phases:
20
+ *
21
+ * 1. `uploadAndRender(glManager, columns, startRow, endRow)`.
22
+ * Driven by the plugin wrapper once per data chunk. The subclass
23
+ * runs its build pipeline (axis/series resolution, record
24
+ * generation, domain accumulation) and pushes typed-array results
25
+ * into GPU buffers via `glManager.bufferPool`. Most charts also
26
+ * compile their shaders lazily here on first call.
27
+ *
28
+ * 2. `requestRender(glManager)` — single entrypoint for triggering a
29
+ * paint. Routes through the module-level scheduler
30
+ * ([render/scheduler.ts]) which coalesces by glManager and runs
31
+ * `_fullRender` + `awaitGpuFence` + `endFrame` on the next RAF.
32
+ * Concurrent requests collapse to one `_fullRender` per frame and
33
+ * fence waits across charts run in parallel, so per-chart latency
34
+ * is bounded by that chart's own GPU work.
35
+ *
36
+ * 3. `_fullRender(glManager)` — the subclass implements its own draw
37
+ * loop: resolve visible domains from the zoom controller, build
38
+ * projection matrices, call into its glyph draw helpers, and paint
39
+ * the chrome overlay (axes, legend, tooltip).
40
+ *
41
+ * `destroy()` is called by the plugin wrapper on teardown. It detaches
42
+ * tooltip listeners, then invokes the subclass's `destroyInternal()`
43
+ * to free chart-specific GL resources.
44
+ *
45
+ * ## What subclasses implement
46
+ * - `uploadAndRender` — phase 1; ends by `await this.requestRender(glManager)`.
47
+ * - `tooltipCallbacks()` — return chart-specific hover/click handlers.
48
+ * - `_fullRender` — phase 3; must be safe to call with no data
49
+ * (subclass guards on its own state machine — empty trees, missing
50
+ * programs, etc — and returns early without touching GL).
51
+ * - `destroyInternal` — release chart-specific resources.
52
+ *
53
+ * `getZoomConfig()` is an optional override; default = both axes
54
+ * zoom-unlocked. See {@link ZoomConfig}.
55
+ */
56
+ export declare abstract class AbstractChart implements ChartImplementation {
57
+ _glManager: WebGLContextManager | null;
58
+ _gridlineCanvas: HTMLCanvasElement | OffscreenCanvas | null;
59
+ _chromeCanvas: HTMLCanvasElement | OffscreenCanvas | null;
60
+ /**
61
+ * Host-supplied CSS-variable map. The host snapshots its DOM via
62
+ * `snapshotThemeVars(el)` and ships it over the control channel;
63
+ * the chart decodes via `resolveThemeFromVars` lazily in
64
+ * `_resolveTheme()`. The chart never reads the DOM itself (it
65
+ * always runs inside `WorkerRenderer`, possibly off-thread).
66
+ */
67
+ _themeVars: Record<string, string>;
68
+ _zoomController: ZoomController | null;
69
+ /**
70
+ * Per-facet zoom controllers. Populated when `zoom_mode ===
71
+ * "independent"` and the chart enters faceted mode; each facet's
72
+ * render path reads its own viewport from the matching entry.
73
+ *
74
+ * Shared-zoom mode leaves this empty; `_zoomController` is the
75
+ * single domain used for every facet.
76
+ */
77
+ _facetZoomControllers: ZoomController[];
78
+ _columnSlots: (string | null)[];
79
+ _groupBy: string[];
80
+ _splitBy: string[];
81
+ _columnTypes: Record<string, string>;
82
+ /**
83
+ * Effective shared-axis flags for the most recent faceted frame.
84
+ * Derived per-frame from `_facetConfig.shared_x_axis` /
85
+ * `shared_y_axis` and `zoom_mode` via
86
+ * {@link computeEffectiveFacetFlags} — independent-zoom mode forces
87
+ * both off because an outer axis band has no single domain it could
88
+ * display. Stored here (rather than mutated back onto
89
+ * `_facetConfig`) so the user's configured shared-axis preferences
90
+ * survive a "shared → independent → shared" round-trip. Read by
91
+ * chrome-overlay code (e.g. `renderFacetedChromeOverlay`,
92
+ * `renderFacetedHeatmapChromeOverlay`) after the main render pass
93
+ * sets them.
94
+ */
95
+ _lastEffectiveSharedX: boolean;
96
+ _lastEffectiveSharedY: boolean;
97
+ /**
98
+ * Source-column types for `group_by` columns — sourced from
99
+ * `table.schema()` (plain columns) merged with `view.expression_schema()`
100
+ * (expression-typed group_bys). Distinct from `_columnTypes` (which
101
+ * is the post-aggregation `view.schema()` map): the level-type
102
+ * lookup for `__ROW_PATH_N__` columns must use the unaggregated
103
+ * type, since `view.schema()` doesn't key these synthetic columns.
104
+ */
105
+ _groupByTypes: Record<string, string>;
106
+ _columnsConfig: Record<string, any>;
107
+ /**
108
+ * Pre-compiled per-column value formatters, keyed by the **source**
109
+ * column name (synthetic split-by paths are normalized via
110
+ * `sourceColumn`). Rebuilt by `setColumnsConfig` from the active
111
+ * plugin's `column_config_schema` output, then consulted by axis /
112
+ * tooltip / legend paths via {@link getColumnFormatter}.
113
+ *
114
+ * `undefined` means "no configured formatter for this column" — the
115
+ * caller falls back to the chart's hand-rolled tick formatter.
116
+ */
117
+ _columnFormatters: Map<string, (v: number) => string>;
118
+ _defaultChartType: string | undefined;
119
+ _facetConfig: FacetConfig;
120
+ /**
121
+ * Plugin-scoped global configuration. Updated by `setPluginConfig`
122
+ * (driven from the host's `plugin.restore()`) and read by render-
123
+ * path glyphs (`line_width_px`, `point_size_px`, etc.) and by the
124
+ * build pipelines (`auto_alt_y_axis`, `band_inner_frac`,
125
+ * `bar_inner_pad`). Defaults preserve the previous compile-time
126
+ * constants so first-frame rendering before `restore()` matches
127
+ * the pre-refactor output.
128
+ */
129
+ _pluginConfig: PluginConfig;
130
+ _tooltip: TooltipController;
131
+ /**
132
+ * Reference to the active host sink, captured in {@link attachTooltip}.
133
+ * Used to emit `perspective-click` / `perspective-global-filter` user
134
+ * events back to the host. Distinct from `_tooltip._host` to avoid
135
+ * reaching into the tooltip controller's internals.
136
+ */
137
+ _hostSink: HostSink | null;
138
+ /**
139
+ * Promise chain that serializes user-event emissions so a rapid
140
+ * pin → unpin sequence stays in order even when `buildClickDetail`
141
+ * awaits `_lazyRows.fetchRow`. Without the queue, click 1's async
142
+ * row fetch could resolve AFTER click 2's synchronous `emitUnselect`
143
+ * — flipping the host's observed event order. All emit helpers
144
+ * (`emitClickAndSelect`, `emitUserClick`, `emitUserSelect`,
145
+ * `emitUnselect`) chain through this.
146
+ */
147
+ _emitQueue: Promise<void>;
148
+ /**
149
+ * Cached resolved theme — populated on first `_resolveTheme()` call,
150
+ * cleared by `invalidateTheme()` (driven from `plugin.restyle()`).
151
+ * `getComputedStyle` / `getPropertyValue` reads cost ~100µs each;
152
+ * zoom/hover dispatch redraws at 60Hz so we resolve once and reuse.
153
+ */
154
+ _theme: Theme | null;
155
+ /**
156
+ * On-demand single-row fetcher used by lazy tooltip column
157
+ * lookups. Reset on every `setView` call; subclasses read
158
+ * `_lazyRows.fetchRow(rowIdx)` from their hover/pin paths and
159
+ * compare a captured serial against the current hovered/pinned
160
+ * state at resolution time, so stale fetches never paint.
161
+ *
162
+ * Can be `null` on chart types that don't surface the View
163
+ * (unit-tested charts) or before the first `draw`.
164
+ */
165
+ _lazyRows: LazyRowFetcher | null;
166
+ setGridlineCanvas(canvas: HTMLCanvasElement | OffscreenCanvas): void;
167
+ setChromeCanvas(canvas: HTMLCanvasElement | OffscreenCanvas): void;
168
+ setTheme(vars: Record<string, string>): void;
169
+ setZoomController(zc: ZoomController): void;
170
+ /**
171
+ * Resolve the zoom controller that owns facet `idx`. In shared-zoom
172
+ * mode (default) this is always the chart's single `_zoomController`.
173
+ * In independent-zoom mode the router provisions one controller per
174
+ * facet; this returns the matching entry, allocating on demand so
175
+ * the render path never has to check `zoom_mode` itself.
176
+ */
177
+ getZoomControllerForFacet(idx: number): ZoomController | null;
178
+ /**
179
+ * Derive the effective shared-X / shared-Y flags for the current
180
+ * frame and stamp them onto `_lastEffectiveSharedX/Y` for downstream
181
+ * chrome-overlay code to consume. Independent-zoom mode forces both
182
+ * shared flags off — the outer axis band cannot display per-cell
183
+ * viewports — without mutating the user's stored `_facetConfig`.
184
+ *
185
+ * Returns `{ independentZoom, effectiveSharedX, effectiveSharedY }`
186
+ * for callers that need the values immediately (e.g. to pass
187
+ * `xAxis: "outer" | "cell"` into `buildFacetGrid`).
188
+ */
189
+ computeEffectiveFacetFlags(): {
190
+ independentZoom: boolean;
191
+ effectiveSharedX: boolean;
192
+ effectiveSharedY: boolean;
193
+ };
194
+ /**
195
+ * Wire every active zoom controller's layout pointer for the
196
+ * supplied facet cells. In shared-zoom mode every
197
+ * `getZoomControllerForFacet(i)` returns the same `_zoomController`,
198
+ * so iterating past the first cell would just re-write the same
199
+ * pointer — `break`-on-shared keeps the cost O(1) and avoids the
200
+ * subtle bug where every facet's `updateLayout` overwrites the
201
+ * previous one with the last cell's layout.
202
+ */
203
+ syncFacetZoomLayouts(cells: ReadonlyArray<{
204
+ layout: import("../layout/plot-layout").PlotLayout;
205
+ }>): void;
206
+ /**
207
+ * Set base domain on every zoom controller owned by this chart.
208
+ */
209
+ setZoomBaseDomain(xMin: number, xMax: number, yMin: number, yMax: number): void;
210
+ /**
211
+ * Zoom-controller config for this chart type. Subclasses override to
212
+ * pin an axis (e.g. bar charts pin the categorical axis). Default:
213
+ * both axes freely zoomable.
214
+ */
215
+ protected getZoomConfig(): ZoomConfig;
216
+ setColumnSlots(slots: (string | null)[]): void;
217
+ setViewPivots(groupBy: string[], splitBy: string[]): void;
218
+ setColumnTypes(schema: Record<string, string>): void;
219
+ /**
220
+ * Clear any `domain_mode: "expand"` accumulator state. Driven by
221
+ * `plugin.draw()` (a fresh `draw` always indicates a view-level
222
+ * change — viewer config, filters, sorts, etc. — that invalidates
223
+ * the previously-accumulated extent) and by the worker's
224
+ * `resetAllZooms` path (user clicked "Reset Zoom"). `plugin.update()`
225
+ * deliberately does *not* call this — same view, more data, the
226
+ * accumulator should keep growing. No-op on the base; chart
227
+ * families that hold accumulator fields override.
228
+ */
229
+ resetExpandedDomain(): void;
230
+ setGroupByTypes(schema: Record<string, string>): void;
231
+ setColumnsConfig(cfg: Record<string, any>): void;
232
+ /**
233
+ * Rebuild {@link _columnFormatters} from `_columnsConfig` +
234
+ * `_columnTypes`. Called from both `setColumnsConfig` and
235
+ * `setColumnTypes` since either side of the (config, types) pair
236
+ * can arrive first depending on the host's restore order. Idempotent.
237
+ */
238
+ private _rebuildColumnFormatters;
239
+ private _compileColumnFormatter;
240
+ /**
241
+ * Returns the formatter for `columnName` if one has been configured
242
+ * (via `column_config_schema` + the user's sidebar choices), else a
243
+ * type-appropriate fallback for the chart context.
244
+ *
245
+ * @param columnName May be a synthetic split-by path
246
+ * (`<split_val>|...|<source_col>`); the source column is recovered
247
+ * internally before lookup.
248
+ * @param context `"tick"` returns `undefined` when no per-column
249
+ * formatter is configured, so the receiving axis renderer can
250
+ * apply its own step-aware default (adaptive date precision from
251
+ * tick spacing, K/M/B suffixes for numerics). `"value"` returns
252
+ * a precise `Intl.NumberFormat` / `Intl.DateTimeFormat` fallback —
253
+ * appropriate for tooltips, legends, overlays where the caller
254
+ * invokes the formatter directly and needs a guaranteed function.
255
+ */
256
+ getColumnFormatter(columnName: string | null | undefined, context: "tick"): ((v: number) => string) | undefined;
257
+ getColumnFormatter(columnName: string | null | undefined, context?: "value"): (v: number) => string;
258
+ setDefaultChartType(chartType: string): void;
259
+ setFacetConfig(cfg: FacetConfig): void;
260
+ /**
261
+ * Apply plugin-scoped global config. Stores `cfg` for later reads
262
+ * and mirrors the overlapping fields onto adjacent state so deep
263
+ * render code keeps reading the single struct it already does:
264
+ *
265
+ * - `facet_mode` / `facet_zoom_mode` sync into `_facetConfig` so
266
+ * `cartesian-render.ts` (and the treemap/sunburst grid checks)
267
+ * keep working unchanged.
268
+ * - `series_zoom_mode` toggles the `_autoFitValue` flag declared
269
+ * on `CategoricalYChart` ("dynamic" = refit on zoom, "fixed" =
270
+ * pinned to full extent). Harmless write on charts that don't
271
+ * expose the field.
272
+ *
273
+ * Render-path uniform fields (`line_width_px`, `point_size_px`,
274
+ * `wick_width_px`, `ohlc_line_width_px`) are read directly from
275
+ * `_pluginConfig` by their respective glyphs on each draw — no
276
+ * sync needed. Build-time fields (`auto_alt_y_axis`,
277
+ * `band_inner_frac`, `bar_inner_pad`) are read by the pipeline
278
+ * inputs in `uploadAndRender`; they take effect on next data load.
279
+ */
280
+ setPluginConfig(cfg: PluginConfig): void;
281
+ /**
282
+ * Lazily decode the host-supplied theme vars. Subsequent calls hit
283
+ * the cache until `invalidateTheme()` clears it. Render-path
284
+ * callers should always read theme values through this method so
285
+ * the parsed `Theme` (gradient stops, palette, etc.) amortizes
286
+ * across an entire frame.
287
+ */
288
+ _resolveTheme(): Theme;
289
+ /**
290
+ * Drop the cached theme so the next `_resolveTheme()` call re-decodes
291
+ * from `_themeVars`. Wired to `plugin.restyle()` — the host pushes
292
+ * a fresh var snapshot before invalidating.
293
+ */
294
+ invalidateTheme(): void;
295
+ /**
296
+ * Install a new view for lazy row fetches. Disposes any prior
297
+ * fetcher and dismisses the pinned tooltip — the prior pinned
298
+ * row index has no guaranteed correspondence in the new view
299
+ * (pivot / filter / sort changes can all reshuffle rows).
300
+ */
301
+ setView(view: View): void;
302
+ /**
303
+ * Build the chart-specific {@link TooltipCallbacks} object — the
304
+ * `onHover` / `onLeave` / `onClickPre` / `onPin` / `onDblClick`
305
+ * surface that mediates between the cursor and chart state.
306
+ * Subclasses override this; the base returns a no-op pair.
307
+ */
308
+ protected tooltipCallbacks(): TooltipCallbacks;
309
+ /**
310
+ * Wire the chart's `TooltipController` for virtual-dispatch
311
+ * `InteractionEvent`s forwarded from the host, and install the
312
+ * host sink that materializes pinned tooltips and cursor changes
313
+ * host-side.
314
+ */
315
+ attachTooltip(host: HostSink): void;
316
+ /**
317
+ * Build a `PerspectiveClickDetail` payload from a per-family
318
+ * resolved click target. Fetches the source-view row via
319
+ * `_lazyRows` (returns `row: {}` if the row can't be resolved —
320
+ * e.g., aggregate / density cells), and concatenates the
321
+ * `group_by` and `split_by` pivot values into a
322
+ * `viewer.restore({ filter })`-shaped patch.
323
+ *
324
+ * Mirrors the filter-building logic in datagrid's
325
+ * `getCellConfig` ([packages/viewer-datagrid/src/ts/get_cell_config.ts]),
326
+ * but operates on `AbstractChart` state rather than a `DatagridModel`.
327
+ */
328
+ buildClickDetail(target: {
329
+ rowIdx: number | null;
330
+ columnName: string;
331
+ groupByValues: (string | number | null)[];
332
+ splitByValues: (string | number | null)[];
333
+ }): Promise<PerspectiveClickDetail>;
334
+ /**
335
+ * Forward a `perspective-click` to the host. No-op when the chart
336
+ * has not been wired to a host sink (e.g., unit-tested charts).
337
+ * Synchronous; callers needing ordering with async emits should
338
+ * chain through `_emitQueue`.
339
+ */
340
+ emitUserClick(detail: PerspectiveClickDetail): void;
341
+ /**
342
+ * Forward a `perspective-global-filter` to the host. The host
343
+ * transport materializes a `PerspectiveSelectDetail` from this plus
344
+ * its cached previous-insert config and dispatches. Synchronous.
345
+ */
346
+ emitUserSelect(args: {
347
+ selected: boolean;
348
+ row: Record<string, unknown>;
349
+ column_names: string[];
350
+ insertConfig: Partial<ViewConfig>;
351
+ }): void;
352
+ /**
353
+ * Convenience: fire both `perspective-click` and
354
+ * `perspective-global-filter` (`selected: true`) from a resolved
355
+ * click target. Used by chart families where every click both
356
+ * "selects" and "filters" (series, heatmap, candlestick, scatter,
357
+ * treemap-leaf, etc.). Treemap branch / breadcrumb gestures use
358
+ * the lower-level helpers directly.
359
+ *
360
+ * Chains through `_emitQueue` so the row-fetch await can't reorder
361
+ * this emit behind a follow-up `emitUnselect`.
362
+ */
363
+ emitClickAndSelect(target: {
364
+ rowIdx: number | null;
365
+ columnName: string;
366
+ groupByValues: (string | number | null)[];
367
+ splitByValues: (string | number | null)[];
368
+ }): Promise<void>;
369
+ /**
370
+ * Fire a `perspective-global-filter` with `selected: false`. Used
371
+ * by treemap / sunburst breadcrumb navigation and by chart-base's
372
+ * own `setView` when a view change implicitly dismisses any active
373
+ * pin. Chains through `_emitQueue` so it lands AFTER any in-flight
374
+ * `emitClickAndSelect`.
375
+ */
376
+ emitUnselect(args?: {
377
+ row?: Record<string, unknown>;
378
+ column_names?: string[];
379
+ }): void;
380
+ /**
381
+ * Public coalesced render. Routes through the module-level
382
+ * scheduler so concurrent calls collapse to one `_fullRender` per
383
+ * RAF and the host blitter receives one bitmap per frame. The
384
+ * returned promise resolves after this chart's `awaitGpuFence` +
385
+ * `endFrame` chain — independent of other charts in the same
386
+ * RAF, which run their fence waits in parallel.
387
+ *
388
+ * Every render-triggering caller — upload chunks, zoom / pan,
389
+ * resize, theme invalidation, host-driven redraws — calls this.
390
+ * The only sanctioned bypass is `snapshotPng`, which calls
391
+ * `_fullRender` directly to keep the GL backbuffer intact for
392
+ * `gl.readPixels`.
393
+ */
394
+ requestRender(glManager: WebGLContextManager): Promise<void>;
395
+ destroy(): void;
396
+ abstract uploadAndRender(glManager: WebGLContextManager, columns: ColumnDataMap, startRow: number, endRow: number): Promise<void>;
397
+ abstract _fullRender(glManager: WebGLContextManager): void;
398
+ /**
399
+ * Release chart-specific GL/CPU resources. `destroy` calls this.
400
+ */
401
+ protected abstract destroyInternal(): void;
402
+ }