@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,469 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import type { ColumnDataMap } from "../../data/view-reader";
14
+ import type { WebGLContextManager } from "../../webgl/context-manager";
15
+ import { AbstractChart } from "../chart-base";
16
+ import { SpatialHitTester } from "../../interaction/hit-test";
17
+ import { PlotLayout } from "../../layout/plot-layout";
18
+ import { type AxisDomain } from "../../axis/numeric-axis";
19
+ import type { GradientTextureCache } from "../../webgl/gradient-texture";
20
+ import type { Glyph } from "./glyph";
21
+ import {
22
+ initCartesianPipeline,
23
+ processCartesianChunk,
24
+ } from "./cartesian-build";
25
+ import {
26
+ renderCartesianFrame,
27
+ renderCartesianChromeOverlay,
28
+ } from "./cartesian-render";
29
+ import {
30
+ handleCartesianHover,
31
+ showCartesianPinnedTooltip,
32
+ dismissCartesianPinnedTooltip,
33
+ } from "./cartesian-interact";
34
+ import type { LabelInterner } from "./label-interner";
35
+ import { LazyTooltip } from "../../interaction/lazy-tooltip";
36
+
37
+ export interface SplitGroup {
38
+ prefix: string;
39
+ xColName: string;
40
+ yColName: string;
41
+ colorColName: string;
42
+ sizeColName: string;
43
+ labelColName: string;
44
+ }
45
+
46
+ /**
47
+ * Unified continuous (numeric X/Y) chart. Glyphs plug in to render
48
+ * points, lines, or (future) areas over the shared data pipeline:
49
+ * streaming chunk upload, per-series slotted buffer layout, pan/zoom,
50
+ * spatial hit testing, chrome overlay, tooltip controller.
51
+ *
52
+ * Fields are package-internal (no `private`) so the split helper
53
+ * modules and glyphs can read/write them.
54
+ */
55
+ export class CartesianChart extends AbstractChart {
56
+ readonly glyph: Glyph;
57
+
58
+ constructor(glyph: Glyph) {
59
+ super();
60
+ this.glyph = glyph;
61
+ }
62
+
63
+ /**
64
+ * Rendering pipeline selector. `"cartesian"` is the default —
65
+ * draws axes, gridlines, and ticks via the chrome canvas.
66
+ * `"map"` (set by `MapChart` subclasses) suppresses cartesian
67
+ * chrome and inserts a raster tile layer underneath the glyph
68
+ * draw in `_fullRender`, so the same glyphs (point / line /
69
+ * density) render on top of a basemap.
70
+ *
71
+ * Read in `cartesian-render.ts` at three branch points; the
72
+ * `"cartesian"` path is byte-for-byte unchanged by the addition
73
+ * of this enum.
74
+ */
75
+ _renderMode: "cartesian" | "map" = "cartesian";
76
+
77
+ /**
78
+ * Per-point data-space projection hook. Default is identity; map
79
+ * subclasses override to map (lon, lat) → Mercator meters. Called
80
+ * from `processCartesianChunk` immediately after the NaN guard,
81
+ * before extent accumulation and the `_xData` / `_yData` slot
82
+ * writes — so every downstream consumer (axis domain, projection
83
+ * matrix, spatial hit-test, glyph buffers) sees projected space
84
+ * uniformly. Returning `[NaN, NaN]` from a subclass discards the
85
+ * row (e.g. Mercator's ±85° latitude clamp).
86
+ */
87
+ projectPoint(x: number, y: number): [number, number] {
88
+ return [x, y];
89
+ }
90
+
91
+ /**
92
+ * Paint a per-frame background inside the plot-frame scissor,
93
+ * before the glyph draw. Map subclasses override to render the
94
+ * raster tile basemap; the default no-op leaves cartesian charts
95
+ * byte-for-byte unchanged.
96
+ *
97
+ * Called once per facet in faceted mode (each call's `projection`
98
+ * and `domain` are that cell's), wrapped in the cell's scissor —
99
+ * just like `glyph.drawSeries`.
100
+ *
101
+ * `xOrigin` / `yOrigin` are the rebase origins the projection
102
+ * matrix bakes in (see `buildProjectionMatrix`). Glyphs ship
103
+ * pre-rebased positions, so the background pass must subtract
104
+ * them from absolute-domain coords (e.g. tile Mercator extents)
105
+ * before uploading vertex positions; otherwise the matrix
106
+ * over-corrects and the background lands off-screen by
107
+ * `sx * xOrigin` clip units.
108
+ */
109
+ renderBackground(
110
+ _glManager: import("../../webgl/context-manager").WebGLContextManager,
111
+ _layout: import("../../layout/plot-layout").PlotLayout,
112
+ _projection: Float32Array,
113
+ _domain: { xMin: number; xMax: number; yMin: number; yMax: number },
114
+ _xOrigin: number,
115
+ _yOrigin: number,
116
+ ): void {
117
+ // no-op for cartesian charts
118
+ }
119
+
120
+ /**
121
+ * Paint chrome (attribution, scale bar) for map mode on top of the
122
+ * chrome canvas, in place of the cartesian axes/gridlines/legend.
123
+ * Called only when `_renderMode === "map"`. Default no-op so
124
+ * cartesian charts still go through `renderAxesChrome`.
125
+ */
126
+ renderMapChrome(
127
+ _canvas: import("../canvas-types").Canvas2D | null,
128
+ _layout: import("../../layout/plot-layout").PlotLayout,
129
+ _theme: import("../../theme/theme").Theme,
130
+ _dpr: number,
131
+ ): void {
132
+ // no-op for cartesian charts
133
+ }
134
+
135
+ // GL resources
136
+ // Shared: gradient LUT texture (used by both glyphs for color mapping).
137
+ _gradientCache: GradientTextureCache | null = null;
138
+
139
+ // Column roles
140
+ _xName = "";
141
+ _yName = "";
142
+ _xLabel = "";
143
+ _yLabel = "";
144
+ _xIsRowIndex = false;
145
+ _colorName = "";
146
+ _sizeName = "";
147
+ _labelName = "";
148
+ _colorIsString = false;
149
+ _splitGroups: SplitGroup[] = [];
150
+
151
+ // Data extents
152
+ _xMin = Infinity;
153
+ _xMax = -Infinity;
154
+ _yMin = Infinity;
155
+ _yMax = -Infinity;
156
+
157
+ /**
158
+ * Origin used to rebase x values before f32 narrowing. With datetime
159
+ * x columns the absolute timestamp is ~1.7e12, beyond f32 precision;
160
+ * storing `(x - _xOrigin)` keeps sub-millisecond fidelity in the
161
+ * `_xData` mirror, the GPU position attribute, and the projection
162
+ * matrix's `tx` term, avoiding the catastrophic cancellation that
163
+ * would otherwise push points outside the clip volume. NaN until
164
+ * the first valid x sample is observed.
165
+ */
166
+ _xOrigin = NaN;
167
+ _yOrigin = NaN;
168
+ _colorMin = Infinity;
169
+ _colorMax = -Infinity;
170
+ _sizeMin = Infinity;
171
+ _sizeMax = -Infinity;
172
+
173
+ /**
174
+ * `domain_mode: "expand"` accumulators. The build pipeline seeds
175
+ * `_xMin/_xMax/_yMin/_yMax/_colorMin/_colorMax/_sizeMin/_sizeMax`
176
+ * from these instead of `±Infinity` when expand mode is active, so
177
+ * the per-row scan naturally unions new data into the running
178
+ * extent. Mirrored back from the live fields at the end of every
179
+ * `processCartesianChunk` so multi-chunk uploads accumulate into
180
+ * the same union. Cleared via `resetExpandedDomain` (called from
181
+ * the worker's `resetAllZooms` and the view-config setters on
182
+ * `AbstractChart`).
183
+ */
184
+ _expandedXMin = Infinity;
185
+ _expandedXMax = -Infinity;
186
+ _expandedYMin = Infinity;
187
+ _expandedYMax = -Infinity;
188
+ _expandedColorMin = Infinity;
189
+ _expandedColorMax = -Infinity;
190
+ _expandedSizeMin = Infinity;
191
+ _expandedSizeMax = -Infinity;
192
+
193
+ // Data buffers (per-series slotted)
194
+ // Series `s` owns indices `[s*_seriesCapacity, (s+1)*_seriesCapacity)`
195
+ // in the flat `_xData`/`_yData`/`_colorData` arrays and their GPU
196
+ // counterparts. `_seriesUploadedCounts[s]` tracks how many slots at
197
+ // the head of series `s` hold valid data; glyphs dispatch tight
198
+ // per-series draws using this count so the tail slots are never
199
+ // rasterized.
200
+ _seriesCapacity = 0;
201
+ _seriesUploadedCounts: number[] = [];
202
+ _maxSeriesUploaded = 0;
203
+
204
+ _xData: Float32Array | null = null;
205
+ _yData: Float32Array | null = null;
206
+ _colorData: Float32Array | null = null;
207
+
208
+ /**
209
+ * Source view row index for each slot in `_xData` / `_yData`,
210
+ * sized and laid out identically. Split expansion duplicates the
211
+ * same arrow source row across every series; this sidecar stores
212
+ * that source index so lazy tooltip fetches can retrieve the
213
+ * original row. Int32 for compactness — at 1M points this is
214
+ * ~4 MB, a small fraction of the ~70 MB that the prior eager
215
+ * row-data buffers cost.
216
+ */
217
+ _rowIndexData: Int32Array | null = null;
218
+
219
+ /**
220
+ * Slot-indexed string store for the scatter "Label" column. `null`
221
+ * when no label column was wired. See {@link LabelInterner} — the
222
+ * three formerly-separate label fields (`_labelData`,
223
+ * `_labelDictionary`, `_labelDictMap`) live there as one unit, so
224
+ * future label-related state stays cohesive instead of accreting
225
+ * sibling fields on the chart.
226
+ */
227
+ _labels: LabelInterner | null = null;
228
+ _dataCount = 0;
229
+ _uniqueColorLabels: Map<string, number> = new Map();
230
+
231
+ /**
232
+ * Lazy-tooltip cache. `lines` is `null` until the async row fetch
233
+ * resolves — the chrome overlay skips the tooltip text box in
234
+ * that state but still paints the crosshair + highlight ring
235
+ * from geometry data so the hover cue is immediate. The
236
+ * controller owns the serial dance that drops stale resolves
237
+ * when the user moves before the fetch returns. Target type is
238
+ * the flat slot index of the hovered point.
239
+ */
240
+ _lazyTooltip = new LazyTooltip<number>();
241
+
242
+ // Staging scratch (reused across chunks)
243
+ _stagingPositions: Float32Array | null = null;
244
+ _stagingColors: Float32Array | null = null;
245
+ _stagingSizes: Float32Array | null = null;
246
+ _stagingChunkSize = 0;
247
+
248
+ // Interaction
249
+ _hitTest = new SpatialHitTester();
250
+ _lastLayout: PlotLayout | null = null;
251
+ _hoveredIndex = -1;
252
+ _pinnedIndex = -1;
253
+
254
+ /**
255
+ * Source facet for the current hover (`-1` when not over any facet).
256
+ * Drives coordinated hover indicator painting in other facets.
257
+ */
258
+ _hoveredFacet = -1;
259
+
260
+ // Facet state (set when rendering in grid mode)
261
+ _facetGrid: import("../../layout/facet-grid").FacetGrid | null = null;
262
+
263
+ // Last-frame cache (for chrome overlay-only redraws)
264
+ _lastXDomain: AxisDomain | null = null;
265
+ _lastYDomain: AxisDomain | null = null;
266
+ _lastXTicks: number[] | null = null;
267
+ _lastYTicks: number[] | null = null;
268
+ _lastGradientStops: import("../../theme/gradient").GradientStop[] | null =
269
+ null;
270
+ _lastHasColorCol = false;
271
+
272
+ // Memoized categorical LUT stops — `ensureGradientTexture` uses
273
+ // reference-equality on this array to skip rebuilding the 256-sample
274
+ // texture. The cache key carries the inputs that determine the
275
+ // resolved palette: `seriesPalette` reference (changes per theme,
276
+ // since `_resolveTheme` returns a fresh `Theme` after
277
+ // `invalidateTheme()` clears the cache) plus `labelCount`. Without
278
+ // the `seriesPalette` reference compare a `restyle()` could leave
279
+ // the chart painting with the prior theme's colors — same
280
+ // `labelCount`/palette length but different RGB values.
281
+ _lastLutStops: import("../../theme/gradient").GradientStop[] | null = null;
282
+ _lastLutSeriesPalette: [number, number, number][] | null = null;
283
+ _lastLutLabelCount = -1;
284
+
285
+ protected override tooltipCallbacks() {
286
+ return {
287
+ onHover: (mx: number, my: number) =>
288
+ handleCartesianHover(this, mx, my),
289
+ onLeave: () => {
290
+ if (this._hoveredIndex !== -1) {
291
+ this._hoveredIndex = -1;
292
+ renderCartesianChromeOverlay(this);
293
+ }
294
+ },
295
+ onPin: (mx: number, my: number) => {
296
+ // Refresh the hit-test at the click coords so the pin
297
+ // path doesn't depend on the RAF-throttled hover state
298
+ // — see comment in `series.ts` `onPin`.
299
+ handleCartesianHover(this, mx, my);
300
+ if (this._hoveredIndex >= 0) {
301
+ const flatIdx = this._hoveredIndex;
302
+ showCartesianPinnedTooltip(this, flatIdx);
303
+ void this._emitCartesianClickSelect(flatIdx);
304
+ }
305
+ },
306
+ onUnpin: () => {
307
+ this.emitUnselect();
308
+ },
309
+ };
310
+ }
311
+
312
+ /**
313
+ * Resolve a clicked cartesian point into a `PerspectiveClickDetail`
314
+ * and emit both `perspective-click` and
315
+ * `perspective-global-filter selected:true`.
316
+ *
317
+ * Cartesian charts don't use `group_by` for positioning; X and Y
318
+ * come from explicit user-selected columns. The only filter clause
319
+ * we can build is the split-by prefix (when present). The source
320
+ * row index is the chart's per-point `_rowIndexData[flatIdx]`
321
+ * mirror — same lookup the lazy tooltip uses.
322
+ */
323
+ private async _emitCartesianClickSelect(flatIdx: number): Promise<void> {
324
+ if (!this._rowIndexData) {
325
+ return;
326
+ }
327
+
328
+ const rowIdx = this._rowIndexData[flatIdx];
329
+ const yColumn = this._columnSlots[1] || this._columnSlots[0] || "";
330
+
331
+ let splitByValues: (string | null)[] = [];
332
+ if (this._splitGroups.length > 0 && this._seriesCapacity > 0) {
333
+ const seriesIdx = Math.floor(flatIdx / this._seriesCapacity);
334
+ const sg = this._splitGroups[seriesIdx];
335
+ if (sg?.prefix && this._splitBy.length > 0) {
336
+ splitByValues = sg.prefix.split("|");
337
+ }
338
+ }
339
+
340
+ await this.emitClickAndSelect({
341
+ rowIdx: rowIdx != null && rowIdx >= 0 ? rowIdx : null,
342
+ columnName: yColumn,
343
+ groupByValues: [],
344
+ splitByValues,
345
+ });
346
+ }
347
+
348
+ async uploadAndRender(
349
+ glManager: WebGLContextManager,
350
+ columns: ColumnDataMap,
351
+ startRow: number,
352
+ endRow: number,
353
+ ): Promise<void> {
354
+ const chunkLength = endRow - startRow;
355
+ this._glManager = glManager;
356
+ if (startRow === 0) {
357
+ initCartesianPipeline(this, glManager, columns, endRow);
358
+ }
359
+
360
+ if (chunkLength === 0) {
361
+ return;
362
+ }
363
+
364
+ processCartesianChunk(
365
+ this,
366
+ glManager,
367
+ columns,
368
+ startRow,
369
+ chunkLength,
370
+ endRow,
371
+ );
372
+
373
+ // `domain_mode: "expand"` mirror-back. `processCartesianChunk`
374
+ // updates `_xMin/_xMax` etc. in place against the seeded value
375
+ // (the prior accumulator); the union is in `_xMin` etc., so we
376
+ // copy it back. Idempotent across multi-chunk uploads — every
377
+ // chunk leaves the accumulator equal to the running union.
378
+ if (this._pluginConfig.domain_mode === "expand") {
379
+ this._expandedXMin = this._xMin;
380
+ this._expandedXMax = this._xMax;
381
+ this._expandedYMin = this._yMin;
382
+ this._expandedYMax = this._yMax;
383
+ this._expandedColorMin = this._colorMin;
384
+ this._expandedColorMax = this._colorMax;
385
+ this._expandedSizeMin = this._sizeMin;
386
+ this._expandedSizeMax = this._sizeMax;
387
+ }
388
+
389
+ await this.requestRender(glManager);
390
+ }
391
+
392
+ override resetExpandedDomain(): void {
393
+ this._expandedXMin = Infinity;
394
+ this._expandedXMax = -Infinity;
395
+ this._expandedYMin = Infinity;
396
+ this._expandedYMax = -Infinity;
397
+ this._expandedColorMin = Infinity;
398
+ this._expandedColorMax = -Infinity;
399
+ this._expandedSizeMin = Infinity;
400
+ this._expandedSizeMax = -Infinity;
401
+ }
402
+
403
+ _fullRender(glManager: WebGLContextManager): void {
404
+ if (glManager.uploadedCount === 0 && this._dataCount === 0) {
405
+ return;
406
+ }
407
+
408
+ this._glManager = glManager;
409
+ renderCartesianFrame(this, glManager);
410
+ }
411
+
412
+ protected destroyInternal(): void {
413
+ this.glyph.destroy(this);
414
+ this._gradientCache = null;
415
+ this._xData = null;
416
+ this._yData = null;
417
+ this._colorData = null;
418
+ this._rowIndexData = null;
419
+ this._labels = null;
420
+ this._lazyTooltip.clearHover();
421
+ this._uniqueColorLabels.clear();
422
+ this._hitTest.clear();
423
+ this._stagingPositions = null;
424
+ this._stagingColors = null;
425
+ this._stagingSizes = null;
426
+ this._splitGroups = [];
427
+ this._seriesUploadedCounts = [];
428
+ dismissCartesianPinnedTooltip(this);
429
+ }
430
+ }
431
+
432
+ // Convenience subclasses with nullary constructors
433
+ // `index.ts` registers plugin tags via `new ImplClass()`, so each chart
434
+ // type needs a parameterless constructor. These wrappers pin the glyph.
435
+
436
+ import { PointGlyph } from "./glyphs/points";
437
+ import { LineGlyph } from "./glyphs/lines";
438
+ import { DensityGlyph } from "./glyphs/density";
439
+
440
+ /**
441
+ * X/Y Scatter — continuous chart with the point glyph.
442
+ */
443
+ export class ScatterChart extends CartesianChart {
444
+ constructor() {
445
+ super(new PointGlyph());
446
+ }
447
+ }
448
+
449
+ /**
450
+ * X/Y Line — continuous chart with the line glyph.
451
+ */
452
+ export class LineChart extends CartesianChart {
453
+ constructor() {
454
+ super(new LineGlyph());
455
+ }
456
+ }
457
+
458
+ /**
459
+ * Density — continuous chart that rasterizes each row as an
460
+ * additive radial splat, producing a density field over the plot rect.
461
+ * Shares the cartesian pipeline (build, hit-test, zoom, facets,
462
+ * tooltips); the glyph swaps the per-point glyph for the heat
463
+ * accumulation + resolve pair.
464
+ */
465
+ export class DensityChart extends CartesianChart {
466
+ constructor() {
467
+ super(new DensityGlyph());
468
+ }
469
+ }
@@ -0,0 +1,81 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import type { WebGLContextManager } from "../../webgl/context-manager";
14
+ import type { CartesianChart } from "./cartesian";
15
+
16
+ /**
17
+ * A Glyph is a pluggable renderer for a {@link CartesianChart}. The
18
+ * chart owns all data and shared pipeline (init, chunk processing, hover,
19
+ * chrome, tooltip plumbing); the glyph owns its shader program, draw
20
+ * call, and per-glyph tooltip lines.
21
+ */
22
+ export interface Glyph {
23
+ /**
24
+ * `"point"` for scatter-style markers; `"line"` for polylines;
25
+ * `"density"` for the density-field shader glyph.
26
+ */
27
+ readonly name: "point" | "line" | "density";
28
+
29
+ /**
30
+ * Compile the program + cache attrib/uniform locations on first
31
+ * frame. Subsequent frames are a no-op.
32
+ */
33
+ ensureProgram(chart: CartesianChart, glManager: WebGLContextManager): void;
34
+
35
+ /**
36
+ * Issue the draw call(s) for this glyph's visible geometry.
37
+ */
38
+ draw(
39
+ chart: CartesianChart,
40
+ glManager: WebGLContextManager,
41
+ projection: Float32Array,
42
+ ): void;
43
+
44
+ /**
45
+ * Issue draw calls for a single series' slice only. Used by
46
+ * faceted rendering: one facet per split, each facet's scissor
47
+ * clips to its plot rect and only that series rasterizes inside.
48
+ *
49
+ * Implementations should bind uniforms/buffers once (same as
50
+ * `draw`) and dispatch only the drawArrays call(s) for
51
+ * `seriesIdx`.
52
+ */
53
+ drawSeries(
54
+ chart: CartesianChart,
55
+ glManager: WebGLContextManager,
56
+ projection: Float32Array,
57
+ seriesIdx: number,
58
+ ): void;
59
+
60
+ /**
61
+ * Per-hover tooltip content for the point at `flatIdx`. Returns a
62
+ * Promise because some glyphs (notably `PointGlyph`) need to fetch
63
+ * the source row from the view on demand for extra-column lookups.
64
+ * Glyphs whose tooltip is geometry-only (e.g. `LineGlyph`) return
65
+ * a microtask-resolved promise.
66
+ */
67
+ buildTooltipLines(
68
+ chart: CartesianChart,
69
+ flatIdx: number,
70
+ ): Promise<string[]>;
71
+
72
+ /**
73
+ * Hover-overlay options (crosshair, highlight radius).
74
+ */
75
+ tooltipOptions(): { crosshair: boolean; highlightRadius: number };
76
+
77
+ /**
78
+ * Release GL resources created by `ensureProgram`.
79
+ */
80
+ destroy(chart: CartesianChart): void;
81
+ }