@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,247 @@
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 { TreeChartBase } from "../common/tree-chart";
16
+ import { NULL_NODE } from "../common/node-store";
17
+ import {
18
+ type BreadcrumbRegion,
19
+ processTreemapChunk,
20
+ finalizeTreemap,
21
+ resetTreemapState,
22
+ } from "./treemap-layout";
23
+ import { renderTreemapFrame } from "./treemap-render";
24
+ import {
25
+ handleTreemapHover,
26
+ handleTreemapClick,
27
+ handleTreemapDblClick,
28
+ dismissTreemapPinnedTooltip,
29
+ } from "./treemap-interact";
30
+
31
+ export interface TreemapLocations {
32
+ u_resolution: WebGLUniformLocation | null;
33
+ a_position: number;
34
+ a_color: number;
35
+ }
36
+
37
+ /**
38
+ * Sentinel fallback for the Size slot when the user hasn't picked one:
39
+ * use the first non-metadata column in the incoming view. Treemap
40
+ * still needs *some* numeric-ish column to size rects.
41
+ */
42
+ function firstNonMetadataColumn(columns: ColumnDataMap): string {
43
+ for (const k of columns.keys()) {
44
+ if (!k.startsWith("__")) {
45
+ return k;
46
+ }
47
+ }
48
+
49
+ return "";
50
+ }
51
+
52
+ /**
53
+ * Treemap chart. Shares tree storage + streaming-pipeline + color-mode
54
+ * state with `TreeChartBase`; adds rectangular layout + WebGL quad
55
+ * rendering + drill / tooltip interactions.
56
+ */
57
+ export class TreemapChart extends TreeChartBase {
58
+ _program: WebGLProgram | null = null;
59
+ _locations: TreemapLocations | null = null;
60
+ _positionBuffer: WebGLBuffer | null = null;
61
+ _colorBuffer: WebGLBuffer | null = null;
62
+ _vertexCount = 0;
63
+
64
+ // Interaction
65
+ _hoveredNodeId: number = NULL_NODE;
66
+ _pinnedNodeId: number = NULL_NODE;
67
+ _breadcrumbRegions: BreadcrumbRegion[] = [];
68
+ _chromeCache: ImageBitmap | null = null;
69
+ _chromeCacheDirty = true;
70
+
71
+ /**
72
+ * Monotonic generation counter bumped every time the static chrome
73
+ * content changes (a new `drawStaticChrome` call). The async
74
+ * `createImageBitmap` callback captures the current gen at kickoff
75
+ * and only installs the resulting bitmap if its gen is still the
76
+ * most-recent one. Without this, out-of-order bitmap resolutions
77
+ * can store a stale bitmap in `_chromeCache` — any subsequent
78
+ * hover-only overlay call then blits that stale snapshot over the
79
+ * fresh chart, producing "leftover labels / cells" artefacts.
80
+ */
81
+ _chromeCacheGen = 0;
82
+
83
+ // Faceted state
84
+ /**
85
+ * Per-facet drill roots in split_by mode. Key is the facet label
86
+ * (the top-level child of `_rootId`); value is the currently drilled
87
+ * node inside that facet's subtree. Missing keys mean the facet
88
+ * shows its full subtree.
89
+ */
90
+ _facetDrillRoots: Map<string, number> = new Map();
91
+ _facetGrid: import("../../layout/facet-grid").FacetGrid | null = null;
92
+
93
+ /** When `false`, branch nodes at relDepth=1 render as a centered
94
+ * overlay (same style as relDepth=2) and no top-of-rect label
95
+ * reservation is made in `squarify`. Default `true` preserves the
96
+ * legacy title-bar look. */
97
+ _showBranchHeader = false;
98
+
99
+ /**
100
+ * Parallel to `_visibleNodeIds`. Each entry stores the depth of the
101
+ * drill root that owns the corresponding visible node, so render
102
+ * paths can compute `relDepth` uniformly without knowing whether
103
+ * faceting is active. Populated in `renderTreemapFrame` during
104
+ * layout.
105
+ */
106
+ _visibleBaseDepths: Int32Array | null = null;
107
+
108
+ /**
109
+ * Parallel to `_visibleNodeIds`. The drill-root node id that owns
110
+ * each visible node (= `_currentRootId` in non-facet mode, per-
111
+ * facet drill root in facet mode). Used by hit-testing and chrome
112
+ * to skip the drill-root itself without a separate equality check.
113
+ */
114
+ _visibleRootIds: Int32Array | null = null;
115
+
116
+ protected override tooltipCallbacks() {
117
+ return {
118
+ onHover: (mx: number, my: number) =>
119
+ handleTreemapHover(this, mx, my),
120
+ onLeave: () => {
121
+ if (
122
+ this._hoveredNodeId !== NULL_NODE &&
123
+ this._pinnedNodeId === NULL_NODE
124
+ ) {
125
+ this._hoveredNodeId = NULL_NODE;
126
+ if (this._glManager) {
127
+ renderTreemapFrame(this, this._glManager);
128
+ }
129
+ }
130
+ },
131
+ onClickPre: (mx: number, my: number) => {
132
+ handleTreemapClick(this, mx, my);
133
+ return true; // treemap owns all click logic
134
+ },
135
+ onDblClick: (mx: number, my: number) =>
136
+ handleTreemapDblClick(this, mx, my),
137
+ };
138
+ }
139
+
140
+ async uploadAndRender(
141
+ glManager: WebGLContextManager,
142
+ columns: ColumnDataMap,
143
+ startRow: number,
144
+ _endRow: number,
145
+ ): Promise<void> {
146
+ this._glManager = glManager;
147
+
148
+ if (startRow === 0) {
149
+ const slots = this._columnSlots;
150
+ this._sizeName = slots[0] || firstNonMetadataColumn(columns) || "";
151
+ this._colorName = slots[1] || "";
152
+ if (!this._colorName) {
153
+ this._colorMode = "empty";
154
+ } else {
155
+ const t = this._columnTypes[this._colorName];
156
+ const isNumeric =
157
+ t === "float" ||
158
+ t === "integer" ||
159
+ t === "date" ||
160
+ t === "datetime";
161
+ this._colorMode = isNumeric ? "numeric" : "series";
162
+ }
163
+
164
+ // Clear per-draw state that's tied to the OLD tree. Node
165
+ // IDs from the previous render don't map to anything in
166
+ // the fresh tree; leaving them around lets stale drill
167
+ // roots, hovered/pinned IDs, breadcrumb regions, the
168
+ // cached chrome bitmap, or an old WebGL vertex count bleed
169
+ // into the new render as ghost rects / labels / hit
170
+ // targets. See tree-data.ts's `resetTreeState` for the
171
+ // shared fields; everything below is treemap-specific.
172
+ this._hoveredNodeId = NULL_NODE;
173
+ this._pinnedNodeId = NULL_NODE;
174
+ this._breadcrumbRegions = [];
175
+ this._facetDrillRoots.clear();
176
+ this._facetGrid = null;
177
+ this._visibleBaseDepths = null;
178
+ this._visibleRootIds = null;
179
+
180
+ // Invalidate the GPU buffer contents so any render that
181
+ // fires before `generateAndUploadTreemap` has refilled the
182
+ // buffers draws zero triangles instead of the previous
183
+ // tree's geometry.
184
+ this._vertexCount = 0;
185
+
186
+ // Drop any in-flight hover tooltip promise — bumping the
187
+ // controller's serials makes stale resolutions no-ops
188
+ // rather than painting old lines on the new chart.
189
+ this._lazyTooltip.clearHover();
190
+ this._lazyTooltip.invalidatePin();
191
+ dismissTreemapPinnedTooltip(this);
192
+ this._chromeCache?.close();
193
+ this._chromeCache = null;
194
+ this._chromeCacheDirty = true;
195
+ this._chromeCacheGen++;
196
+
197
+ resetTreemapState(this);
198
+ }
199
+
200
+ processTreemapChunk(this, columns);
201
+ finalizeTreemap(this);
202
+ if (this._rootId !== NULL_NODE) {
203
+ await this.requestRender(glManager);
204
+ }
205
+ }
206
+
207
+ _fullRender(glManager: WebGLContextManager): void {
208
+ if (this._rootId === NULL_NODE) {
209
+ return;
210
+ }
211
+
212
+ this._glManager = glManager;
213
+ renderTreemapFrame(this, glManager);
214
+ }
215
+
216
+ protected destroyInternal(): void {
217
+ dismissTreemapPinnedTooltip(this);
218
+ this._chromeCache?.close();
219
+ this._chromeCache = null;
220
+ const gl = this._glManager?.gl;
221
+ if (gl) {
222
+ if (this._positionBuffer) {
223
+ gl.deleteBuffer(this._positionBuffer);
224
+ }
225
+
226
+ if (this._colorBuffer) {
227
+ gl.deleteBuffer(this._colorBuffer);
228
+ }
229
+ }
230
+
231
+ this._positionBuffer = null;
232
+ this._colorBuffer = null;
233
+ this._program = null;
234
+ this._locations = null;
235
+ this._rootId = NULL_NODE;
236
+ this._currentRootId = NULL_NODE;
237
+ this._breadcrumbIds = [];
238
+ this._childLookup.clear();
239
+ this._visibleNodeIds = null;
240
+ this._visibleNodeCount = 0;
241
+ this._breadcrumbRegions = [];
242
+ this._facetDrillRoots.clear();
243
+ this._facetGrid = null;
244
+ this._visibleBaseDepths = null;
245
+ this._visibleRootIds = null;
246
+ }
247
+ }
@@ -0,0 +1,41 @@
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
+ /**
14
+ * Renderer mode. `"worker"` runs the chart code in a Web Worker (off
15
+ * the main thread, gets parallelism but pays a postMessage hop on
16
+ * every interaction). `"inprocess"` dynamic-imports the same worker
17
+ * module on the main thread so the bundle stays single-copy without
18
+ * the worker boundary. The two paths share a `MessageChannel`-shaped
19
+ * control protocol — only the handle around it differs.
20
+ */
21
+ export const RUNTIME_MODE: "worker" | "inprocess" = "worker";
22
+
23
+ /**
24
+ * Build-time toggle between the two GL-canvas display strategies.
25
+ *
26
+ * - `"direct"` — host transfers `.webgl-canvas` to the renderer via
27
+ * `transferControlToOffscreen`. The renderer's GL context renders
28
+ * straight into the visible drawing buffer.
29
+ *
30
+ * - `"blit"` — host keeps the visible canvas main-thread with a 2D
31
+ * context. The renderer creates its own internal `OffscreenCanvas`
32
+ * for GL rendering and emits each completed frame as an
33
+ * `ImageBitmap` over the control channel; the host blits the bitmap
34
+ * into the visible canvas via `drawImage`.
35
+ */
36
+ export const RENDER_BLIT_MODE: "direct" | "blit" = "direct";
37
+
38
+ /**
39
+ * Strict-mode validation for `BufferPool.upload`.
40
+ */
41
+ export const BUFFER_POOL_STRICT: boolean = false;
@@ -0,0 +1,140 @@
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 { View } from "@perspective-dev/client";
14
+
15
+ /**
16
+ * A single row's column values, keyed by column name. Numeric columns
17
+ * yield a `number`; string (dictionary) columns yield the decoded
18
+ * `string`; invalid (null) cells yield `null`.
19
+ */
20
+ export type LazyRow = Map<string, string | number | null>;
21
+
22
+ const DEFAULT_CACHE_SIZE = 128;
23
+
24
+ /**
25
+ * On-demand single-row fetcher backing lazy tooltip lookups. Given a
26
+ * view row index, performs `view.with_typed_arrays({start_row, end_row:
27
+ * start_row+1})` and projects the result into a plain `Map`. Concurrent
28
+ * fetches for the same index are deduped into one Promise; resolved
29
+ * rows are cached in a bounded LRU keyed by rowIdx.
30
+ *
31
+ * Invalidation is lifecycle-driven: the owning chart disposes and
32
+ * constructs a new fetcher whenever its underlying view changes (i.e.
33
+ * on each `draw`). In-flight fetches from the prior fetcher still
34
+ * resolve, but callers stamp each fetch with a serial and discard
35
+ * results whose serial no longer matches — so stale rows never reach
36
+ * the tooltip. See the per-chart hover/pin paths for that plumbing.
37
+ */
38
+ export class LazyRowFetcher {
39
+ private _view: View | null;
40
+ private _cache: Map<number, LazyRow> = new Map();
41
+ private _inFlight: Map<number, Promise<LazyRow>> = new Map();
42
+ private readonly _maxCacheSize: number;
43
+
44
+ constructor(view: View, maxCacheSize: number = DEFAULT_CACHE_SIZE) {
45
+ this._view = view;
46
+ this._maxCacheSize = maxCacheSize;
47
+ }
48
+
49
+ async fetchRow(rowIdx: number): Promise<LazyRow> {
50
+ if (!this._view) {
51
+ throw new Error("LazyRowFetcher disposed");
52
+ }
53
+
54
+ const cached = this._cache.get(rowIdx);
55
+ if (cached) {
56
+ // LRU touch: re-insert to move to tail.
57
+ this._cache.delete(rowIdx);
58
+ this._cache.set(rowIdx, cached);
59
+ return cached;
60
+ }
61
+
62
+ const inflight = this._inFlight.get(rowIdx);
63
+ if (inflight) {
64
+ return inflight;
65
+ }
66
+
67
+ const p = this._fetch(rowIdx);
68
+ this._inFlight.set(rowIdx, p);
69
+ try {
70
+ const result = await p;
71
+ if (!this._view) {
72
+ return result;
73
+ } // disposed mid-flight
74
+
75
+ this._cache.set(rowIdx, result);
76
+ if (this._cache.size > this._maxCacheSize) {
77
+ const oldest = this._cache.keys().next().value;
78
+ if (oldest !== undefined) {
79
+ this._cache.delete(oldest);
80
+ }
81
+ }
82
+
83
+ return result;
84
+ } finally {
85
+ this._inFlight.delete(rowIdx);
86
+ }
87
+ }
88
+
89
+ private async _fetch(rowIdx: number): Promise<LazyRow> {
90
+ const view = this._view;
91
+ if (!view) {
92
+ throw new Error("LazyRowFetcher disposed");
93
+ }
94
+
95
+ const row: LazyRow = new Map();
96
+ await (view as any).with_typed_arrays(
97
+ {
98
+ start_row: rowIdx,
99
+ end_row: rowIdx + 1,
100
+ float32: true,
101
+ },
102
+ (
103
+ names: string[],
104
+ values: ArrayLike<number>[],
105
+ validities: (Uint8Array | null)[],
106
+ dictionaries: (string[] | null)[],
107
+ ) => {
108
+ for (let i = 0; i < names.length; i++) {
109
+ const name = names[i];
110
+ if (name.startsWith("__")) {
111
+ continue;
112
+ }
113
+
114
+ const vals = values[i];
115
+ const valid = validities[i];
116
+ const dict = dictionaries[i];
117
+ const isInvalid = valid ? !((valid[0] >> 0) & 1) : false;
118
+ if (isInvalid) {
119
+ row.set(name, null);
120
+ } else if (dict) {
121
+ row.set(name, dict[vals[0] as number]);
122
+ } else {
123
+ row.set(name, vals[0] as number);
124
+ }
125
+ }
126
+ },
127
+ );
128
+ return row;
129
+ }
130
+
131
+ dispose(): void {
132
+ this._view = null;
133
+ this._cache.clear();
134
+ this._inFlight.clear();
135
+ }
136
+
137
+ get isDisposed(): boolean {
138
+ return this._view === null;
139
+ }
140
+ }
@@ -0,0 +1,97 @@
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 "./view-reader";
14
+
15
+ export interface SplitGroup {
16
+ /**
17
+ * Composite prefix (e.g., "East", "East|Enterprise" for multi-level).
18
+ */
19
+ prefix: string;
20
+
21
+ /**
22
+ * Map of base column name → full Arrow column name ("prefix|base").
23
+ */
24
+ colNames: Map<string, string>;
25
+ }
26
+
27
+ /**
28
+ * Group Arrow column names by their split prefix (everything before the
29
+ * last "|"). A split exists for a prefix only when every `requiredBases`
30
+ * entry has a non-empty column present for that prefix. `optionalBases`
31
+ * are included when present but do not gate group inclusion.
32
+ *
33
+ * Empty/falsy entries in either base list are skipped.
34
+ */
35
+ export function buildSplitGroups(
36
+ columns: ColumnDataMap,
37
+ requiredBases: string[],
38
+ optionalBases: string[] = [],
39
+ ): SplitGroup[] {
40
+ const prefixCols = new Map<string, Set<string>>();
41
+ for (const key of columns.keys()) {
42
+ if (key.startsWith("__")) {
43
+ continue;
44
+ }
45
+
46
+ const pipeIdx = key.lastIndexOf("|");
47
+ if (pipeIdx === -1) {
48
+ continue;
49
+ }
50
+
51
+ const prefix = key.substring(0, pipeIdx);
52
+ if (!prefixCols.has(prefix)) {
53
+ prefixCols.set(prefix, new Set());
54
+ }
55
+
56
+ prefixCols.get(prefix)!.add(key);
57
+ }
58
+
59
+ const out: SplitGroup[] = [];
60
+ for (const [prefix, keys] of prefixCols) {
61
+ const resolved = new Map<string, string>();
62
+ let ok = true;
63
+ for (const base of requiredBases) {
64
+ if (!base) {
65
+ continue;
66
+ }
67
+
68
+ const full = `${prefix}|${base}`;
69
+ const col = columns.get(full);
70
+ if (!keys.has(full) || !col?.values) {
71
+ ok = false;
72
+ break;
73
+ }
74
+
75
+ resolved.set(base, full);
76
+ }
77
+
78
+ if (!ok) {
79
+ continue;
80
+ }
81
+
82
+ for (const base of optionalBases) {
83
+ if (!base) {
84
+ continue;
85
+ }
86
+
87
+ const full = `${prefix}|${base}`;
88
+ if (keys.has(full) && columns.get(full)?.values) {
89
+ resolved.set(base, full);
90
+ }
91
+ }
92
+
93
+ out.push({ prefix, colNames: resolved });
94
+ }
95
+
96
+ return out;
97
+ }
@@ -0,0 +1,107 @@
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 { View } from "@perspective-dev/client";
14
+
15
+ export interface ColumnData {
16
+ type: "float32" | "float64" | "int32" | "string";
17
+ values?: Float32Array | Float64Array | Int32Array;
18
+
19
+ /**
20
+ * Dictionary key indices for string columns.
21
+ */
22
+ indices?: Int32Array;
23
+
24
+ /**
25
+ * Dictionary values for string columns.
26
+ */
27
+ dictionary?: string[];
28
+
29
+ /**
30
+ * Arrow validity bitfield (1 bit per row).
31
+ */
32
+ valid?: Uint8Array;
33
+ }
34
+
35
+ export type ColumnDataMap = Map<string, ColumnData>;
36
+
37
+ export interface TypedArrayWindowOptions {
38
+ start_row?: number;
39
+ end_row?: number;
40
+ start_col?: number;
41
+ end_col?: number;
42
+ float32?: boolean;
43
+ }
44
+
45
+ /**
46
+ * Fetches all columns from a View using `with_typed_arrays` and
47
+ * builds a `ColumnDataMap`. The `values` typed arrays and `valid`
48
+ * bitmaps are zero-copy views into WASM memory and remain valid only
49
+ * for the duration of the `render` callback — if `render` returns a
50
+ * `Promise`, the underlying `with_typed_arrays` call awaits it before
51
+ * releasing the backing Arrow buffer. Callers must not retain any
52
+ * `ColumnData` reference past `render`'s resolution.
53
+ */
54
+ export async function viewToColumnDataMap(
55
+ view: View,
56
+ render: (data: ColumnDataMap) => void | Promise<void>,
57
+ options?: TypedArrayWindowOptions,
58
+ ): Promise<void> {
59
+ const result: ColumnDataMap = new Map();
60
+
61
+ await (view as any).with_typed_arrays(
62
+ options ?? {},
63
+ async (
64
+ names: string[],
65
+ values: ArrayLike<number>[],
66
+ validities: (Uint8Array | null)[],
67
+ dictionaries: (string[] | null)[],
68
+ ) => {
69
+ for (let i = 0; i < names.length; i++) {
70
+ const name = names[i];
71
+ const vals = values[i];
72
+ const valid = validities[i] ?? undefined;
73
+ const dict = dictionaries[i];
74
+
75
+ if (dict !== null) {
76
+ result.set(name, {
77
+ type: "string",
78
+ indices: vals as Int32Array,
79
+ dictionary: dict,
80
+ valid,
81
+ });
82
+ } else if (vals instanceof Float32Array) {
83
+ result.set(name, { type: "float32", values: vals, valid });
84
+ } else if (vals instanceof Int32Array) {
85
+ result.set(name, { type: "int32", values: vals, valid });
86
+ } else if (vals instanceof Float64Array) {
87
+ // Datetime/Date columns are emitted as Float64 to keep
88
+ // millisecond precision; numeric Float64 also lands here
89
+ // when `float32` mode is off. Keep them as f64 — the
90
+ // chart's CPU mirrors and extents will rebase to f32 at
91
+ // upload time.
92
+ result.set(name, { type: "float64", values: vals, valid });
93
+ } else {
94
+ // Fallback: treat as float32
95
+ // TODO: Instance check if this needs a copy?
96
+ result.set(name, {
97
+ type: "float32",
98
+ values: new Float32Array(vals as any),
99
+ valid,
100
+ });
101
+ }
102
+ }
103
+
104
+ await render(result);
105
+ },
106
+ );
107
+ }
@@ -0,0 +1,44 @@
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 { ViewConfig } from "@perspective-dev/client";
14
+
15
+ /**
16
+ * Detail payload for the `perspective-click` CustomEvent dispatched on
17
+ * the `<perspective-viewer>` host when the user clicks a chart glyph.
18
+ * Shape matches the equivalent type in `@perspective-dev/viewer-datagrid`
19
+ * so consumers can listen to either plugin uniformly.
20
+ */
21
+ export interface PerspectiveClickDetail {
22
+ /**
23
+ * Source-view row data — keys are column names, values are scalar
24
+ * cell values. Empty `{}` when the click hit a non-leaf aggregate
25
+ * (e.g. a treemap branch).
26
+ */
27
+ row: Record<string, unknown>;
28
+
29
+ /**
30
+ * Aggregate column(s) the click targeted. Single-entry for series /
31
+ * heatmap / tree charts; multi-entry would only appear for plugins
32
+ * that surface multiple measures per glyph (none today).
33
+ */
34
+ column_names: string[];
35
+
36
+ /**
37
+ * Pre-built `viewer.restore({ filter })` patch — concatenates the
38
+ * group_by and split_by pivot values at the click target as
39
+ * `[<col>, "==", <value>]` clauses.
40
+ */
41
+ config: Partial<ViewConfig>;
42
+ }
43
+
44
+ export { PerspectiveSelectDetail } from "@perspective-dev/viewer/src/ts/extensions.js";