@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,367 @@
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 { CategoricalYChart } from "../common/categorical-y-chart";
16
+ import {
17
+ buildCandlestickPipeline,
18
+ emptyCandleColumns,
19
+ type CandleColumns,
20
+ type CandleSeriesInfo,
21
+ type NumericCategoryDomain,
22
+ } from "./candlestick-build";
23
+ import {
24
+ renderCandlestickFrame,
25
+ renderCandlestickChromeOverlay,
26
+ invalidateGlyphBuffers,
27
+ rebuildGlyphBuffers,
28
+ ensureUpDownColors,
29
+ } from "./candlestick-render";
30
+ import {
31
+ handleCandlestickHover,
32
+ showCandlestickPinnedTooltip,
33
+ } from "./candlestick-interact";
34
+ import { BodyWickGlyph } from "./glyphs/draw-candlesticks";
35
+ import { OHLCGlyph } from "./glyphs/draw-ohlc";
36
+
37
+ /**
38
+ * Per-frame memo of the auto-fit Y extent for a {@link CandlestickChart},
39
+ * keyed on the visible X window. Hover-only redraws hit the cache.
40
+ */
41
+ export interface CandlestickAutoFitCache {
42
+ // Cache key — the categorical (X) window.
43
+ xMin: number;
44
+ xMax: number;
45
+
46
+ // VisibleExtent payload — value axis min/max + hasFit flag.
47
+ min: number;
48
+ max: number;
49
+ hasFit: boolean;
50
+ }
51
+
52
+ export interface CandlestickLocations {
53
+ u_proj_left: WebGLUniformLocation | null;
54
+ u_proj_right: WebGLUniformLocation | null;
55
+ u_hover_series: WebGLUniformLocation | null;
56
+ a_corner: number;
57
+ a_x_center: number;
58
+ a_half_width: number;
59
+ a_y0: number;
60
+ a_y1: number;
61
+ a_color: number;
62
+ a_series_id: number;
63
+ a_axis: number;
64
+ }
65
+
66
+ /**
67
+ * Candlestick / OHLC chart. Both plugins (`y-candlestick`, `y-ohlc`)
68
+ * share this class — the only per-plugin difference is
69
+ * `_defaultChartType` (`"candlestick"` vs `"ohlc"`), which
70
+ * {@link renderCandlestickFrame} uses to pick the glyph draw function.
71
+ *
72
+ * Fields are package-internal (no `private`) so helper modules in this
73
+ * folder can read/write them.
74
+ */
75
+ export class CandlestickChart extends CategoricalYChart {
76
+ _locations: CandlestickLocations | null = null;
77
+
78
+ // `_rowPaths`, `_numCategories`, `_rowOffset`, `_program`,
79
+ // `_cornerBuffer`, `_lastLayout`, `_lastXDomain`, `_lastYDomain`,
80
+ // and `_lastYTicks` all live on `CategoricalYChart`.
81
+ _splitPrefixes: string[] = [];
82
+ _series: CandleSeriesInfo[] = [];
83
+
84
+ /**
85
+ * Columnar candle records. Indexed in `[0, _candles.count)`.
86
+ * Replaces the legacy `CandleRecord[]` to avoid per-record POJO
87
+ * allocation on data load.
88
+ */
89
+ _candles: CandleColumns = emptyCandleColumns();
90
+
91
+ _yDomain: { min: number; max: number } = { min: 0, max: 1 };
92
+
93
+ /**
94
+ * `domain_mode: "expand"` accumulators. Hold the running union of
95
+ * the value-axis (and, in numeric-category mode, category-axis)
96
+ * extent across data loads. Cleared in `resetExpandedDomain` —
97
+ * wired from the worker's `resetAllZooms` and from view-config
98
+ * mutations on `AbstractChart`. `null` whenever the option is
99
+ * `"fit"` or the accumulator has just been cleared.
100
+ */
101
+ _expandedYDomain: { min: number; max: number } | null = null;
102
+ _expandedCategoryDomain: { min: number; max: number } | null = null;
103
+
104
+ /**
105
+ * Numeric category-axis state (single non-string group_by).
106
+ */
107
+ _categoryAxisMode: "category" | "numeric" = "category";
108
+ _numericCategoryDomain: NumericCategoryDomain | null = null;
109
+ _categoryPositions: Float64Array | null = null;
110
+ _lastCatTicks: number[] | null = null;
111
+
112
+ /**
113
+ * Origin used to rebase candle xCenters before f32 narrowing — see {@link SeriesChart._categoryOrigin}.
114
+ */
115
+ _categoryOrigin = 0;
116
+
117
+ /**
118
+ * Gradient-sampled colors for the up (close ≥ open) / down sides.
119
+ * Cached via `_upDownColorKey` — only `restyle()` (which clears the
120
+ * theme cache) or a data load forces re-sampling.
121
+ */
122
+ _upColor: [number, number, number] = [0, 0.8, 0.4];
123
+ _downColor: [number, number, number] = [0.8, 0.2, 0.2];
124
+
125
+ /**
126
+ * Identity of the gradient-stops reference last used to sample the
127
+ * up/down colors. When this matches the current `theme.gradientStops`
128
+ * reference, `ensureUpDownColors` short-circuits.
129
+ */
130
+ _upDownColorKey: unknown = null;
131
+
132
+ _hoveredIdx = -1;
133
+ _pinnedIdx = -1;
134
+
135
+ /**
136
+ * Typed glyph composition. Each glyph owns its own program cache
137
+ * and persistent vertex buffers privately; the chart routes
138
+ * draw/rebuild/invalidate via `_glyphs`. `_defaultChartType`
139
+ * (`"candlestick"` vs `"ohlc"`) selects which glyph the frame
140
+ * builder dispatches to.
141
+ */
142
+ readonly _glyphs = {
143
+ bodyWick: new BodyWickGlyph(),
144
+ ohlc: new OHLCGlyph(),
145
+ } as const;
146
+
147
+ /**
148
+ * Auto-fit the price (Y) axis to the `low`/`high` extent of
149
+ * candles whose `xCenter` falls inside the visible X window. Pairs
150
+ * with the locked Y axis: the lock means user input can't zoom Y
151
+ * directly, auto-fit is what actually moves it as the user scrolls
152
+ * through time. Default: on (financial-chart convention).
153
+ */
154
+ override _autoFitValue = true;
155
+
156
+ /**
157
+ * Per-frame memo of the auto-fit Y extent keyed on the visible X
158
+ * window. Hover-only redraws (X window unchanged) hit the cache.
159
+ * Reset to null on data upload.
160
+ */
161
+ _autoFitCache: CandlestickAutoFitCache | null = null;
162
+
163
+ protected override tooltipCallbacks() {
164
+ return {
165
+ onHover: (mx: number, my: number) =>
166
+ handleCandlestickHover(this, mx, my),
167
+ onLeave: () => {
168
+ if (this._hoveredIdx !== -1) {
169
+ this._hoveredIdx = -1;
170
+
171
+ // Hover state only affects the chrome overlay
172
+ // (tooltip box) — the WebGL pass is unchanged. Skip
173
+ // the full repaint (which would rebuild glyph
174
+ // buffers and shake out one more frame of latency).
175
+ renderCandlestickChromeOverlay(this);
176
+ }
177
+ },
178
+ onPin: (mx: number, my: number) => {
179
+ // Refresh the hit-test at the click coords so the pin
180
+ // path doesn't depend on the RAF-throttled hover state
181
+ // — see comment in `series.ts` `onPin`.
182
+ handleCandlestickHover(this, mx, my);
183
+ if (this._hoveredIdx >= 0) {
184
+ const idx = this._hoveredIdx;
185
+ showCandlestickPinnedTooltip(this, idx);
186
+ void this._emitCandleClickSelect(idx);
187
+ }
188
+ },
189
+ onUnpin: () => {
190
+ this.emitUnselect();
191
+ },
192
+ };
193
+ }
194
+
195
+ /**
196
+ * Resolve a clicked candle into a `PerspectiveClickDetail` and
197
+ * emit both `perspective-click` and
198
+ * `perspective-global-filter selected:true`.
199
+ *
200
+ * One candle per (catIdx, splitIdx). Like the series pipeline,
201
+ * `catIdx + _rowOffset` is the source-view row; the column name is
202
+ * the Close column (the canonical "y" target for OHLC). Group-by
203
+ * values come from `_rowPaths`; split-by values come from
204
+ * `_splitPrefixes[splitIdx]` split on `|`.
205
+ */
206
+ private async _emitCandleClickSelect(idx: number): Promise<void> {
207
+ if (idx < 0 || idx >= this._candles.count) {
208
+ return;
209
+ }
210
+
211
+ const catIdx = this._candles.catIdx[idx];
212
+ const splitIdx = this._candles.splitIdx[idx];
213
+ const groupByValues: (string | null)[] = this._rowPaths.map(
214
+ (level) => level.labels[catIdx] ?? null,
215
+ );
216
+ const splitKey = this._splitPrefixes[splitIdx] ?? "";
217
+ const splitByValues =
218
+ this._splitBy.length > 0 && splitKey !== ""
219
+ ? splitKey.split("|")
220
+ : [];
221
+
222
+ // OHLC plugins put Close in slot 1 (FIN_NAMES = ["Open",
223
+ // "Close", "High", "Low", "Tooltip"]). Fall back to the first
224
+ // non-null slot if Close isn't configured.
225
+ const columnName =
226
+ this._columnSlots[1] ||
227
+ this._columnSlots.find((s): s is string => !!s) ||
228
+ "";
229
+
230
+ await this.emitClickAndSelect({
231
+ rowIdx: catIdx + this._rowOffset,
232
+ columnName,
233
+ groupByValues,
234
+ splitByValues,
235
+ });
236
+ }
237
+
238
+ override invalidateTheme(): void {
239
+ super.invalidateTheme();
240
+
241
+ // Up/down colors are sampled from `theme.gradientStops`. Drop the
242
+ // identity key so the next render re-samples after a `restyle()`.
243
+ this._upDownColorKey = null;
244
+ }
245
+
246
+ async uploadAndRender(
247
+ glManager: WebGLContextManager,
248
+ columns: ColumnDataMap,
249
+ startRow: number,
250
+ endRow: number,
251
+ ): Promise<void> {
252
+ this._glManager = glManager;
253
+ if (startRow !== 0) {
254
+ return;
255
+ }
256
+
257
+ const result = buildCandlestickPipeline({
258
+ columns,
259
+ numRows: endRow,
260
+ columnSlots: this._columnSlots,
261
+ groupBy: this._groupBy,
262
+ splitBy: this._splitBy,
263
+ groupByTypes: this._groupByTypes,
264
+ bandInnerFrac: this._pluginConfig.band_inner_frac,
265
+ barInnerPad: this._pluginConfig.bar_inner_pad,
266
+ scratchCandles: this._candles,
267
+ });
268
+ // `domain_mode: "expand"` post-build union — mirrors the series
269
+ // pipeline. Mutate the pipeline result in place so the
270
+ // assignments below pick up the grown extent automatically.
271
+ if (this._pluginConfig.domain_mode === "expand") {
272
+ if (this._expandedYDomain) {
273
+ result.yDomain.min = Math.min(
274
+ this._expandedYDomain.min,
275
+ result.yDomain.min,
276
+ );
277
+ result.yDomain.max = Math.max(
278
+ this._expandedYDomain.max,
279
+ result.yDomain.max,
280
+ );
281
+ }
282
+
283
+ this._expandedYDomain = { ...result.yDomain };
284
+
285
+ if (result.numericCategoryDomain) {
286
+ if (this._expandedCategoryDomain) {
287
+ result.numericCategoryDomain.min = Math.min(
288
+ this._expandedCategoryDomain.min,
289
+ result.numericCategoryDomain.min,
290
+ );
291
+ result.numericCategoryDomain.max = Math.max(
292
+ this._expandedCategoryDomain.max,
293
+ result.numericCategoryDomain.max,
294
+ );
295
+ }
296
+
297
+ this._expandedCategoryDomain = {
298
+ min: result.numericCategoryDomain.min,
299
+ max: result.numericCategoryDomain.max,
300
+ };
301
+ }
302
+ } else {
303
+ this._expandedYDomain = null;
304
+ this._expandedCategoryDomain = null;
305
+ }
306
+
307
+ this._rowPaths = result.rowPaths;
308
+ this._numCategories = result.numCategories;
309
+ this._rowOffset = result.rowOffset;
310
+ this._splitPrefixes = result.splitPrefixes;
311
+ this._series = result.series;
312
+ this._candles = result.candles;
313
+ this._yDomain = result.yDomain;
314
+ this._categoryAxisMode = result.axisMode.mode;
315
+ this._numericCategoryDomain = result.numericCategoryDomain;
316
+ this._categoryPositions = result.categoryPositions;
317
+ this._categoryOrigin = result.numericCategoryDomain?.min ?? 0;
318
+
319
+ // New candles invalidate any auto-fit extent memo. Color key
320
+ // stays — gradient stops are theme-bound, not data-bound — but
321
+ // the persistent vertex buffers must be rebuilt to reflect the
322
+ // new candle set.
323
+ this._autoFitCache = null;
324
+
325
+ // Resolve up/down colors (cheap on cache hit) before rebuilding
326
+ // glyph buffers so the persistent body buffer captures the
327
+ // correct per-candle RGB. Then rebuild buffers.
328
+ ensureUpDownColors(this);
329
+ invalidateGlyphBuffers(this);
330
+ rebuildGlyphBuffers(this, glManager);
331
+
332
+ await this.requestRender(glManager);
333
+ }
334
+
335
+ _fullRender(glManager: WebGLContextManager): void {
336
+ this._glManager = glManager;
337
+ renderCandlestickFrame(this, glManager);
338
+ }
339
+
340
+ override resetExpandedDomain(): void {
341
+ this._expandedYDomain = null;
342
+ this._expandedCategoryDomain = null;
343
+ }
344
+
345
+ protected destroyInternal(): void {
346
+ if (this._glManager) {
347
+ const gl = this._glManager.gl;
348
+ if (this._cornerBuffer) {
349
+ gl.deleteBuffer(this._cornerBuffer);
350
+ }
351
+
352
+ // Each glyph owns its program-local GPU resources +
353
+ // persistent vertex buffers; `destroy` frees both.
354
+ this._glyphs.bodyWick.destroy(this);
355
+ this._glyphs.ohlc.destroy(this);
356
+ }
357
+
358
+ this._program = null;
359
+ this._locations = null;
360
+ this._cornerBuffer = null;
361
+ this._candles = emptyCandleColumns();
362
+ this._series = [];
363
+ this._rowPaths = [];
364
+ this._numCategories = 0;
365
+ this._upDownColorKey = null;
366
+ }
367
+ }