@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,20 @@
1
+ import type { ColumnDataMap } from "./view-reader";
2
+ export interface SplitGroup {
3
+ /**
4
+ * Composite prefix (e.g., "East", "East|Enterprise" for multi-level).
5
+ */
6
+ prefix: string;
7
+ /**
8
+ * Map of base column name → full Arrow column name ("prefix|base").
9
+ */
10
+ colNames: Map<string, string>;
11
+ }
12
+ /**
13
+ * Group Arrow column names by their split prefix (everything before the
14
+ * last "|"). A split exists for a prefix only when every `requiredBases`
15
+ * entry has a non-empty column present for that prefix. `optionalBases`
16
+ * are included when present but do not gate group inclusion.
17
+ *
18
+ * Empty/falsy entries in either base list are skipped.
19
+ */
20
+ export declare function buildSplitGroups(columns: ColumnDataMap, requiredBases: string[], optionalBases?: string[]): SplitGroup[];
@@ -0,0 +1,35 @@
1
+ import type { View } from "@perspective-dev/client";
2
+ export interface ColumnData {
3
+ type: "float32" | "float64" | "int32" | "string";
4
+ values?: Float32Array | Float64Array | Int32Array;
5
+ /**
6
+ * Dictionary key indices for string columns.
7
+ */
8
+ indices?: Int32Array;
9
+ /**
10
+ * Dictionary values for string columns.
11
+ */
12
+ dictionary?: string[];
13
+ /**
14
+ * Arrow validity bitfield (1 bit per row).
15
+ */
16
+ valid?: Uint8Array;
17
+ }
18
+ export type ColumnDataMap = Map<string, ColumnData>;
19
+ export interface TypedArrayWindowOptions {
20
+ start_row?: number;
21
+ end_row?: number;
22
+ start_col?: number;
23
+ end_col?: number;
24
+ float32?: boolean;
25
+ }
26
+ /**
27
+ * Fetches all columns from a View using `with_typed_arrays` and
28
+ * builds a `ColumnDataMap`. The `values` typed arrays and `valid`
29
+ * bitmaps are zero-copy views into WASM memory and remain valid only
30
+ * for the duration of the `render` callback — if `render` returns a
31
+ * `Promise`, the underlying `with_typed_arrays` call awaits it before
32
+ * releasing the backing Arrow buffer. Callers must not retain any
33
+ * `ColumnData` reference past `render`'s resolution.
34
+ */
35
+ export declare function viewToColumnDataMap(view: View, render: (data: ColumnDataMap) => void | Promise<void>, options?: TypedArrayWindowOptions): Promise<void>;
@@ -0,0 +1,28 @@
1
+ import type { ViewConfig } from "@perspective-dev/client";
2
+ /**
3
+ * Detail payload for the `perspective-click` CustomEvent dispatched on
4
+ * the `<perspective-viewer>` host when the user clicks a chart glyph.
5
+ * Shape matches the equivalent type in `@perspective-dev/viewer-datagrid`
6
+ * so consumers can listen to either plugin uniformly.
7
+ */
8
+ export interface PerspectiveClickDetail {
9
+ /**
10
+ * Source-view row data — keys are column names, values are scalar
11
+ * cell values. Empty `{}` when the click hit a non-leaf aggregate
12
+ * (e.g. a treemap branch).
13
+ */
14
+ row: Record<string, unknown>;
15
+ /**
16
+ * Aggregate column(s) the click targeted. Single-entry for series /
17
+ * heatmap / tree charts; multi-entry would only appear for plugins
18
+ * that surface multiple measures per glyph (none today).
19
+ */
20
+ column_names: string[];
21
+ /**
22
+ * Pre-built `viewer.restore({ filter })` patch — concatenates the
23
+ * group_by and split_by pivot values at the click target as
24
+ * `[<col>, "==", <value>]` clauses.
25
+ */
26
+ config: Partial<ViewConfig>;
27
+ }
28
+ export { PerspectiveSelectDetail } from "@perspective-dev/viewer/src/ts/extensions.js";
@@ -0,0 +1,3 @@
1
+ export type { PerspectiveClickDetail } from "./event-detail";
2
+ export { PerspectiveSelectDetail } from "./event-detail";
3
+ export declare function register(...plugin_names: string[]): void;
@@ -0,0 +1,30 @@
1
+ export interface HitBounds {
2
+ xMin: number;
3
+ xMax: number;
4
+ yMin: number;
5
+ yMax: number;
6
+ }
7
+ /**
8
+ * Wraps SpatialGrid with dirty-flag bookkeeping + the cell-size heuristic
9
+ * (~√n cells), so chart code no longer repeats the insertion loop scaffold.
10
+ * Callers drive the iteration through `rebuild` and the `visit` callback,
11
+ * which lets scatter (flat array) and line (series-indexed array) share
12
+ * the same code path.
13
+ */
14
+ export declare class SpatialHitTester {
15
+ private _grid;
16
+ private _dirty;
17
+ markDirty(): void;
18
+ get isDirty(): boolean;
19
+ /**
20
+ * Rebuild the grid. `forEachPoint` is called once with an insert
21
+ * function; the caller drives iteration. Cleared when `pointCount`
22
+ * is zero.
23
+ */
24
+ rebuild(bounds: HitBounds, pointCount: number, forEachPoint: (insert: (idx: number, x: number, y: number) => void) => void): void;
25
+ /**
26
+ * Query the nearest point within `radiusPx` of (dataX, dataY).
27
+ */
28
+ query(dataX: number, dataY: number, radiusPx: number, pxPerDataX: number, pxPerDataY: number, xData: Float32Array | null, yData: Float32Array | null): number;
29
+ clear(): void;
30
+ }
@@ -0,0 +1,19 @@
1
+ import type { CssBounds, HostSink } from "./tooltip-controller";
2
+ /**
3
+ * Host-side `HostSink` that materializes pinned tooltips as a `<div>`
4
+ * next to the GL canvas, and applies cursor changes to the canvas's
5
+ * own `style.cursor`. Host-only — depends on `document` /
6
+ * `getComputedStyle`.
7
+ */
8
+ export declare class DomHostSink implements HostSink {
9
+ private _glCanvas;
10
+ private _parent;
11
+ private _div;
12
+ constructor(glCanvas: HTMLCanvasElement, parent: HTMLElement);
13
+ pin(lines: string[], pos: {
14
+ px: number;
15
+ py: number;
16
+ }, bounds: CssBounds): void;
17
+ dismiss(): void;
18
+ setCursor(cursor: string): void;
19
+ }
@@ -0,0 +1,46 @@
1
+ import type { CssBounds, HostSink, UserClickPayload, UserSelectPayload } from "./tooltip-controller";
2
+ /**
3
+ * Envelope shape sent by `MessageHostSink`. The transport translates
4
+ * each one into a corresponding `WorkerMsg` (`pinTooltip` /
5
+ * `dismissTooltip` / `setCursor` / `userClick` / `userSelect`).
6
+ */
7
+ export type HostSinkEnvelope = {
8
+ kind: "pin";
9
+ payload: {
10
+ lines: string[];
11
+ pos: {
12
+ px: number;
13
+ py: number;
14
+ };
15
+ bounds: CssBounds;
16
+ };
17
+ } | {
18
+ kind: "dismiss";
19
+ } | {
20
+ kind: "setCursor";
21
+ cursor: string;
22
+ } | {
23
+ kind: "userClick";
24
+ payload: UserClickPayload;
25
+ } | {
26
+ kind: "userSelect";
27
+ payload: UserSelectPayload;
28
+ };
29
+ /**
30
+ * `HostSink` that posts pin / dismiss / setCursor / user-event intents
31
+ * over a `postMessage`-style channel. The host-side transport listens
32
+ * for these envelopes and drives a `DomHostSink` for pin/dismiss and
33
+ * dispatches `CustomEvent`s on the viewer for user events.
34
+ */
35
+ export declare class MessageHostSink implements HostSink {
36
+ private _send;
37
+ constructor(send: (msg: HostSinkEnvelope) => void);
38
+ pin(lines: string[], pos: {
39
+ px: number;
40
+ py: number;
41
+ }, bounds: CssBounds): void;
42
+ dismiss(): void;
43
+ setCursor(cursor: string): void;
44
+ emitUserClick(payload: UserClickPayload): void;
45
+ emitUserSelect(payload: UserSelectPayload): void;
46
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Serial-checked async tooltip cache.
3
+ *
4
+ * Every chart family that paints tooltip text from a lazy row fetch
5
+ * needs the same dance: each hover (or pin) bumps a serial; the async
6
+ * line-build resolves later; if the user has moved on by then the
7
+ * resolved lines must be discarded so we don't paint stale text.
8
+ *
9
+ * Hit-test logic stays per-chart — that genuinely diverges (spatial
10
+ * grid for cartesian, walk-visible-nodes for treemap, angular for
11
+ * sunburst). The serial discipline is what was getting copy-pasted.
12
+ *
13
+ * `Target` is whatever identity the chart uses for hover/pin (flat
14
+ * slot index, node id, etc.); it's stored on `hoveredTarget` so the
15
+ * render path can tell whether cached `lines` belong to the currently
16
+ * hovered entity (some charts paint tooltip text only when both
17
+ * agree).
18
+ */
19
+ export declare class LazyTooltip<Target> {
20
+ /**
21
+ * Cached lines for the latest committed hover, or `null`.
22
+ */
23
+ lines: string[] | null;
24
+ /**
25
+ * Identity of the entity `lines` describe. `null` when cleared.
26
+ */
27
+ hoveredTarget: Target | null;
28
+ private _hoverSerial;
29
+ private _pinSerial;
30
+ /**
31
+ * Begin a new hover. Call this only when the hovered entity has
32
+ * actually changed. Clears the cached lines, records the new
33
+ * target, bumps the hover serial, and returns the new value — pass
34
+ * it back to {@link commitHover} from your async resolver to gate
35
+ * the write.
36
+ */
37
+ beginHover(target: Target): number;
38
+ /**
39
+ * Commit a freshly-resolved line list for `serial`. Returns true
40
+ * when the write happened (caller should repaint), false when the
41
+ * serial was stale.
42
+ */
43
+ commitHover(serial: number, lines: string[]): boolean;
44
+ /**
45
+ * Clear hover state (mouse left, view changed, etc.).
46
+ */
47
+ clearHover(): void;
48
+ /**
49
+ * Begin a pin operation. Returns the serial; pass it to
50
+ * {@link isPinFresh} from your async resolver.
51
+ */
52
+ beginPin(): number;
53
+ /**
54
+ * True when `serial` still names the latest pin attempt.
55
+ */
56
+ isPinFresh(serial: number): boolean;
57
+ /**
58
+ * Bump the pin serial without starting a new pin (e.g. dismiss).
59
+ */
60
+ invalidatePin(): void;
61
+ }
@@ -0,0 +1,27 @@
1
+ import type { InteractionEvent } from "../transport/protocol";
2
+ /**
3
+ * Worker-mode counterpart to {@link ZoomRouter}. Captures wheel /
4
+ * pointer events on the GL canvas, normalizes coords to canvas-relative
5
+ * CSS pixels, and emits semantic {@link InteractionEvent}s to the
6
+ * Renderer over its transport. The Renderer (running in a Web Worker)
7
+ * owns the `ZoomController`s and runs the actual hit-test + apply
8
+ * logic — see `applyWheel` / `applyPan` in `zoom-router.ts`.
9
+ *
10
+ * Pointer capture is set on `pointerdown` and released on `pointerup`
11
+ * so drags continue to deliver `pointermove` events when the cursor
12
+ * leaves the canvas, matching the in-process `ZoomRouter` behavior.
13
+ */
14
+ export declare class RawEventForwarder {
15
+ private _element;
16
+ private _emit;
17
+ private _pointerId;
18
+ private _onWheel;
19
+ private _onPointerDown;
20
+ private _onPointerMove;
21
+ private _onPointerUp;
22
+ private _onPointerLeave;
23
+ private _onClick;
24
+ private _onDblClick;
25
+ attach(element: HTMLElement, emit: (e: InteractionEvent) => void): void;
26
+ detach(): void;
27
+ }
@@ -0,0 +1,15 @@
1
+ export declare class SpatialGrid {
2
+ private _cells;
3
+ private _xMin;
4
+ private _yMin;
5
+ private _cellSize;
6
+ private _cols;
7
+ constructor(xMin: number, xMax: number, yMin: number, yMax: number, cellSize: number);
8
+ private _cellKey;
9
+ insert(index: number, x: number, y: number): void;
10
+ /**
11
+ * Find the nearest point to (dataX, dataY) within the given radius,
12
+ * measured in pixel distance using the provided scale factors.
13
+ */
14
+ query(dataX: number, dataY: number, radiusPx: number, pxPerDataX: number, pxPerDataY: number, xData: Float32Array, yData: Float32Array): number;
15
+ }
@@ -0,0 +1,193 @@
1
+ import type { Canvas2D } from "../charts/canvas-types";
2
+ import type { PlotLayout } from "../layout/plot-layout";
3
+ import type { Theme } from "../theme/theme";
4
+ /**
5
+ * Minimal positioning input — PlotLayout satisfies this.
6
+ */
7
+ export interface CssBounds {
8
+ cssWidth: number;
9
+ cssHeight: number;
10
+ }
11
+ export interface TooltipCallbacks {
12
+ /**
13
+ * RAF-throttled mouse position in CSS pixels, relative to the GL
14
+ * canvas (host already subtracted `getBoundingClientRect`).
15
+ */
16
+ onHover(mx: number, my: number): void;
17
+ /**
18
+ * Fires on mouseleave; skipped while a pinned tooltip is active.
19
+ */
20
+ onLeave(): void;
21
+ /**
22
+ * Fires on click with mouse position. Return true to consume the click
23
+ * (skipping the default pin/dismiss flow — used for legend clicks).
24
+ */
25
+ onClickPre?(mx: number, my: number): boolean;
26
+ /**
27
+ * Fires when a click should pin the current hover target.
28
+ */
29
+ onPin?(mx: number, my: number): void;
30
+ /**
31
+ * Fires on dblclick (treemap drill-up gesture). Optional — charts
32
+ * that don't bind a handler simply ignore the event.
33
+ */
34
+ onDblClick?(mx: number, my: number): void;
35
+ /**
36
+ * Fires when an active pin is dismissed by a click on the
37
+ * already-pinned target (the "click again to unpin" gesture in
38
+ * `dispatchClick`). Chart impls hook this to emit a
39
+ * `perspective-global-filter` with `selected: false`. Does *not*
40
+ * fire on the implicit dismiss inside `pin()` that replaces an
41
+ * existing pin — that path is followed by a fresh `onPin` which
42
+ * emits its own `selected: true`.
43
+ */
44
+ onUnpin?(): void;
45
+ }
46
+ export interface RenderTooltipOptions {
47
+ /**
48
+ * Draw a dashed crosshair at `pos`. Used by scatter/line.
49
+ */
50
+ crosshair?: boolean;
51
+ /**
52
+ * Draw a ring of `radius` CSS pixels at `pos`. Used to highlight a
53
+ * hovered point. Omit for bars (where the bar itself highlights).
54
+ */
55
+ highlightRadius?: number;
56
+ }
57
+ /**
58
+ * Side-channel from the chart back to the host's DOM. The chart calls
59
+ * into a sink rather than touching the DOM itself; the host
60
+ * materializes the actual visual (`<div>` for pinned tooltip, cursor
61
+ * mutation on the GL canvas).
62
+ *
63
+ * - `MessageHostSink` (in worker/) — forwards calls over a
64
+ * `postMessage`-shaped channel back to
65
+ * the host.
66
+ * - `DomHostSink` (in host transport) — receives the matching
67
+ * envelopes and applies them to the DOM.
68
+ *
69
+ * The controller's `_pinned` flag is the source of truth for whether
70
+ * hover updates are gated; the sink only owns the visual artifact.
71
+ */
72
+ export interface HostSink {
73
+ pin(lines: string[], pos: {
74
+ px: number;
75
+ py: number;
76
+ }, bounds: CssBounds): void;
77
+ dismiss(): void;
78
+ setCursor(cursor: string): void;
79
+ /**
80
+ * Forward a `perspective-click` to the host. Optional — only the
81
+ * worker-bound `MessageHostSink` implements it; `DomHostSink` (the
82
+ * host-side consumer of pin/dismiss) never sees user-event calls,
83
+ * so omits the implementation.
84
+ */
85
+ emitUserClick?(detail: UserClickPayload): void;
86
+ /**
87
+ * Forward a `perspective-global-filter` to the host with the
88
+ * `selected: true` / `selected: false` semantics. The host owns the
89
+ * `removeConfigs` history (mirrors datagrid's
90
+ * `model._last_insert_configs`); the sink only ships the new state.
91
+ */
92
+ emitUserSelect?(payload: UserSelectPayload): void;
93
+ }
94
+ /**
95
+ * Plain-object payload for `HostSink.emitUserClick`. Matches
96
+ * `PerspectiveClickDetail` byte-for-byte; defined locally to avoid a
97
+ * cycle through `event-detail.ts`.
98
+ */
99
+ export interface UserClickPayload {
100
+ row: Record<string, unknown>;
101
+ column_names: string[];
102
+ config: {
103
+ filter?: unknown[];
104
+ };
105
+ }
106
+ /**
107
+ * Plain-object payload for `HostSink.emitUserSelect`. The host
108
+ * transport reconstructs a `PerspectiveSelectDetail` class instance
109
+ * from this plus its cached `_lastInsertConfig`.
110
+ */
111
+ export interface UserSelectPayload {
112
+ selected: boolean;
113
+ row: Record<string, unknown>;
114
+ column_names: string[];
115
+ insertConfig: {
116
+ filter?: unknown[];
117
+ };
118
+ }
119
+ /**
120
+ * Owns the hover/click/dblclick state machine and the pinned-tooltip
121
+ * lifecycle. The renderer drives this purely through
122
+ * `dispatchHover` / `dispatchLeave` / `dispatchClick` /
123
+ * `dispatchDblClick` — the host's `RawEventForwarder` captures DOM
124
+ * events on the GL canvas and posts them as `InteractionEvent`s.
125
+ *
126
+ * Pinning + cursor changes go through a {@link HostSink} so the actual
127
+ * DOM mutations happen host-side regardless of where the chart runs.
128
+ */
129
+ export declare class TooltipController {
130
+ private _callbacks;
131
+ private _hoverRAFId;
132
+ private _hoverTimeoutId;
133
+ private _host;
134
+ private _pinned;
135
+ get isPinned(): boolean;
136
+ /**
137
+ * Replace the active host sink. Dismisses any existing pin via the
138
+ * prior sink so we never leak a pinned artifact across resets —
139
+ * though in practice each chart instance uses one sink for its
140
+ * lifetime.
141
+ */
142
+ setHost(sink: HostSink): void;
143
+ /**
144
+ * Forward a cursor change to the host. No-op when no host sink is
145
+ * installed (chart constructed without a transport).
146
+ */
147
+ setCursor(cursor: string): void;
148
+ /**
149
+ * Install the chart's tooltip callbacks. The renderer drives the
150
+ * controller via `dispatchHover` / `dispatchLeave` /
151
+ * `dispatchClick` / `dispatchDblClick`; this controller never
152
+ * touches the DOM directly.
153
+ */
154
+ attach(callbacks: TooltipCallbacks): void;
155
+ detach(): void;
156
+ /**
157
+ * Schedule an `onHover` callback for the given canvas-relative
158
+ * coords. Coalesces multiple calls within one animation frame so
159
+ * pointer streams don't backlog the chart's hit-test path.
160
+ *
161
+ * Workers ship with `requestAnimationFrame` (DedicatedWorkerGlobalScope
162
+ * exposes it for OffscreenCanvas painting), so the same coalescer
163
+ * works in both modes. We fall back to setTimeout if RAF is missing
164
+ * (e.g. node tests without a polyfill).
165
+ */
166
+ dispatchHover(mx: number, my: number): void;
167
+ dispatchLeave(): void;
168
+ dispatchClick(mx: number, my: number): void;
169
+ dispatchDblClick(mx: number, my: number): void;
170
+ /**
171
+ * Pin a tooltip (or replace an active one). Forwards through the
172
+ * configured sink and flips the controller's pinned flag so hover
173
+ * dispatch is suppressed until dismissal.
174
+ */
175
+ pin(lines: string[], pos: {
176
+ px: number;
177
+ py: number;
178
+ }, bounds: CssBounds): void;
179
+ dismiss(): void;
180
+ }
181
+ /**
182
+ * Paint a canvas tooltip (crosshair, highlight ring, box + text) onto
183
+ * `canvas`. The helper normalizes the 2D context to a DPR-scaled
184
+ * identity transform on entry and restores prior state on exit, so it
185
+ * composes cleanly with other chrome painters that may have already
186
+ * called `initCanvas` on the same canvas — re-applying `scale(dpr,dpr)`
187
+ * blind would double-scale in that case, misplacing the tooltip
188
+ * proportionally to its distance from the origin.
189
+ */
190
+ export declare function renderCanvasTooltip(canvas: Canvas2D | null, pos: {
191
+ px: number;
192
+ py: number;
193
+ }, lines: string[], layout: PlotLayout, theme: Theme, dpr: number, options?: RenderTooltipOptions): void;
@@ -0,0 +1,106 @@
1
+ import type { PlotLayout } from "../layout/plot-layout";
2
+ export interface ZoomState {
3
+ scaleX: number;
4
+ scaleY: number;
5
+ normTranslateX: number;
6
+ normTranslateY: number;
7
+ }
8
+ /**
9
+ * Runtime config for `ZoomController`. Not part of `ZoomState` — wired
10
+ * by the owning chart at construction, not serialized with zoom level.
11
+ *
12
+ * `lockAxis` pins one axis at `scale=1, translate=0` and suppresses
13
+ * wheel / pan updates on that axis, leaving the other axis fully
14
+ * zoomable. Categorical axes are the typical candidates.
15
+ *
16
+ * `lockAspect` keeps `dataPerPixel` equal on both axes by padding the
17
+ * narrower axis of the rendered domain to match the plot rect's aspect
18
+ * ratio. Required by map plugins (Mercator preserves local angle, so
19
+ * map glyphs distort under independent X/Y zoom), and useful for any
20
+ * cartesian view where stretching points along one axis would lie
21
+ * about the data.
22
+ */
23
+ export interface ZoomConfig {
24
+ lockAxis?: "x" | "y" | null;
25
+ lockAspect?: boolean;
26
+ }
27
+ export declare const MAX_ZOOM = 100000;
28
+ export declare const MIN_ZOOM = 1;
29
+ export declare class ZoomController {
30
+ private _scaleX;
31
+ private _scaleY;
32
+ private _normTX;
33
+ private _normTY;
34
+ private _baseXMin;
35
+ private _baseXMax;
36
+ private _baseYMin;
37
+ private _baseYMax;
38
+ private _lockAxis;
39
+ private _lockAspect;
40
+ private _element;
41
+ private _layout;
42
+ private _onUpdate;
43
+ private _pointerDown;
44
+ private _lastPointerX;
45
+ private _lastPointerY;
46
+ private _onWheel;
47
+ private _onPointerDown;
48
+ private _onPointerMove;
49
+ private _onPointerUp;
50
+ get lockedAxis(): "x" | "y" | null;
51
+ get scaleX(): number;
52
+ get scaleY(): number;
53
+ set scaleX(v: number);
54
+ set scaleY(v: number);
55
+ get normTranslateX(): number;
56
+ get normTranslateY(): number;
57
+ set normTranslateX(v: number);
58
+ set normTranslateY(v: number);
59
+ get baseXRange(): number;
60
+ get baseYRange(): number;
61
+ /**
62
+ * Update the base (full-data) domain that this controller's
63
+ * normalized translate is interpreted against, while preserving
64
+ * the *absolute* center of any user-applied pan.
65
+ *
66
+ * `_normTX` / `_normTY` are stored as fractions of the base
67
+ * range, not absolute coordinates. A naive "swap base, keep
68
+ * normTranslate" update reinterprets the same fraction against a
69
+ * new range, so when an external `draw()` updates the extent
70
+ * (via `processCartesianChunk` → `setZoomBaseDomain`) the user's
71
+ * pan-offset visible center jumps to a different absolute
72
+ * position. With concurrent pan events feeding in offsets that
73
+ * were computed against the old base, the jump can project the
74
+ * visible center past the data entirely, leaving `_fullRender`
75
+ * to draw zero glyphs onto a freshly-cleared canvas — a blank
76
+ * bitmap reaches the host as a flicker.
77
+ *
78
+ * When the user is in default state (no pan, no zoom — fresh
79
+ * controller, or just-reset), no rebase is needed; just swap the
80
+ * base and let the chart auto-fit to the new data. Otherwise
81
+ * recompute `_normTX` / `_normTY` so the visible center stays at
82
+ * the same absolute (data-coordinate) position before and after
83
+ * the swap.
84
+ */
85
+ setBaseDomain(xMin: number, xMax: number, yMin: number, yMax: number): void;
86
+ /**
87
+ * Apply config. Called once by the chart during `setZoomController`.
88
+ * Locking an axis snaps its `scale`/`translate` to identity so any
89
+ * pre-existing state on that axis is cleared; subsequent wheel /
90
+ * pan events leave the locked axis alone.
91
+ */
92
+ configure(config: ZoomConfig): void;
93
+ isDefault(): boolean;
94
+ getVisibleDomain(): {
95
+ xMin: number;
96
+ xMax: number;
97
+ yMin: number;
98
+ yMax: number;
99
+ };
100
+ attach(element: HTMLElement, layout: PlotLayout, onUpdate: () => void): void;
101
+ updateLayout(layout: PlotLayout): void;
102
+ detach(): void;
103
+ reset(): void;
104
+ serialize(): ZoomState;
105
+ restore(state: ZoomState): void;
106
+ }
@@ -0,0 +1,48 @@
1
+ import type { PlotLayout } from "../layout/plot-layout";
2
+ import { type ZoomController } from "./zoom-controller";
3
+ /**
4
+ * Resolver that maps a cursor position to `{ controller, layout }` —
5
+ * returns `null` when the cursor is not inside any facet. In
6
+ * independent-zoom mode the facet under the cursor owns its events; in
7
+ * shared-zoom mode the resolver always returns the same controller for
8
+ * every plot rect in the grid.
9
+ */
10
+ export interface ZoomTarget {
11
+ controller: ZoomController;
12
+ layout: PlotLayout;
13
+ }
14
+ export type ZoomTargetResolver = (mx: number, my: number) => ZoomTarget | null;
15
+ /**
16
+ * One set of wheel / pointer listeners on the GL canvas that dispatches
17
+ * zoom + pan events to a {@link ZoomController} resolved from the
18
+ * cursor position. Replaces `ZoomController.attach` so multiple
19
+ * controllers (one per facet) can coexist on a single canvas.
20
+ */
21
+ export declare class ZoomRouter {
22
+ private _element;
23
+ private _resolve;
24
+ private _onUpdate;
25
+ private _pointerDown;
26
+ private _pointerTarget;
27
+ private _lastPointerX;
28
+ private _lastPointerY;
29
+ private _onWheel;
30
+ private _onPointerDown;
31
+ private _onPointerMove;
32
+ private _onPointerUp;
33
+ attach(element: HTMLElement, resolve: ZoomTargetResolver, onUpdate: () => void): void;
34
+ detach(): void;
35
+ }
36
+ /**
37
+ * Apply a wheel-zoom delta to the resolved target. Exported for
38
+ * re-use inside the worker, where the renderer dispatches interaction
39
+ * events forwarded from the host's `RawEventForwarder` instead of
40
+ * receiving DOM events directly.
41
+ */
42
+ export declare function applyWheel(target: ZoomTarget, mouseX: number, mouseY: number, deltaY: number): void;
43
+ /**
44
+ * Apply a drag-pan delta to the resolved target. Exported for the
45
+ * same reason as {@link applyWheel}: worker-mode interaction
46
+ * dispatch reuses the math without owning DOM listeners.
47
+ */
48
+ export declare function applyPan(target: ZoomTarget, dx: number, dy: number): void;