@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,235 @@
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
+ * Struct-of-arrays storage for a hierarchical tree (treemap + sunburst).
15
+ * A node is a numeric `id` into parallel typed arrays; hot numeric
16
+ * fields live in `Float32Array` / `Int32Array` so iteration is
17
+ * cache-linear and heap pressure stays flat.
18
+ *
19
+ * Children are a singly-linked list per parent (`firstChild` /
20
+ * `nextSibling`, with `lastChild` for O(1) append). The `NULL_NODE = -1`
21
+ * sentinel marks "no node" for `parent`, end-of-list for `nextSibling`,
22
+ * and "leaf" for `firstChild`.
23
+ *
24
+ * Layout fields come in two flavors:
25
+ * - `x0 / y0 / x1 / y1` — rectangular coords (treemap, future bar
26
+ * hierarchies)
27
+ * - `a0 / a1 / r0 / r1` — polar coords (sunburst)
28
+ * Each chart populates only its own flavor; the other set wastes ~16 B
29
+ * per node (32 MB at 2M nodes) — a small price for keeping a single
30
+ * unified store across hierarchical chart types.
31
+ *
32
+ * At typical tree shapes the SOA + linked-list representation is ~10×
33
+ * cheaper on heap and ~4× faster to build than per-node `Object` +
34
+ * `Array<Child>` (which allocates ~300 B / node and is O(N²) for naive
35
+ * child-name lookup). At 2M nodes the former OOMs the tab; the latter
36
+ * stays under 100 MB.
37
+ */
38
+ export const NULL_NODE = -1;
39
+
40
+ export class NodeStore {
41
+ // Hot numeric fields (tight-loop iteration in layout / render).
42
+ size!: Float32Array;
43
+ value!: Float32Array;
44
+ colorValue!: Float32Array;
45
+
46
+ /**
47
+ * Sign of the leaf's raw size column value: `-1` when the source row
48
+ * was negative, `1` otherwise. `size` itself always stores the
49
+ * magnitude so layout code continues to treat negatives as positive
50
+ * area; render code uses `sizeSign` to apply a lower alpha on
51
+ * negative leaves. Always `1` for branches.
52
+ */
53
+ sizeSign!: Int8Array;
54
+
55
+ // Rectangular layout (treemap).
56
+ x0!: Float32Array;
57
+ y0!: Float32Array;
58
+ x1!: Float32Array;
59
+ y1!: Float32Array;
60
+
61
+ // Polar layout (sunburst). `a0 / a1` in radians, `r0 / r1` in pixels.
62
+ a0!: Float32Array;
63
+ a1!: Float32Array;
64
+ r0!: Float32Array;
65
+ r1!: Float32Array;
66
+
67
+ depth!: Int32Array;
68
+
69
+ // Tree topology.
70
+ parent!: Int32Array;
71
+ firstChild!: Int32Array;
72
+ nextSibling!: Int32Array;
73
+ lastChild!: Int32Array;
74
+ childCount!: Int32Array;
75
+
76
+ // Leaf source-row link. `-1` for branches; for leaves, the index
77
+ // into the chart's row-data column buffers (enables O(1) tooltip
78
+ // lookup without per-node `Map` allocations).
79
+ leafRowIdx!: Int32Array;
80
+
81
+ // Cold (only read on hover / label draw): plain JS arrays.
82
+ name!: string[];
83
+ colorLabel!: string[];
84
+
85
+ count = 0;
86
+ capacity = 0;
87
+
88
+ constructor(initialCapacity = 1024) {
89
+ this._allocate(initialCapacity);
90
+ }
91
+
92
+ reset(): void {
93
+ // Zero the layout typed arrays for slots that were occupied
94
+ // before. `squarify` / `partitionSunburst` overwrite visited
95
+ // nodes before any read, but early-bail branches (node area
96
+ // below `MIN_VISIBLE_AREA`) skip the recursion and leave
97
+ // descendants untouched. Re-using those slots in the next
98
+ // render with stale `x0/y0/x1/y1/a0/a1/r0/r1` leaks the
99
+ // previous render's rectangles / arcs through `collectVisible`
100
+ // into the new scene — the "leftover hoverable cells" bug.
101
+ //
102
+ // Fill only up to the prior `count` (the tree's logical size)
103
+ // — capacity can be much larger after growth and filling it
104
+ // whole is O(capacity) unnecessary work.
105
+ if (this.count > 0) {
106
+ this.x0.fill(0, 0, this.count);
107
+ this.y0.fill(0, 0, this.count);
108
+ this.x1.fill(0, 0, this.count);
109
+ this.y1.fill(0, 0, this.count);
110
+ this.a0.fill(0, 0, this.count);
111
+ this.a1.fill(0, 0, this.count);
112
+ this.r0.fill(0, 0, this.count);
113
+ this.r1.fill(0, 0, this.count);
114
+ }
115
+
116
+ this.count = 0;
117
+ }
118
+
119
+ /**
120
+ * Reserve a new node id. Caller must immediately initialize the
121
+ * hot numeric fields and set `parent` / `depth`; topology fields
122
+ * default to `NULL_NODE`.
123
+ */
124
+ allocate(): number {
125
+ if (this.count === this.capacity) {
126
+ this._allocate(this.capacity * 2);
127
+ }
128
+
129
+ const id = this.count++;
130
+ this.firstChild[id] = NULL_NODE;
131
+ this.nextSibling[id] = NULL_NODE;
132
+ this.lastChild[id] = NULL_NODE;
133
+ this.childCount[id] = 0;
134
+ this.leafRowIdx[id] = NULL_NODE;
135
+ this.size[id] = 0;
136
+ this.value[id] = 0;
137
+ this.colorValue[id] = NaN;
138
+ this.sizeSign[id] = 1;
139
+ this.name[id] = "";
140
+ this.colorLabel[id] = "";
141
+ return id;
142
+ }
143
+
144
+ /**
145
+ * O(1) append `childId` as the last child of `parentId`.
146
+ */
147
+ appendChild(parentId: number, childId: number): void {
148
+ this.parent[childId] = parentId;
149
+ this.depth[childId] = this.depth[parentId] + 1;
150
+ this.nextSibling[childId] = NULL_NODE;
151
+ const last = this.lastChild[parentId];
152
+ if (last === NULL_NODE) {
153
+ this.firstChild[parentId] = childId;
154
+ } else {
155
+ this.nextSibling[last] = childId;
156
+ }
157
+
158
+ this.lastChild[parentId] = childId;
159
+ this.childCount[parentId]++;
160
+ }
161
+
162
+ /**
163
+ * `true` if the node has no children (branches set firstChild when they acquire one).
164
+ */
165
+ isLeaf(id: number): boolean {
166
+ return this.firstChild[id] === NULL_NODE;
167
+ }
168
+
169
+ private _allocate(newCapacity: number): void {
170
+ const cap = Math.max(newCapacity, 1024);
171
+
172
+ const grow = <T extends Float32Array | Int32Array | Int8Array>(
173
+ old: T | undefined,
174
+ ctor: { new (n: number): T },
175
+ ): T => {
176
+ const next = new ctor(cap);
177
+ if (old && old.length > 0) {
178
+ next.set(old);
179
+ }
180
+
181
+ return next;
182
+ };
183
+
184
+ this.size = grow(this.size, Float32Array);
185
+ this.value = grow(this.value, Float32Array);
186
+ this.colorValue = grow(this.colorValue, Float32Array);
187
+ this.sizeSign = grow(this.sizeSign, Int8Array);
188
+ this.x0 = grow(this.x0, Float32Array);
189
+ this.y0 = grow(this.y0, Float32Array);
190
+ this.x1 = grow(this.x1, Float32Array);
191
+ this.y1 = grow(this.y1, Float32Array);
192
+ this.a0 = grow(this.a0, Float32Array);
193
+ this.a1 = grow(this.a1, Float32Array);
194
+ this.r0 = grow(this.r0, Float32Array);
195
+ this.r1 = grow(this.r1, Float32Array);
196
+ this.depth = grow(this.depth, Int32Array);
197
+ this.parent = grow(this.parent, Int32Array);
198
+ this.firstChild = grow(this.firstChild, Int32Array);
199
+ this.nextSibling = grow(this.nextSibling, Int32Array);
200
+ this.lastChild = grow(this.lastChild, Int32Array);
201
+ this.childCount = grow(this.childCount, Int32Array);
202
+ this.leafRowIdx = grow(this.leafRowIdx, Int32Array);
203
+
204
+ // JS arrays: preserve existing, extend with empty slots.
205
+ if (!this.name) {
206
+ this.name = new Array(cap);
207
+ } else {
208
+ this.name.length = cap;
209
+ }
210
+
211
+ if (!this.colorLabel) {
212
+ this.colorLabel = new Array(cap);
213
+ } else {
214
+ this.colorLabel.length = cap;
215
+ }
216
+
217
+ this.capacity = cap;
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Walk the ancestor chain back to (but not including) the synthetic
223
+ * root, topmost first. Allocates a fresh string array — callers that
224
+ * care about allocations should inline the walk.
225
+ */
226
+ export function ancestorNames(store: NodeStore, id: number): string[] {
227
+ const out: string[] = [];
228
+ let n = id;
229
+ while (store.parent[n] !== NULL_NODE) {
230
+ out.push(store.name[n]);
231
+ n = store.parent[n];
232
+ }
233
+
234
+ return out.reverse();
235
+ }
@@ -0,0 +1,76 @@
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 { AbstractChart } from "../chart-base";
14
+ import { NodeStore, NULL_NODE } from "./node-store";
15
+ import { LazyTooltip } from "../../interaction/lazy-tooltip";
16
+
17
+ /**
18
+ * Shared state for hierarchical charts (treemap, sunburst). Holds the
19
+ * tree store + streaming-insert scaffolding + per-row tooltip data
20
+ * buffers. Concrete chart classes extend this and add their own
21
+ * layout / render / interact state.
22
+ *
23
+ * Fields are `public` so the `tree-data.ts` helpers and per-chart
24
+ * layout modules can read/write them without friction.
25
+ */
26
+ export abstract class TreeChartBase extends AbstractChart {
27
+ // Shared column-slot resolution
28
+ _sizeName = "";
29
+ _colorName = "";
30
+
31
+ /**
32
+ * Color-slot semantics.
33
+ * - `"empty"`: no Color slot → single palette[0], legend suppressed.
34
+ * - `"numeric"`: Color column is float / integer / date / datetime →
35
+ * continuous gradient via `colorValueToT`.
36
+ * - `"series"`: Color column is any other type → discrete series
37
+ * palette keyed by the composite of group_by level values.
38
+ */
39
+ _colorMode: "empty" | "numeric" | "series" = "empty";
40
+
41
+ // Tree storage (SOA + linked-list children)
42
+ _nodeStore: NodeStore = new NodeStore();
43
+ _rootId: number = NULL_NODE;
44
+ _currentRootId: number = NULL_NODE;
45
+ _breadcrumbIds: number[] = [];
46
+
47
+ /**
48
+ * Per-parent `Map<childName, childId>` for O(1) find-or-create
49
+ * during streaming tree insertion. Rebuilt on each dataset reset.
50
+ */
51
+ _childLookup: Map<number, Map<string, number>> = new Map();
52
+
53
+ // Streaming-insert row counter
54
+ // Source-view row offset tracked across chunks so `leafRowIdx` on
55
+ // each leaf points back to the correct view row for lazy tooltip
56
+ // fetches via `AbstractChart._lazyRows`.
57
+ _rowCount = 0;
58
+
59
+ // Color extents / categorical key table
60
+ _colorMin = Infinity;
61
+ _colorMax = -Infinity;
62
+ _uniqueColorLabels: Map<string, number> = new Map();
63
+
64
+ // Visible-node cache (populated per frame by layout/collect) ──────
65
+ _visibleNodeIds: Int32Array | null = null;
66
+ _visibleNodeCount = 0;
67
+
68
+ /**
69
+ * Lazy-tooltip cache. `lines` is `null` until the async row fetch
70
+ * resolves; the controller's serial dance drops stale results so
71
+ * rapid mouse motion doesn't paint out-of-date text. The render
72
+ * path consults `hoveredTarget` to verify cached lines belong to
73
+ * the currently hovered node before painting.
74
+ */
75
+ _lazyTooltip = new LazyTooltip<number>();
76
+ }
@@ -0,0 +1,123 @@
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 { Context2D } from "../canvas-types";
14
+ import type { TreeChartBase } from "./tree-chart";
15
+ import { drawTooltipBox } from "./draw-tooltip-box";
16
+
17
+ /**
18
+ * Click target for one breadcrumb segment. Tree-chart hit-testing
19
+ * checks `_breadcrumbRegions` first so a click on the trail re-roots
20
+ * the view to that ancestor.
21
+ */
22
+ export interface BreadcrumbRegion {
23
+ nodeId: number;
24
+ x0: number;
25
+ y0: number;
26
+ x1: number;
27
+ y1: number;
28
+ }
29
+
30
+ const BREADCRUMB_HEIGHT = 24;
31
+ const BREADCRUMB_PAD_X = 8;
32
+ const BREADCRUMB_TEXT_Y = 12;
33
+ const BREADCRUMB_HIT_PAD = 2;
34
+ const BREADCRUMB_SEPARATOR = " › ";
35
+
36
+ /**
37
+ * Paint the ancestor-path strip across the top of a tree chart and
38
+ * record per-crumb hit regions on `chart._breadcrumbRegions`. Mirrors
39
+ * the structure used by both treemap and sunburst — they only differ
40
+ * in their hover-highlight geometry, so this strip is shared verbatim.
41
+ */
42
+ export function renderBreadcrumbs(
43
+ chart: TreeChartBase & { _breadcrumbRegions: BreadcrumbRegion[] },
44
+ ctx: Context2D,
45
+ cssWidth: number,
46
+ fontFamily: string,
47
+ textColor: string,
48
+ ): void {
49
+ chart._breadcrumbRegions = [];
50
+
51
+ const bgColor = chart._resolveTheme().tooltipBg;
52
+ ctx.fillStyle = bgColor;
53
+ ctx.fillRect(0, 0, cssWidth, BREADCRUMB_HEIGHT);
54
+
55
+ ctx.font = `11px ${fontFamily}`;
56
+ ctx.textAlign = "left";
57
+ ctx.textBaseline = "middle";
58
+
59
+ let x = BREADCRUMB_PAD_X;
60
+ const store = chart._nodeStore;
61
+
62
+ for (let i = 0; i < chart._breadcrumbIds.length; i++) {
63
+ const crumbId = chart._breadcrumbIds[i];
64
+ const isLast = i === chart._breadcrumbIds.length - 1;
65
+ const label = store.name[crumbId];
66
+
67
+ ctx.fillStyle = textColor;
68
+ const textW = ctx.measureText(label).width;
69
+ ctx.fillText(label, x, BREADCRUMB_TEXT_Y);
70
+
71
+ chart._breadcrumbRegions.push({
72
+ nodeId: crumbId,
73
+ x0: x - BREADCRUMB_HIT_PAD,
74
+ y0: 0,
75
+ x1: x + textW + BREADCRUMB_HIT_PAD,
76
+ y1: BREADCRUMB_HEIGHT,
77
+ });
78
+
79
+ x += textW;
80
+
81
+ if (!isLast) {
82
+ ctx.fillText(BREADCRUMB_SEPARATOR, x, BREADCRUMB_TEXT_Y);
83
+ x += ctx.measureText(BREADCRUMB_SEPARATOR).width;
84
+ }
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Paint the lazy-tooltip box for a tree-chart node, anchored at
90
+ * `(cx, cy)`. Returns early when no lines are cached for `nodeId`
91
+ * (the lazy lookup hasn't resolved yet, or `nodeId` doesn't match the
92
+ * currently-hovered target). Both treemap (rect-center) and sunburst
93
+ * (arc-mid) charts only differ in how they compute the anchor.
94
+ */
95
+ export function renderTreeTooltip(
96
+ chart: TreeChartBase,
97
+ ctx: Context2D,
98
+ nodeId: number,
99
+ cx: number,
100
+ cy: number,
101
+ cssWidth: number,
102
+ cssHeight: number,
103
+ fontFamily: string,
104
+ ): void {
105
+ const lines =
106
+ chart._lazyTooltip.hoveredTarget === nodeId
107
+ ? (chart._lazyTooltip.lines ?? [])
108
+ : [];
109
+ if (lines.length === 0) {
110
+ return;
111
+ }
112
+
113
+ drawTooltipBox(
114
+ ctx,
115
+ chart._resolveTheme(),
116
+ lines,
117
+ cx,
118
+ cy,
119
+ cssWidth,
120
+ cssHeight,
121
+ fontFamily,
122
+ );
123
+ }