@primeui/chart-core 0.0.1-alpha.1

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 (299) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +1 -0
  3. package/dist/animations/index.d.mts +136 -0
  4. package/dist/animations/index.mjs +18 -0
  5. package/dist/annotation.utils-Bm0lOO1o.d.mts +290 -0
  6. package/dist/borderRadius.utils-Cz73LLR_.d.mts +54 -0
  7. package/dist/canvas-D4vigq47.d.mts +34 -0
  8. package/dist/canvas.utils-D2WHi2gL.d.mts +167 -0
  9. package/dist/cartesian/index.d.mts +94 -0
  10. package/dist/cartesian/index.mjs +93 -0
  11. package/dist/chunk-22ST6YPP.mjs +304 -0
  12. package/dist/chunk-2QK2KOBN.mjs +10 -0
  13. package/dist/chunk-2QRS4YQ5.mjs +18 -0
  14. package/dist/chunk-3FFJEX4A.mjs +261 -0
  15. package/dist/chunk-3IYSJ2U7.mjs +567 -0
  16. package/dist/chunk-3OZLP4I4.mjs +190 -0
  17. package/dist/chunk-3WEMHXZI.mjs +198 -0
  18. package/dist/chunk-3Z62EUJN.mjs +138 -0
  19. package/dist/chunk-4C6EVJ54.mjs +362 -0
  20. package/dist/chunk-53HW45JB.mjs +102 -0
  21. package/dist/chunk-55Y3WI6S.mjs +186 -0
  22. package/dist/chunk-5JCI2DEB.mjs +97 -0
  23. package/dist/chunk-66T4MRC5.mjs +113 -0
  24. package/dist/chunk-6HSEJLSR.mjs +376 -0
  25. package/dist/chunk-6STOLMCA.mjs +187 -0
  26. package/dist/chunk-7CMVDIOU.mjs +54 -0
  27. package/dist/chunk-7QQ6ETB4.mjs +228 -0
  28. package/dist/chunk-A6ZQZFL2.mjs +272 -0
  29. package/dist/chunk-ADKLH73T.mjs +1 -0
  30. package/dist/chunk-AGU3NG6D.mjs +22 -0
  31. package/dist/chunk-AHYIS6EB.mjs +230 -0
  32. package/dist/chunk-AP3UYWYT.mjs +4 -0
  33. package/dist/chunk-ARB5T6MP.mjs +326 -0
  34. package/dist/chunk-ARRGOEFX.mjs +585 -0
  35. package/dist/chunk-AUF4CHDP.mjs +422 -0
  36. package/dist/chunk-B4FTADAZ.mjs +561 -0
  37. package/dist/chunk-BABQKA6K.mjs +339 -0
  38. package/dist/chunk-BETFQBM2.mjs +197 -0
  39. package/dist/chunk-BKP26M4K.mjs +413 -0
  40. package/dist/chunk-BZN2QHGP.mjs +200 -0
  41. package/dist/chunk-C36VWQ7A.mjs +86 -0
  42. package/dist/chunk-CHW4RKY3.mjs +16 -0
  43. package/dist/chunk-CINXJIRR.mjs +120 -0
  44. package/dist/chunk-DN6AXQYZ.mjs +667 -0
  45. package/dist/chunk-DP2IZNN3.mjs +92 -0
  46. package/dist/chunk-DTWTCFRG.mjs +119 -0
  47. package/dist/chunk-EAMUNLRU.mjs +172 -0
  48. package/dist/chunk-EDAKJLNA.mjs +17 -0
  49. package/dist/chunk-ERVQB2VZ.mjs +59 -0
  50. package/dist/chunk-FFMT6OCO.mjs +92 -0
  51. package/dist/chunk-FHTC2YDB.mjs +102 -0
  52. package/dist/chunk-FRST55HY.mjs +16 -0
  53. package/dist/chunk-HDFGCN2F.mjs +132 -0
  54. package/dist/chunk-IEGLX7VL.mjs +42 -0
  55. package/dist/chunk-ILUWFYGY.mjs +220 -0
  56. package/dist/chunk-IXOWSEHO.mjs +114 -0
  57. package/dist/chunk-J4RI2C2G.mjs +172 -0
  58. package/dist/chunk-J65DBT4R.mjs +13 -0
  59. package/dist/chunk-JGOVWSKH.mjs +179 -0
  60. package/dist/chunk-JO7VACY2.mjs +25 -0
  61. package/dist/chunk-JWFBOPM6.mjs +122 -0
  62. package/dist/chunk-KNDZP446.mjs +895 -0
  63. package/dist/chunk-KP2TWD4Z.mjs +90 -0
  64. package/dist/chunk-KQIFO5I3.mjs +225 -0
  65. package/dist/chunk-KVDEROP6.mjs +59 -0
  66. package/dist/chunk-LKC7MZKK.mjs +87 -0
  67. package/dist/chunk-LVMDQ4OJ.mjs +305 -0
  68. package/dist/chunk-M7B3JF43.mjs +90 -0
  69. package/dist/chunk-MTGMXRNF.mjs +136 -0
  70. package/dist/chunk-N3TIT3OH.mjs +1040 -0
  71. package/dist/chunk-NHRK5KU2.mjs +890 -0
  72. package/dist/chunk-NKUYIWAP.mjs +243 -0
  73. package/dist/chunk-NPDZLYIF.mjs +238 -0
  74. package/dist/chunk-O2X6FF45.mjs +499 -0
  75. package/dist/chunk-OGJ6IIBW.mjs +176 -0
  76. package/dist/chunk-OHGCZZPZ.mjs +403 -0
  77. package/dist/chunk-OWW3K55O.mjs +351 -0
  78. package/dist/chunk-OXTFAWSK.mjs +60 -0
  79. package/dist/chunk-PLSDU3C2.mjs +890 -0
  80. package/dist/chunk-PRDVPOZX.mjs +223 -0
  81. package/dist/chunk-Q6PPVIHU.mjs +21 -0
  82. package/dist/chunk-QQBXUDM4.mjs +885 -0
  83. package/dist/chunk-QS76E3TD.mjs +111 -0
  84. package/dist/chunk-QWQ6HY4I.mjs +209 -0
  85. package/dist/chunk-R6Y3R7EW.mjs +135 -0
  86. package/dist/chunk-RBLZRT5K.mjs +190 -0
  87. package/dist/chunk-RO4N6YFS.mjs +167 -0
  88. package/dist/chunk-RQ3CKQOX.mjs +984 -0
  89. package/dist/chunk-SALTGZFR.mjs +208 -0
  90. package/dist/chunk-SANZPAJ4.mjs +14 -0
  91. package/dist/chunk-SDBPQ5CF.mjs +624 -0
  92. package/dist/chunk-SSLTFJ3U.mjs +364 -0
  93. package/dist/chunk-SXHVDJGF.mjs +77 -0
  94. package/dist/chunk-TA4MVAEX.mjs +243 -0
  95. package/dist/chunk-TAHCOZHF.mjs +1772 -0
  96. package/dist/chunk-TQ6S34QZ.mjs +152 -0
  97. package/dist/chunk-UPRXABX5.mjs +90 -0
  98. package/dist/chunk-VGLSBZDN.mjs +71 -0
  99. package/dist/chunk-VN7CKCSE.mjs +364 -0
  100. package/dist/chunk-VVI3OBPJ.mjs +524 -0
  101. package/dist/chunk-VWF57TS3.mjs +62 -0
  102. package/dist/chunk-WA3OVISZ.mjs +179 -0
  103. package/dist/chunk-WCG35U6M.mjs +964 -0
  104. package/dist/chunk-WFTX4AQJ.mjs +194 -0
  105. package/dist/chunk-WFVOQ2QZ.mjs +18 -0
  106. package/dist/chunk-WH3C3Y7P.mjs +149 -0
  107. package/dist/chunk-WPFUV7K3.mjs +488 -0
  108. package/dist/chunk-WRULPWHD.mjs +492 -0
  109. package/dist/chunk-WS64BZXT.mjs +1 -0
  110. package/dist/chunk-WY4AURRE.mjs +2419 -0
  111. package/dist/chunk-WYLILAOO.mjs +167 -0
  112. package/dist/chunk-X4D7FKUS.mjs +62 -0
  113. package/dist/chunk-X7T34OLW.mjs +139 -0
  114. package/dist/chunk-XIHBK5D3.mjs +68 -0
  115. package/dist/chunk-XQQCGFYB.mjs +50 -0
  116. package/dist/chunk-XTVE4P3L.mjs +214 -0
  117. package/dist/chunk-XUAASRXW.mjs +579 -0
  118. package/dist/chunk-Y3L3D4GQ.mjs +685 -0
  119. package/dist/chunk-YBJ56XJS.mjs +132 -0
  120. package/dist/chunk-ZQFK6CAE.mjs +1 -0
  121. package/dist/chunk-ZT2Z7ERM.mjs +874 -0
  122. package/dist/chunk-ZTL2FQEW.mjs +714 -0
  123. package/dist/circular/arc/index.d.mts +8 -0
  124. package/dist/circular/arc/index.mjs +3 -0
  125. package/dist/circular/index.d.mts +44 -0
  126. package/dist/circular/index.mjs +13 -0
  127. package/dist/collect.utils-DiKB4ciO.d.mts +12 -0
  128. package/dist/computeChartState-BTVIqwyO.d.mts +304 -0
  129. package/dist/controller-BJE1AZ3q.d.mts +82 -0
  130. package/dist/controller-BoNigQJr.d.mts +63 -0
  131. package/dist/controllers/index.d.mts +16 -0
  132. package/dist/controllers/index.mjs +110 -0
  133. package/dist/datalabel.utils-CkjGeB8S.d.mts +122 -0
  134. package/dist/decimation.utils-CcvJVhI4.d.mts +244 -0
  135. package/dist/geometry-DUUQJXVM.d.mts +60 -0
  136. package/dist/index-DseIZa1j.d.mts +167 -0
  137. package/dist/index.d.mts +88 -0
  138. package/dist/index.mjs +110 -0
  139. package/dist/orchestrator/index.d.mts +264 -0
  140. package/dist/orchestrator/index.mjs +33 -0
  141. package/dist/plugins/index.d.mts +18 -0
  142. package/dist/plugins/index.mjs +1 -0
  143. package/dist/property-animations-D433wXzz.d.mts +580 -0
  144. package/dist/property-store-NORUWFND.d.mts +17 -0
  145. package/dist/radial/index.d.mts +14 -0
  146. package/dist/radial/index.mjs +37 -0
  147. package/dist/renderers/axis/index.d.mts +39 -0
  148. package/dist/renderers/axis/index.mjs +8 -0
  149. package/dist/renderers/circular/index.d.mts +13 -0
  150. package/dist/renderers/circular/index.mjs +13 -0
  151. package/dist/renderers/index.d.mts +83 -0
  152. package/dist/renderers/index.mjs +75 -0
  153. package/dist/renderers/navigator/index.d.mts +103 -0
  154. package/dist/renderers/navigator/index.mjs +8 -0
  155. package/dist/resize.utils-D_2qm6rv.d.mts +142 -0
  156. package/dist/ring.utils-DXvrxMkU.d.mts +138 -0
  157. package/dist/scale-KFv30jqZ.d.mts +307 -0
  158. package/dist/scales-Drf8AIhL.d.mts +75 -0
  159. package/dist/series/bar/canvas/index.d.mts +8 -0
  160. package/dist/series/bar/canvas/index.mjs +10 -0
  161. package/dist/series/bar/controller/index.d.mts +105 -0
  162. package/dist/series/bar/controller/index.mjs +44 -0
  163. package/dist/series/bar/controller-canvas/index.d.mts +7 -0
  164. package/dist/series/bar/controller-canvas/index.mjs +49 -0
  165. package/dist/series/bar/controller-svg/index.d.mts +7 -0
  166. package/dist/series/bar/controller-svg/index.mjs +49 -0
  167. package/dist/series/bar/index.d.mts +60 -0
  168. package/dist/series/bar/index.mjs +13 -0
  169. package/dist/series/bar/svg/index.d.mts +8 -0
  170. package/dist/series/bar/svg/index.mjs +11 -0
  171. package/dist/series/candlestick/canvas/index.d.mts +8 -0
  172. package/dist/series/candlestick/canvas/index.mjs +8 -0
  173. package/dist/series/candlestick/controller/index.d.mts +123 -0
  174. package/dist/series/candlestick/controller/index.mjs +40 -0
  175. package/dist/series/candlestick/controller-canvas/index.d.mts +7 -0
  176. package/dist/series/candlestick/controller-canvas/index.mjs +45 -0
  177. package/dist/series/candlestick/controller-svg/index.d.mts +7 -0
  178. package/dist/series/candlestick/controller-svg/index.mjs +45 -0
  179. package/dist/series/candlestick/index.d.mts +11 -0
  180. package/dist/series/candlestick/index.mjs +10 -0
  181. package/dist/series/candlestick/svg/index.d.mts +8 -0
  182. package/dist/series/candlestick/svg/index.mjs +8 -0
  183. package/dist/series/heatmap/canvas/index.d.mts +16 -0
  184. package/dist/series/heatmap/canvas/index.mjs +9 -0
  185. package/dist/series/heatmap/controller/index.d.mts +110 -0
  186. package/dist/series/heatmap/controller/index.mjs +23 -0
  187. package/dist/series/heatmap/controller-canvas/index.d.mts +7 -0
  188. package/dist/series/heatmap/controller-canvas/index.mjs +28 -0
  189. package/dist/series/heatmap/controller-svg/index.d.mts +7 -0
  190. package/dist/series/heatmap/controller-svg/index.mjs +28 -0
  191. package/dist/series/heatmap/index.d.mts +34 -0
  192. package/dist/series/heatmap/index.mjs +13 -0
  193. package/dist/series/heatmap/svg/index.d.mts +15 -0
  194. package/dist/series/heatmap/svg/index.mjs +10 -0
  195. package/dist/series/line/canvas/index.d.mts +6 -0
  196. package/dist/series/line/canvas/index.mjs +9 -0
  197. package/dist/series/line/controller/index.d.mts +111 -0
  198. package/dist/series/line/controller/index.mjs +47 -0
  199. package/dist/series/line/controller-canvas/index.d.mts +7 -0
  200. package/dist/series/line/controller-canvas/index.mjs +54 -0
  201. package/dist/series/line/controller-svg/index.d.mts +7 -0
  202. package/dist/series/line/controller-svg/index.mjs +54 -0
  203. package/dist/series/line/index.d.mts +49 -0
  204. package/dist/series/line/index.mjs +13 -0
  205. package/dist/series/line/svg/index.d.mts +6 -0
  206. package/dist/series/line/svg/index.mjs +9 -0
  207. package/dist/series/pie/canvas/index.d.mts +8 -0
  208. package/dist/series/pie/canvas/index.mjs +10 -0
  209. package/dist/series/pie/controller/index.d.mts +174 -0
  210. package/dist/series/pie/controller/index.mjs +110 -0
  211. package/dist/series/pie/controller-canvas/index.d.mts +8 -0
  212. package/dist/series/pie/controller-canvas/index.mjs +119 -0
  213. package/dist/series/pie/controller-svg/index.d.mts +8 -0
  214. package/dist/series/pie/controller-svg/index.mjs +118 -0
  215. package/dist/series/pie/index.d.mts +59 -0
  216. package/dist/series/pie/index.mjs +15 -0
  217. package/dist/series/pie/svg/index.d.mts +6 -0
  218. package/dist/series/pie/svg/index.mjs +11 -0
  219. package/dist/series/polar/canvas/index.d.mts +6 -0
  220. package/dist/series/polar/canvas/index.mjs +7 -0
  221. package/dist/series/polar/controller/index.d.mts +102 -0
  222. package/dist/series/polar/controller/index.mjs +46 -0
  223. package/dist/series/polar/controller-canvas/index.d.mts +8 -0
  224. package/dist/series/polar/controller-canvas/index.mjs +52 -0
  225. package/dist/series/polar/controller-svg/index.d.mts +8 -0
  226. package/dist/series/polar/controller-svg/index.mjs +52 -0
  227. package/dist/series/polar/index.d.mts +25 -0
  228. package/dist/series/polar/index.mjs +16 -0
  229. package/dist/series/polar/svg/index.d.mts +10 -0
  230. package/dist/series/polar/svg/index.mjs +8 -0
  231. package/dist/series/radar/canvas/index.d.mts +6 -0
  232. package/dist/series/radar/canvas/index.mjs +8 -0
  233. package/dist/series/radar/controller/index.d.mts +121 -0
  234. package/dist/series/radar/controller/index.mjs +43 -0
  235. package/dist/series/radar/controller-canvas/index.d.mts +8 -0
  236. package/dist/series/radar/controller-canvas/index.mjs +51 -0
  237. package/dist/series/radar/controller-svg/index.d.mts +8 -0
  238. package/dist/series/radar/controller-svg/index.mjs +51 -0
  239. package/dist/series/radar/index.d.mts +40 -0
  240. package/dist/series/radar/index.mjs +13 -0
  241. package/dist/series/radar/svg/index.d.mts +12 -0
  242. package/dist/series/radar/svg/index.mjs +9 -0
  243. package/dist/series/scatter/canvas/index.d.mts +8 -0
  244. package/dist/series/scatter/canvas/index.mjs +11 -0
  245. package/dist/series/scatter/controller/index.d.mts +124 -0
  246. package/dist/series/scatter/controller/index.mjs +44 -0
  247. package/dist/series/scatter/controller-canvas/index.d.mts +7 -0
  248. package/dist/series/scatter/controller-canvas/index.mjs +51 -0
  249. package/dist/series/scatter/controller-svg/index.d.mts +7 -0
  250. package/dist/series/scatter/controller-svg/index.mjs +51 -0
  251. package/dist/series/scatter/index.d.mts +25 -0
  252. package/dist/series/scatter/index.mjs +14 -0
  253. package/dist/series/scatter/svg/index.d.mts +8 -0
  254. package/dist/series/scatter/svg/index.mjs +12 -0
  255. package/dist/series/treemap/canvas/index.d.mts +50 -0
  256. package/dist/series/treemap/canvas/index.mjs +10 -0
  257. package/dist/series/treemap/controller/index.d.mts +130 -0
  258. package/dist/series/treemap/controller/index.mjs +20 -0
  259. package/dist/series/treemap/controller-canvas/index.d.mts +7 -0
  260. package/dist/series/treemap/controller-canvas/index.mjs +25 -0
  261. package/dist/series/treemap/controller-svg/index.d.mts +7 -0
  262. package/dist/series/treemap/controller-svg/index.mjs +25 -0
  263. package/dist/series/treemap/index.d.mts +15 -0
  264. package/dist/series/treemap/index.mjs +12 -0
  265. package/dist/series/treemap/svg/index.d.mts +15 -0
  266. package/dist/series/treemap/svg/index.mjs +9 -0
  267. package/dist/slices-DtewiwJx.d.mts +72 -0
  268. package/dist/spatialIndex.utils-B_GJkotZ.d.mts +5 -0
  269. package/dist/squarify.utils-B9CQBpa1.d.mts +50 -0
  270. package/dist/stacking-CChuAcLN.d.mts +319 -0
  271. package/dist/streaming.utils-DH-g1gNP.d.mts +49 -0
  272. package/dist/sync/index.d.mts +130 -0
  273. package/dist/sync/index.mjs +5 -0
  274. package/dist/tooltip.renderer-D5wpSlBa.d.mts +210 -0
  275. package/dist/utils/color/index.d.mts +58 -0
  276. package/dist/utils/color/index.mjs +4 -0
  277. package/dist/utils/data/index.d.mts +180 -0
  278. package/dist/utils/data/index.mjs +7 -0
  279. package/dist/utils/export/index.d.mts +14 -0
  280. package/dist/utils/export/index.mjs +6 -0
  281. package/dist/utils/index.d.mts +49 -0
  282. package/dist/utils/index.mjs +29 -0
  283. package/dist/utils/interaction/index.d.mts +255 -0
  284. package/dist/utils/interaction/index.mjs +9 -0
  285. package/dist/utils/layout/index.d.mts +3 -0
  286. package/dist/utils/layout/index.mjs +10 -0
  287. package/dist/utils/math/index.d.mts +162 -0
  288. package/dist/utils/math/index.mjs +1 -0
  289. package/dist/utils/render/index.d.mts +19 -0
  290. package/dist/utils/render/index.mjs +3 -0
  291. package/dist/utils/specialized/index.d.mts +37 -0
  292. package/dist/utils/specialized/index.mjs +66 -0
  293. package/dist/utils/text/index.d.mts +39 -0
  294. package/dist/utils/text/index.mjs +8 -0
  295. package/dist/utils/theme/index.d.mts +295 -0
  296. package/dist/utils/theme/index.mjs +5 -0
  297. package/dist/utils/zoom/index.d.mts +90 -0
  298. package/dist/utils/zoom/index.mjs +3 -0
  299. package/package.json +56 -0
