@chartgpu/chartgpu 0.2.5

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 (273) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +208 -0
  3. package/dist/ChartGPU.d.ts +146 -0
  4. package/dist/ChartGPU.d.ts.map +1 -0
  5. package/dist/components/createAnnotationConfigDialog.d.ts +24 -0
  6. package/dist/components/createAnnotationConfigDialog.d.ts.map +1 -0
  7. package/dist/components/createDataZoomSlider.d.ts +14 -0
  8. package/dist/components/createDataZoomSlider.d.ts.map +1 -0
  9. package/dist/components/createLegend.d.ts +9 -0
  10. package/dist/components/createLegend.d.ts.map +1 -0
  11. package/dist/components/createTextOverlay.d.ts +17 -0
  12. package/dist/components/createTextOverlay.d.ts.map +1 -0
  13. package/dist/components/createTooltip.d.ts +12 -0
  14. package/dist/components/createTooltip.d.ts.map +1 -0
  15. package/dist/components/formatTooltip.d.ts +19 -0
  16. package/dist/components/formatTooltip.d.ts.map +1 -0
  17. package/dist/config/OptionResolver.d.ts +137 -0
  18. package/dist/config/OptionResolver.d.ts.map +1 -0
  19. package/dist/config/defaults.d.ts +56 -0
  20. package/dist/config/defaults.d.ts.map +1 -0
  21. package/dist/config/types.d.ts +553 -0
  22. package/dist/config/types.d.ts.map +1 -0
  23. package/dist/core/GPUContext.d.ts +242 -0
  24. package/dist/core/GPUContext.d.ts.map +1 -0
  25. package/dist/core/RenderScheduler.d.ts +174 -0
  26. package/dist/core/RenderScheduler.d.ts.map +1 -0
  27. package/dist/core/createAnimationController.d.ts +15 -0
  28. package/dist/core/createAnimationController.d.ts.map +1 -0
  29. package/dist/core/createRenderCoordinator.d.ts +78 -0
  30. package/dist/core/createRenderCoordinator.d.ts.map +1 -0
  31. package/dist/core/renderCoordinator/animation/animationHelpers.d.ts +183 -0
  32. package/dist/core/renderCoordinator/animation/animationHelpers.d.ts.map +1 -0
  33. package/dist/core/renderCoordinator/annotations/processAnnotations.d.ts +88 -0
  34. package/dist/core/renderCoordinator/annotations/processAnnotations.d.ts.map +1 -0
  35. package/dist/core/renderCoordinator/axis/axisLabelHelpers.d.ts +91 -0
  36. package/dist/core/renderCoordinator/axis/axisLabelHelpers.d.ts.map +1 -0
  37. package/dist/core/renderCoordinator/axis/computeAxisTicks.d.ts +53 -0
  38. package/dist/core/renderCoordinator/axis/computeAxisTicks.d.ts.map +1 -0
  39. package/dist/core/renderCoordinator/data/computeVisibleSlice.d.ts +66 -0
  40. package/dist/core/renderCoordinator/data/computeVisibleSlice.d.ts.map +1 -0
  41. package/dist/core/renderCoordinator/gpu/textureManager.d.ts +69 -0
  42. package/dist/core/renderCoordinator/gpu/textureManager.d.ts.map +1 -0
  43. package/dist/core/renderCoordinator/interaction/interactionHelpers.d.ts +160 -0
  44. package/dist/core/renderCoordinator/interaction/interactionHelpers.d.ts.map +1 -0
  45. package/dist/core/renderCoordinator/render/renderAnnotationLabels.d.ts +36 -0
  46. package/dist/core/renderCoordinator/render/renderAnnotationLabels.d.ts.map +1 -0
  47. package/dist/core/renderCoordinator/render/renderAxisLabels.d.ts +40 -0
  48. package/dist/core/renderCoordinator/render/renderAxisLabels.d.ts.map +1 -0
  49. package/dist/core/renderCoordinator/render/renderOverlays.d.ts +70 -0
  50. package/dist/core/renderCoordinator/render/renderOverlays.d.ts.map +1 -0
  51. package/dist/core/renderCoordinator/render/renderSeries.d.ts +146 -0
  52. package/dist/core/renderCoordinator/render/renderSeries.d.ts.map +1 -0
  53. package/dist/core/renderCoordinator/renderers/rendererPool.d.ts +112 -0
  54. package/dist/core/renderCoordinator/renderers/rendererPool.d.ts.map +1 -0
  55. package/dist/core/renderCoordinator/types.d.ts +19 -0
  56. package/dist/core/renderCoordinator/types.d.ts.map +1 -0
  57. package/dist/core/renderCoordinator/ui/tooltipLegendHelpers.d.ts +104 -0
  58. package/dist/core/renderCoordinator/ui/tooltipLegendHelpers.d.ts.map +1 -0
  59. package/dist/core/renderCoordinator/utils/axisUtils.d.ts +122 -0
  60. package/dist/core/renderCoordinator/utils/axisUtils.d.ts.map +1 -0
  61. package/dist/core/renderCoordinator/utils/boundsComputation.d.ts +69 -0
  62. package/dist/core/renderCoordinator/utils/boundsComputation.d.ts.map +1 -0
  63. package/dist/core/renderCoordinator/utils/canvasUtils.d.ts +52 -0
  64. package/dist/core/renderCoordinator/utils/canvasUtils.d.ts.map +1 -0
  65. package/dist/core/renderCoordinator/utils/dataPointUtils.d.ts +71 -0
  66. package/dist/core/renderCoordinator/utils/dataPointUtils.d.ts.map +1 -0
  67. package/dist/core/renderCoordinator/utils/index.d.ts +12 -0
  68. package/dist/core/renderCoordinator/utils/index.d.ts.map +1 -0
  69. package/dist/core/renderCoordinator/utils/timeAxisUtils.d.ts +149 -0
  70. package/dist/core/renderCoordinator/utils/timeAxisUtils.d.ts.map +1 -0
  71. package/dist/core/renderCoordinator/zoom/zoomHelpers.d.ts +129 -0
  72. package/dist/core/renderCoordinator/zoom/zoomHelpers.d.ts.map +1 -0
  73. package/dist/data/cartesianData.d.ts +72 -0
  74. package/dist/data/cartesianData.d.ts.map +1 -0
  75. package/dist/data/createDataStore.d.ts +27 -0
  76. package/dist/data/createDataStore.d.ts.map +1 -0
  77. package/dist/data/createStreamBuffer.d.ts +20 -0
  78. package/dist/data/createStreamBuffer.d.ts.map +1 -0
  79. package/dist/data/lttbSample.d.ts +5 -0
  80. package/dist/data/lttbSample.d.ts.map +1 -0
  81. package/dist/data/ohlcSample.d.ts +21 -0
  82. package/dist/data/ohlcSample.d.ts.map +1 -0
  83. package/dist/data/packDataPoints.d.ts +65 -0
  84. package/dist/data/packDataPoints.d.ts.map +1 -0
  85. package/dist/data/sampleSeries.d.ts +20 -0
  86. package/dist/data/sampleSeries.d.ts.map +1 -0
  87. package/dist/esm/ChartGPUWorkerController-B50J-8sx.js +772 -0
  88. package/dist/esm/ChartGPUWorkerController-B50J-8sx.js.map +1 -0
  89. package/dist/esm/OptionResolver-R_gJDRSD.js +7150 -0
  90. package/dist/esm/OptionResolver-R_gJDRSD.js.map +1 -0
  91. package/dist/esm/assets/worker-entry-Wg897auv.js +779 -0
  92. package/dist/esm/assets/worker-entry-Wg897auv.js.map +1 -0
  93. package/dist/esm/createChartInWorker-C4fEeJL8.js +1224 -0
  94. package/dist/esm/createChartInWorker-C4fEeJL8.js.map +1 -0
  95. package/dist/esm/index.js +795 -0
  96. package/dist/esm/index.js.map +1 -0
  97. package/dist/index.cjs +1270 -0
  98. package/dist/index.cjs.map +1 -0
  99. package/dist/index.d.ts +30 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +10504 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/interaction/createAnnotationAuthoring.d.ts +115 -0
  104. package/dist/interaction/createAnnotationAuthoring.d.ts.map +1 -0
  105. package/dist/interaction/createAnnotationDragHandler.d.ts +28 -0
  106. package/dist/interaction/createAnnotationDragHandler.d.ts.map +1 -0
  107. package/dist/interaction/createAnnotationHitTester.d.ts +32 -0
  108. package/dist/interaction/createAnnotationHitTester.d.ts.map +1 -0
  109. package/dist/interaction/createChartSync.d.ts +27 -0
  110. package/dist/interaction/createChartSync.d.ts.map +1 -0
  111. package/dist/interaction/createEventManager.d.ts +24 -0
  112. package/dist/interaction/createEventManager.d.ts.map +1 -0
  113. package/dist/interaction/createHoverState.d.ts +20 -0
  114. package/dist/interaction/createHoverState.d.ts.map +1 -0
  115. package/dist/interaction/createInsideZoom.d.ts +14 -0
  116. package/dist/interaction/createInsideZoom.d.ts.map +1 -0
  117. package/dist/interaction/createZoomState.d.ts +63 -0
  118. package/dist/interaction/createZoomState.d.ts.map +1 -0
  119. package/dist/interaction/findCandlestick.d.ts +41 -0
  120. package/dist/interaction/findCandlestick.d.ts.map +1 -0
  121. package/dist/interaction/findNearestPoint.d.ts +61 -0
  122. package/dist/interaction/findNearestPoint.d.ts.map +1 -0
  123. package/dist/interaction/findPieSlice.d.ts +36 -0
  124. package/dist/interaction/findPieSlice.d.ts.map +1 -0
  125. package/dist/interaction/findPointsAtX.d.ts +37 -0
  126. package/dist/interaction/findPointsAtX.d.ts.map +1 -0
  127. package/dist/renderers/createAnnotationMarkerRenderer.d.ts +58 -0
  128. package/dist/renderers/createAnnotationMarkerRenderer.d.ts.map +1 -0
  129. package/dist/renderers/createAreaRenderer.d.ts +19 -0
  130. package/dist/renderers/createAreaRenderer.d.ts.map +1 -0
  131. package/dist/renderers/createAxisRenderer.d.ts +19 -0
  132. package/dist/renderers/createAxisRenderer.d.ts.map +1 -0
  133. package/dist/renderers/createBarRenderer.d.ts +20 -0
  134. package/dist/renderers/createBarRenderer.d.ts.map +1 -0
  135. package/dist/renderers/createCandlestickRenderer.d.ts +19 -0
  136. package/dist/renderers/createCandlestickRenderer.d.ts.map +1 -0
  137. package/dist/renderers/createCrosshairRenderer.d.ts +43 -0
  138. package/dist/renderers/createCrosshairRenderer.d.ts.map +1 -0
  139. package/dist/renderers/createGridRenderer.d.ts +45 -0
  140. package/dist/renderers/createGridRenderer.d.ts.map +1 -0
  141. package/dist/renderers/createHighlightRenderer.d.ts +41 -0
  142. package/dist/renderers/createHighlightRenderer.d.ts.map +1 -0
  143. package/dist/renderers/createLineRenderer.d.ts +18 -0
  144. package/dist/renderers/createLineRenderer.d.ts.map +1 -0
  145. package/dist/renderers/createPieRenderer.d.ts +18 -0
  146. package/dist/renderers/createPieRenderer.d.ts.map +1 -0
  147. package/dist/renderers/createReferenceLineRenderer.d.ts +81 -0
  148. package/dist/renderers/createReferenceLineRenderer.d.ts.map +1 -0
  149. package/dist/renderers/createScatterDensityRenderer.d.ts +14 -0
  150. package/dist/renderers/createScatterDensityRenderer.d.ts.map +1 -0
  151. package/dist/renderers/createScatterRenderer.d.ts +20 -0
  152. package/dist/renderers/createScatterRenderer.d.ts.map +1 -0
  153. package/dist/renderers/rendererUtils.d.ts +100 -0
  154. package/dist/renderers/rendererUtils.d.ts.map +1 -0
  155. package/dist/themes/darkTheme.d.ts +11 -0
  156. package/dist/themes/darkTheme.d.ts.map +1 -0
  157. package/dist/themes/index.d.ts +8 -0
  158. package/dist/themes/index.d.ts.map +1 -0
  159. package/dist/themes/lightTheme.d.ts +11 -0
  160. package/dist/themes/lightTheme.d.ts.map +1 -0
  161. package/dist/themes/types.d.ts +14 -0
  162. package/dist/themes/types.d.ts.map +1 -0
  163. package/dist/types/ChartGPU.d.ts +99 -0
  164. package/dist/types/ChartGPU.d.ts.map +1 -0
  165. package/dist/types/components/createDataZoomSlider.d.ts +14 -0
  166. package/dist/types/components/createDataZoomSlider.d.ts.map +1 -0
  167. package/dist/types/components/createLegend.d.ts +9 -0
  168. package/dist/types/components/createLegend.d.ts.map +1 -0
  169. package/dist/types/components/createTextOverlay.d.ts +17 -0
  170. package/dist/types/components/createTextOverlay.d.ts.map +1 -0
  171. package/dist/types/components/createTooltip.d.ts +12 -0
  172. package/dist/types/components/createTooltip.d.ts.map +1 -0
  173. package/dist/types/components/formatTooltip.d.ts +19 -0
  174. package/dist/types/components/formatTooltip.d.ts.map +1 -0
  175. package/dist/types/config/OptionResolver.d.ts +134 -0
  176. package/dist/types/config/OptionResolver.d.ts.map +1 -0
  177. package/dist/types/config/defaults.d.ts +55 -0
  178. package/dist/types/config/defaults.d.ts.map +1 -0
  179. package/dist/types/config/types.d.ts +485 -0
  180. package/dist/types/config/types.d.ts.map +1 -0
  181. package/dist/types/core/GPUContext.d.ts +242 -0
  182. package/dist/types/core/GPUContext.d.ts.map +1 -0
  183. package/dist/types/core/RenderScheduler.d.ts +174 -0
  184. package/dist/types/core/RenderScheduler.d.ts.map +1 -0
  185. package/dist/types/core/createAnimationController.d.ts +15 -0
  186. package/dist/types/core/createAnimationController.d.ts.map +1 -0
  187. package/dist/types/core/createRenderCoordinator.d.ts +129 -0
  188. package/dist/types/core/createRenderCoordinator.d.ts.map +1 -0
  189. package/dist/types/data/createDataStore.d.ts +33 -0
  190. package/dist/types/data/createDataStore.d.ts.map +1 -0
  191. package/dist/types/data/createStreamBuffer.d.ts +20 -0
  192. package/dist/types/data/createStreamBuffer.d.ts.map +1 -0
  193. package/dist/types/data/lttbSample.d.ts +5 -0
  194. package/dist/types/data/lttbSample.d.ts.map +1 -0
  195. package/dist/types/data/ohlcSample.d.ts +21 -0
  196. package/dist/types/data/ohlcSample.d.ts.map +1 -0
  197. package/dist/types/data/packDataPoints.d.ts +79 -0
  198. package/dist/types/data/packDataPoints.d.ts.map +1 -0
  199. package/dist/types/data/sampleSeries.d.ts +3 -0
  200. package/dist/types/data/sampleSeries.d.ts.map +1 -0
  201. package/dist/types/index.d.ts +35 -0
  202. package/dist/types/index.d.ts.map +1 -0
  203. package/dist/types/interaction/createChartSync.d.ts +12 -0
  204. package/dist/types/interaction/createChartSync.d.ts.map +1 -0
  205. package/dist/types/interaction/createEventManager.d.ts +24 -0
  206. package/dist/types/interaction/createEventManager.d.ts.map +1 -0
  207. package/dist/types/interaction/createHoverState.d.ts +20 -0
  208. package/dist/types/interaction/createHoverState.d.ts.map +1 -0
  209. package/dist/types/interaction/createInsideZoom.d.ts +14 -0
  210. package/dist/types/interaction/createInsideZoom.d.ts.map +1 -0
  211. package/dist/types/interaction/createZoomState.d.ts +63 -0
  212. package/dist/types/interaction/createZoomState.d.ts.map +1 -0
  213. package/dist/types/interaction/findCandlestick.d.ts +41 -0
  214. package/dist/types/interaction/findCandlestick.d.ts.map +1 -0
  215. package/dist/types/interaction/findNearestPoint.d.ts +61 -0
  216. package/dist/types/interaction/findNearestPoint.d.ts.map +1 -0
  217. package/dist/types/interaction/findPieSlice.d.ts +36 -0
  218. package/dist/types/interaction/findPieSlice.d.ts.map +1 -0
  219. package/dist/types/interaction/findPointsAtX.d.ts +37 -0
  220. package/dist/types/interaction/findPointsAtX.d.ts.map +1 -0
  221. package/dist/types/renderers/createAreaRenderer.d.ts +18 -0
  222. package/dist/types/renderers/createAreaRenderer.d.ts.map +1 -0
  223. package/dist/types/renderers/createAxisRenderer.d.ts +19 -0
  224. package/dist/types/renderers/createAxisRenderer.d.ts.map +1 -0
  225. package/dist/types/renderers/createBarRenderer.d.ts +20 -0
  226. package/dist/types/renderers/createBarRenderer.d.ts.map +1 -0
  227. package/dist/types/renderers/createCandlestickRenderer.d.ts +19 -0
  228. package/dist/types/renderers/createCandlestickRenderer.d.ts.map +1 -0
  229. package/dist/types/renderers/createCrosshairRenderer.d.ts +43 -0
  230. package/dist/types/renderers/createCrosshairRenderer.d.ts.map +1 -0
  231. package/dist/types/renderers/createGridRenderer.d.ts +45 -0
  232. package/dist/types/renderers/createGridRenderer.d.ts.map +1 -0
  233. package/dist/types/renderers/createHighlightRenderer.d.ts +41 -0
  234. package/dist/types/renderers/createHighlightRenderer.d.ts.map +1 -0
  235. package/dist/types/renderers/createLineRenderer.d.ts +18 -0
  236. package/dist/types/renderers/createLineRenderer.d.ts.map +1 -0
  237. package/dist/types/renderers/createPieRenderer.d.ts +18 -0
  238. package/dist/types/renderers/createPieRenderer.d.ts.map +1 -0
  239. package/dist/types/renderers/createScatterDensityRenderer.d.ts +14 -0
  240. package/dist/types/renderers/createScatterDensityRenderer.d.ts.map +1 -0
  241. package/dist/types/renderers/createScatterRenderer.d.ts +19 -0
  242. package/dist/types/renderers/createScatterRenderer.d.ts.map +1 -0
  243. package/dist/types/renderers/rendererUtils.d.ts +100 -0
  244. package/dist/types/renderers/rendererUtils.d.ts.map +1 -0
  245. package/dist/types/themes/darkTheme.d.ts +11 -0
  246. package/dist/types/themes/darkTheme.d.ts.map +1 -0
  247. package/dist/types/themes/index.d.ts +8 -0
  248. package/dist/types/themes/index.d.ts.map +1 -0
  249. package/dist/types/themes/lightTheme.d.ts +11 -0
  250. package/dist/types/themes/lightTheme.d.ts.map +1 -0
  251. package/dist/types/themes/types.d.ts +14 -0
  252. package/dist/types/themes/types.d.ts.map +1 -0
  253. package/dist/types/utils/axisLabelStyling.d.ts +27 -0
  254. package/dist/types/utils/axisLabelStyling.d.ts.map +1 -0
  255. package/dist/types/utils/checkWebGPU.d.ts +39 -0
  256. package/dist/types/utils/checkWebGPU.d.ts.map +1 -0
  257. package/dist/types/utils/colors.d.ts +14 -0
  258. package/dist/types/utils/colors.d.ts.map +1 -0
  259. package/dist/types/utils/easing.d.ts +9 -0
  260. package/dist/types/utils/easing.d.ts.map +1 -0
  261. package/dist/types/utils/scales.d.ts +79 -0
  262. package/dist/types/utils/scales.d.ts.map +1 -0
  263. package/dist/utils/axisLabelStyling.d.ts +20 -0
  264. package/dist/utils/axisLabelStyling.d.ts.map +1 -0
  265. package/dist/utils/checkWebGPU.d.ts +39 -0
  266. package/dist/utils/checkWebGPU.d.ts.map +1 -0
  267. package/dist/utils/colors.d.ts +14 -0
  268. package/dist/utils/colors.d.ts.map +1 -0
  269. package/dist/utils/easing.d.ts +9 -0
  270. package/dist/utils/easing.d.ts.map +1 -0
  271. package/dist/utils/scales.d.ts +79 -0
  272. package/dist/utils/scales.d.ts.map +1 -0
  273. package/package.json +64 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createChartInWorker-C4fEeJL8.js","sources":["../../src/components/createDataZoomSlider.ts","../../src/worker/types.ts","../../src/worker/ChartGPUWorkerProxy.ts","../../src/worker/createChartInWorker.ts"],"sourcesContent":["import type { ZoomRange, ZoomState } from '../interaction/createZoomState';\nimport type { ThemeConfig } from '../themes/types';\n\nexport interface DataZoomSlider {\n update(theme: ThemeConfig): void;\n dispose(): void;\n}\n\nexport interface DataZoomSliderOptions {\n readonly height?: number;\n readonly marginTop?: number;\n readonly zIndex?: number;\n readonly showPreview?: boolean;\n}\n\nconst clamp = (v: number, lo: number, hi: number): number => Math.min(hi, Math.max(lo, v));\n\nconst normalizeRange = (range: ZoomRange): ZoomRange => {\n let { start, end } = range;\n if (start > end) {\n const t = start;\n start = end;\n end = t;\n }\n return { start: clamp(start, 0, 100), end: clamp(end, 0, 100) };\n};\n\ntype DragMode = 'left-handle' | 'right-handle' | 'pan-window';\n\nexport function createDataZoomSlider(\n container: HTMLElement,\n zoomState: ZoomState,\n options?: DataZoomSliderOptions\n): DataZoomSlider {\n const height = options?.height ?? 32;\n const marginTop = options?.marginTop ?? 8;\n const zIndex = options?.zIndex ?? 4;\n const showPreview = options?.showPreview ?? false;\n\n const root = document.createElement('div');\n root.style.display = 'block';\n root.style.width = '100%';\n root.style.height = `${height}px`;\n root.style.marginTop = `${marginTop}px`;\n root.style.boxSizing = 'border-box';\n root.style.position = 'relative';\n root.style.zIndex = `${zIndex}`;\n root.style.userSelect = 'none';\n root.style.touchAction = 'none';\n\n // track: full-width bar that hosts preview + window selection.\n const track = document.createElement('div');\n track.style.position = 'relative';\n track.style.height = '100%';\n track.style.width = '100%';\n track.style.boxSizing = 'border-box';\n track.style.borderRadius = '8px';\n track.style.borderStyle = 'solid';\n track.style.borderWidth = '1px';\n track.style.overflow = 'hidden';\n root.appendChild(track);\n\n // preview: miniature context under the selection (optional; can be a solid bar for now).\n const preview = document.createElement('div');\n preview.style.position = 'absolute';\n preview.style.inset = '0';\n preview.style.pointerEvents = 'none';\n preview.style.opacity = '0.4';\n preview.style.display = showPreview ? 'block' : 'none';\n track.appendChild(preview);\n\n // window: the selected range.\n const windowEl = document.createElement('div');\n windowEl.style.position = 'absolute';\n windowEl.style.top = '0';\n windowEl.style.bottom = '0';\n windowEl.style.left = '0%';\n windowEl.style.width = '100%';\n windowEl.style.boxSizing = 'border-box';\n windowEl.style.cursor = 'grab';\n track.appendChild(windowEl);\n\n // left/right handles.\n const leftHandle = document.createElement('div');\n leftHandle.style.position = 'absolute';\n leftHandle.style.left = '0';\n leftHandle.style.top = '0';\n leftHandle.style.bottom = '0';\n leftHandle.style.width = '10px';\n leftHandle.style.cursor = 'ew-resize';\n windowEl.appendChild(leftHandle);\n\n const rightHandle = document.createElement('div');\n rightHandle.style.position = 'absolute';\n rightHandle.style.right = '0';\n rightHandle.style.top = '0';\n rightHandle.style.bottom = '0';\n rightHandle.style.width = '10px';\n rightHandle.style.cursor = 'ew-resize';\n windowEl.appendChild(rightHandle);\n\n // center grip (hit target for panning).\n const centerGrip = document.createElement('div');\n centerGrip.style.position = 'absolute';\n centerGrip.style.left = '10px';\n centerGrip.style.right = '10px';\n centerGrip.style.top = '0';\n centerGrip.style.bottom = '0';\n centerGrip.style.cursor = 'grab';\n windowEl.appendChild(centerGrip);\n\n container.appendChild(root);\n\n let disposed = false;\n let activeDragCleanup: (() => void) | null = null;\n\n const applyRangeToDom = (range: ZoomRange): void => {\n const r = normalizeRange(range);\n const span = clamp(r.end - r.start, 0, 100);\n windowEl.style.left = `${r.start}%`;\n windowEl.style.width = `${span}%`;\n };\n\n const getTrackWidthPx = (): number | null => {\n // getBoundingClientRect() is robust even if the container is scaled.\n const w = track.getBoundingClientRect().width;\n return Number.isFinite(w) && w > 0 ? w : null;\n };\n\n const pxToPercent = (dxPx: number): number | null => {\n const w = getTrackWidthPx();\n if (w === null) return null;\n const p = (dxPx / w) * 100;\n return Number.isFinite(p) ? p : null;\n };\n\n const setPointerCaptureBestEffort = (el: Element, pointerId: number): void => {\n try {\n (el as HTMLElement).setPointerCapture(pointerId);\n } catch {\n // Ignore (best-effort).\n }\n };\n\n const releasePointerCaptureBestEffort = (el: Element, pointerId: number): void => {\n try {\n (el as HTMLElement).releasePointerCapture(pointerId);\n } catch {\n // Ignore (best-effort).\n }\n };\n\n const startDrag = (e: PointerEvent, mode: DragMode): void => {\n if (disposed) return;\n if (e.button !== 0) return;\n\n e.preventDefault();\n\n // If we somehow start a new drag while another is in-flight, clean up first.\n activeDragCleanup?.();\n activeDragCleanup = null;\n\n const dragStartX = e.clientX;\n const startRange = zoomState.getRange();\n\n const target = e.currentTarget instanceof Element ? e.currentTarget : windowEl;\n setPointerCaptureBestEffort(target, e.pointerId);\n\n if (mode === 'pan-window') {\n windowEl.style.cursor = 'grabbing';\n centerGrip.style.cursor = 'grabbing';\n }\n\n const onMove = (ev: PointerEvent): void => {\n if (disposed) return;\n if (ev.pointerId !== e.pointerId) return;\n\n ev.preventDefault();\n\n const dxPercent = pxToPercent(ev.clientX - dragStartX);\n if (dxPercent === null) return;\n\n switch (mode) {\n case 'left-handle': {\n // UX: don't allow handle crossing; clamp left <= current end.\n const nextStart = Math.min(startRange.end, startRange.start + dxPercent);\n const anchored = zoomState as unknown as Partial<{\n setRangeAnchored: (start: number, end: number, anchor: 'start' | 'end' | 'center') => void;\n }>;\n if (anchored.setRangeAnchored) {\n // When clamped by minSpan/maxSpan, keep the right edge anchored (prevents jumpiness).\n anchored.setRangeAnchored(nextStart, startRange.end, 'end');\n } else {\n zoomState.setRange(nextStart, startRange.end);\n }\n return;\n }\n case 'right-handle': {\n // UX: don't allow handle crossing; clamp right >= current start.\n const nextEnd = Math.max(startRange.start, startRange.end + dxPercent);\n const anchored = zoomState as unknown as Partial<{\n setRangeAnchored: (start: number, end: number, anchor: 'start' | 'end' | 'center') => void;\n }>;\n if (anchored.setRangeAnchored) {\n // When clamped by minSpan/maxSpan, keep the left edge anchored (prevents jumpiness).\n anchored.setRangeAnchored(startRange.start, nextEnd, 'start');\n } else {\n zoomState.setRange(startRange.start, nextEnd);\n }\n return;\n }\n case 'pan-window': {\n zoomState.setRange(startRange.start + dxPercent, startRange.end + dxPercent);\n return;\n }\n }\n };\n\n let cleanedUp = false;\n\n const cleanup = (): void => {\n if (cleanedUp) return;\n cleanedUp = true;\n\n window.removeEventListener('pointermove', onMove);\n window.removeEventListener('pointerup', finish);\n window.removeEventListener('pointercancel', finish);\n\n if (mode === 'pan-window') {\n windowEl.style.cursor = 'grab';\n centerGrip.style.cursor = 'grab';\n }\n\n releasePointerCaptureBestEffort(target, e.pointerId);\n\n // Only clear if we're still the active drag.\n if (activeDragCleanup === cleanup) activeDragCleanup = null;\n };\n\n const finish = (ev: PointerEvent): void => {\n if (ev.pointerId !== e.pointerId) return;\n cleanup();\n };\n\n activeDragCleanup = cleanup;\n\n window.addEventListener('pointermove', onMove, { passive: false });\n window.addEventListener('pointerup', finish, { passive: true });\n window.addEventListener('pointercancel', finish, { passive: true });\n };\n\n const onLeftDown = (e: PointerEvent): void => startDrag(e, 'left-handle');\n const onRightDown = (e: PointerEvent): void => startDrag(e, 'right-handle');\n const onPanDown = (e: PointerEvent): void => startDrag(e, 'pan-window');\n\n leftHandle.addEventListener('pointerdown', onLeftDown, { passive: false });\n rightHandle.addEventListener('pointerdown', onRightDown, { passive: false });\n centerGrip.addEventListener('pointerdown', onPanDown, { passive: false });\n\n // Keep DOM in sync with state.\n const unsubscribe = zoomState.onChange((range) => {\n if (disposed) return;\n applyRangeToDom(range);\n });\n\n // Initialize UI.\n applyRangeToDom(zoomState.getRange());\n\n const update: DataZoomSlider['update'] = (theme) => {\n if (disposed) return;\n\n // Baseline track styling.\n track.style.background = theme.backgroundColor;\n track.style.borderColor = theme.axisLineColor;\n\n // Preview styling (placeholder).\n preview.style.background = theme.gridLineColor;\n\n // Window styling.\n windowEl.style.background = theme.gridLineColor;\n windowEl.style.border = `1px solid ${theme.axisTickColor}`;\n windowEl.style.borderRadius = '8px';\n windowEl.style.boxSizing = 'border-box';\n\n // Handles styling.\n const handleBorder = `1px solid ${theme.axisLineColor}`;\n leftHandle.style.background = theme.axisTickColor;\n leftHandle.style.borderRight = handleBorder;\n rightHandle.style.background = theme.axisTickColor;\n rightHandle.style.borderLeft = handleBorder;\n\n // Center grip styling: subtle stripes.\n centerGrip.style.background = 'transparent';\n centerGrip.style.backgroundImage =\n 'linear-gradient(90deg, rgba(255,255,255,0.0) 0, rgba(255,255,255,0.0) 42%, rgba(255,255,255,0.18) 42%, rgba(255,255,255,0.18) 46%, rgba(255,255,255,0.0) 46%, rgba(255,255,255,0.0) 54%, rgba(255,255,255,0.18) 54%, rgba(255,255,255,0.18) 58%, rgba(255,255,255,0.0) 58%, rgba(255,255,255,0.0) 100%)';\n centerGrip.style.mixBlendMode = 'normal';\n };\n\n const dispose: DataZoomSlider['dispose'] = () => {\n if (disposed) return;\n disposed = true;\n\n // If dispose happens during an active drag, ensure we remove all window listeners.\n activeDragCleanup?.();\n activeDragCleanup = null;\n\n try {\n unsubscribe();\n } catch {\n // Best-effort.\n }\n\n leftHandle.removeEventListener('pointerdown', onLeftDown);\n rightHandle.removeEventListener('pointerdown', onRightDown);\n centerGrip.removeEventListener('pointerdown', onPanDown);\n\n root.remove();\n };\n\n return { update, dispose };\n}\n\n","/**\n * Worker-related types for ChartGPU worker thread support.\n */\n\n/**\n * Branded type for stride values in bytes.\n * Ensures type safety when passing stride information for data point formats.\n */\nexport type StrideBytes = number & { readonly __brand: 'StrideBytes' };\n\n/**\n * Stride for DataPoint format: [x, y] = 2 floats × 4 bytes = 8 bytes.\n */\nexport const XY_STRIDE: StrideBytes = 8 as StrideBytes;\n\n/**\n * Stride for OHLCDataPoint format: [t, o, h, l, c] = 5 floats × 4 bytes = 20 bytes.\n */\nexport const OHLC_STRIDE: StrideBytes = 20 as StrideBytes;\n\n/**\n * Configuration for creating a worker-based chart instance.\n */\nexport interface WorkerConfig {\n /** Web Worker instance to use for rendering. */\n readonly worker: Worker;\n /** Chart ID for worker communication (auto-generated if not provided). */\n readonly chartId?: string;\n /** Timeout in milliseconds for message responses (default: 30000). */\n readonly messageTimeout?: number;\n /** Optional WebGPU initialization options. */\n readonly gpuOptions?: {\n readonly powerPreference?: 'low-power' | 'high-performance';\n readonly requiredFeatures?: ReadonlyArray<string>;\n };\n}\n\n/**\n * Error thrown when worker operations fail.\n */\nexport class ChartGPUWorkerError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly operation: string,\n public readonly chartId?: string\n ) {\n super(message);\n this.name = 'ChartGPUWorkerError';\n }\n}\n\n/**\n * Internal pending request tracker for message correlation.\n * \n * Generic type T represents the expected response message type.\n * This ensures type safety when resolving promises with specific message types.\n * \n * @example\n * ```typescript\n * const pending: PendingRequest<ReadyMessage> = {\n * resolve: (msg: ReadyMessage) => console.log(msg.capabilities),\n * reject: (err: Error) => console.error(err),\n * timeout: setTimeout(...),\n * operation: 'init'\n * };\n * ```\n */\nexport interface PendingRequest<T = unknown> {\n readonly resolve: (value: T) => void;\n readonly reject: (error: Error) => void;\n readonly timeout: ReturnType<typeof setTimeout>;\n /** Operation name for debugging and error reporting. */\n readonly operation: string;\n}\n\n/**\n * Constants for maximum safe buffer sizes.\n * Based on browser structured clone algorithm limits (~2GB) and WebGPU buffer limits.\n */\nexport const MAX_BUFFER_SIZE = 2_147_483_648; // 2GB\n\n/**\n * Maximum safe point counts for different data types.\n * Calculated based on MAX_BUFFER_SIZE and stride per point.\n */\nexport const MAX_XY_POINTS = Math.floor(MAX_BUFFER_SIZE / 8); // 268,435,456 points\nexport const MAX_OHLC_POINTS = Math.floor(MAX_BUFFER_SIZE / 20); // 107,374,182 points\n","/**\n * ChartGPUWorkerProxy - Main-thread proxy for worker-based chart rendering.\n * \n * Implements ChartGPUInstance interface while delegating rendering to a Web Worker.\n * Maintains local state cache for synchronous getters and provides message-based\n * communication with request/response correlation.\n * \n * ## Architecture\n * \n * - **Message Correlation**: Unique message IDs track request/response pairs\n * - **State Cache**: Local copies of options, disposed, interactionX, zoomRange\n * - **Event System**: Re-emits worker events to registered listeners\n * - **Timeout Handling**: 30s default timeout for async operations\n * \n * ## Usage\n * \n * ```typescript\n * const worker = new Worker('chart-worker.js');\n * const proxy = new ChartGPUWorkerProxy(worker, container, options);\n * await proxy.init(); // Wait for worker initialization\n * \n * // Use like regular ChartGPUInstance\n * proxy.on('click', (payload) => console.log(payload));\n * proxy.setOption(newOptions);\n * proxy.dispose();\n * ```\n */\n\nimport type {\n ChartGPUInstance,\n ChartGPUEventName,\n ChartGPUEventCallback,\n ChartGPUCrosshairMoveCallback,\n ChartGPUEventPayload,\n ChartGPUCrosshairMovePayload,\n} from '../ChartGPU';\nimport type {\n ChartGPUOptions,\n DataPoint,\n OHLCDataPoint,\n PointerEventData,\n PerformanceMetrics,\n PerformanceCapabilities,\n} from '../config/types';\nimport type { ThemeConfig } from '../themes/types';\nimport type {\n WorkerInboundMessage,\n WorkerOutboundMessage,\n ReadyMessage,\n TooltipUpdateMessage,\n LegendUpdateMessage,\n AxisLabelsUpdateMessage,\n} from './protocol';\nimport type { WorkerConfig, PendingRequest, StrideBytes } from './types';\nimport { ChartGPUWorkerError, XY_STRIDE, OHLC_STRIDE } from './types';\nimport { createTooltip } from '../components/createTooltip';\nimport type { Tooltip } from '../components/createTooltip';\nimport { createLegend } from '../components/createLegend';\nimport type { Legend } from '../components/createLegend';\nimport { createTextOverlay } from '../components/createTextOverlay';\nimport type { TextOverlay } from '../components/createTextOverlay';\nimport { createDataZoomSlider } from '../components/createDataZoomSlider';\nimport type { DataZoomSlider } from '../components/createDataZoomSlider';\nimport { createZoomState } from '../interaction/createZoomState';\nimport type { ZoomState } from '../interaction/createZoomState';\nimport { addAxisLabelsToOverlay } from '../utils/axisLabelStyling';\n\ntype AnyChartGPUEventCallback = ChartGPUEventCallback | ChartGPUCrosshairMoveCallback;\n\n/**\n * Generates a unique message ID for request/response correlation.\n * Uses timestamp + counter for collision resistance.\n */\nlet messageIdCounter = 0;\nfunction generateMessageId(): string {\n return `msg_${Date.now()}_${++messageIdCounter}`;\n}\n\n/**\n * Generates a unique chart ID for worker communication.\n * Uses timestamp + random suffix for collision resistance.\n */\nfunction generateChartId(): string {\n return `chart_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;\n}\n\n// Data zoom slider overlay reserves bottom chart space (CSS px).\n// Keep in sync with ChartGPU.ts and createDataZoomSliderHost() in this file.\nconst DATA_ZOOM_SLIDER_RESERVE_CSS_PX = 40;\n\n/**\n * Serializes DataPoint or OHLCDataPoint arrays to ArrayBuffer for zero-copy transfer.\n * \n * Uses Float32Array for GPU compatibility (GPUs use Float32 precision).\n * \n * @param points - Array of data points to serialize\n * @returns Tuple of [ArrayBuffer, stride] where stride is 8 for DataPoint, 20 for OHLCDataPoint\n */\nfunction serializeDataPoints(\n points: ReadonlyArray<DataPoint> | ReadonlyArray<OHLCDataPoint>\n): [ArrayBuffer, number] {\n if (points.length === 0) {\n return [new ArrayBuffer(0), 0];\n }\n\n // Detect point type from first element\n const firstPoint = points[0];\n const isOHLC = Array.isArray(firstPoint)\n ? firstPoint.length === 5\n : 'timestamp' in firstPoint && 'open' in firstPoint;\n\n if (isOHLC) {\n // OHLCDataPoint: [timestamp, open, close, low, high] (5 × 4 bytes = 20 bytes)\n const stride = 20;\n const buffer = new ArrayBuffer(points.length * stride);\n const view = new Float32Array(buffer);\n \n for (let i = 0, offset = 0; i < points.length; i++, offset += 5) {\n const p = points[i] as OHLCDataPoint;\n if (Array.isArray(p)) {\n view[offset] = p[0]; // timestamp\n view[offset + 1] = p[1]; // open\n view[offset + 2] = p[2]; // close\n view[offset + 3] = p[3]; // low\n view[offset + 4] = p[4]; // high\n } else {\n // Type assertion: we know it's OHLCDataPointObject at this point\n const ohlcObj = p as import('../config/types').OHLCDataPointObject;\n view[offset] = ohlcObj.timestamp;\n view[offset + 1] = ohlcObj.open;\n view[offset + 2] = ohlcObj.close;\n view[offset + 3] = ohlcObj.low;\n view[offset + 4] = ohlcObj.high;\n }\n }\n \n return [buffer, stride];\n } else {\n // DataPoint: [x, y] pairs (2 × 4 bytes = 8 bytes)\n const stride = 8;\n const buffer = new ArrayBuffer(points.length * stride);\n const view = new Float32Array(buffer);\n \n for (let i = 0, offset = 0; i < points.length; i++, offset += 2) {\n const p = points[i] as DataPoint;\n if (Array.isArray(p)) {\n view[offset] = p[0]; // x\n view[offset + 1] = p[1]; // y\n } else {\n // Type assertion: we know it's { x, y } at this point\n const dataObj = p as { x: number; y: number };\n view[offset] = dataObj.x;\n view[offset + 1] = dataObj.y;\n }\n }\n \n return [buffer, stride];\n }\n}\n\n/**\n * Pending overlay updates for RAF batching.\n */\ntype PendingOverlayUpdates = {\n tooltip?: TooltipUpdateMessage;\n legend?: LegendUpdateMessage;\n axisLabels?: AxisLabelsUpdateMessage;\n};\n\n/**\n * Computes PointerEventData fields from a PointerEvent and canvas element.\n * Calculates canvas-local coordinates, grid margins, plot dimensions, and isInGrid flag.\n * \n * This function provides the same coordinate calculation logic as the main-thread\n * createEventManager.ts to ensure parity between worker and non-worker charts.\n * \n * CRITICAL: Accounts for slider bottom-space reservation to prevent grid/isInGrid mismatch.\n * When a slider-type dataZoom is configured, the worker chart reserves additional bottom\n * space (40px) for the slider overlay. This function must apply the same reservation to\n * ensure pointer events are correctly classified as inside/outside the grid.\n * \n * @param event - Native PointerEvent from canvas\n * @param canvas - Canvas element for getBoundingClientRect()\n * @param options - Chart options for grid margin defaults\n * @returns PointerEventData without the 'type' field (caller adds type)\n */\nfunction computePointerEventData(\n event: PointerEvent,\n canvas: HTMLCanvasElement,\n options: ChartGPUOptions\n): Omit<PointerEventData, 'type'> {\n const rect = canvas.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n \n // Compute base grid margins from options (match defaults in createEventManager.ts)\n const plotLeftCss = options.grid?.left ?? 60;\n const plotTopCss = options.grid?.top ?? 40;\n const plotRightCss = options.grid?.right ?? 20;\n let plotBottomCss = options.grid?.bottom ?? 40;\n \n // CRITICAL: Account for slider bottom-space reservation\n // When slider dataZoom exists, resolveOptionsForChart adds 40px to grid.bottom\n // to prevent x-axis labels from being overlaid by the slider. This function must\n // apply the SAME reservation to ensure pointer events are correctly classified.\n // Without this, events near the bottom edge would be incorrectly marked as isInGrid=true\n // when they're actually over the slider overlay.\n const hasSliderZoom = options.dataZoom?.some((z) => z?.type === 'slider') ?? false;\n if (hasSliderZoom) {\n plotBottomCss += DATA_ZOOM_SLIDER_RESERVE_CSS_PX;\n }\n \n // Compute plot dimensions\n const plotWidthCss = rect.width - plotLeftCss - plotRightCss;\n const plotHeightCss = rect.height - plotTopCss - plotBottomCss;\n \n // Compute grid-local coordinates\n const gridX = x - plotLeftCss;\n const gridY = y - plotTopCss;\n \n // Check if pointer is inside the grid/plot area\n const isInGrid = gridX >= 0 && gridX <= plotWidthCss && gridY >= 0 && gridY <= plotHeightCss;\n \n return {\n x,\n y,\n gridX,\n gridY,\n plotWidthCss,\n plotHeightCss,\n isInGrid,\n timestamp: event.timeStamp,\n };\n}\n\n\n/**\n * ChartGPUWorkerProxy - Main-thread proxy for worker-based rendering.\n * \n * Implements ChartGPUInstance interface, delegating all rendering to a Web Worker\n * while maintaining local state cache for synchronous operations.\n */\nexport class ChartGPUWorkerProxy implements ChartGPUInstance {\n private readonly worker: Worker;\n private readonly chartId: string;\n private readonly messageTimeout: number;\n \n // State cache (synchronized with worker)\n private cachedOptions: ChartGPUOptions;\n private isDisposed = false;\n private isInitialized = false;\n private cachedInteractionX: number | null = null;\n private cachedZoomRange: Readonly<{ start: number; end: number }> | null = null;\n /**\n * Best-effort local series point counts used to keep dataset-aware zoom constraints\n * in sync with worker zoom behavior (especially for streaming appendData()).\n */\n private cachedSeriesPointCountsForZoom: number[] = [];\n \n // Performance metrics cache\n private cachedPerformanceMetrics: Readonly<PerformanceMetrics> | null = null;\n private cachedPerformanceCapabilities: Readonly<PerformanceCapabilities> | null = null;\n private performanceUpdateCallbacks = new Set<(metrics: Readonly<PerformanceMetrics>) => void>();\n \n // Message correlation system\n private readonly pendingRequests = new Map<string, PendingRequest>();\n \n // Event system\n private readonly listeners = new Map<ChartGPUEventName, Set<AnyChartGPUEventCallback>>();\n \n // Worker message handler (bound once)\n private readonly boundMessageHandler: (event: MessageEvent) => void;\n \n // DOM overlays\n private tooltip: Tooltip | null = null;\n private legend: Legend | null = null;\n private textOverlay: TextOverlay | null = null;\n private dataZoomSlider: DataZoomSlider | null = null;\n private dataZoomSliderHost: HTMLDivElement | null = null;\n private zoomState: ZoomState | null = null;\n \n // RAF batching for overlay updates\n private pendingOverlayUpdates: PendingOverlayUpdates = {};\n private overlayUpdateRafId: number | null = null;\n \n // Zoom echo suppression flag\n // Set to true when processing zoom changes FROM the worker to prevent sending them back\n private isProcessingWorkerZoomUpdate = false;\n \n // Event forwarding to worker\n private readonly boundEventHandlers: {\n pointerdown: ((e: PointerEvent) => void) | null;\n pointermove: ((e: PointerEvent) => void) | null;\n pointerup: ((e: PointerEvent) => void) | null;\n pointerleave: ((e: PointerEvent) => void) | null;\n wheel: ((e: WheelEvent) => void) | null;\n } = {\n pointerdown: null,\n pointermove: null,\n pointerup: null,\n pointerleave: null,\n wheel: null,\n };\n \n // RAF throttling for pointermove events\n private pendingMoveEvent: PointerEvent | null = null;\n private moveThrottleRafId: number | null = null;\n \n // Click detection state\n private tapCandidate: {\n readonly startX: number;\n readonly startY: number;\n readonly startTime: number;\n } | null = null;\n \n private readonly TAP_MAX_DISTANCE_PX = 6;\n private readonly TAP_MAX_TIME_MS = 500;\n \n // ResizeObserver and device pixel ratio monitoring\n private resizeObserver: ResizeObserver | null = null;\n private currentDpr: number = 1;\n private dprMediaQuery: MediaQueryList | null = null;\n private boundDprChangeHandler: ((e: MediaQueryListEvent) => void) | null = null;\n private pendingResize: { width: number; height: number } | null = null;\n private resizeRafId: number | null = null;\n \n /**\n * Creates a new worker-based chart proxy.\n * \n * @param config - Worker configuration\n * @param container - HTML element to attach canvas to\n * @param options - Chart options\n */\n constructor(\n config: WorkerConfig,\n private readonly container: HTMLElement,\n options: ChartGPUOptions\n ) {\n this.worker = config.worker;\n this.chartId = config.chartId ?? generateChartId();\n this.messageTimeout = config.messageTimeout ?? 30000;\n this.cachedOptions = options;\n this.recomputeCachedSeriesPointCountsForZoom(options);\n \n // Initialize event listener maps\n this.listeners.set('click', new Set());\n this.listeners.set('mouseover', new Set());\n this.listeners.set('mouseout', new Set());\n this.listeners.set('crosshairMove', new Set());\n \n // Bind message handler once (avoid creating new function on every message)\n this.boundMessageHandler = this.handleWorkerMessage.bind(this);\n this.worker.addEventListener('message', this.boundMessageHandler);\n }\n\n private recomputeCachedSeriesPointCountsForZoom(options: ChartGPUOptions): void {\n const series = options.series ?? [];\n const next = new Array(series.length);\n for (let i = 0; i < series.length; i++) {\n const s: any = series[i];\n if (!s || s.type === 'pie') {\n next[i] = 0;\n continue;\n }\n const raw = (s.rawData ?? s.data) as unknown;\n next[i] = Array.isArray(raw) ? raw.length : 0;\n }\n this.cachedSeriesPointCountsForZoom = next;\n }\n\n private incrementCachedSeriesPointCountForZoom(seriesIndex: number, deltaPoints: number): void {\n if (!Number.isFinite(deltaPoints) || deltaPoints <= 0) return;\n const next = Math.floor(deltaPoints);\n if (next <= 0) return;\n\n const counts = this.cachedSeriesPointCountsForZoom;\n if (seriesIndex >= counts.length) {\n for (let i = counts.length; i <= seriesIndex; i++) counts[i] = 0;\n }\n counts[seriesIndex] = (counts[seriesIndex] ?? 0) + next;\n }\n \n /**\n * Initializes the worker chart instance.\n * Must be called before using the chart.\n * \n * @returns Promise that resolves when worker is ready\n */\n async init(): Promise<void> {\n // Create OffscreenCanvas for worker rendering\n const canvas = document.createElement('canvas');\n canvas.style.display = 'block';\n canvas.style.width = '100%';\n canvas.style.height = '100%';\n this.container.appendChild(canvas);\n\n // Get canvas dimensions\n const rect = canvas.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n const width = Math.max(1, Math.round(rect.width * dpr));\n const height = Math.max(1, Math.round(rect.height * dpr));\n\n canvas.width = width;\n canvas.height = height;\n \n // Set up event listeners on canvas BEFORE transferring to worker\n this.setupEventListeners(canvas);\n \n // Set up ResizeObserver and device pixel ratio monitoring BEFORE transferring canvas\n this.setupResizeObserver(canvas);\n this.setupDevicePixelRatioMonitoring();\n \n // Create DOM overlays AFTER canvas is in DOM (overlays need container)\n this.createOverlays();\n \n // Transfer canvas to worker\n const offscreenCanvas = canvas.transferControlToOffscreen();\n \n // Send init message and wait for ready response\n await this.sendMessageWithResponse<ReadyMessage>({\n type: 'init',\n chartId: this.chartId,\n messageId: generateMessageId(),\n canvas: offscreenCanvas,\n devicePixelRatio: dpr,\n options: this.cachedOptions,\n }, [offscreenCanvas]);\n }\n \n // =============================================================================\n // Event Forwarding to Worker\n // =============================================================================\n \n /**\n * Sets up pointer and wheel event listeners on the canvas.\n * Forwards events to worker for interaction handling (hover, click, zoom, pan).\n * \n * @param canvas - Canvas element to attach listeners to\n */\n private setupEventListeners(canvas: HTMLCanvasElement): void {\n if (this.isDisposed) return;\n \n // Pointer down handler - stores tap candidate for click detection\n // Does NOT send message yet - waits for pointer up to determine if it's a tap/click\n this.boundEventHandlers.pointerdown = (e: PointerEvent) => {\n if (this.isDisposed || !this.isInitialized) return;\n if (!e.isPrimary) return; // Only track primary pointer\n if (e.button !== 0) return; // Only left mouse button\n \n // Store tap candidate with start position and time\n this.tapCandidate = {\n startX: e.clientX,\n startY: e.clientY,\n startTime: e.timeStamp,\n };\n };\n \n // Pointer move handler - throttled to 60fps via RAF\n // \n // PERFORMANCE: pointermove can fire at 120-500 Hz on modern devices. Without throttling,\n // this would flood the worker with messages, causing:\n // 1. Worker message queue backup (messages queued faster than processed)\n // 2. Stale hover state (processing events that are 100s of ms old)\n // 3. Excessive postMessage overhead (serialization + transfer costs)\n // \n // RAF throttling (60fps) provides optimal balance:\n // - Smooth hover interactions (16.67ms latency is imperceptible)\n // - Reduces message rate by 2-8x (120-500 Hz → 60 Hz)\n // - Aligns with display refresh rate (no visual benefit beyond 60fps)\n // \n // CONCURRENCY: Uses \"latest event wins\" strategy - only the most recent move event\n // within each RAF frame is sent. Earlier events are discarded (they're already stale).\n this.boundEventHandlers.pointermove = (e: PointerEvent) => {\n if (this.isDisposed || !this.isInitialized) return;\n \n // Store latest move event (overwrites previous if multiple events in same frame)\n this.pendingMoveEvent = e;\n \n // Schedule RAF if not already scheduled (coalesce multiple moves per frame)\n if (this.moveThrottleRafId === null) {\n this.moveThrottleRafId = requestAnimationFrame(() => {\n this.moveThrottleRafId = null;\n if (this.isDisposed || !this.isInitialized || !this.pendingMoveEvent) return;\n \n const canvas = this.container.querySelector('canvas');\n if (!canvas) return;\n \n const computed = computePointerEventData(this.pendingMoveEvent, canvas, this.cachedOptions);\n this.pendingMoveEvent = null;\n \n console.log('[ChartGPUWorkerProxy] Sending move event:', {\n gridX: computed.gridX,\n gridY: computed.gridY,\n isInGrid: computed.isInGrid,\n });\n this.sendMessage({\n type: 'forwardPointerEvent',\n chartId: this.chartId,\n event: {\n ...computed,\n type: 'move',\n },\n });\n });\n }\n };\n \n // Pointer up handler - detects clicks (taps) and sends 'click' events\n // Only sends message if tap criteria are met (distance <= 6px, time <= 500ms)\n this.boundEventHandlers.pointerup = (e: PointerEvent) => {\n if (this.isDisposed || !this.isInitialized) return;\n if (!e.isPrimary) return; // Only handle primary pointer\n \n // Check if we have a tap candidate\n if (this.tapCandidate) {\n const dt = e.timeStamp - this.tapCandidate.startTime;\n const dx = e.clientX - this.tapCandidate.startX;\n const dy = e.clientY - this.tapCandidate.startY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n // Clear tap candidate\n this.tapCandidate = null;\n \n // Check if tap criteria are met\n if (dt <= this.TAP_MAX_TIME_MS && distance <= this.TAP_MAX_DISTANCE_PX) {\n // It's a tap/click - compute coordinates and send message\n const canvas = this.container.querySelector('canvas');\n if (!canvas) return;\n \n const computed = computePointerEventData(e, canvas, this.cachedOptions);\n \n console.log('[ChartGPUWorkerProxy] Sending click event:', {\n gridX: computed.gridX,\n gridY: computed.gridY,\n isInGrid: computed.isInGrid,\n });\n this.sendMessage({\n type: 'forwardPointerEvent',\n chartId: this.chartId,\n event: {\n ...computed,\n type: 'click',\n },\n });\n }\n // If not a tap (drag or too long), ignore - don't send message\n }\n };\n \n // Pointer leave handler - clears hover state and tap candidate\n this.boundEventHandlers.pointerleave = (e: PointerEvent) => {\n if (this.isDisposed || !this.isInitialized) return;\n \n // Clear tap candidate on leave\n this.tapCandidate = null;\n \n const canvas = this.container.querySelector('canvas');\n if (!canvas) return;\n \n const computed = computePointerEventData(e, canvas, this.cachedOptions);\n \n this.sendMessage({\n type: 'forwardPointerEvent',\n chartId: this.chartId,\n event: {\n ...computed,\n type: 'leave',\n },\n });\n };\n \n // Wheel handler - for zoom interactions\n this.boundEventHandlers.wheel = (e: WheelEvent) => {\n if (this.isDisposed || !this.isInitialized) return;\n \n // Convert WheelEvent to PointerEventData with wheel-specific fields\n // Use shared logic for coordinate calculation (includes slider bottom-space)\n const rect = canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n \n const plotLeftCss = this.cachedOptions.grid?.left ?? 60;\n const plotTopCss = this.cachedOptions.grid?.top ?? 40;\n const plotRightCss = this.cachedOptions.grid?.right ?? 20;\n let plotBottomCss = this.cachedOptions.grid?.bottom ?? 40;\n \n // CRITICAL: Account for slider bottom-space reservation (same as computePointerEventData)\n const hasSliderZoom = this.cachedOptions.dataZoom?.some((z) => z?.type === 'slider') ?? false;\n if (hasSliderZoom) {\n plotBottomCss += DATA_ZOOM_SLIDER_RESERVE_CSS_PX;\n }\n \n const plotWidthCss = rect.width - plotLeftCss - plotRightCss;\n const plotHeightCss = rect.height - plotTopCss - plotBottomCss;\n \n const gridX = x - plotLeftCss;\n const gridY = y - plotTopCss;\n const isInGrid = gridX >= 0 && gridX <= plotWidthCss && gridY >= 0 && gridY <= plotHeightCss;\n \n const wheelEvent: PointerEventData = {\n type: 'wheel',\n x,\n y,\n gridX,\n gridY,\n plotWidthCss,\n plotHeightCss,\n isInGrid,\n timestamp: e.timeStamp,\n deltaX: e.deltaX,\n deltaY: e.deltaY,\n deltaZ: e.deltaZ,\n deltaMode: e.deltaMode,\n };\n \n this.sendMessage({\n type: 'forwardPointerEvent',\n chartId: this.chartId,\n event: wheelEvent,\n });\n \n // Prevent default scroll behavior when zooming\n if (isInGrid) {\n e.preventDefault();\n }\n };\n \n // Attach all event listeners\n canvas.addEventListener('pointerdown', this.boundEventHandlers.pointerdown);\n canvas.addEventListener('pointermove', this.boundEventHandlers.pointermove);\n canvas.addEventListener('pointerup', this.boundEventHandlers.pointerup);\n canvas.addEventListener('pointerleave', this.boundEventHandlers.pointerleave);\n // IMPORTANT: passive: false allows preventDefault() in wheel handler for custom zoom behavior\n // Without this, browsers may apply default scroll behavior before our handler runs\n canvas.addEventListener('wheel', this.boundEventHandlers.wheel, { passive: false });\n }\n \n /**\n * Removes all event listeners from the canvas and cleans up RAF throttling.\n */\n private cleanupEventListeners(): void {\n const canvas = this.container.querySelector('canvas');\n if (!canvas) return;\n \n // Cancel pending RAF for throttled move events\n if (this.moveThrottleRafId !== null) {\n cancelAnimationFrame(this.moveThrottleRafId);\n this.moveThrottleRafId = null;\n }\n \n // Clear pending move event\n this.pendingMoveEvent = null;\n \n // Clear tap candidate state\n this.tapCandidate = null;\n \n // Remove all event listeners\n if (this.boundEventHandlers.pointerdown) {\n canvas.removeEventListener('pointerdown', this.boundEventHandlers.pointerdown);\n this.boundEventHandlers.pointerdown = null;\n }\n if (this.boundEventHandlers.pointermove) {\n canvas.removeEventListener('pointermove', this.boundEventHandlers.pointermove);\n this.boundEventHandlers.pointermove = null;\n }\n if (this.boundEventHandlers.pointerup) {\n canvas.removeEventListener('pointerup', this.boundEventHandlers.pointerup);\n this.boundEventHandlers.pointerup = null;\n }\n if (this.boundEventHandlers.pointerleave) {\n canvas.removeEventListener('pointerleave', this.boundEventHandlers.pointerleave);\n this.boundEventHandlers.pointerleave = null;\n }\n if (this.boundEventHandlers.wheel) {\n canvas.removeEventListener('wheel', this.boundEventHandlers.wheel);\n this.boundEventHandlers.wheel = null;\n }\n }\n \n // =============================================================================\n // ResizeObserver and Device Pixel Ratio Monitoring\n // =============================================================================\n \n /**\n * Sets up ResizeObserver to monitor container size changes.\n * Uses RAF batching to throttle rapid resize events (e.g., during window drag-resize).\n * \n * @param canvas - Canvas element to measure dimensions from\n */\n private setupResizeObserver(canvas: HTMLCanvasElement): void {\n if (this.isDisposed) return;\n \n // Track last known dimensions to avoid no-op resizes\n let lastWidth = canvas.clientWidth;\n let lastHeight = canvas.clientHeight;\n \n this.resizeObserver = new ResizeObserver((entries) => {\n if (this.isDisposed) return;\n if (!entries[0]) return;\n \n // CRITICAL: After transferControlToOffscreen(), canvas.clientWidth/Height are invalid!\n // Use contentBoxSize from ResizeObserverEntry instead\n const contentBoxSize = entries[0].contentBoxSize?.[0];\n if (!contentBoxSize) return;\n \n const newWidth = contentBoxSize.inlineSize;\n const newHeight = contentBoxSize.blockSize;\n \n // Check if dimensions actually changed (ResizeObserver can fire on layout shifts)\n if (newWidth === lastWidth && newHeight === lastHeight) {\n return; // No-op resize\n }\n \n lastWidth = newWidth;\n lastHeight = newHeight;\n \n // Store pending dimensions and schedule RAF if not already scheduled\n this.pendingResize = { width: newWidth, height: newHeight };\n \n if (this.resizeRafId === null) {\n this.resizeRafId = requestAnimationFrame(() => {\n this.resizeRafId = null;\n \n // Safety: Check disposed and pendingResize before proceeding\n if (this.isDisposed) return;\n if (!this.pendingResize) return;\n \n const { width, height } = this.pendingResize;\n this.pendingResize = null;\n\n // Send resize message to worker with CSS pixels\n // WorkerController will multiply by devicePixelRatio to get physical pixels\n const dpr = this.currentDpr;\n\n this.sendMessage({\n type: 'resize',\n chartId: this.chartId,\n width: Math.max(1, width), // CSS pixels, minimum 1\n height: Math.max(1, height), // CSS pixels, minimum 1\n devicePixelRatio: dpr,\n requestRender: true,\n });\n });\n }\n });\n \n // Start observing the canvas element (more precise than observing container)\n this.resizeObserver.observe(canvas);\n }\n \n /**\n * Sets up device pixel ratio monitoring using matchMedia.\n * Handles window zoom, moving between displays, and OS display scaling changes.\n */\n private setupDevicePixelRatioMonitoring(): void {\n if (this.isDisposed) return;\n \n // Initialize current DPR\n this.currentDpr = window.devicePixelRatio || 1;\n \n // Create media query for current DPR\n this.dprMediaQuery = window.matchMedia(`(resolution: ${this.currentDpr}dppx)`);\n \n // Bind handler once to avoid creating new functions\n this.boundDprChangeHandler = (_e: MediaQueryListEvent) => {\n if (this.isDisposed) return;\n \n // DPR has changed - update tracked value\n const newDpr = window.devicePixelRatio || 1;\n if (newDpr === this.currentDpr) return;\n \n this.currentDpr = newDpr;\n \n // Recreate media query for new DPR\n if (this.dprMediaQuery && this.boundDprChangeHandler) {\n this.dprMediaQuery.removeEventListener('change', this.boundDprChangeHandler);\n }\n this.dprMediaQuery = window.matchMedia(`(resolution: ${this.currentDpr}dppx)`);\n if (this.boundDprChangeHandler) {\n this.dprMediaQuery.addEventListener('change', this.boundDprChangeHandler);\n }\n \n // Trigger resize with new DPR\n const canvas = this.container.querySelector('canvas');\n if (!canvas) return;\n\n const width = canvas.clientWidth;\n const height = canvas.clientHeight;\n\n this.sendMessage({\n type: 'resize',\n chartId: this.chartId,\n width: Math.max(1, width), // CSS pixels\n height: Math.max(1, height), // CSS pixels\n devicePixelRatio: this.currentDpr,\n requestRender: true,\n });\n };\n \n this.dprMediaQuery.addEventListener('change', this.boundDprChangeHandler);\n }\n \n /**\n * Cleans up ResizeObserver and device pixel ratio monitoring.\n */\n private cleanupResizeMonitoring(): void {\n // Disconnect ResizeObserver\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n \n // Cancel pending RAF for resize\n if (this.resizeRafId !== null) {\n cancelAnimationFrame(this.resizeRafId);\n this.resizeRafId = null;\n }\n \n // Clear pending resize state\n this.pendingResize = null;\n \n // Remove DPR media query listener\n if (this.dprMediaQuery && this.boundDprChangeHandler) {\n this.dprMediaQuery.removeEventListener('change', this.boundDprChangeHandler);\n this.dprMediaQuery = null;\n this.boundDprChangeHandler = null;\n }\n }\n \n // =============================================================================\n // DOM Overlay Management\n // =============================================================================\n \n /**\n * Creates DOM overlays for tooltip, legend, text labels, and data zoom slider.\n * Called after canvas is appended to container.\n */\n private createOverlays(): void {\n if (this.isDisposed) return;\n \n // Always create tooltip (for hover interactions)\n this.tooltip = createTooltip(this.container);\n \n // Always create text overlay (for axis labels)\n this.textOverlay = createTextOverlay(this.container);\n \n // Always create legend (worker will send updates if needed)\n // Default position is 'right' - worker may override via messages\n this.legend = createLegend(this.container, 'right');\n \n // Create data zoom slider if configured\n const hasSliderZoom = this.cachedOptions.dataZoom?.some(z => z?.type === 'slider') ?? false;\n \n if (hasSliderZoom) {\n // Create zoom state that delegates to worker via setZoomRange\n const initialStart = this.cachedZoomRange?.start ?? 0;\n const initialEnd = this.cachedZoomRange?.end ?? 100;\n const constraints = this.computeZoomSpanConstraints(this.cachedOptions);\n this.zoomState = createZoomState(initialStart, initialEnd, constraints);\n \n // Sync zoom state changes to worker\n // CRITICAL: Echo suppression - only send changes to worker if they originated from UI\n // (slider drag, programmatic setZoomRange calls), NOT from worker zoom messages\n this.zoomState.onChange((range) => {\n if (this.isDisposed) return;\n \n // Prevent echo: Don't send zoom changes back to worker if they came FROM the worker\n if (this.isProcessingWorkerZoomUpdate) return;\n \n this.setZoomRange(range.start, range.end);\n });\n \n // Create slider host element with absolute positioning at bottom\n // This matches the non-worker ChartGPU implementation\n this.dataZoomSliderHost = this.createDataZoomSliderHost();\n \n // Create slider inside host with marginTop: 0 (host provides padding)\n const DATA_ZOOM_SLIDER_HEIGHT_CSS_PX = 32;\n this.dataZoomSlider = createDataZoomSlider(this.dataZoomSliderHost, this.zoomState, {\n height: DATA_ZOOM_SLIDER_HEIGHT_CSS_PX,\n marginTop: 0, // host provides vertical spacing\n });\n \n // Apply theme to slider\n const themeConfig = this.resolveThemeConfig();\n this.dataZoomSlider.update(themeConfig);\n }\n }\n \n /**\n * Creates and configures the data zoom slider host element.\n * The host is absolutely positioned at the bottom of the container.\n * \n * @returns Host element for the data zoom slider\n */\n private createDataZoomSliderHost(): HTMLDivElement {\n // Ensure the container has a positioning context for absolute positioning\n // Only set if currently 'static' to avoid overwriting user styles\n try {\n const pos = window.getComputedStyle(this.container).position;\n if (pos === 'static') {\n this.container.style.position = 'relative';\n }\n } catch {\n // Best effort - continue even if getComputedStyle fails\n }\n \n const DATA_ZOOM_SLIDER_HEIGHT_CSS_PX = 32;\n const DATA_ZOOM_SLIDER_MARGIN_TOP_CSS_PX = 8;\n const DATA_ZOOM_SLIDER_RESERVE_CSS_PX = DATA_ZOOM_SLIDER_HEIGHT_CSS_PX + DATA_ZOOM_SLIDER_MARGIN_TOP_CSS_PX;\n \n const host = document.createElement('div');\n host.style.position = 'absolute';\n host.style.left = '0';\n host.style.right = '0';\n host.style.bottom = '0';\n host.style.height = `${DATA_ZOOM_SLIDER_RESERVE_CSS_PX}px`;\n host.style.paddingTop = `${DATA_ZOOM_SLIDER_MARGIN_TOP_CSS_PX}px`;\n host.style.boxSizing = 'border-box';\n host.style.pointerEvents = 'auto';\n host.style.zIndex = '10'; // Above canvas and other overlays\n \n this.container.appendChild(host);\n \n return host;\n }\n\n /**\n * Computes effective zoom span constraints for the local slider zoomState.\n *\n * This must match the worker coordinator's clamping behavior so that:\n * - slider drags clamp identically to wheel zoom in the worker\n * - UI stays perfectly in sync with worker zoomChange messages\n */\n private computeZoomSpanConstraints(\n options: ChartGPUOptions\n ): { readonly minSpan?: number; readonly maxSpan?: number } {\n const clampPercent = (v: number): number => Math.min(100, Math.max(0, v));\n\n // Aggregate constraints across all dataZoom configs (inside + slider share the same zoom window).\n let minSpan: number | null = null;\n let maxSpan: number | null = null;\n for (const z of options.dataZoom ?? []) {\n if (!z) continue;\n if (z.type !== 'inside' && z.type !== 'slider') continue;\n\n if (Number.isFinite(z.minSpan as number)) {\n const v = clampPercent(z.minSpan as number);\n minSpan = minSpan == null ? v : Math.max(minSpan, v);\n }\n if (Number.isFinite(z.maxSpan as number)) {\n const v = clampPercent(z.maxSpan as number);\n maxSpan = maxSpan == null ? v : Math.min(maxSpan, v);\n }\n }\n\n // Dataset-aware default: for numeric/time x axes, allow zooming to roughly one interval\n // by using 100/(N-1) where N is the densest (max-length) raw series.\n const xAxisType = options.xAxis?.type ?? 'value';\n let datasetMin: number | null = null;\n if (xAxisType !== 'category') {\n let maxPoints = 0;\n const series = options.series ?? [];\n for (let i = 0; i < series.length; i++) {\n const s: any = series[i];\n if (!s || s.type === 'pie') continue;\n const len = this.cachedSeriesPointCountsForZoom[i] ?? 0;\n maxPoints = Math.max(maxPoints, len);\n }\n if (maxPoints >= 2) {\n const v = 100 / (maxPoints - 1);\n datasetMin = Number.isFinite(v) ? clampPercent(v) : null;\n }\n }\n\n const effectiveMin = minSpan != null ? minSpan : datasetMin ?? 0.5;\n const effectiveMax = maxSpan != null ? maxSpan : 100;\n return { minSpan: effectiveMin, maxSpan: effectiveMax };\n }\n \n /**\n * Resolves ThemeConfig from options, handling both string presets and custom configs.\n */\n private resolveThemeConfig(): ThemeConfig {\n const theme = this.cachedOptions.theme;\n \n // Default theme values\n const defaults: ThemeConfig = {\n colorPalette: [],\n backgroundColor: '#1a1a2e',\n textColor: '#e0e0e0',\n axisLineColor: 'rgba(224,224,224,0.2)',\n axisTickColor: 'rgba(224,224,224,0.4)',\n gridLineColor: 'rgba(224,224,224,0.1)',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n fontSize: 12,\n };\n \n if (!theme || typeof theme === 'string') {\n // Theme is either undefined or a string preset ('dark' | 'light')\n // For now, just use defaults\n return defaults;\n }\n \n // Theme is a custom ThemeConfig object - merge with defaults\n return {\n colorPalette: theme.colorPalette ?? defaults.colorPalette,\n backgroundColor: theme.backgroundColor ?? defaults.backgroundColor,\n textColor: theme.textColor ?? defaults.textColor,\n axisLineColor: theme.axisLineColor ?? defaults.axisLineColor,\n axisTickColor: theme.axisTickColor ?? defaults.axisTickColor,\n gridLineColor: theme.gridLineColor ?? defaults.gridLineColor,\n fontFamily: theme.fontFamily ?? defaults.fontFamily,\n fontSize: theme.fontSize ?? defaults.fontSize,\n };\n }\n \n /**\n * Disposes all DOM overlays and cleans up RAF batching.\n */\n private disposeOverlays(): void {\n // Cancel any pending RAF for overlay updates\n if (this.overlayUpdateRafId !== null) {\n cancelAnimationFrame(this.overlayUpdateRafId);\n this.overlayUpdateRafId = null;\n }\n \n // Clear pending updates\n this.pendingOverlayUpdates = {};\n \n // Dispose all overlays\n this.tooltip?.dispose();\n this.tooltip = null;\n \n this.legend?.dispose();\n this.legend = null;\n \n this.textOverlay?.dispose();\n this.textOverlay = null;\n \n this.dataZoomSlider?.dispose();\n this.dataZoomSlider = null;\n \n // Remove slider host from DOM\n this.dataZoomSliderHost?.remove();\n this.dataZoomSliderHost = null;\n \n this.zoomState = null;\n }\n \n /**\n * Schedules overlay updates in the next RAF to batch multiple updates.\n * \n * **Batching strategy**: Worker can send multiple overlay update messages per frame\n * (tooltip + legend + axis labels). By batching them in RAF, we:\n * 1. Reduce layout thrashing (DOM reads/writes grouped)\n * 2. Ensure visual consistency (all overlays update simultaneously)\n * 3. Prevent redundant style calculations (browser optimizes batched changes)\n * \n * **Concurrency safety**: Uses overlayUpdateRafId guard to prevent duplicate RAF scheduling.\n * Multiple calls within the same frame will coalesce into a single RAF callback.\n */\n private scheduleOverlayUpdates(): void {\n if (this.isDisposed) return;\n if (this.overlayUpdateRafId !== null) return; // Already scheduled - coalesce updates\n \n this.overlayUpdateRafId = requestAnimationFrame(() => {\n this.overlayUpdateRafId = null;\n if (this.isDisposed) return;\n \n this.applyPendingOverlayUpdates();\n });\n }\n \n /**\n * Applies all pending overlay updates in a single batch.\n */\n private applyPendingOverlayUpdates(): void {\n const { tooltip: tooltipMsg, legend: legendMsg, axisLabels: axisLabelsMsg } = this.pendingOverlayUpdates;\n \n // Apply tooltip update\n if (tooltipMsg && this.tooltip) {\n if (tooltipMsg.data) {\n this.tooltip.show(tooltipMsg.data.x, tooltipMsg.data.y, tooltipMsg.data.content);\n } else {\n this.tooltip.hide();\n }\n }\n \n // Apply legend update\n if (legendMsg && this.legend) {\n // Convert LegendItem[] to minimal SeriesConfig[] for legend component\n const minimalSeries = legendMsg.items.map((item) => ({\n type: 'line' as const,\n name: item.name,\n color: item.color,\n data: [],\n }));\n \n const themeConfig = this.resolveThemeConfig();\n this.legend.update(minimalSeries, themeConfig);\n }\n \n // Apply axis labels update\n if (axisLabelsMsg && this.textOverlay) {\n // Get theme config for label styling\n const themeConfig = this.resolveThemeConfig();\n\n // Use shared utility for consistent styling\n addAxisLabelsToOverlay(\n this.textOverlay,\n axisLabelsMsg.xLabels,\n axisLabelsMsg.yLabels,\n themeConfig\n );\n }\n \n // Clear pending updates\n this.pendingOverlayUpdates = {};\n }\n \n // =============================================================================\n // ChartGPUInstance Interface Implementation\n // =============================================================================\n \n get options(): Readonly<ChartGPUOptions> {\n return this.cachedOptions;\n }\n \n get disposed(): boolean {\n return this.isDisposed;\n }\n \n setOption(options: ChartGPUOptions): void {\n if (this.isDisposed) {\n throw new ChartGPUWorkerError(\n 'Cannot setOption on disposed chart',\n 'DISPOSED',\n 'setOption',\n this.chartId\n );\n }\n \n // Check if dataZoom slider needs to be added or removed\n const prevOptions = this.cachedOptions;\n const hadSliderZoom = prevOptions.dataZoom?.some(z => z?.type === 'slider') ?? false;\n const hasSliderZoom = options.dataZoom?.some(z => z?.type === 'slider') ?? false;\n \n this.cachedOptions = options;\n this.recomputeCachedSeriesPointCountsForZoom(options);\n \n // Recreate overlays if dataZoom slider presence changed\n if (hadSliderZoom !== hasSliderZoom) {\n // Dispose old overlays\n this.disposeOverlays();\n // Recreate with new configuration\n this.createOverlays();\n } else if (hasSliderZoom && this.zoomState) {\n // Update span constraints at runtime (matches worker coordinator behavior).\n const constraints = this.computeZoomSpanConstraints(options);\n const withConstraints = this.zoomState as unknown as {\n setSpanConstraints?: (minSpan: number, maxSpan: number) => void;\n };\n withConstraints.setSpanConstraints?.(\n (constraints.minSpan as number) ?? 0.5,\n (constraints.maxSpan as number) ?? 100\n );\n }\n \n this.sendMessage({\n type: 'setOption',\n chartId: this.chartId,\n options,\n });\n }\n \n /**\n * Appends data points to a series (DataPoint[] or OHLCDataPoint[] form).\n * \n * @param seriesIndex - Index of the series to append to\n * @param newPoints - Array of data points to append\n */\n appendData(seriesIndex: number, newPoints: DataPoint[] | OHLCDataPoint[]): void;\n \n /**\n * Appends data points to a series (pre-packed typed array form for zero-copy transfer).\n * \n * **Performance**: The typed array's underlying ArrayBuffer is transferred to the worker,\n * making the source array detached (length = 0) after the call. Use this overload when\n * you need maximum performance and can tolerate the source array becoming unusable.\n * \n * **Usage**:\n * ```typescript\n * import { packDataPoints, XY_STRIDE } from 'chart-gpu';\n * \n * const points = [{ x: 0, y: 10 }, { x: 1, y: 20 }];\n * const packed = packDataPoints(points);\n * chart.appendData(0, packed, 'xy');\n * // packed.length === 0 (detached after transfer)\n * ```\n * \n * @param seriesIndex - Index of the series to append to\n * @param data - Pre-packed Float32Array or Float64Array (will be detached after call)\n * @param pointType - Type of points: 'xy' for DataPoint, 'ohlc' for OHLCDataPoint\n */\n appendData(seriesIndex: number, data: Float32Array | Float64Array, pointType: 'xy' | 'ohlc'): void;\n \n // Implementation\n appendData(\n seriesIndex: number,\n newPointsOrData: DataPoint[] | OHLCDataPoint[] | Float32Array | Float64Array,\n pointType?: 'xy' | 'ohlc'\n ): void {\n if (this.isDisposed) {\n throw new ChartGPUWorkerError(\n 'Cannot appendData on disposed chart',\n 'DISPOSED',\n 'appendData',\n this.chartId\n );\n }\n \n if (!Number.isInteger(seriesIndex) || seriesIndex < 0) {\n throw new ChartGPUWorkerError(\n `Invalid seriesIndex: ${seriesIndex}. Must be a non-negative integer.`,\n 'INVALID_ARGUMENT',\n 'appendData',\n this.chartId\n );\n }\n \n // Handle typed array form (zero-copy transfer)\n if (newPointsOrData instanceof Float32Array || newPointsOrData instanceof Float64Array) {\n if (!pointType) {\n throw new ChartGPUWorkerError(\n 'pointType parameter is required when passing typed arrays',\n 'INVALID_ARGUMENT',\n 'appendData',\n this.chartId\n );\n }\n \n const sourceArray = newPointsOrData;\n \n if (sourceArray.length === 0) {\n return; // No-op for empty arrays\n }\n \n // Determine expected format based on point type\n const floatsPerPoint = pointType === 'xy' ? 2 : 5;\n const pointCount = sourceArray.length / floatsPerPoint;\n const stride: StrideBytes = pointType === 'xy' ? XY_STRIDE : OHLC_STRIDE;\n \n // Validate that length is a multiple of floatsPerPoint\n if (sourceArray.length % floatsPerPoint !== 0) {\n throw new ChartGPUWorkerError(\n `Invalid typed array length: ${sourceArray.length}. Expected multiple of ${floatsPerPoint} for '${pointType}' points.`,\n 'INVALID_ARGUMENT',\n 'appendData',\n this.chartId\n );\n }\n \n // CRITICAL: GPU buffers use Float32, so convert Float64Array to Float32Array\n let typedArray: Float32Array;\n if (sourceArray instanceof Float64Array) {\n // Convert Float64Array to Float32Array (precision loss acceptable for GPU rendering)\n typedArray = new Float32Array(sourceArray);\n } else {\n // Already Float32Array - use directly\n typedArray = sourceArray;\n }\n \n // Check for detached buffer before transfer\n if (typedArray.buffer.byteLength === 0) {\n console.error(\n `ChartGPU: Cannot transfer detached ArrayBuffer. ` +\n `The buffer may have already been transferred to another context.`\n );\n return;\n }\n \n // Validate stride alignment\n const expectedBytes = pointCount * stride;\n const actualBytes = typedArray.byteLength;\n if (actualBytes !== expectedBytes) {\n console.warn(\n `ChartGPU: Data buffer size mismatch. Expected ${expectedBytes} bytes ` +\n `(${pointCount} points × ${stride} stride), got ${actualBytes} bytes.`\n );\n }\n \n // Validate buffer is 4-byte aligned (WebGPU requirement)\n if (typedArray.byteLength % 4 !== 0) {\n throw new ChartGPUWorkerError(\n `Buffer size (${typedArray.byteLength} bytes) is not 4-byte aligned (WebGPU requirement)`,\n 'INVALID_ARGUMENT',\n 'appendData',\n this.chartId\n );\n }\n \n // CRITICAL: Zero-copy optimization - transfer the entire underlying buffer\n // If the typed array uses the full buffer (no byteOffset), transfer directly\n // Otherwise, we must slice() to create a new buffer (creates a copy, but unavoidable)\n let buffer: ArrayBuffer;\n if (typedArray.byteOffset === 0 && typedArray.byteLength === typedArray.buffer.byteLength) {\n // Optimal path: Transfer the entire buffer without copying\n buffer = typedArray.buffer as ArrayBuffer;\n } else {\n // Subarray case: Must copy to create a transferable buffer\n // This happens when the typed array is a view into a larger buffer\n // Note: slice() returns ArrayBufferLike but will always be ArrayBuffer in practice\n buffer = typedArray.buffer.slice(typedArray.byteOffset, typedArray.byteOffset + typedArray.byteLength) as ArrayBuffer;\n \n console.warn(\n `ChartGPU: Typed array uses a subarray view (byteOffset=${typedArray.byteOffset}). ` +\n `A buffer copy is required for transfer. For best performance, ensure typed arrays ` +\n `own their entire underlying buffer.`\n );\n }\n \n // Keep dataset-aware slider constraints in sync with streaming appends.\n this.incrementCachedSeriesPointCountForZoom(seriesIndex, pointCount);\n if (this.zoomState) {\n const constraints = this.computeZoomSpanConstraints(this.cachedOptions);\n const withConstraints = this.zoomState as unknown as {\n setSpanConstraints?: (minSpan: number, maxSpan: number) => void;\n };\n withConstraints.setSpanConstraints?.(\n (constraints.minSpan as number) ?? 0.5,\n (constraints.maxSpan as number) ?? 100\n );\n }\n\n this.sendMessage({\n type: 'appendData',\n chartId: this.chartId,\n seriesIndex,\n data: buffer,\n pointCount,\n stride,\n }, [buffer]);\n \n return;\n }\n \n // Handle DataPoint[] or OHLCDataPoint[] form (existing behavior)\n const newPoints = newPointsOrData as DataPoint[] | OHLCDataPoint[];\n \n if (!newPoints || newPoints.length === 0) {\n return; // No-op for empty arrays\n }\n \n // Warn about large tuple arrays for better performance\n if (Array.isArray(newPoints) && newPoints.length > 10_000) {\n console.warn(\n `ChartGPU: appendData called with ${newPoints.length.toLocaleString()} points as array. ` +\n `Consider using Float32Array for better performance:\\n\\n` +\n ` import { packDataPoints } from 'chart-gpu';\\n` +\n ` const packed = packDataPoints(points);\\n` +\n ` chart.appendData(seriesIndex, packed, 'xy');\\n\\n` +\n `This can reduce memory usage by 50% and eliminate serialization overhead ` +\n `(~${(newPoints.length * 0.00002).toFixed(2)}ms saved per append).`\n );\n }\n \n const [data, stride] = serializeDataPoints(newPoints);\n \n // Keep dataset-aware slider constraints in sync with streaming appends.\n this.incrementCachedSeriesPointCountForZoom(seriesIndex, newPoints.length);\n if (this.zoomState) {\n const constraints = this.computeZoomSpanConstraints(this.cachedOptions);\n const withConstraints = this.zoomState as unknown as {\n setSpanConstraints?: (minSpan: number, maxSpan: number) => void;\n };\n withConstraints.setSpanConstraints?.(\n (constraints.minSpan as number) ?? 0.5,\n (constraints.maxSpan as number) ?? 100\n );\n }\n\n this.sendMessage({\n type: 'appendData',\n chartId: this.chartId,\n seriesIndex,\n data,\n pointCount: newPoints.length,\n stride: stride as StrideBytes,\n }, [data]);\n }\n \n resize(): void {\n if (this.isDisposed) {\n return; // Silent no-op for disposed charts\n }\n \n // Get current canvas dimensions from container\n const canvas = this.container.querySelector('canvas');\n if (!canvas) {\n console.warn('ChartGPUWorkerProxy.resize(): Canvas not found in container');\n return;\n }\n\n const rect = canvas.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n const width = Math.max(1, rect.width); // CSS pixels\n const height = Math.max(1, rect.height); // CSS pixels\n\n this.sendMessage({\n type: 'resize',\n chartId: this.chartId,\n width,\n height,\n devicePixelRatio: dpr,\n requestRender: true,\n });\n }\n \n dispose(): void {\n if (this.isDisposed) {\n return; // Already disposed\n }\n \n this.isDisposed = true;\n this.isInitialized = false;\n \n // Clean up event listeners FIRST to stop event flow\n this.cleanupEventListeners();\n \n // Clean up resize monitoring (ResizeObserver and DPR monitoring)\n this.cleanupResizeMonitoring();\n \n // Dispose overlays BEFORE worker disposal to prevent memory leaks\n this.disposeOverlays();\n \n // Send dispose message to worker\n this.sendMessage({\n type: 'dispose',\n chartId: this.chartId,\n });\n \n // Reject all pending requests\n for (const pending of this.pendingRequests.values()) {\n clearTimeout(pending.timeout);\n pending.reject(new ChartGPUWorkerError(\n 'Chart disposed before operation completed',\n 'DISPOSED',\n pending.operation,\n this.chartId\n ));\n }\n this.pendingRequests.clear();\n \n // Clear all event listeners\n for (const listeners of this.listeners.values()) {\n listeners.clear();\n }\n \n // Remove worker message handler\n this.worker.removeEventListener('message', this.boundMessageHandler);\n \n // Remove canvas from container\n const canvas = this.container.querySelector('canvas');\n if (canvas) {\n canvas.remove();\n }\n }\n \n on(eventName: 'crosshairMove', callback: ChartGPUCrosshairMoveCallback): void;\n on(eventName: ChartGPUEventName, callback: ChartGPUEventCallback): void;\n on(eventName: ChartGPUEventName, callback: AnyChartGPUEventCallback): void {\n if (this.isDisposed) {\n return; // Silent no-op for disposed charts\n }\n \n const listeners = this.listeners.get(eventName);\n if (listeners) {\n listeners.add(callback);\n }\n }\n \n off(eventName: 'crosshairMove', callback: ChartGPUCrosshairMoveCallback): void;\n off(eventName: ChartGPUEventName, callback: ChartGPUEventCallback): void;\n off(eventName: ChartGPUEventName, callback: AnyChartGPUEventCallback): void {\n const listeners = this.listeners.get(eventName);\n if (listeners) {\n listeners.delete(callback);\n }\n }\n \n getInteractionX(): number | null {\n if (this.isDisposed) {\n return null;\n }\n return this.cachedInteractionX;\n }\n \n setInteractionX(x: number | null, source?: unknown): void {\n if (this.isDisposed) {\n return; // Silent no-op for disposed charts\n }\n \n this.cachedInteractionX = x;\n \n this.sendMessage({\n type: 'setInteractionX',\n chartId: this.chartId,\n x,\n source: source as string | undefined,\n });\n }\n \n setCrosshairX(x: number | null, source?: unknown): void {\n // Alias for setInteractionX\n this.setInteractionX(x, source);\n }\n \n onInteractionXChange(callback: (x: number | null, source?: unknown) => void): () => void {\n // Subscribe to crosshairMove events\n const wrappedCallback = (payload: ChartGPUCrosshairMovePayload) => {\n callback(payload.x, payload.source);\n };\n \n this.on('crosshairMove', wrappedCallback as ChartGPUCrosshairMoveCallback);\n \n // Return unsubscribe function\n return () => {\n this.off('crosshairMove', wrappedCallback as ChartGPUCrosshairMoveCallback);\n };\n }\n \n getZoomRange(): Readonly<{ start: number; end: number }> | null {\n if (this.isDisposed) {\n return null;\n }\n return this.cachedZoomRange;\n }\n \n setZoomRange(start: number, end: number): void {\n if (this.isDisposed) {\n return; // Silent no-op for disposed charts\n }\n \n // Validate zoom range (percent space [0, 100])\n if (start < 0 || start > 100 || end < 0 || end > 100) {\n throw new ChartGPUWorkerError(\n `Invalid zoom range: [${start}, ${end}]. Values must be in [0, 100] (percent space).`,\n 'INVALID_ARGUMENT',\n 'setZoomRange',\n this.chartId\n );\n }\n if (start >= end) {\n throw new ChartGPUWorkerError(\n `Invalid zoom range: start (${start}) must be less than end (${end}).`,\n 'INVALID_ARGUMENT',\n 'setZoomRange',\n this.chartId\n );\n }\n \n this.cachedZoomRange = { start, end };\n \n this.sendMessage({\n type: 'setZoomRange',\n chartId: this.chartId,\n start,\n end,\n });\n }\n\n /**\n * Gets the latest performance metrics from the worker.\n * Returns cached metrics updated every frame.\n * \n * @returns Current performance metrics, or null if not available yet\n */\n getPerformanceMetrics(): Readonly<PerformanceMetrics> | null {\n if (this.isDisposed) {\n return null;\n }\n return this.cachedPerformanceMetrics;\n }\n\n /**\n * Gets the performance capabilities of the worker environment.\n * Indicates which performance features are supported.\n * \n * @returns Performance capabilities, or null if not initialized yet\n */\n getPerformanceCapabilities(): Readonly<PerformanceCapabilities> | null {\n if (this.isDisposed) {\n return null;\n }\n return this.cachedPerformanceCapabilities;\n }\n\n /**\n * Registers a callback to be notified of performance metric updates.\n * Callback is invoked every frame with the latest metrics.\n * \n * @param callback - Function to call with updated metrics\n * @returns Unsubscribe function to remove the callback\n */\n onPerformanceUpdate(callback: (metrics: Readonly<PerformanceMetrics>) => void): () => void {\n if (this.isDisposed) {\n return () => {}; // No-op unsubscribe for disposed charts\n }\n \n this.performanceUpdateCallbacks.add(callback);\n \n // Return unsubscribe function\n return () => {\n this.performanceUpdateCallbacks.delete(callback);\n };\n }\n\n /**\n * Enables or disables GPU timing for performance metrics.\n * GPU timing requires the 'timestamp-query' WebGPU feature.\n * \n * @param enabled - Whether to enable GPU timing\n */\n setGPUTiming(enabled: boolean): void {\n if (this.isDisposed) {\n return; // Silent no-op for disposed charts\n }\n \n this.sendMessage({\n type: 'setGPUTiming',\n chartId: this.chartId,\n enabled,\n });\n }\n \n // =============================================================================\n // Worker Communication\n // =============================================================================\n \n /**\n * Sends a message to the worker without expecting a response.\n * \n * @param message - Message to send\n * @param transfer - Optional transferable objects\n */\n private sendMessage(message: WorkerInboundMessage, transfer?: Transferable[]): void {\n if (this.isDisposed) {\n return; // Silent no-op for disposed charts\n }\n \n try {\n if (transfer && transfer.length > 0) {\n this.worker.postMessage(message, transfer);\n } else {\n this.worker.postMessage(message);\n }\n } catch (error) {\n throw new ChartGPUWorkerError(\n `Failed to send message to worker: ${error instanceof Error ? error.message : String(error)}`,\n 'COMMUNICATION_ERROR',\n message.type,\n this.chartId\n );\n }\n }\n \n /**\n * Sends a message to the worker and waits for a response.\n * \n * **Message Correlation**: Uses unique messageId to match request/response pairs.\n * The worker MUST echo the messageId in its response for correlation to work.\n * \n * **Timeout Behavior**: \n * - Default timeout: 30 seconds (configurable via WorkerConfig.messageTimeout)\n * - On timeout: Promise rejects with TIMEOUT error and pending request is cleaned up\n * - Prevents indefinite promise accumulation if worker hangs or message is lost\n * - Timeout starts when message is sent (not when promise is created)\n * \n * **Error Handling**:\n * - Send failure: Immediately rejects and cleans up timeout\n * - Worker error: Rejects with error from ErrorMessage (matched by messageId)\n * - Disposal: All pending requests rejected with DISPOSED error\n * \n * **Concurrency Safety**: Multiple concurrent requests are supported via Map-based tracking.\n * Each request has a unique messageId, preventing response cross-contamination.\n * \n * @param message - Message to send (must have messageId)\n * @param transfer - Optional transferable objects (e.g., OffscreenCanvas, ArrayBuffer)\n * @returns Promise that resolves with the response or rejects on timeout/error\n */\n private sendMessageWithResponse<T extends WorkerOutboundMessage>(\n message: WorkerInboundMessage & { messageId: string },\n transfer?: Transferable[]\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const { messageId } = message;\n \n // Set up timeout to prevent indefinite promise accumulation\n const timeout = setTimeout(() => {\n this.pendingRequests.delete(messageId);\n reject(new ChartGPUWorkerError(\n `Operation \"${message.type}\" timed out after ${this.messageTimeout}ms. ` +\n `Worker may be unresponsive or message was lost.`,\n 'TIMEOUT',\n message.type,\n this.chartId\n ));\n }, this.messageTimeout);\n \n // Track pending request for response correlation\n this.pendingRequests.set(messageId, {\n resolve: resolve as (value: unknown) => void,\n reject,\n timeout,\n operation: message.type,\n });\n \n // Send message (may throw if worker is terminated or message is invalid)\n try {\n this.sendMessage(message, transfer);\n } catch (error) {\n // Clean up pending request on send failure\n clearTimeout(timeout);\n this.pendingRequests.delete(messageId);\n reject(error);\n }\n });\n }\n \n /**\n * Handles incoming messages from the worker.\n * Routes messages to appropriate handlers based on type.\n * \n * @param event - Message event from worker\n */\n private handleWorkerMessage(event: MessageEvent): void {\n const message = event.data as WorkerOutboundMessage;\n \n // Ignore messages for other chart instances\n if (message.chartId !== this.chartId) {\n return;\n }\n \n // Handle message based on type\n switch (message.type) {\n case 'ready':\n this.handleReadyMessage(message);\n break;\n \n case 'rendered':\n // No-op: rendered messages are informational only\n break;\n \n case 'performance-update':\n this.handlePerformanceUpdateMessage(message);\n break;\n \n case 'tooltipUpdate':\n this.handleTooltipUpdateMessage(message);\n break;\n \n case 'legendUpdate':\n this.handleLegendUpdateMessage(message);\n break;\n \n case 'axisLabelsUpdate':\n this.handleAxisLabelsUpdateMessage(message);\n break;\n \n case 'hoverChange':\n this.handleHoverChangeMessage(message);\n break;\n \n case 'click':\n this.handleClickMessage(message);\n break;\n \n case 'crosshairMove':\n this.handleCrosshairMoveMessage(message);\n break;\n \n case 'zoomChange':\n this.handleZoomChangeMessage(message);\n break;\n \n case 'deviceLost':\n this.handleDeviceLostMessage(message);\n break;\n \n case 'disposed':\n // Worker confirmed disposal - already handled locally\n break;\n \n case 'error':\n this.handleErrorMessage(message);\n break;\n \n default:\n // Exhaustive type check\n const exhaustive: never = message;\n console.warn('ChartGPUWorkerProxy: Unknown message type:', (exhaustive as any).type);\n }\n }\n \n /**\n * Handles ready message from worker.\n * Resolves the pending init request and caches performance capabilities.\n */\n private handleReadyMessage(message: ReadyMessage): void {\n // Mark as initialized to enable event forwarding\n this.isInitialized = true;\n \n // Cache performance capabilities from worker\n this.cachedPerformanceCapabilities = message.performanceCapabilities;\n \n // CRITICAL: Initialize zoom range from ready message\n // The ready message now includes the initial zoom range to avoid race conditions\n // where the slider is created with default [0, 100] before the worker's zoomChange message is processed\n if (message.initialZoomRange) {\n // Update cached zoom range\n this.cachedZoomRange = { start: message.initialZoomRange.start, end: message.initialZoomRange.end };\n \n // If slider exists, update it with the correct initial zoom range\n if (this.zoomState) {\n const currentRange = this.zoomState.getRange();\n // Only update if the slider is still at the default [0, 100] but actual range differs\n if ((currentRange.start === 0 && currentRange.end === 100) &&\n (message.initialZoomRange.start !== 0 || message.initialZoomRange.end !== 100)) {\n this.isProcessingWorkerZoomUpdate = true;\n try {\n this.zoomState.setRange(message.initialZoomRange.start, message.initialZoomRange.end);\n } finally {\n this.isProcessingWorkerZoomUpdate = false;\n }\n }\n }\n }\n \n const pending = this.pendingRequests.get(message.messageId);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingRequests.delete(message.messageId);\n pending.resolve(message);\n }\n }\n \n /**\n * Handles hover change messages from worker.\n * Emits mouseover/mouseout events to registered listeners.\n */\n private handleHoverChangeMessage(message: import('./protocol').HoverChangeMessage): void {\n if (message.payload) {\n // Hover entered\n const payload: ChartGPUEventPayload = {\n seriesIndex: message.payload.seriesIndex,\n dataIndex: message.payload.dataIndex,\n value: message.payload.value as readonly [number, number],\n seriesName: null, // Worker doesn't send series name\n event: this.createSyntheticPointerEvent(message.payload.x, message.payload.y),\n };\n this.emit('mouseover', payload);\n } else {\n // Hover cleared\n const payload: ChartGPUEventPayload = {\n seriesIndex: null,\n dataIndex: null,\n value: null,\n seriesName: null,\n event: this.createSyntheticPointerEvent(0, 0),\n };\n this.emit('mouseout', payload);\n }\n }\n \n /**\n * Handles click messages from worker.\n * Emits click events to registered listeners.\n */\n private handleClickMessage(message: import('./protocol').ClickMessage): void {\n const payload: ChartGPUEventPayload = {\n seriesIndex: message.payload.seriesIndex,\n dataIndex: message.payload.dataIndex,\n value: message.payload.value as readonly [number, number],\n seriesName: null, // Worker doesn't send series name\n event: this.createSyntheticPointerEvent(message.payload.x, message.payload.y),\n };\n this.emit('click', payload);\n }\n \n /**\n * Handles crosshair move messages from worker.\n * Updates cached interaction X and emits crosshairMove events.\n */\n private handleCrosshairMoveMessage(message: import('./protocol').CrosshairMoveMessage): void {\n this.cachedInteractionX = message.x;\n \n const payload: ChartGPUCrosshairMovePayload = {\n x: message.x,\n source: message.source,\n };\n this.emit('crosshairMove', payload);\n }\n \n /**\n * Handles zoom change messages from worker.\n * Updates cached zoom range and zoom state with echo loop prevention.\n * \n * CRITICAL: Echo suppression strategy\n * - Sets isProcessingWorkerZoomUpdate flag before calling setRange\n * - The onChange callback checks this flag and skips sending message back to worker\n * - This prevents zoom changes originated in the worker from echoing back\n * - UI-originated changes (slider drag) still propagate normally to worker\n */\n private handleZoomChangeMessage(message: import('./protocol').ZoomChangeMessage): void {\n this.cachedZoomRange = { start: message.start, end: message.end };\n \n // Update zoom state if slider exists\n if (this.zoomState) {\n const currentRange = this.zoomState.getRange();\n \n // Only call setRange if values actually changed (avoids no-op updates)\n if (currentRange.start !== message.start || currentRange.end !== message.end) {\n // Set echo suppression flag before updating zoom state\n // This prevents the onChange callback from sending the change back to worker\n this.isProcessingWorkerZoomUpdate = true;\n \n try {\n this.zoomState.setRange(message.start, message.end);\n } finally {\n // Always clear flag in finally block to ensure cleanup even on error\n this.isProcessingWorkerZoomUpdate = false;\n }\n }\n }\n }\n \n /**\n * Handles device lost messages from worker.\n * Marks chart as disposed and cleans up resources.\n */\n private handleDeviceLostMessage(message: import('./protocol').DeviceLostMessage): void {\n console.error(\n `ChartGPU: WebGPU device lost for chart \"${this.chartId}\".`,\n `Reason: ${message.reason}`,\n message.message ? `Message: ${message.message}` : ''\n );\n \n // Device loss is terminal - dispose the chart\n this.dispose();\n }\n \n /**\n * Handles error messages from worker.\n * Rejects pending requests or logs errors.\n */\n private handleErrorMessage(message: import('./protocol').ErrorMessage): void {\n const error = new ChartGPUWorkerError(\n message.message,\n message.code,\n message.operation,\n this.chartId\n );\n \n // If this error is correlated with a pending request, reject it\n if (message.messageId) {\n const pending = this.pendingRequests.get(message.messageId);\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingRequests.delete(message.messageId);\n pending.reject(error);\n return;\n }\n }\n \n // Otherwise, log the error\n console.error('ChartGPUWorkerProxy: Worker error:', error);\n }\n \n /**\n * Handles tooltip update messages from worker.\n * Batches updates via RAF to prevent layout thrashing.\n */\n private handleTooltipUpdateMessage(message: TooltipUpdateMessage): void {\n this.pendingOverlayUpdates.tooltip = message;\n this.scheduleOverlayUpdates();\n }\n \n /**\n * Handles legend update messages from worker.\n * Batches updates via RAF to prevent layout thrashing.\n */\n private handleLegendUpdateMessage(message: LegendUpdateMessage): void {\n this.pendingOverlayUpdates.legend = message;\n this.scheduleOverlayUpdates();\n }\n \n /**\n * Handles axis labels update messages from worker.\n * Batches updates via RAF to prevent layout thrashing.\n */\n private handleAxisLabelsUpdateMessage(message: AxisLabelsUpdateMessage): void {\n this.pendingOverlayUpdates.axisLabels = message;\n this.scheduleOverlayUpdates();\n }\n\n /**\n * Handles performance update messages from worker.\n * Updates cached metrics and notifies subscribers.\n */\n private handlePerformanceUpdateMessage(message: import('./protocol').PerformanceUpdateMessage): void {\n // Update cached metrics\n this.cachedPerformanceMetrics = message.metrics;\n \n // Notify all registered callbacks\n for (const callback of this.performanceUpdateCallbacks) {\n try {\n callback(message.metrics);\n } catch (error) {\n console.error('Error in performance update callback:', error);\n }\n }\n }\n \n /**\n * Emits an event to all registered listeners.\n * \n * @param eventName - Event name\n * @param payload - Event payload\n */\n private emit(\n eventName: ChartGPUEventName,\n payload: ChartGPUEventPayload | ChartGPUCrosshairMovePayload\n ): void {\n const listeners = this.listeners.get(eventName);\n if (!listeners) return;\n \n for (const callback of listeners) {\n try {\n (callback as (p: typeof payload) => void)(payload);\n } catch (error) {\n console.error(`Error in ${eventName} event handler:`, error);\n }\n }\n }\n \n /**\n * Creates a synthetic PointerEvent for event payloads.\n * Worker can't transfer real PointerEvents, so we create a minimal synthetic one.\n * \n * @param x - Canvas-local CSS pixel x coordinate\n * @param y - Canvas-local CSS pixel y coordinate\n * @returns Synthetic PointerEvent\n */\n private createSyntheticPointerEvent(x: number, y: number): PointerEvent {\n // Create a minimal synthetic PointerEvent\n // This is necessary because worker can't transfer real PointerEvents\n const canvas = this.container.querySelector('canvas');\n const rect = canvas?.getBoundingClientRect() || { left: 0, top: 0 };\n \n return new PointerEvent('pointermove', {\n bubbles: false,\n cancelable: false,\n clientX: rect.left + x,\n clientY: rect.top + y,\n pointerId: -1, // Synthetic event marker\n pointerType: 'mouse',\n isPrimary: true,\n });\n }\n}\n","/**\n * Factory function for creating worker-based ChartGPU instances.\n * \n * Creates a chart that renders in a Web Worker using OffscreenCanvas for improved\n * main thread performance. The factory handles canvas setup, worker initialization,\n * and returns a ChartGPUInstance-compatible proxy.\n * \n * ## Usage\n * \n * ```typescript\n * // Use built-in worker\n * const chart = await createChartInWorker(container, options);\n * \n * // Use custom worker URL\n * const chart = await createChartInWorker(container, options, './my-worker.js');\n * \n * // Use existing worker instance\n * const worker = new Worker('./chart-worker.js', { type: 'module' });\n * const chart = await createChartInWorker(container, options, worker);\n * ```\n * \n * ## Error Handling\n * \n * - Throws if container is not an HTMLElement\n * - Throws if canvas creation or transfer fails\n * - Throws if worker initialization fails (30s timeout)\n * - Cleans up resources (worker, canvas) on failure\n */\n\nimport type { ChartGPUInstance } from '../ChartGPU';\nimport type { ChartGPUOptions } from '../config/types';\nimport { ChartGPUWorkerProxy } from './ChartGPUWorkerProxy';\nimport { ChartGPUWorkerError } from './types';\n\nconst WORKER_INIT_TIMEOUT_MS = 30000;\n\n/**\n * Creates a worker-based chart instance with OffscreenCanvas rendering.\n * \n * @param container - HTML element to attach canvas to\n * @param options - Chart configuration options\n * @param workerOrUrl - Worker instance, URL, or undefined for built-in worker\n * @returns Promise that resolves to ChartGPUInstance proxy\n * @throws {ChartGPUWorkerError} If container is invalid, canvas creation fails, or worker initialization fails\n */\nexport async function createChartInWorker(\n container: HTMLElement,\n options: ChartGPUOptions,\n workerOrUrl?: Worker | string | URL\n): Promise<ChartGPUInstance> {\n // Validate container\n if (!container || !(container instanceof HTMLElement)) {\n throw new ChartGPUWorkerError(\n 'Invalid container: must be an HTMLElement',\n 'INVALID_ARGUMENT',\n 'createChartInWorker',\n 'unknown'\n );\n }\n\n let worker: Worker | null = null;\n let workerCreated = false;\n const chartId = `chart_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;\n\n try {\n // Initialize worker based on input type\n if (workerOrUrl instanceof Worker) {\n // Use provided worker instance\n worker = workerOrUrl;\n workerCreated = false;\n } else if (typeof workerOrUrl === 'string' || workerOrUrl instanceof URL) {\n // Create worker from URL string or URL object\n try {\n worker = new Worker(workerOrUrl, { type: 'module' });\n workerCreated = true;\n } catch (error) {\n throw new ChartGPUWorkerError(\n `Failed to create worker from URL: ${error instanceof Error ? error.message : String(error)}`,\n 'WEBGPU_INIT_FAILED',\n 'createChartInWorker',\n chartId\n );\n }\n } else {\n // Use built-in worker (bundler will resolve this)\n try {\n worker = new Worker(new URL('./worker-entry.ts', import.meta.url), { type: 'module' });\n workerCreated = true;\n } catch (error) {\n throw new ChartGPUWorkerError(\n `Failed to create built-in worker: ${error instanceof Error ? error.message : String(error)}`,\n 'WEBGPU_INIT_FAILED',\n 'createChartInWorker',\n chartId\n );\n }\n }\n\n // Create proxy instance\n const proxy = new ChartGPUWorkerProxy(\n {\n worker,\n chartId,\n messageTimeout: WORKER_INIT_TIMEOUT_MS,\n },\n container,\n options\n );\n\n // Initialize worker and wait for ready response\n // The proxy.init() method handles:\n // - Creating canvas element with proper styling\n // - Appending canvas to container\n // - Measuring dimensions and calculating device pixel ratio\n // - Calling canvas.transferControlToOffscreen()\n // - Sending InitMessage with offscreenCanvas, dimensions, devicePixelRatio\n // - Transferring OffscreenCanvas ownership\n // - Waiting for ready message from worker\n // - Timeout handling (30s default)\n try {\n await proxy.init();\n } catch (error) {\n // Clean up proxy resources on initialization failure\n proxy.dispose();\n throw error;\n }\n\n return proxy;\n } catch (error) {\n // Clean up resources on any failure\n if (worker && workerCreated) {\n // Only terminate worker if we created it (not if user provided it)\n try {\n worker.terminate();\n } catch {\n // Best effort cleanup\n }\n }\n\n // Re-throw as ChartGPUWorkerError if not already\n if (error instanceof ChartGPUWorkerError) {\n throw error;\n }\n\n throw new ChartGPUWorkerError(\n `Failed to create worker chart: ${error instanceof Error ? error.message : String(error)}`,\n 'UNKNOWN',\n 'createChartInWorker',\n chartId\n );\n }\n}\n"],"names":["clamp","v","lo","hi","normalizeRange","range","start","end","t","createDataZoomSlider","container","zoomState","options","height","marginTop","zIndex","showPreview","root","track","preview","windowEl","leftHandle","rightHandle","centerGrip","disposed","activeDragCleanup","applyRangeToDom","r","span","getTrackWidthPx","w","pxToPercent","dxPx","p","setPointerCaptureBestEffort","el","pointerId","releasePointerCaptureBestEffort","startDrag","e","mode","dragStartX","startRange","target","onMove","ev","dxPercent","nextStart","anchored","nextEnd","cleanedUp","cleanup","finish","onLeftDown","onRightDown","onPanDown","unsubscribe","theme","handleBorder","XY_STRIDE","OHLC_STRIDE","ChartGPUWorkerError","message","code","operation","chartId","messageIdCounter","generateMessageId","generateChartId","DATA_ZOOM_SLIDER_RESERVE_CSS_PX","serializeDataPoints","points","firstPoint","buffer","view","i","offset","ohlcObj","dataObj","computePointerEventData","event","canvas","rect","x","y","plotLeftCss","_a","plotTopCss","_b","plotRightCss","_c","plotBottomCss","_d","_e","z","plotWidthCss","plotHeightCss","gridX","gridY","isInGrid","ChartGPUWorkerProxy","config","series","next","s","raw","seriesIndex","deltaPoints","counts","dpr","width","offscreenCanvas","computed","dt","dx","dy","distance","wheelEvent","lastWidth","lastHeight","entries","contentBoxSize","newWidth","newHeight","newDpr","createTooltip","createTextOverlay","createLegend","initialStart","initialEnd","constraints","createZoomState","DATA_ZOOM_SLIDER_HEIGHT_CSS_PX","themeConfig","DATA_ZOOM_SLIDER_MARGIN_TOP_CSS_PX","host","clampPercent","minSpan","maxSpan","xAxisType","datasetMin","maxPoints","len","defaults","tooltipMsg","legendMsg","axisLabelsMsg","minimalSeries","item","addAxisLabelsToOverlay","hadSliderZoom","hasSliderZoom","withConstraints","newPointsOrData","pointType","sourceArray","floatsPerPoint","pointCount","stride","typedArray","expectedBytes","actualBytes","newPoints","data","pending","listeners","eventName","callback","source","wrappedCallback","payload","enabled","transfer","error","resolve","reject","messageId","timeout","currentRange","WORKER_INIT_TIMEOUT_MS","createChartInWorker","workerOrUrl","worker","workerCreated","proxy"],"mappings":"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"}