@@ -0,0 +1,1040 @@
1
+ import { lineHitTest, lineFindAllNearest, computeStackBases } from './chunk-WFTX4AQJ.mjs';
2
+ import { buildLinePath, buildStackedFillPath, buildFillPath, hitTestLine, calculateLineLayout, applyTipExtension, restoreTipExtension, buildRangeFillPath, buildDualRangeFillPaths } from './chunk-6HSEJLSR.mjs';
3
+ import { collectLineMarkerOverlays } from './chunk-X4D7FKUS.mjs';
4
+ import { registerDatasetLayers, triggerCompositorRepaint } from './chunk-Q6PPVIHU.mjs';
5
+ import { resolvePointLabels } from './chunk-66T4MRC5.mjs';
6
+ import { renderResolvedLabels } from './chunk-QQBXUDM4.mjs';
7
+ import { AnimatedScene, resolveAnimatedProps, LINE_ANIMATABLE_PROPS } from './chunk-VN7CKCSE.mjs';
8
+ import { reconcileSvgChildren } from './chunk-KP2TWD4Z.mjs';
9
+ import { parseAnimationConfig } from './chunk-3WEMHXZI.mjs';
10
+ import { cancelRaf, raf } from './chunk-EDAKJLNA.mjs';
11
+ import { buildAccessibilityRenderContext, generateSeriesDescription } from './chunk-OGJ6IIBW.mjs';
12
+ import { collectItems } from './chunk-FFMT6OCO.mjs';
13
+ import { DEFAULT_HOVER_DIM_OPACITY, DEFAULT_HOVER_BRIGHTNESS, DEFAULT_FALLBACK_COLOR } from './chunk-NKUYIWAP.mjs';
14
+ import { streamingPointsInterpolator, buildLineFingerprint, detectStreamingUpdateKind } from './chunk-XQQCGFYB.mjs';
15
+ import { getDefaultColor, isGradientColor, createCanvasGradientFromColor, createSvgGradientFromColor } from './chunk-O2X6FF45.mjs';
16
+ import { createSvgDefs, appendChild, createSvgPath, setAttr, createSvgGroup, materializeSvgNode } from './chunk-SSLTFJ3U.mjs';
17
+
18
+ // src/series/line/controller/helpers.ts
19
+ function resolveLineAnimationPlan(layouts, animConfig, isInitial, lastFingerprint, sceneElementCount) {
20
+ const updateMode = animConfig?.updateMode ?? "auto";
21
+ const { enabled: animEnabled, duration, easing } = parseAnimationConfig(animConfig);
22
+ const limit = animConfig?.limit ?? 5e3;
23
+ const fingerprint = buildLineFingerprint(layouts);
24
+ const phase = isInitial ? "entrance" : lastFingerprint !== "" && fingerprint !== lastFingerprint ? "update" : "static";
25
+ let totalPoints = 0;
26
+ for (const [, layout] of layouts) {
27
+ totalPoints += layout.points.length;
28
+ }
29
+ const shouldAnimate = animEnabled && duration > 0 && totalPoints <= limit && (totalPoints > 0 || sceneElementCount > 0) && phase !== "static";
30
+ return { fingerprint, updateMode, limit, phase, totalPoints, shouldAnimate, duration, easing };
31
+ }
32
+ function findNearestPointIndexByX(layout, axisX) {
33
+ const pts = layout.visiblePoints;
34
+ const bandStep = pts.length >= 2 ? Math.abs(pts[1].x - pts[0].x) : Infinity;
35
+ const halfStep = isFinite(bandStep) ? bandStep / 2 : Infinity;
36
+ let bestIdx = null;
37
+ let bestDist = Infinity;
38
+ for (const pt of pts) {
39
+ const d = Math.abs(pt.x - axisX);
40
+ if (d < bestDist) {
41
+ bestDist = d;
42
+ bestIdx = pt.dataIndex;
43
+ }
44
+ }
45
+ if (bestDist > halfStep) bestIdx = null;
46
+ return bestIdx;
47
+ }
48
+ function computeTipPositions(layouts, tipProgress, isExiting) {
49
+ const positions = /* @__PURE__ */ new Map();
50
+ for (const [id, layout] of layouts) {
51
+ if (isExiting(id)) continue;
52
+ const points = layout.visiblePoints;
53
+ if (points.length < 2) continue;
54
+ const last = points[points.length - 1];
55
+ const prev = points[points.length - 2];
56
+ const x = prev.x + (last.x - prev.x) * tipProgress;
57
+ const y = prev.y + (last.y - prev.y) * tipProgress;
58
+ positions.set(id, { x, y });
59
+ }
60
+ return positions.size > 0 ? positions : null;
61
+ }
62
+
63
+ // src/series/line/controller/types.ts
64
+ var LINE_REGISTRY = {
65
+ number: [],
66
+ color: [],
67
+ custom: {
68
+ geometry: streamingPointsInterpolator
69
+ }
70
+ };
71
+
72
+ // src/series/line/controller/hover.ts
73
+ function applyHoverToProps(ctx, propsMap) {
74
+ if (ctx._hoverPropsCacheResult && ctx._hoverPropsCacheHover === ctx.hover && ctx._hoverPropsCachePropsMap === propsMap) {
75
+ return ctx._hoverPropsCacheResult;
76
+ }
77
+ const result = /* @__PURE__ */ new Map();
78
+ const anyHovered = ctx.hover.datasetId !== null && ctx.lastInput?.hoverConfig != null;
79
+ const axisX = ctx.hover.axisX;
80
+ const axisIndex = ctx.hover.axisIndex;
81
+ const isAxisMode = axisX != null || axisIndex != null;
82
+ for (const [dsId, props] of propsMap) {
83
+ const isThisSeries = ctx.hover.datasetId === dsId;
84
+ let hoveredIndex;
85
+ if (axisX != null) {
86
+ const layout = ctx.layoutCache.get(dsId);
87
+ hoveredIndex = layout ? findNearestPointIndexByX(layout, axisX) : null;
88
+ } else {
89
+ hoveredIndex = axisIndex != null ? axisIndex : isThisSeries ? ctx.hover.index : null;
90
+ }
91
+ result.set(dsId, {
92
+ ...props,
93
+ interaction: {
94
+ ...props.interaction,
95
+ hoveredIndex,
96
+ isSeriesDimmed: isAxisMode ? false : anyHovered && !isThisSeries
97
+ }
98
+ });
99
+ }
100
+ ctx._hoverPropsCacheHover = ctx.hover;
101
+ ctx._hoverPropsCachePropsMap = propsMap;
102
+ ctx._hoverPropsCacheResult = result;
103
+ return result;
104
+ }
105
+ function applyHover(ctx, hover) {
106
+ ctx.hover = hover;
107
+ if (!ctx.lastRenderedLayouts || ctx.lastRenderedLayouts.size === 0 || !ctx.lastInput) return;
108
+ const input = ctx.lastInput;
109
+ if (triggerCompositorRepaint(input.renderer, ctx.canvasEl, input.compositor)) {
110
+ return;
111
+ }
112
+ if (ctx._animRafId !== null) return;
113
+ if (input.renderer === "svg" && ctx.svgGroup && ctx.lastRenderedLayouts) {
114
+ const context = {
115
+ chartId: input.chartId,
116
+ width: input.width,
117
+ height: input.height,
118
+ renderer: "svg",
119
+ chartArea: input.chartArea,
120
+ theme: input.theme
121
+ };
122
+ const layouts = ctx.lastRenderedLayouts;
123
+ const hoveredPropsMap = applyHoverToProps(ctx, ctx.activeRenderPropsCache);
124
+ const tipStates = [];
125
+ if (ctx.tipProgress < 1) {
126
+ for (const [id, layout] of layouts) {
127
+ const el = ctx._scene.getElement(id);
128
+ if (!el || el.current.isExiting) continue;
129
+ const state = applyTipExtension(layout, ctx.tipProgress);
130
+ if (state) tipStates.push({ layout, state });
131
+ }
132
+ }
133
+ try {
134
+ const children = buildLineSvgChildren({
135
+ paint: ctx._paint,
136
+ layouts,
137
+ renderPropsMap: hoveredPropsMap,
138
+ context,
139
+ datasetVisibility: input.datasetVisibility,
140
+ labelConfig: input.labelConfig,
141
+ rangeGroups: input.rangeGroups,
142
+ theme: input.theme
143
+ });
144
+ reconcileSvgChildren(ctx.svgGroup, children);
145
+ } finally {
146
+ for (const { layout, state } of tipStates) {
147
+ restoreTipExtension(layout, state);
148
+ }
149
+ }
150
+ return;
151
+ }
152
+ ctx.renderFrameCycle();
153
+ }
154
+
155
+ // src/series/line/controller/paint.ts
156
+ function renderLinesFrame(params) {
157
+ const { paint, renderer, group, canvas, layouts, renderPropsMap, context, chartArea, rangeGroups, labelConfig, clipProgress, datasetVisibility } = params;
158
+ if (renderer === "svg" && group) {
159
+ while (group.firstChild) group.removeChild(group.firstChild);
160
+ let dataTarget = group;
161
+ if (clipProgress !== void 0 && clipProgress < 1) {
162
+ const clipId = `line-entrance-clip-${context.chartId}`;
163
+ const clipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
164
+ clipPath.setAttribute("id", clipId);
165
+ const clipRect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
166
+ clipRect.setAttribute("x", String(chartArea.x));
167
+ clipRect.setAttribute("y", String(chartArea.y));
168
+ clipRect.setAttribute("width", String(Math.max(0, chartArea.width * clipProgress)));
169
+ clipRect.setAttribute("height", String(chartArea.height));
170
+ clipPath.appendChild(clipRect);
171
+ group.appendChild(clipPath);
172
+ dataTarget = document.createElementNS("http://www.w3.org/2000/svg", "g");
173
+ dataTarget.setAttribute("clip-path", `url(#${clipId})`);
174
+ }
175
+ const children = buildLineSvgChildren({ paint, layouts, renderPropsMap, context, datasetVisibility, labelConfig, rangeGroups, theme: context.theme });
176
+ dataTarget.replaceChildren(...children.map(materializeSvgNode));
177
+ if (dataTarget !== group) {
178
+ group.appendChild(dataTarget);
179
+ }
180
+ }
181
+ if (renderer === "canvas") {
182
+ const ctx = canvas?.getContext("2d");
183
+ if (!ctx) return;
184
+ if (clipProgress !== void 0 && clipProgress < 1) {
185
+ ctx.save();
186
+ ctx.beginPath();
187
+ ctx.rect(chartArea.x, chartArea.y, chartArea.width * clipProgress, chartArea.height);
188
+ ctx.clip();
189
+ }
190
+ if (rangeGroups) {
191
+ renderRangeFillsCanvas(ctx, rangeGroups, layouts, renderPropsMap, chartArea, context.theme);
192
+ }
193
+ for (const [, lineLayout] of layouts) {
194
+ const props = renderPropsMap.get(lineLayout.datasetId);
195
+ if (!props) continue;
196
+ const hasCustomRenderMarker = !!props.renderMarker;
197
+ const renderProps = hasCustomRenderMarker ? { ...props, showMarkers: false, interaction: { ...props.interaction, hoveredIndex: null } } : { ...props, interaction: { ...props.interaction, hoveredIndex: null } };
198
+ paint.renderCanvas(renderProps, lineLayout, ctx, context);
199
+ }
200
+ for (const [, lineLayout] of layouts) {
201
+ const props = renderPropsMap.get(lineLayout.datasetId);
202
+ if (!props) continue;
203
+ const hoveredIndex = props.interaction?.hoveredIndex ?? null;
204
+ if (hoveredIndex === null) continue;
205
+ if (props.renderMarker) continue;
206
+ const markerOnlyProps = { ...props, showMarkers: false, fillOpacity: 0, lineStrokeWidth: 0 };
207
+ paint.renderCanvas(markerOnlyProps, lineLayout, ctx, context);
208
+ }
209
+ if (labelConfig) {
210
+ for (const [, lineLayout] of layouts) {
211
+ if (datasetVisibility?.get(lineLayout.datasetId) === false) continue;
212
+ const props = renderPropsMap.get(lineLayout.datasetId);
213
+ if (!props) continue;
214
+ const seriesColor = typeof lineLayout.lineColor === "string" ? lineLayout.lineColor : getDefaultColor(lineLayout.seriesIdx, context.theme);
215
+ const total = lineLayout.visiblePoints.reduce((sum, pt) => sum + (pt.value ?? 0), 0);
216
+ const labels = resolvePointLabels(lineLayout.visiblePoints, seriesColor, total, labelConfig, props.name, props.data);
217
+ renderResolvedLabels(labels, labelConfig, { renderer: "canvas", ctx, theme: context.theme });
218
+ }
219
+ }
220
+ if (clipProgress !== void 0 && clipProgress < 1) {
221
+ ctx.restore();
222
+ }
223
+ }
224
+ }
225
+ function buildLineSvgChildren(params) {
226
+ const { paint, layouts, renderPropsMap, context, datasetVisibility, labelConfig, rangeGroups, theme } = params;
227
+ const children = [];
228
+ if (rangeGroups) {
229
+ for (const [rgKey, rg] of rangeGroups) {
230
+ if (rg.datasetIds.length < 2) continue;
231
+ const layoutA = layouts.get(rg.datasetIds[0]);
232
+ const layoutB = layouts.get(rg.datasetIds[1]);
233
+ if (!layoutA || !layoutB) continue;
234
+ const dimOpacity = computeRangeDimOpacity(rg, renderPropsMap);
235
+ const propsA = renderPropsMap.get(rg.datasetIds[0]);
236
+ const curve = propsA?.curve ?? "linear";
237
+ const tension = propsA?.tension;
238
+ if (rg.color !== void 0) {
239
+ const pathD = buildRangeFillPath(layoutA.visiblePoints, layoutB.visiblePoints, curve, tension);
240
+ if (pathD) {
241
+ let fill;
242
+ if (isGradientColor(rg.color)) {
243
+ const ca = layoutA.chartArea;
244
+ const gradId = `p-chart-range-grad-${rgKey}-${rg.datasetIds[0]}`;
245
+ const defs = createSvgDefs();
246
+ appendChild(defs, createSvgGradientFromColor(rg.color, gradId, { x: ca.x + ca.width / 2, y: ca.y + ca.height / 2 }, Math.max(ca.width, ca.height) / 2, ca, "vertical"));
247
+ children.push(defs);
248
+ fill = `url(#${gradId})`;
249
+ } else {
250
+ fill = typeof rg.color === "string" ? rg.color : DEFAULT_FALLBACK_COLOR;
251
+ }
252
+ children.push(createSvgPath(pathD, { fill, opacity: rg.fillOpacity * dimOpacity }));
253
+ }
254
+ } else {
255
+ const result = buildDualRangeFillPaths(layoutA.visiblePoints, layoutB.visiblePoints, curve, tension);
256
+ if (result) {
257
+ const colorA = typeof layoutA.lineColor === "string" ? layoutA.lineColor : getDefaultColor(layoutA.seriesIdx, theme);
258
+ const colorB = typeof layoutB.lineColor === "string" ? layoutB.lineColor : getDefaultColor(layoutB.seriesIdx, theme);
259
+ const opacity = rg.fillOpacity * dimOpacity;
260
+ for (const d of result.abovePaths) children.push(createSvgPath(d, { fill: colorA, opacity }));
261
+ for (const d of result.belowPaths) children.push(createSvgPath(d, { fill: colorB, opacity }));
262
+ }
263
+ }
264
+ }
265
+ }
266
+ for (const [dsId, lineLayout] of layouts) {
267
+ const props = renderPropsMap.get(dsId);
268
+ if (!props) continue;
269
+ const hasCustomRenderMarker = !!props.renderMarker;
270
+ const renderProps = hasCustomRenderMarker ? { ...props, showMarkers: false, interaction: { ...props.interaction, hoveredIndex: null } } : { ...props, interaction: { ...props.interaction, hoveredIndex: null } };
271
+ const node = paint.renderSvg(renderProps, lineLayout, context);
272
+ setAttr(node, "data-dataset", dsId);
273
+ if (context.accessibility?.enabled && context.accessibility.landmarkVerbosity === "all") {
274
+ setAttr(node, "role", "region");
275
+ setAttr(node, "aria-label", generateSeriesDescription(props.name ?? dsId, "line", lineLayout.visiblePoints.length));
276
+ }
277
+ children.push(node);
278
+ }
279
+ for (const [dsId, lineLayout] of layouts) {
280
+ const props = renderPropsMap.get(dsId);
281
+ if (!props) continue;
282
+ const hoveredIndex = props.interaction?.hoveredIndex ?? null;
283
+ if (hoveredIndex === null) continue;
284
+ if (props.renderMarker) continue;
285
+ const markerOnlyProps = { ...props, showMarkers: false, fillOpacity: 0, lineStrokeWidth: 0 };
286
+ const node = paint.renderSvg(markerOnlyProps, lineLayout, context);
287
+ setAttr(node, "data-dataset", `${dsId}-hover`);
288
+ children.push(node);
289
+ }
290
+ if (labelConfig && !labelConfig.render) {
291
+ const labelGroup = createSvgGroup();
292
+ for (const [, lineLayout] of layouts) {
293
+ if (datasetVisibility?.get(lineLayout.datasetId) === false) continue;
294
+ const seriesColor = typeof lineLayout.lineColor === "string" ? lineLayout.lineColor : getDefaultColor(lineLayout.seriesIdx, context.theme);
295
+ const total = lineLayout.visiblePoints.reduce((sum, pt) => sum + (pt.value ?? 0), 0);
296
+ const labels = resolvePointLabels(lineLayout.visiblePoints, seriesColor, total, labelConfig, renderPropsMap.get(lineLayout.datasetId)?.name, renderPropsMap.get(lineLayout.datasetId)?.data);
297
+ renderResolvedLabels(labels, labelConfig, { renderer: "svg", svgGroup: labelGroup, theme: context.theme });
298
+ }
299
+ children.push(labelGroup);
300
+ }
301
+ return children;
302
+ }
303
+ function computeRangeDimOpacity(rg, renderPropsMap) {
304
+ const propsA = renderPropsMap.get(rg.datasetIds[0]);
305
+ const propsB = renderPropsMap.get(rg.datasetIds[1]);
306
+ const dimmedA = propsA?.interaction?.isSeriesDimmed ?? false;
307
+ const dimmedB = propsB?.interaction?.isSeriesDimmed ?? false;
308
+ if (dimmedA && dimmedB) {
309
+ const effects = propsA?.effects ?? propsB?.effects;
310
+ return effects?.dimOpacity ?? DEFAULT_HOVER_DIM_OPACITY;
311
+ }
312
+ return 1;
313
+ }
314
+ function renderRangeFillsCanvas(ctx, rangeGroups, layouts, renderPropsMap, chartArea, theme) {
315
+ ctx.save();
316
+ ctx.beginPath();
317
+ ctx.rect(chartArea.x, chartArea.y, chartArea.width, chartArea.height);
318
+ ctx.clip();
319
+ for (const [, rg] of rangeGroups) {
320
+ if (rg.datasetIds.length < 2) continue;
321
+ const layoutA = layouts.get(rg.datasetIds[0]);
322
+ const layoutB = layouts.get(rg.datasetIds[1]);
323
+ if (!layoutA || !layoutB) continue;
324
+ const dimOpacity = computeRangeDimOpacity(rg, renderPropsMap);
325
+ const propsA = renderPropsMap.get(rg.datasetIds[0]);
326
+ const curve = propsA?.curve ?? "linear";
327
+ const tension = propsA?.tension;
328
+ if (rg.color !== void 0) {
329
+ const pathD = buildRangeFillPath(layoutA.visiblePoints, layoutB.visiblePoints, curve, tension);
330
+ if (pathD) {
331
+ const fill = isGradientColor(rg.color) ? createCanvasGradientFromColor(ctx, rg.color, { x: chartArea.x + chartArea.width / 2, y: chartArea.y + chartArea.height / 2 }, Math.max(chartArea.width, chartArea.height) / 2, chartArea, "vertical") : typeof rg.color === "string" ? rg.color : DEFAULT_FALLBACK_COLOR;
332
+ fillPathCanvas(ctx, pathD, fill, rg.fillOpacity * dimOpacity);
333
+ }
334
+ } else {
335
+ const result = buildDualRangeFillPaths(layoutA.visiblePoints, layoutB.visiblePoints, curve, tension);
336
+ if (!result) continue;
337
+ const colorA = typeof layoutA.lineColor === "string" ? layoutA.lineColor : getDefaultColor(layoutA.seriesIdx, theme);
338
+ const colorB = typeof layoutB.lineColor === "string" ? layoutB.lineColor : getDefaultColor(layoutB.seriesIdx, theme);
339
+ const opacity = rg.fillOpacity * dimOpacity;
340
+ for (const d of result.abovePaths) fillPathCanvas(ctx, d, colorA, opacity);
341
+ for (const d of result.belowPaths) fillPathCanvas(ctx, d, colorB, opacity);
342
+ }
343
+ }
344
+ ctx.restore();
345
+ }
346
+ function fillPathCanvas(ctx, pathD, color, opacity) {
347
+ ctx.save();
348
+ ctx.globalAlpha *= opacity;
349
+ ctx.fillStyle = color;
350
+ ctx.fill(new Path2D(pathD));
351
+ ctx.restore();
352
+ }
353
+ function renderSvgFrame(ctx) {
354
+ if (!ctx.lastInput || !ctx.lastRenderedLayouts) return;
355
+ const input = ctx.lastInput;
356
+ const layouts = ctx.lastRenderedLayouts;
357
+ const context = {
358
+ chartId: input.chartId,
359
+ width: input.width,
360
+ height: input.height,
361
+ renderer: "svg",
362
+ chartArea: input.chartArea,
363
+ theme: input.theme
364
+ };
365
+ const tipStates = [];
366
+ if (ctx.tipProgress < 1) {
367
+ for (const [id, layout] of layouts) {
368
+ const el = ctx._scene.getElement(id);
369
+ if (!el || el.current.isExiting) continue;
370
+ const state = applyTipExtension(layout, ctx.tipProgress);
371
+ if (state) tipStates.push({ layout, state });
372
+ }
373
+ }
374
+ try {
375
+ renderLinesFrame({
376
+ paint: ctx._paint,
377
+ renderer: "svg",
378
+ group: ctx.svgGroup,
379
+ canvas: null,
380
+ layouts,
381
+ renderPropsMap: applyHoverToProps(ctx, ctx.activeRenderPropsCache),
382
+ context,
383
+ chartArea: input.chartArea,
384
+ rangeGroups: input.rangeGroups,
385
+ labelConfig: input.labelConfig,
386
+ clipProgress: ctx.entranceClipProgress < 1 ? ctx.entranceClipProgress : void 0,
387
+ dir: input.dir,
388
+ datasetVisibility: input.datasetVisibility
389
+ });
390
+ } finally {
391
+ for (const { layout, state } of tipStates) {
392
+ restoreTipExtension(layout, state);
393
+ }
394
+ }
395
+ }
396
+ function paintCanvasLayer(ctx, canvasCtx, dsId, rangeFirstDs, context) {
397
+ const frameLayouts = ctx.lastRenderedLayouts;
398
+ const layout = frameLayouts?.get(dsId);
399
+ if (!layout || !ctx.lastInput) return;
400
+ const input = ctx.lastInput;
401
+ const el = ctx._scene.getElement(dsId);
402
+ const isExiting = el?.current.isExiting ?? false;
403
+ const hoveredProps = applyHoverToProps(ctx, ctx.activeRenderPropsCache);
404
+ const props = hoveredProps.get(dsId);
405
+ if (!props) return;
406
+ const clip = ctx.entranceClipProgress;
407
+ const clipActive = clip < 1;
408
+ if (clipActive) {
409
+ canvasCtx.save();
410
+ canvasCtx.beginPath();
411
+ canvasCtx.rect(input.chartArea.x, input.chartArea.y, Math.max(0, input.chartArea.width * clip), input.chartArea.height);
412
+ canvasCtx.clip();
413
+ }
414
+ const tipState = ctx.tipProgress < 1 && !isExiting ? applyTipExtension(layout, ctx.tipProgress) : null;
415
+ try {
416
+ if (rangeFirstDs.has(dsId) && input.rangeGroups) {
417
+ renderRangeFillsCanvas(canvasCtx, input.rangeGroups, frameLayouts, hoveredProps, input.chartArea, input.theme);
418
+ }
419
+ const renderProps = props.renderMarker ? { ...props, showMarkers: false, interaction: { ...props.interaction, hoveredIndex: null } } : props;
420
+ ctx._paint.renderCanvas(renderProps, layout, canvasCtx, context);
421
+ if (input.labelConfig && input.datasetVisibility?.get(dsId) !== false) {
422
+ const seriesColor = typeof layout.lineColor === "string" ? layout.lineColor : getDefaultColor(layout.seriesIdx, input.theme);
423
+ const total = layout.visiblePoints.reduce((sum, pt) => sum + (pt.value ?? 0), 0);
424
+ const labels = resolvePointLabels(layout.visiblePoints, seriesColor, total, input.labelConfig, props.name, props.data);
425
+ renderResolvedLabels(labels, input.labelConfig, { renderer: "canvas", ctx: canvasCtx, theme: input.theme });
426
+ }
427
+ } finally {
428
+ if (tipState) restoreTipExtension(layout, tipState);
429
+ if (clipActive) canvasCtx.restore();
430
+ }
431
+ }
432
+
433
+ // src/series/line/controller/scene.ts
434
+ function clamp01(v) {
435
+ if (v < 0) return 0;
436
+ if (v > 1) return 1;
437
+ return v;
438
+ }
439
+ function cancelRafCtx(ctx) {
440
+ if (ctx._animRafId !== null) {
441
+ cancelRaf(ctx._animRafId);
442
+ ctx._animRafId = null;
443
+ }
444
+ }
445
+ function commit(ctx, fingerprint) {
446
+ ctx._isInitial = false;
447
+ ctx._lastFingerprint = fingerprint;
448
+ }
449
+ function startEntranceLoop(ctx, duration, easing) {
450
+ const startAt = performance.now();
451
+ const tick = (now) => {
452
+ ctx._animRafId = null;
453
+ const rawProgress = clamp01((now - startAt) / duration);
454
+ if (rawProgress >= 1) {
455
+ ctx.entranceClipProgress = 1;
456
+ renderFrameCycle(ctx);
457
+ return;
458
+ }
459
+ ctx.entranceClipProgress = easing(rawProgress);
460
+ renderFrameCycle(ctx);
461
+ ctx._animRafId = raf(tick);
462
+ };
463
+ ctx._animRafId = raf(tick);
464
+ }
465
+ function startSceneUpdateLoop(ctx, easing) {
466
+ const tipWasActive = ctx.tipDuration > 0;
467
+ const tick = (now) => {
468
+ ctx._animRafId = null;
469
+ const { allIdle } = ctx._scene.tick(now);
470
+ const tipRaw = ctx.tipDuration > 0 ? clamp01((now - ctx.tipStartAt) / ctx.tipDuration) : 1;
471
+ ctx.tipProgress = tipRaw >= 1 ? 1 : easing(tipRaw);
472
+ ctx.entranceClipProgress = 1;
473
+ renderFrameCycle(ctx);
474
+ if (ctx.tipProgress < 1 && ctx._lastTipPositions) {
475
+ for (const cb of ctx._tipSubscribers) cb(ctx._lastTipPositions);
476
+ }
477
+ const tipDone = tipRaw >= 1;
478
+ if (!allIdle || !tipDone) {
479
+ ctx._animRafId = raf(tick);
480
+ return;
481
+ }
482
+ ctx.tipProgress = 1;
483
+ ctx.tipDuration = 0;
484
+ ctx.entranceClipProgress = 1;
485
+ ctx._lastTipPositions = null;
486
+ if (tipWasActive) {
487
+ for (const cb of ctx._tipSubscribers) cb(null);
488
+ }
489
+ renderFrameCycle(ctx);
490
+ };
491
+ ctx._animRafId = raf(tick);
492
+ }
493
+ function buildSceneTargets(ctx, visibleDatasets, renderPropsMap, input, explicitMode) {
494
+ const targets = /* @__PURE__ */ new Map();
495
+ let anyTip = false;
496
+ for (const ds of visibleDatasets) {
497
+ const newValues = input.lineTransformedValues?.get(ds.id) ?? [];
498
+ const axisId = ds.props[input.axisIdProp] ?? input.firstValueAxisId;
499
+ const stackOrder = input.datasets.get(ds.id)?.order ?? 0;
500
+ const props = ds.props;
501
+ const renderProps = renderPropsMap.get(ds.id) ?? props;
502
+ let hint;
503
+ if (explicitMode === "auto") {
504
+ const prev = ctx._scene.getElement(ds.id)?.current.geometry.values;
505
+ hint = prev ? detectStreamingUpdateKind(prev, newValues) : "update";
506
+ } else {
507
+ hint = explicitMode;
508
+ }
509
+ if (hint === "append" || hint === "scroll") anyTip = true;
510
+ targets.set(ds.id, {
511
+ geometry: { values: newValues, streamingHint: hint },
512
+ datasetId: ds.id,
513
+ axisId,
514
+ stackOrder,
515
+ props,
516
+ renderProps,
517
+ isExiting: false
518
+ });
519
+ }
520
+ return { targets, anyTip };
521
+ }
522
+ function renderSceneFrame(ctx) {
523
+ const layouts = /* @__PURE__ */ new Map();
524
+ if (!ctx.lastInput) return layouts;
525
+ const input = ctx.lastInput;
526
+ if (!input.categoryScale || !input.valueScales || input.valueScales.size === 0) return layouts;
527
+ const elements = ctx._scene.getElements();
528
+ if (elements.length === 0) return layouts;
529
+ const sharedValueScale = input.valueScales.values().next().value;
530
+ const orderedElements = [...elements].sort((a, b) => a.current.stackOrder - b.current.stackOrder);
531
+ let categoryCount = 0;
532
+ for (const el of orderedElements) {
533
+ categoryCount = Math.max(categoryCount, el.current.geometry.values.length);
534
+ }
535
+ const stackedElements = orderedElements.filter((el) => el.current.props.stackId !== void 0);
536
+ const stackBasesMap = stackedElements.length > 0 && categoryCount > 0 ? computeStackBases(
537
+ stackedElements.map((el) => el.current.datasetId),
538
+ stackedElements.map((el) => el.current.geometry.values),
539
+ categoryCount,
540
+ { isStacked: true, isWaterfall: false }
541
+ ) : /* @__PURE__ */ new Map();
542
+ let datasetIndex = 0;
543
+ for (const el of orderedElements) {
544
+ const state = el.current;
545
+ const targetValueScale = input.valueScales.get(state.axisId) ?? sharedValueScale;
546
+ const groupedData = input.groupedDataOverride?.get(state.datasetId);
547
+ const propsForLayout = groupedData ? { ...state.props, data: groupedData } : state.props;
548
+ const isStacked = state.props.stackId !== void 0;
549
+ const baseLayout = calculateLineLayout(propsForLayout, input.chartArea, {
550
+ categoryScale: input.categoryScale,
551
+ valueScale: targetValueScale,
552
+ stackBases: isStacked ? stackBasesMap.get(state.datasetId) : void 0,
553
+ transformedValues: state.geometry.values,
554
+ seriesId: state.datasetId
555
+ });
556
+ layouts.set(state.datasetId, { ...baseLayout, datasetIndex: datasetIndex++ });
557
+ }
558
+ return layouts;
559
+ }
560
+ function updateRenderState(ctx) {
561
+ const layouts = renderSceneFrame(ctx);
562
+ const activeRenderProps = /* @__PURE__ */ new Map();
563
+ for (const el of ctx._scene.getElements()) {
564
+ const baseProps = el.current.renderProps;
565
+ const overrides = ctx._propertyOverrides.get(el.current.datasetId);
566
+ const merged = overrides ? { ...baseProps, ...overrides } : baseProps;
567
+ activeRenderProps.set(el.current.datasetId, merged);
568
+ }
569
+ ctx.activeRenderPropsCache = activeRenderProps;
570
+ ctx.lastRenderedLayouts = layouts;
571
+ ctx._markerOverlays = collectLineMarkerOverlays(layouts, activeRenderProps, ctx.lastInput?.renderer === "canvas");
572
+ if (ctx.tipProgress < 1) {
573
+ ctx._lastTipPositions = computeTipPositions(layouts, ctx.tipProgress, (id) => {
574
+ const el = ctx._scene.getElement(id);
575
+ return !el || el.current.isExiting;
576
+ });
577
+ } else {
578
+ ctx._lastTipPositions = null;
579
+ }
580
+ }
581
+ function renderFrameCycle(ctx) {
582
+ if (!ctx.lastInput) return;
583
+ updateRenderState(ctx);
584
+ const input = ctx.lastInput;
585
+ if (triggerCompositorRepaint(input.renderer, ctx.canvasEl, input.compositor)) {
586
+ ctx.onFrame?.();
587
+ return;
588
+ }
589
+ if (input.renderer === "svg") {
590
+ renderSvgFrame(ctx);
591
+ } else if (input.renderer === "canvas" && ctx.lastRenderedLayouts) {
592
+ const layouts = ctx.lastRenderedLayouts;
593
+ const tipStates = [];
594
+ if (ctx.tipProgress < 1) {
595
+ for (const [id, layout] of layouts) {
596
+ const el = ctx._scene.getElement(id);
597
+ if (!el || el.current.isExiting) continue;
598
+ const state = applyTipExtension(layout, ctx.tipProgress);
599
+ if (state) tipStates.push({ layout, state });
600
+ }
601
+ }
602
+ try {
603
+ renderLinesFrame({
604
+ paint: ctx._paint,
605
+ renderer: "canvas",
606
+ group: null,
607
+ canvas: ctx.canvasEl,
608
+ layouts,
609
+ renderPropsMap: applyHoverToProps(ctx, ctx.activeRenderPropsCache),
610
+ context: {
611
+ chartId: input.chartId,
612
+ width: input.width,
613
+ height: input.height,
614
+ renderer: "canvas",
615
+ chartArea: input.chartArea,
616
+ theme: input.theme
617
+ },
618
+ chartArea: input.chartArea,
619
+ rangeGroups: input.rangeGroups,
620
+ labelConfig: input.labelConfig,
621
+ clipProgress: ctx.entranceClipProgress < 1 ? ctx.entranceClipProgress : void 0,
622
+ dir: input.dir,
623
+ datasetVisibility: input.datasetVisibility
624
+ });
625
+ } finally {
626
+ for (const { layout, state } of tipStates) {
627
+ restoreTipExtension(layout, state);
628
+ }
629
+ }
630
+ }
631
+ ctx.onFrame?.();
632
+ }
633
+
634
+ // src/series/line/controller/index.ts
635
+ var LineRendererController = class {
636
+ constructor(paint) {
637
+ // Animation lifecycle — local raf handle, initial-render flag, and
638
+ // fingerprint for static-phase detection.
639
+ this._animRafId = null;
640
+ this._isInitial = true;
641
+ this._lastFingerprint = "";
642
+ // Tip-position subscribers — fired every animation frame so cross-controller
643
+ // consumers (e.g. custom markers in CartesianRenderer) can imperatively sync
644
+ // their DOM positions during tip extension. Replaces the old
645
+ // `orchestrator.share/notify('line:tipPositions', ...)` pub/sub.
646
+ this._tipSubscribers = /* @__PURE__ */ new Set();
647
+ // Layout caches (read by hit test / legend)
648
+ this.layoutCache = /* @__PURE__ */ new Map();
649
+ this.renderPropsCache = /* @__PURE__ */ new Map();
650
+ this.lineDatasets = [];
651
+ this.storedLayoutData = null;
652
+ // Last rendered state (for SVG re-render on hover; canvas paint callback reads this)
653
+ this.lastRenderedLayouts = null;
654
+ this.activeRenderPropsCache = /* @__PURE__ */ new Map();
655
+ /**
656
+ * Per-dataset property-animation overrides. Layered onto scene-derived renderProps
657
+ * at read time inside updateRenderState. Property animations write to this map;
658
+ * scene tick never touches it. Cleared in destroy().
659
+ */
660
+ this._propertyOverrides = /* @__PURE__ */ new Map();
661
+ // Controller-level clocks. Value-channel tweens are owned by `_scene`;
662
+ // tip extension (geometric last-segment animation) and entrance clip-reveal
663
+ // remain manual clocks for parity with the prior dual-channel design.
664
+ this.tipProgress = 1;
665
+ this.entranceClipProgress = 1;
666
+ this.tipStartAt = 0;
667
+ this.tipDuration = 0;
668
+ // Current state.
669
+ // Single source of truth for the current hover. Written ONLY by applyHover (never
670
+ // re-seeded from input.hover), read by applyHoverToProps for every render path. Hover
671
+ // is event-driven and always arrives via applyHover, so re-seeding from the swappable
672
+ // input would let a stale input.hover clobber the live hover. Mirrors candlestick/
673
+ // heatmap/radar/polar.
674
+ this.hover = { datasetId: null, index: null };
675
+ this.lastInput = null;
676
+ this._markerOverlays = [];
677
+ this._lastTipPositions = null;
678
+ // applyHoverToProps memo — paintCanvasLayer asks for the full hovered props
679
+ // map once per dataset per compositor.repaint; without this cache that's
680
+ // O(D²×P) work per mouse-driven repaint on synced/crosshair pages.
681
+ // Keys: hover ref + input propsMap ref. The hover ref is replaced wholesale by
682
+ // applyHover() and the propsMap by update(), so reference identity is a safe key.
683
+ this._hoverPropsCacheHover = null;
684
+ this._hoverPropsCachePropsMap = null;
685
+ this._hoverPropsCacheResult = null;
686
+ // DOM targets
687
+ this.svgGroup = null;
688
+ this.canvasEl = null;
689
+ this.onFrame = null;
690
+ this._paint = paint;
691
+ this._scene = new AnimatedScene({
692
+ // ENTER: lines enter from zeros at the same x positions.
693
+ // values=[] is intentional — the controller seeds the real "zeros" array
694
+ // at _buildSceneTargets time (it needs to know category count).
695
+ emptyState: (target) => ({
696
+ ...target,
697
+ geometry: { values: target.geometry.values.map(() => 0), streamingHint: "update" },
698
+ isExiting: false
699
+ }),
700
+ // EXIT: shrink to zeros at current x positions.
701
+ exitEmptyState: (target) => ({
702
+ ...target,
703
+ geometry: { values: target.geometry.values.map(() => 0), streamingHint: "update" },
704
+ isExiting: true
705
+ }),
706
+ registry: LINE_REGISTRY
707
+ });
708
+ }
709
+ // ================================================================
710
+ // PUBLIC API
711
+ // ================================================================
712
+ update(input) {
713
+ this.lastInput = input;
714
+ this.svgGroup = input.svgGroup ?? null;
715
+ this.canvasEl = input.canvasEl ?? null;
716
+ this.storedLayoutData = input.layoutData ?? null;
717
+ const { datasets, datasetVisibility, features, compositor } = input;
718
+ const sortedDatasets = Array.from(datasets.entries()).sort(([, a], [, b]) => a.order - b.order);
719
+ this.lineDatasets = collectItems(sortedDatasets, datasetVisibility).line;
720
+ let layoutResult = input.layoutResult ?? this.computeLayout(input);
721
+ if (!layoutResult && this._scene.getElements().length > 0 && input.categoryScale && input.valueScales && input.valueScales.size > 0) {
722
+ layoutResult = { layouts: /* @__PURE__ */ new Map(), renderPropsMap: /* @__PURE__ */ new Map(), visibleDatasets: [] };
723
+ }
724
+ if (!layoutResult) {
725
+ this.layoutCache.clear();
726
+ this.renderPropsCache.clear();
727
+ this.activeRenderPropsCache.clear();
728
+ this.lastRenderedLayouts = null;
729
+ this._cancelRaf();
730
+ this._scene.reset();
731
+ this._isInitial = true;
732
+ this._lastFingerprint = "";
733
+ this.tipProgress = 1;
734
+ this.tipDuration = 0;
735
+ if (input.renderer === "svg" && this.svgGroup) {
736
+ while (this.svgGroup.firstChild) this.svgGroup.removeChild(this.svgGroup.firstChild);
737
+ }
738
+ return;
739
+ }
740
+ if (input.renderer === "svg" && !this.svgGroup) return;
741
+ const { layouts, renderPropsMap, visibleDatasets } = layoutResult;
742
+ this.layoutCache = layouts;
743
+ this.renderPropsCache = renderPropsMap;
744
+ const context = {
745
+ chartId: input.chartId,
746
+ width: input.width,
747
+ height: input.height,
748
+ renderer: input.renderer,
749
+ chartArea: input.chartArea,
750
+ theme: input.theme,
751
+ accessibility: buildAccessibilityRenderContext(features)
752
+ };
753
+ const animConfig = features.get("animation")?.props;
754
+ const { fingerprint, updateMode, phase, shouldAnimate, duration, easing } = resolveLineAnimationPlan(layouts, animConfig, this._isInitial, this._lastFingerprint, this._scene.getElements().length);
755
+ const { targets: sceneTargets, anyTip } = buildSceneTargets(this, visibleDatasets, renderPropsMap, input, updateMode);
756
+ if (input.renderer === "canvas" && compositor) {
757
+ compositor.removeLayersByPrefix?.("line:");
758
+ const rangeFirstDs = /* @__PURE__ */ new Set();
759
+ if (input.rangeGroups) {
760
+ for (const [, rg] of input.rangeGroups) {
761
+ if (rg.datasetIds.length >= 2) rangeFirstDs.add(rg.datasetIds[0]);
762
+ }
763
+ }
764
+ const layerIds = /* @__PURE__ */ new Set([...layouts.keys(), ...this._scene.getElements().map((el) => el.current.datasetId)]);
765
+ registerDatasetLayers(
766
+ compositor,
767
+ "line",
768
+ layerIds,
769
+ (dsId) => sceneTargets.get(dsId)?.stackOrder ?? this._scene.getElement(dsId)?.current.stackOrder ?? 0,
770
+ (dsId) => (ctx) => paintCanvasLayer(this, ctx, dsId, rangeFirstDs, context)
771
+ );
772
+ }
773
+ const opts = {
774
+ numbers: { duration: shouldAnimate ? duration : 0, easing },
775
+ colors: { duration: shouldAnimate ? duration : 0, easing }
776
+ };
777
+ if (phase === "static" && this._animRafId !== null) {
778
+ this._commit(fingerprint);
779
+ return;
780
+ }
781
+ if (!shouldAnimate) {
782
+ this._cancelRaf();
783
+ this.tipProgress = 1;
784
+ this.tipDuration = 0;
785
+ this.entranceClipProgress = 1;
786
+ this._scene.diff(sceneTargets, opts);
787
+ this._scene.tick(performance.now());
788
+ this.renderFrameCycle();
789
+ this._commit(fingerprint);
790
+ return;
791
+ }
792
+ if (phase === "entrance") {
793
+ this._cancelRaf();
794
+ this.tipProgress = 1;
795
+ this.tipDuration = 0;
796
+ this.entranceClipProgress = 0;
797
+ this._scene.diff(sceneTargets, { numbers: { duration: 0, easing }, colors: { duration: 0, easing } });
798
+ this._scene.tick(performance.now());
799
+ this._startEntranceLoop(duration, easing);
800
+ this._commit(fingerprint);
801
+ return;
802
+ }
803
+ this._cancelRaf();
804
+ this._scene.diff(sceneTargets, opts);
805
+ if (anyTip) {
806
+ this.tipStartAt = performance.now();
807
+ this.tipDuration = duration;
808
+ this.tipProgress = 0;
809
+ }
810
+ this._startSceneUpdateLoop(easing);
811
+ this._commit(fingerprint);
812
+ }
813
+ applyHover(hover) {
814
+ applyHover(this, hover);
815
+ }
816
+ applyPropertyAnimations(store) {
817
+ if (!this.lastRenderedLayouts || this.lastRenderedLayouts.size === 0 || !this.lastInput) return;
818
+ const input = this.lastInput;
819
+ let appliedAny = false;
820
+ let needsSvgFullRender = false;
821
+ for (const [dsId, props] of this.activeRenderPropsCache) {
822
+ const overrides = resolveAnimatedProps(store, "line", dsId, LINE_ANIMATABLE_PROPS);
823
+ if (Object.keys(overrides).length === 0) {
824
+ if (this._propertyOverrides.delete(dsId)) appliedAny = true;
825
+ continue;
826
+ }
827
+ appliedAny = true;
828
+ this._propertyOverrides.set(dsId, overrides);
829
+ this.activeRenderPropsCache.set(dsId, { ...props, ...overrides });
830
+ if (input.renderer === "svg" && this.svgGroup) {
831
+ const group = this.svgGroup.querySelector(`[data-dataset="${dsId}"]`);
832
+ if (!group) continue;
833
+ if (Object.keys(overrides).some((k) => k !== "lineStrokeWidth" && k !== "lineDashOffset" && k !== "fillOpacity" && k !== "tension")) {
834
+ needsSvgFullRender = true;
835
+ continue;
836
+ }
837
+ if ("lineStrokeWidth" in overrides) {
838
+ group.querySelectorAll(".line-strokes path").forEach((el) => {
839
+ el.setAttribute("stroke-width", String(overrides.lineStrokeWidth));
840
+ });
841
+ }
842
+ if ("lineDashOffset" in overrides) {
843
+ group.querySelectorAll(".line-strokes path").forEach((el) => {
844
+ el.setAttribute("stroke-dashoffset", String(overrides.lineDashOffset));
845
+ });
846
+ }
847
+ if ("fillOpacity" in overrides) {
848
+ group.querySelectorAll(".line-area path").forEach((el) => {
849
+ el.setAttribute("fill-opacity", String(overrides.fillOpacity));
850
+ });
851
+ }
852
+ if ("tension" in overrides) {
853
+ const layout = this.lastRenderedLayouts.get(dsId);
854
+ if (layout) {
855
+ const { curve, isArea, baselineY } = layout;
856
+ const newTension = overrides.tension;
857
+ const linePathEls = Array.from(group.querySelectorAll(".line-strokes path"));
858
+ const areaPathEls = isArea ? Array.from(group.querySelectorAll(".line-area path")) : [];
859
+ layout.segments.forEach((seg, i) => {
860
+ linePathEls[i]?.setAttribute("d", buildLinePath(seg.points, curve, newTension));
861
+ if (isArea && areaPathEls[i]) {
862
+ const isStacked = seg.points[0]?.baseY !== void 0;
863
+ areaPathEls[i].setAttribute("d", isStacked ? buildStackedFillPath(seg.points, curve, newTension) : buildFillPath(seg.points, curve, baselineY, newTension));
864
+ }
865
+ });
866
+ }
867
+ }
868
+ }
869
+ }
870
+ if (!appliedAny) return;
871
+ if (triggerCompositorRepaint(input.renderer, this.canvasEl, input.compositor)) return;
872
+ if (input.renderer !== "svg" || needsSvgFullRender) {
873
+ this.renderFrameCycle();
874
+ }
875
+ }
876
+ hitTest(x, y) {
877
+ return lineHitTest(x, y, { layouts: this.layoutCache, renderPropsCache: this.renderPropsCache, layoutData: this.storedLayoutData, hitTest: hitTestLine, theme: this.lastInput?.theme });
878
+ }
879
+ findAllNearest(x, y) {
880
+ return lineFindAllNearest(x, y, { layouts: this.layoutCache, renderPropsCache: this.renderPropsCache, layoutData: this.storedLayoutData, hitTest: hitTestLine, theme: this.lastInput?.theme });
881
+ }
882
+ getSvgOutput() {
883
+ return null;
884
+ }
885
+ get hasData() {
886
+ return this.lineDatasets.length > 0;
887
+ }
888
+ get layouts() {
889
+ return this.layoutCache;
890
+ }
891
+ get renderProps() {
892
+ return this.renderPropsCache;
893
+ }
894
+ get markerOverlays() {
895
+ return this._markerOverlays;
896
+ }
897
+ /**
898
+ * Sync line point positions with a chrome-animated category/value scale.
899
+ *
900
+ * Called from the chrome animation loop each frame (canvas: from inside
901
+ * `compositor.repaint`'s `bgPainter`; SVG: directly). We only update the
902
+ * cached input scales — the next line animation frame (or a direct
903
+ * re-render when no line animation is active) picks them up through
904
+ * `_renderSceneFrame`.
905
+ *
906
+ * IMPORTANT: this method must never call `triggerCompositorRepaint` — it
907
+ * can be invoked from inside an in-flight compositor.repaint, and nesting
908
+ * would recurse. On canvas, we only refresh `lastRenderedLayouts` so the
909
+ * outer repaint's data-layer callbacks read the fresh layout.
910
+ */
911
+ syncWithAnimatedScale(categoryScale, valueScales) {
912
+ if (!this.lastInput) return;
913
+ this.lastInput.categoryScale = categoryScale;
914
+ if (valueScales) this.lastInput.valueScales = valueScales;
915
+ if (this._animRafId !== null || this.tipProgress < 1 || this.entranceClipProgress < 1) {
916
+ return;
917
+ }
918
+ updateRenderState(this);
919
+ if (this.lastInput.renderer === "svg" && this.svgGroup) {
920
+ renderSvgFrame(this);
921
+ }
922
+ }
923
+ /**
924
+ * Subscribe to per-frame tip-position updates during tip-extension animation.
925
+ * Returns an unsubscribe function. Callback receives the current map of
926
+ * `datasetId → { x, y }` for the animated last segment endpoint, or `null`
927
+ * when no tip animation is in flight.
928
+ *
929
+ * Used by external consumers (e.g. CartesianRenderer's custom-marker sync)
930
+ * that need to imperatively update DOM positions during the line tip animation.
931
+ */
932
+ subscribeTipPositions(cb) {
933
+ this._tipSubscribers.add(cb);
934
+ return () => {
935
+ this._tipSubscribers.delete(cb);
936
+ };
937
+ }
938
+ destroy() {
939
+ this._cancelRaf();
940
+ this._scene.reset();
941
+ this._isInitial = true;
942
+ this._lastFingerprint = "";
943
+ this._tipSubscribers.clear();
944
+ this.tipProgress = 1;
945
+ this.tipDuration = 0;
946
+ this.entranceClipProgress = 1;
947
+ this._lastTipPositions = null;
948
+ this.lastRenderedLayouts = null;
949
+ this.activeRenderPropsCache.clear();
950
+ this._propertyOverrides.clear();
951
+ this.layoutCache.clear();
952
+ this.renderPropsCache.clear();
953
+ this.lineDatasets = [];
954
+ this.storedLayoutData = null;
955
+ this.lastInput?.compositor?.removeLayersByPrefix("line:");
956
+ this._hoverPropsCacheHover = null;
957
+ this._hoverPropsCachePropsMap = null;
958
+ this._hoverPropsCacheResult = null;
959
+ }
960
+ // ================================================================
961
+ // PRIVATE HELPERS
962
+ // ================================================================
963
+ /** Cancel any in-flight raf. */
964
+ _cancelRaf() {
965
+ cancelRafCtx(this);
966
+ }
967
+ /** Commit fingerprint for next-frame phase detection and mark initial render complete. */
968
+ _commit(fingerprint) {
969
+ commit(this, fingerprint);
970
+ }
971
+ /** Entrance clip-reveal raf loop (delegates to `scene.startEntranceLoop`). */
972
+ _startEntranceLoop(duration, easing) {
973
+ startEntranceLoop(this, duration, easing);
974
+ }
975
+ /** Update/tip raf loop (delegates to `scene.startSceneUpdateLoop`). */
976
+ _startSceneUpdateLoop(easing) {
977
+ startSceneUpdateLoop(this, easing);
978
+ }
979
+ computeLayout(input) {
980
+ const { categoryScale, valueScales, chartArea, axisIdProp, firstValueAxisId, lineStackBasesMap, lineTransformedValues, groupedDataOverride, hoverConfig } = input;
981
+ if (this.lineDatasets.length === 0 || !categoryScale || !valueScales || valueScales.size === 0) return null;
982
+ const visibleDatasets = this.lineDatasets.filter((d) => d.visible);
983
+ if (visibleDatasets.length === 0) return null;
984
+ const layouts = /* @__PURE__ */ new Map();
985
+ const renderPropsMap = /* @__PURE__ */ new Map();
986
+ const sharedValueScale = valueScales.values().next().value;
987
+ let datasetIndex = 0;
988
+ for (const ld of visibleDatasets) {
989
+ const targetAxisId = ld.props[axisIdProp] ?? firstValueAxisId;
990
+ const targetValueScale = valueScales.get(targetAxisId) ?? sharedValueScale;
991
+ const groupedData = groupedDataOverride?.get(ld.id);
992
+ const propsForLayout = groupedData ? { ...ld.props, data: groupedData } : ld.props;
993
+ const baseLayout = calculateLineLayout(propsForLayout, chartArea, {
994
+ categoryScale,
995
+ valueScale: targetValueScale,
996
+ stackBases: lineStackBasesMap?.get(ld.id),
997
+ transformedValues: lineTransformedValues?.get(ld.id),
998
+ seriesId: ld.id
999
+ });
1000
+ layouts.set(ld.id, { ...baseLayout, datasetIndex: datasetIndex++ });
1001
+ const seriesHoverProps = ld.props;
1002
+ renderPropsMap.set(ld.id, {
1003
+ ...ld.props,
1004
+ interaction: { hoveredIndex: null },
1005
+ effects: {
1006
+ hoverBrightness: hoverConfig?.brightness ?? DEFAULT_HOVER_BRIGHTNESS,
1007
+ dimOpacity: hoverConfig?.dimOpacity ?? DEFAULT_HOVER_DIM_OPACITY,
1008
+ hoverRadiusMultiplier: hoverConfig?.radiusMultiplier,
1009
+ hoverBackgroundColor: seriesHoverProps.hoverColor ?? hoverConfig?.backgroundColor,
1010
+ hoverBorderColor: seriesHoverProps.hoverBorderColor ?? hoverConfig?.borderColor,
1011
+ hoverBorderStrokeWidth: hoverConfig?.borderStrokeWidth,
1012
+ hoverPointRadius: seriesHoverProps.hoverPointRadius
1013
+ }
1014
+ });
1015
+ }
1016
+ return { layouts, renderPropsMap, visibleDatasets };
1017
+ }
1018
+ /** Refresh render-state caches from the current scene + progresses. No paint. */
1019
+ updateRenderState() {
1020
+ updateRenderState(this);
1021
+ }
1022
+ /** SVG frame render with inline tip extension (delegates to `paint.renderSvgFrame`). */
1023
+ renderSvgFrame() {
1024
+ renderSvgFrame(this);
1025
+ }
1026
+ /** Full frame: update state then paint (delegates to `scene.renderFrameCycle`). */
1027
+ renderFrameCycle() {
1028
+ renderFrameCycle(this);
1029
+ }
1030
+ /** Canvas compositor layer paint callback (delegates to `paint.paintCanvasLayer`). */
1031
+ paintCanvasLayer(ctx, dsId, rangeFirstDs, context) {
1032
+ paintCanvasLayer(this, ctx, dsId, rangeFirstDs, context);
1033
+ }
1034
+ /** Bake the current hover into render props (delegates to `hover.applyHoverToProps`). */
1035
+ applyHoverToProps(propsMap) {
1036
+ return applyHoverToProps(this, propsMap);
1037
+ }
1038
+ };
1039
+
1040
+ export { LineRendererController };