@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,895 @@
1
+ import { calculateAxisLayout } from './chunk-ZTL2FQEW.mjs';
2
+ import { getEasing, easeOutQuart } from './chunk-3WEMHXZI.mjs';
3
+ import { raf, cancelRaf } from './chunk-EDAKJLNA.mjs';
4
+ import { interpolateCartesianAxisLayout } from './chunk-WH3C3Y7P.mjs';
5
+ import { createLinearScale, createOrdinalTimeScale, createOrdinalTimeBandAdapter, createTimeScale, createTimeBandAdapter } from './chunk-RQ3CKQOX.mjs';
6
+
7
+ // src/animations/axis-transition.ts
8
+ var AXIS_SMOOTHING = 0.225;
9
+ var AXIS_SETTLED_THRESHOLD = 5e-3;
10
+ var AxisTransitionState = class {
11
+ constructor() {
12
+ this.opacities = /* @__PURE__ */ new Map();
13
+ /**
14
+ * Per-axis per-tick opacities. Keyed by axisId, then by tick value
15
+ * (numeric `rawValue` for value axes, string `value` for category axes).
16
+ *
17
+ * Step 11 extension. Populated by `setTickTargets`, advanced by `tick`,
18
+ * read by `applyTicks`. When no entry exists for an axis, `applyTicks`
19
+ * passes ticks through unchanged so existing axes (no per-tick lerp)
20
+ * keep their current behavior.
21
+ */
22
+ this.tickOpacities = /* @__PURE__ */ new Map();
23
+ /**
24
+ * Per-axis rotation interpolation state. Populated by `setRotationTargets`,
25
+ * advanced by `tick`, read by `applyRotations`.
26
+ *
27
+ * Step 11 extension. Reuses `AxisOpacity` shape (`{ current, target }`)
28
+ * since the math is identical — exponential decay at `AXIS_SMOOTHING`.
29
+ */
30
+ this.rotations = /* @__PURE__ */ new Map();
31
+ }
32
+ /**
33
+ * Set opacity targets from axis layout isHidden flags.
34
+ * Call this whenever layoutData changes.
35
+ */
36
+ setTargets(axisLayouts) {
37
+ const activeKeys = /* @__PURE__ */ new Set();
38
+ for (const [key, info] of axisLayouts) {
39
+ activeKeys.add(key);
40
+ const target = info.isHidden ? 0 : 1;
41
+ const existing = this.opacities.get(key);
42
+ if (existing) {
43
+ const previousTarget = existing.target;
44
+ existing.target = target;
45
+ if (target === 0 && previousTarget === 0) {
46
+ existing.current = 0;
47
+ }
48
+ } else {
49
+ this.opacities.set(key, { current: target, target });
50
+ }
51
+ }
52
+ for (const key of this.opacities.keys()) {
53
+ if (!activeKeys.has(key)) {
54
+ this.opacities.delete(key);
55
+ }
56
+ }
57
+ }
58
+ /**
59
+ * Advance all opacity values by one frame using exponential decay.
60
+ * Covers axis-level opacities, per-tick opacities, and per-axis rotations.
61
+ * Returns true if any value is still animating.
62
+ *
63
+ * Per-tick cleanup: an exiting tick (target = 0) that has settled is
64
+ * REMOVED from the per-axis map. This keeps the map size bounded across
65
+ * many domain lerps. Continuing/entering ticks (target = 1) simply snap.
66
+ */
67
+ tick() {
68
+ let anyAnimating = false;
69
+ for (const opacity of this.opacities.values()) {
70
+ const displacement = opacity.target - opacity.current;
71
+ if (Math.abs(displacement) > AXIS_SETTLED_THRESHOLD) {
72
+ opacity.current += displacement * AXIS_SMOOTHING;
73
+ anyAnimating = true;
74
+ } else {
75
+ opacity.current = opacity.target;
76
+ }
77
+ }
78
+ for (const tickMap of this.tickOpacities.values()) {
79
+ for (const [tickKey, opacity] of tickMap) {
80
+ const displacement = opacity.target - opacity.current;
81
+ if (Math.abs(displacement) > AXIS_SETTLED_THRESHOLD) {
82
+ opacity.current += displacement * AXIS_SMOOTHING;
83
+ anyAnimating = true;
84
+ } else {
85
+ opacity.current = opacity.target;
86
+ if (opacity.target === 0) {
87
+ tickMap.delete(tickKey);
88
+ }
89
+ }
90
+ }
91
+ }
92
+ for (const rotation of this.rotations.values()) {
93
+ const displacement = rotation.target - rotation.current;
94
+ if (Math.abs(displacement) > AXIS_SETTLED_THRESHOLD) {
95
+ rotation.current += displacement * AXIS_SMOOTHING;
96
+ anyAnimating = true;
97
+ } else {
98
+ rotation.current = rotation.target;
99
+ }
100
+ }
101
+ return anyAnimating;
102
+ }
103
+ /**
104
+ * Apply animated opacity to axis layouts.
105
+ *
106
+ * - Hidden axis with opacity > threshold: swap in visibleLayout with opacity (fade-out in progress)
107
+ * - Hidden axis settled at 0: use hidden layout as-is (fully invisible)
108
+ * - Visible axis: use layout with current opacity (handles fade-in)
109
+ */
110
+ apply(axisLayouts) {
111
+ const result = /* @__PURE__ */ new Map();
112
+ for (const [key, info] of axisLayouts) {
113
+ const opacityState = this.opacities.get(key);
114
+ if (!opacityState) {
115
+ result.set(key, info);
116
+ continue;
117
+ }
118
+ const opacity = opacityState.current;
119
+ if (info.isHidden && opacity > AXIS_SETTLED_THRESHOLD) {
120
+ result.set(key, {
121
+ ...info,
122
+ layout: { ...info.visibleLayout, opacity }
123
+ });
124
+ } else if (!info.isHidden && opacity < 1 - AXIS_SETTLED_THRESHOLD) {
125
+ result.set(key, {
126
+ ...info,
127
+ layout: { ...info.layout, opacity }
128
+ });
129
+ } else {
130
+ result.set(key, info);
131
+ }
132
+ }
133
+ return result;
134
+ }
135
+ // ========================================================================
136
+ // STEP 11: Per-tick opacity API
137
+ // ========================================================================
138
+ /**
139
+ * Set per-tick opacity targets for one axis from an enter/exit/continuing
140
+ * categorization. Idempotent within a frame — call once per domain lerp init.
141
+ *
142
+ * - Entering tick (new): target = 1, current = 0 if no prior entry exists
143
+ * (animates IN). If a prior entry exists, keep current as-is to handle
144
+ * rapid toggling without snapping.
145
+ * - Exiting tick (removed): target = 0, current = whatever it was last
146
+ * (animates OUT). If no prior entry exists, assume it was visible —
147
+ * start at 1.
148
+ * - Continuing tick (in both start + target): snap to current = target = 1.
149
+ * No animation needed; position lerp via `interpolateCartesianAxisLayout`
150
+ * covers the visible motion.
151
+ *
152
+ * Any tick previously tracked for this axis but NOT in the new `ticks`
153
+ * list is snapped to target 0 (cleanup — no longer part of the lerp).
154
+ * `tick()` will drop it once it settles.
155
+ */
156
+ setTickTargets(axisId, ticks) {
157
+ let tickMap = this.tickOpacities.get(axisId);
158
+ if (!tickMap) {
159
+ tickMap = /* @__PURE__ */ new Map();
160
+ this.tickOpacities.set(axisId, tickMap);
161
+ }
162
+ const activeKeys = /* @__PURE__ */ new Set();
163
+ for (const tick of ticks) {
164
+ activeKeys.add(tick.value);
165
+ const existing = tickMap.get(tick.value);
166
+ if (tick.isEntering) {
167
+ if (existing) {
168
+ existing.target = 1;
169
+ } else {
170
+ tickMap.set(tick.value, { current: 0, target: 1 });
171
+ }
172
+ } else if (tick.isExiting) {
173
+ if (existing) {
174
+ existing.target = 0;
175
+ } else {
176
+ tickMap.set(tick.value, { current: 1, target: 0 });
177
+ }
178
+ } else {
179
+ if (existing) {
180
+ existing.target = 1;
181
+ } else {
182
+ tickMap.set(tick.value, { current: 1, target: 1 });
183
+ }
184
+ }
185
+ }
186
+ for (const key of tickMap.keys()) {
187
+ if (!activeKeys.has(key)) {
188
+ tickMap.get(key).target = 0;
189
+ }
190
+ }
191
+ }
192
+ /**
193
+ * Apply animated per-tick opacities to a tick array. Returns the same
194
+ * array with each tick's `opacity` field set from the internal state.
195
+ *
196
+ * - Axis has no per-tick lerp entry: return ticks unchanged (preserves
197
+ * existing behavior for axes that don't participate in tick fade).
198
+ * - Tick value not in the per-axis map: pass through with opacity 1.
199
+ */
200
+ applyTicks(axisId, ticks) {
201
+ const tickMap = this.tickOpacities.get(axisId);
202
+ if (!tickMap) {
203
+ return ticks;
204
+ }
205
+ return ticks.map((tick) => {
206
+ const key = tick.rawValue ?? tick.value;
207
+ const entry = tickMap.get(key);
208
+ return entry ? { ...tick, opacity: entry.current } : { ...tick, opacity: 1 };
209
+ });
210
+ }
211
+ /**
212
+ * Probe: does this axis still have a per-tick entry for `value`? Returns
213
+ * false once `tick()` has cleaned up a settled exiting entry. Callers
214
+ * (e.g. `advanceDomainLerp`'s exiting-tick merge) use it to decide
215
+ * whether to keep synthesizing a faded-out tick or drop it entirely.
216
+ */
217
+ hasTickEntry(axisId, value) {
218
+ return this.tickOpacities.get(axisId)?.has(value) ?? false;
219
+ }
220
+ // ========================================================================
221
+ // STEP 11: Per-axis rotation interpolation API
222
+ // ========================================================================
223
+ /**
224
+ * Set the target rotation angle (radians or degrees — caller-defined) for
225
+ * one axis. Step 11 extension.
226
+ *
227
+ * - First call for an axis with no `currentAngle`: snap current to target
228
+ * (no initial animation — there's nothing to animate FROM).
229
+ * - First call with `currentAngle` provided: initialize current to that
230
+ * angle so the first lerp animates from layout-resolved rotation to
231
+ * the new target.
232
+ * - Subsequent calls: leave `current` alone (state machine already knows
233
+ * where the visible angle is); only re-target.
234
+ */
235
+ setRotationTargets(axisId, targetAngle, currentAngle) {
236
+ const existing = this.rotations.get(axisId);
237
+ if (!existing) {
238
+ const start = currentAngle ?? targetAngle;
239
+ this.rotations.set(axisId, { current: start, target: targetAngle });
240
+ return;
241
+ }
242
+ existing.target = targetAngle;
243
+ }
244
+ /**
245
+ * Return the interpolated rotation angle for an axis, or `fallback` when
246
+ * no entry exists. Use the renderer-resolved rotation as the fallback so
247
+ * axes with no active rotation lerp stay at whatever `calculateAxisLayout`
248
+ * resolved for them.
249
+ */
250
+ applyRotations(axisId, fallback) {
251
+ const entry = this.rotations.get(axisId);
252
+ return entry ? entry.current : fallback;
253
+ }
254
+ };
255
+
256
+ // src/animations/registry.ts
257
+ var AnimationRegistry = class {
258
+ constructor() {
259
+ this.entries = /* @__PURE__ */ new Map();
260
+ this.rafId = null;
261
+ this.onRepaint = null;
262
+ this.ticking = false;
263
+ /** True when the scheduler calls tick synchronously (detected on first raf call). Tests only. */
264
+ this._isSyncScheduler = false;
265
+ /** Set to true just before calling raf(); if tick fires while this is true, scheduler is sync. */
266
+ this._detectingSync = false;
267
+ // -------------------------------------------------------------------------
268
+ // PRIVATE
269
+ // -------------------------------------------------------------------------
270
+ /**
271
+ * Persistent bound tick function. Using a class arrow ensures the same
272
+ * reference is passed to every raf() call, which enables auto-rescheduling
273
+ * from within the tick body for async (browser) schedulers.
274
+ */
275
+ this.boundTick = (now) => {
276
+ if (this._detectingSync) {
277
+ this._isSyncScheduler = true;
278
+ }
279
+ this.rafId = null;
280
+ this.ticking = true;
281
+ try {
282
+ const completed = [];
283
+ for (const [id, entry] of this.entries) {
284
+ if (entry.startTime === -1) {
285
+ entry.startTime = now + (entry.config.delay ?? 0);
286
+ }
287
+ const elapsed = Math.max(0, now - entry.startTime);
288
+ const { duration, loops = 1, alternate } = entry.config;
289
+ if (loops === Infinity) {
290
+ const cycleIndex = Math.floor(elapsed / duration);
291
+ const cycleElapsed = elapsed % duration;
292
+ const rawProgress = cycleElapsed / duration;
293
+ const directedProgress = alternate && cycleIndex % 2 === 1 ? 1 - rawProgress : rawProgress;
294
+ const easedProgress = entry.easingFn(directedProgress);
295
+ entry.currentValue = entry.config.from + (entry.config.to - entry.config.from) * easedProgress;
296
+ entry.config.onTick?.(entry.currentValue);
297
+ } else {
298
+ const totalDuration = duration * loops;
299
+ if (elapsed >= totalDuration) {
300
+ entry.currentValue = entry.config.to;
301
+ entry.config.onTick?.(entry.currentValue);
302
+ entry.config.onComplete?.();
303
+ completed.push(id);
304
+ } else {
305
+ const cycleElapsed = elapsed % duration;
306
+ const rawProgress = cycleElapsed / duration;
307
+ const easedProgress = entry.easingFn(rawProgress);
308
+ entry.currentValue = entry.config.from + (entry.config.to - entry.config.from) * easedProgress;
309
+ entry.config.onTick?.(entry.currentValue);
310
+ }
311
+ }
312
+ }
313
+ for (const id of completed) {
314
+ this.entries.delete(id);
315
+ }
316
+ if (this.entries.size > 0 || completed.length > 0) {
317
+ this.onRepaint?.();
318
+ }
319
+ } finally {
320
+ this.ticking = false;
321
+ }
322
+ if (this.entries.size > 0 && !this._isSyncScheduler) {
323
+ this.rafId = raf(this.boundTick);
324
+ }
325
+ };
326
+ }
327
+ /**
328
+ * Set the repaint callback. Called after all entries are ticked each frame.
329
+ * Typically triggers a full canvas clear + redraw.
330
+ */
331
+ setRepaintCallback(callback) {
332
+ this.onRepaint = callback;
333
+ }
334
+ /**
335
+ * Register a new animation. If an animation with the same ID exists,
336
+ * it is replaced (restarted). Returns an unregister function.
337
+ */
338
+ register(config) {
339
+ const easingFn = typeof config.easing === "string" ? getEasing(config.easing) : config.easing ?? easeOutQuart;
340
+ const entry = {
341
+ config,
342
+ easingFn,
343
+ startTime: -1,
344
+ // lazily initialized to RAF `now` on first tick
345
+ currentValue: config.from
346
+ };
347
+ this.entries.set(config.id, entry);
348
+ this.ensureLoop();
349
+ return () => this.unregister(config.id);
350
+ }
351
+ /**
352
+ * Unregister an animation by ID.
353
+ */
354
+ unregister(id) {
355
+ this.entries.delete(id);
356
+ }
357
+ /**
358
+ * Check if an animation with the given ID is active.
359
+ */
360
+ has(id) {
361
+ return this.entries.has(id);
362
+ }
363
+ /**
364
+ * Get the current interpolated value for an animation.
365
+ * Returns undefined if the animation is not registered.
366
+ */
367
+ getValue(id) {
368
+ return this.entries.get(id)?.currentValue;
369
+ }
370
+ /**
371
+ * Get snapshots of all active animations.
372
+ */
373
+ getSnapshots() {
374
+ const now = performance.now();
375
+ const snapshots = [];
376
+ for (const [, entry] of this.entries) {
377
+ const elapsed = entry.startTime === -1 ? 0 : Math.max(0, now - entry.startTime);
378
+ const rawProgress = Math.min(elapsed / entry.config.duration, 1);
379
+ snapshots.push({
380
+ id: entry.config.id,
381
+ key: entry.config.key,
382
+ value: entry.currentValue,
383
+ progress: rawProgress
384
+ });
385
+ }
386
+ return snapshots;
387
+ }
388
+ /**
389
+ * Number of active animations.
390
+ */
391
+ get size() {
392
+ return this.entries.size;
393
+ }
394
+ /**
395
+ * Stop all animations and cancel the RAF loop.
396
+ */
397
+ clear() {
398
+ this.entries.clear();
399
+ this.stopLoop();
400
+ }
401
+ /**
402
+ * Full cleanup — clear all animations and remove the repaint callback.
403
+ */
404
+ destroy() {
405
+ this.clear();
406
+ this.onRepaint = null;
407
+ }
408
+ ensureLoop() {
409
+ if (this.rafId !== null || this.ticking) return;
410
+ this._detectingSync = true;
411
+ this.rafId = raf(this.boundTick);
412
+ this._detectingSync = false;
413
+ if (this._isSyncScheduler) {
414
+ this.rafId = null;
415
+ }
416
+ }
417
+ stopLoop() {
418
+ if (this.rafId !== null) {
419
+ cancelRaf(this.rafId);
420
+ this.rafId = null;
421
+ }
422
+ }
423
+ };
424
+
425
+ // src/animations/domain-lerp.ts
426
+ var TICK_VALUE_EPSILON = 1e-9;
427
+ function initDomainLerp(existingLerp, targetDomains, options) {
428
+ const expansionStart = options?.expansionStart === true;
429
+ for (const [axisId, targetDomain] of targetDomains) {
430
+ const existing = existingLerp.get(axisId);
431
+ let currentMin;
432
+ let currentMax;
433
+ if (existing) {
434
+ currentMin = existing.minCurrent;
435
+ currentMax = existing.maxCurrent;
436
+ } else {
437
+ currentMin = targetDomain[0];
438
+ currentMax = targetDomain[1];
439
+ }
440
+ const bidirectionalExpansion = existing !== void 0 && targetDomain[0] < currentMin && targetDomain[1] > currentMax;
441
+ if (expansionStart && !bidirectionalExpansion) {
442
+ currentMin = Math.min(currentMin, targetDomain[0]);
443
+ currentMax = Math.max(currentMax, targetDomain[1]);
444
+ }
445
+ existingLerp.set(axisId, {
446
+ minStart: currentMin,
447
+ maxStart: currentMax,
448
+ minTarget: targetDomain[0],
449
+ maxTarget: targetDomain[1],
450
+ minCurrent: currentMin,
451
+ maxCurrent: currentMax
452
+ });
453
+ }
454
+ for (const id of existingLerp.keys()) {
455
+ if (!targetDomains.has(id)) existingLerp.delete(id);
456
+ }
457
+ }
458
+ function initDomainLerpTickFade(lerpStates, axisLayouts, valueScaleRange, cartesianArea, orientation, axisTransitionState, globalFont, locale) {
459
+ for (const [stateKey, lerp2] of lerpStates) {
460
+ const isXSide = stateKey.startsWith("x:");
461
+ const axisLayoutKey = isXSide ? stateKey : `${orientation === "vertical" ? "y" : "x"}:${stateKey}`;
462
+ const axisInfo = axisLayouts.get(axisLayoutKey);
463
+ if (!axisInfo) continue;
464
+ if (axisInfo.isHidden || axisInfo.props?.type === "logarithmic") {
465
+ lerp2.tickFade = void 0;
466
+ continue;
467
+ }
468
+ if (lerp2.minStart === lerp2.minTarget && lerp2.maxStart === lerp2.maxTarget) {
469
+ lerp2.tickFade = void 0;
470
+ continue;
471
+ }
472
+ const targetTicks = extractRawValues(axisInfo.layout.ticks);
473
+ const startDomain = [lerp2.minStart, lerp2.maxStart];
474
+ const startScale = createLinearScale(startDomain, isXSide ? axisInfo.scale.range() : valueScaleRange);
475
+ const startArea = axisInfo.offset > 0 ? computeOffsetArea(cartesianArea, axisInfo.position, axisInfo.offset) : cartesianArea;
476
+ const startLayout = calculateAxisLayout(startScale, axisInfo.position, startArea, axisInfo.props, axisInfo.extraTitleOffset, globalFont, locale);
477
+ const startTicks = extractRawValues(startLayout.ticks);
478
+ const { entering, exiting, continuing } = diffTickValues(startTicks, targetTicks);
479
+ lerp2.tickFade = { entering, exiting, continuing };
480
+ axisTransitionState.setTickTargets(axisLayoutKey, [
481
+ ...exiting.map((v) => ({ value: v, isEntering: false, isExiting: true })),
482
+ ...entering.map((v) => ({ value: v, isEntering: true, isExiting: false })),
483
+ ...continuing.map((v) => ({ value: v, isEntering: false, isExiting: false }))
484
+ ]);
485
+ const startRotation = extractRepresentativeRotation(startLayout.ticks);
486
+ const targetRotation = extractRepresentativeRotation(axisInfo.layout.ticks);
487
+ if (startRotation !== targetRotation) {
488
+ axisTransitionState.setRotationTargets(axisLayoutKey, targetRotation, startRotation);
489
+ }
490
+ }
491
+ }
492
+ function extractRepresentativeRotation(ticks) {
493
+ for (const t of ticks) {
494
+ if (typeof t.rotation === "number") return t.rotation;
495
+ }
496
+ return 0;
497
+ }
498
+ function extractRawValues(ticks) {
499
+ const out = [];
500
+ for (const t of ticks) {
501
+ if (typeof t.rawValue === "number" && Number.isFinite(t.rawValue)) {
502
+ out.push(t.rawValue);
503
+ }
504
+ }
505
+ return out;
506
+ }
507
+ function diffTickValues(start, target) {
508
+ const entering = [];
509
+ const exiting = [];
510
+ const continuing = [];
511
+ for (const t of target) {
512
+ if (start.some((s) => Math.abs(s - t) < TICK_VALUE_EPSILON)) {
513
+ continuing.push(t);
514
+ } else {
515
+ entering.push(t);
516
+ }
517
+ }
518
+ for (const s of start) {
519
+ if (!target.some((t) => Math.abs(t - s) < TICK_VALUE_EPSILON)) {
520
+ exiting.push(s);
521
+ }
522
+ }
523
+ return { entering, exiting, continuing };
524
+ }
525
+ function advanceDomainLerp(lerpStates, progress, axisLayouts, valueScaleRange, cartesianArea, orientation, baseValueScales, baseValueDomains, globalFont, locale, axisTransitionState) {
526
+ const animatedValueScales = new Map(baseValueScales);
527
+ const animatedValueDomains = new Map(baseValueDomains);
528
+ const animatedAxisLayouts = new Map(axisLayouts);
529
+ let animatedValueXScales;
530
+ for (const [stateKey, lerp2] of lerpStates) {
531
+ const isXSide = stateKey.startsWith("x:");
532
+ const axisLayoutKey = isXSide ? stateKey : `${orientation === "vertical" ? "y" : "x"}:${stateKey}`;
533
+ const axisId = isXSide ? stateKey.slice(2) : stateKey;
534
+ const axisInfo = axisLayouts.get(axisLayoutKey);
535
+ if (axisInfo?.isHidden || axisInfo?.props?.type === "logarithmic" || isXSide && !axisInfo) {
536
+ continue;
537
+ }
538
+ lerp2.minCurrent = lerp2.minStart + (lerp2.minTarget - lerp2.minStart) * progress;
539
+ lerp2.maxCurrent = lerp2.maxStart + (lerp2.maxTarget - lerp2.maxStart) * progress;
540
+ const domain = [lerp2.minCurrent, lerp2.maxCurrent];
541
+ const range = isXSide && axisInfo ? axisInfo.scale.range() : valueScaleRange;
542
+ const scale = createLinearScale(domain, range);
543
+ if (isXSide) {
544
+ (animatedValueXScales ?? (animatedValueXScales = /* @__PURE__ */ new Map())).set(axisId, scale);
545
+ } else {
546
+ animatedValueScales.set(axisId, scale);
547
+ animatedValueDomains.set(axisId, domain);
548
+ }
549
+ if (axisInfo) {
550
+ const area = axisInfo.offset > 0 ? computeOffsetArea(cartesianArea, axisInfo.position, axisInfo.offset) : cartesianArea;
551
+ const newLayout = calculateAxisLayout(scale, axisInfo.position, area, axisInfo.props, axisInfo.extraTitleOffset, globalFont, locale);
552
+ const hasEntry = axisTransitionState ? (v) => axisTransitionState.hasTickEntry(axisLayoutKey, v) : void 0;
553
+ const mergedTicks = lerp2.tickFade && lerp2.tickFade.exiting.length > 0 ? mergeWithExitingTicks(newLayout.ticks, lerp2.tickFade.exiting, scale, axisInfo, area, hasEntry) : newLayout.ticks;
554
+ const mergedGridLines = newLayout.gridLines.length > 0 ? buildGridLinesForTicks(mergedTicks, axisInfo.position, area) : [];
555
+ const opacityTicks = axisTransitionState ? axisTransitionState.applyTicks(axisLayoutKey, mergedTicks) : mergedTicks;
556
+ const rotatedTicks = axisTransitionState ? applyRotationToTicks(opacityTicks, axisTransitionState, axisLayoutKey) : opacityTicks;
557
+ const opacityGridLines = mergedGridLines.map((line, i) => {
558
+ const tickOpacity = rotatedTicks[i]?.opacity;
559
+ return tickOpacity === void 0 ? line : { ...line, opacity: tickOpacity };
560
+ });
561
+ animatedAxisLayouts.set(axisLayoutKey, {
562
+ ...axisInfo,
563
+ layout: { ...newLayout, ticks: rotatedTicks, gridLines: opacityGridLines },
564
+ scale,
565
+ domain
566
+ });
567
+ }
568
+ }
569
+ return {
570
+ valueScales: animatedValueScales,
571
+ valueDomains: animatedValueDomains,
572
+ axisLayouts: animatedAxisLayouts,
573
+ valueXScales: animatedValueXScales
574
+ };
575
+ }
576
+ function mergeWithExitingTicks(currentTicks, exitingValues, intermediateScale, axisInfo, area, hasEntry) {
577
+ const template = currentTicks[0];
578
+ if (!template) return currentTicks;
579
+ const isHorizontal = axisInfo.position === "top" || axisInfo.position === "bottom";
580
+ const [rangeStart, rangeEnd] = intermediateScale.range();
581
+ const rangeMin = Math.min(rangeStart, rangeEnd);
582
+ const rangeMax = Math.max(rangeStart, rangeEnd);
583
+ const exitingTicks = [];
584
+ for (const value of exitingValues) {
585
+ if (hasEntry && !hasEntry(value)) continue;
586
+ const pos = intermediateScale(value);
587
+ if (!Number.isFinite(pos) || pos < rangeMin || pos > rangeMax) continue;
588
+ const rounded = Math.round(pos);
589
+ if (isHorizontal) {
590
+ exitingTicks.push({
591
+ ...template,
592
+ value,
593
+ rawValue: value,
594
+ label: String(value),
595
+ position: pos,
596
+ x1: pos,
597
+ x2: pos,
598
+ y1: template.y1,
599
+ y2: template.y2,
600
+ labelX: rounded,
601
+ labelY: template.labelY
602
+ });
603
+ } else {
604
+ exitingTicks.push({
605
+ ...template,
606
+ value,
607
+ rawValue: value,
608
+ label: String(value),
609
+ position: pos,
610
+ x1: template.x1,
611
+ x2: template.x2,
612
+ y1: pos,
613
+ y2: pos,
614
+ labelX: template.labelX,
615
+ labelY: rounded
616
+ });
617
+ }
618
+ }
619
+ return [...currentTicks, ...exitingTicks];
620
+ }
621
+ function applyRotationToTicks(ticks, axisTransitionState, axisId) {
622
+ let layoutAngle;
623
+ for (const t of ticks) {
624
+ if (typeof t.rotation === "number") {
625
+ layoutAngle = t.rotation;
626
+ break;
627
+ }
628
+ }
629
+ const interpolated = axisTransitionState.applyRotations(axisId, layoutAngle ?? 0);
630
+ if (layoutAngle === void 0 && interpolated === 0) return ticks;
631
+ return ticks.map((t) => ({ ...t, rotation: interpolated !== 0 ? interpolated : void 0 }));
632
+ }
633
+ function buildGridLinesForTicks(ticks, position, area) {
634
+ const isHorizontal = position === "top" || position === "bottom";
635
+ return ticks.map((t) => isHorizontal ? { x1: t.position, y1: area.y, x2: t.position, y2: area.y + area.height } : { x1: area.x, y1: t.position, x2: area.x + area.width, y2: t.position });
636
+ }
637
+ function snapDomainLerp(lerpStates) {
638
+ for (const [, lerp2] of lerpStates) {
639
+ lerp2.minCurrent = lerp2.minTarget;
640
+ lerp2.maxCurrent = lerp2.maxTarget;
641
+ lerp2.minStart = lerp2.minTarget;
642
+ lerp2.maxStart = lerp2.maxTarget;
643
+ lerp2.tickFade = void 0;
644
+ }
645
+ }
646
+ function initTimeDomainLerp(existing, target, options) {
647
+ const expansionStart = options?.expansionStart === true;
648
+ if (existing) {
649
+ const startMin = expansionStart ? Math.min(existing.minCurrent, target[0]) : existing.minCurrent;
650
+ const startMax = expansionStart ? Math.max(existing.maxCurrent, target[1]) : existing.maxCurrent;
651
+ return {
652
+ minStart: startMin,
653
+ maxStart: startMax,
654
+ minTarget: target[0],
655
+ maxTarget: target[1],
656
+ minCurrent: startMin,
657
+ maxCurrent: startMax
658
+ };
659
+ }
660
+ return {
661
+ minStart: target[0],
662
+ maxStart: target[1],
663
+ minTarget: target[0],
664
+ maxTarget: target[1],
665
+ minCurrent: target[0],
666
+ maxCurrent: target[1]
667
+ };
668
+ }
669
+ function advanceTimeDomainLerp(lerp2, progress, axisLayouts, cached) {
670
+ lerp2.minCurrent = lerp2.minStart + (lerp2.minTarget - lerp2.minStart) * progress;
671
+ lerp2.maxCurrent = lerp2.maxStart + (lerp2.maxTarget - lerp2.maxStart) * progress;
672
+ const domain = [lerp2.minCurrent, lerp2.maxCurrent];
673
+ const area = cached.cartesianArea;
674
+ const catRange = cached.orientation === "vertical" ? [area.x, area.x + area.width] : [area.y, area.y + area.height];
675
+ const axisDir = cached.orientation === "vertical" ? "x" : "y";
676
+ let gaplessFlag = false;
677
+ let gaplessPadStart = 0;
678
+ let gaplessPadEnd = 0;
679
+ for (const [, info] of axisLayouts) {
680
+ if (info.axis === axisDir && info.domain) {
681
+ const props = info.props;
682
+ if (props?.gapless) {
683
+ gaplessFlag = true;
684
+ gaplessPadStart = props.chartPaddingMin ?? 0;
685
+ gaplessPadEnd = props.chartPaddingMax ?? 0;
686
+ }
687
+ break;
688
+ }
689
+ }
690
+ let timeScale;
691
+ let categoryScale;
692
+ if (gaplessFlag && cached.timestamps.length > 0) {
693
+ const sortedUnique = [...new Set(cached.timestamps)].sort((a, b) => a - b);
694
+ timeScale = createOrdinalTimeScale(sortedUnique, catRange, { visibleDomain: domain, padStart: gaplessPadStart, padEnd: gaplessPadEnd });
695
+ categoryScale = createOrdinalTimeBandAdapter(sortedUnique, timeScale);
696
+ } else {
697
+ timeScale = createTimeScale(domain, catRange);
698
+ categoryScale = createTimeBandAdapter(cached.timestamps, timeScale);
699
+ }
700
+ const updated = new Map(axisLayouts);
701
+ for (const [key, info] of axisLayouts) {
702
+ if (info.axis === axisDir && info.domain) {
703
+ const remapped = interpolateCartesianAxisLayout(info, timeScale);
704
+ updated.set(key, { ...remapped, scale: timeScale, domain });
705
+ }
706
+ }
707
+ return { categoryScale, axisLayouts: updated };
708
+ }
709
+ function snapTimeDomainLerp(lerp2) {
710
+ lerp2.minCurrent = lerp2.minTarget;
711
+ lerp2.maxCurrent = lerp2.maxTarget;
712
+ lerp2.minStart = lerp2.minTarget;
713
+ lerp2.maxStart = lerp2.maxTarget;
714
+ }
715
+ function computeOffsetArea(area, position, offset) {
716
+ switch (position) {
717
+ case "left":
718
+ return { ...area, x: area.x - offset, width: area.width + offset };
719
+ case "right":
720
+ return { ...area, width: area.width + offset };
721
+ case "top":
722
+ return { ...area, y: area.y - offset, height: area.height + offset };
723
+ case "bottom":
724
+ return { ...area, height: area.height + offset };
725
+ default:
726
+ return area;
727
+ }
728
+ }
729
+
730
+ // src/animations/category-lerp.ts
731
+ function initCategoryLerp(axisLayouts, orientation) {
732
+ const result = /* @__PURE__ */ new Map();
733
+ const isXAxis = orientation === "vertical";
734
+ for (const info of axisLayouts.values()) {
735
+ if (info.axis !== (isXAxis ? "x" : "y")) continue;
736
+ for (const tick of info.layout.ticks) {
737
+ result.set(tick.label, isXAxis ? tick.labelX : tick.labelY);
738
+ }
739
+ }
740
+ return result;
741
+ }
742
+ function advanceCategoryLerp(axisLayouts, prevPositions, progress, orientation) {
743
+ if (prevPositions.size === 0) return axisLayouts;
744
+ const isXAxis = orientation === "vertical";
745
+ const result = new Map(axisLayouts);
746
+ for (const [key, info] of result) {
747
+ if (info.axis !== (isXAxis ? "x" : "y")) continue;
748
+ result.set(key, { ...info, layout: interpolateCategoryAxisLayout(info.layout, prevPositions, progress, isXAxis) });
749
+ }
750
+ return result;
751
+ }
752
+ function snapCategoryLerp(state) {
753
+ state.clear();
754
+ }
755
+ function interpolateCategoryAxisLayout(layout, prevPositions, progress, isXAxis) {
756
+ const deltaByPos = /* @__PURE__ */ new Map();
757
+ const newTicks = layout.ticks.map((tick) => {
758
+ const prevPos = prevPositions.get(tick.label);
759
+ if (prevPos === void 0) return { ...tick, opacity: progress };
760
+ if (isXAxis) {
761
+ const animX = prevPos + (tick.labelX - prevPos) * progress;
762
+ const delta = animX - tick.labelX;
763
+ deltaByPos.set(Math.round(tick.x1), delta);
764
+ return { ...tick, labelX: animX, x1: tick.x1 + delta, x2: tick.x2 + delta };
765
+ } else {
766
+ const animY = prevPos + (tick.labelY - prevPos) * progress;
767
+ const delta = animY - tick.labelY;
768
+ deltaByPos.set(Math.round(tick.y1), delta);
769
+ return { ...tick, labelY: animY, y1: tick.y1 + delta, y2: tick.y2 + delta };
770
+ }
771
+ });
772
+ const newGridLines = layout.gridLines.map((gl) => {
773
+ const key = Math.round(isXAxis ? gl.x1 : gl.y1);
774
+ const delta = deltaByPos.get(key) ?? 0;
775
+ if (delta === 0) return gl;
776
+ return isXAxis ? { ...gl, x1: gl.x1 + delta, x2: gl.x2 + delta } : { ...gl, y1: gl.y1 + delta, y2: gl.y2 + delta };
777
+ });
778
+ return { ...layout, ticks: newTicks, gridLines: newGridLines };
779
+ }
780
+
781
+ // src/animations/canvas-compositor.ts
782
+ var CanvasCompositor = class {
783
+ constructor() {
784
+ this._layers = /* @__PURE__ */ new Map();
785
+ this._sortedLayers = [];
786
+ this._sortDirty = false;
787
+ this._bgPainter = null;
788
+ this._fgPainter = null;
789
+ }
790
+ // -------------------------------------------------------------------------
791
+ // Layer registry
792
+ // -------------------------------------------------------------------------
793
+ /**
794
+ * Register a canvas paint layer (e.g., bar, line, scatter).
795
+ * Layers are painted in `order` between background and foreground.
796
+ * Safe to call multiple times — replaces previous layer with same id.
797
+ */
798
+ registerLayer(layer) {
799
+ this._layers.set(layer.id, layer);
800
+ this._sortDirty = true;
801
+ }
802
+ /** Remove a canvas paint layer by id. */
803
+ removeLayer(id) {
804
+ this._layers.delete(id);
805
+ this._sortDirty = true;
806
+ }
807
+ /**
808
+ * Remove all canvas paint layers whose id starts with the given prefix.
809
+ * Used for per-dataset cleanup (e.g., removeLayersByPrefix('bar:')).
810
+ */
811
+ removeLayersByPrefix(prefix) {
812
+ let removed = false;
813
+ for (const id of this._layers.keys()) {
814
+ if (id.startsWith(prefix)) {
815
+ this._layers.delete(id);
816
+ removed = true;
817
+ }
818
+ }
819
+ if (removed) this._sortDirty = true;
820
+ }
821
+ /** Check if a layer is registered. */
822
+ hasLayer(id) {
823
+ return this._layers.has(id);
824
+ }
825
+ /** Check if compositor has any layers registered. */
826
+ hasLayers() {
827
+ return this._layers.size > 0;
828
+ }
829
+ // -------------------------------------------------------------------------
830
+ // Background / foreground painters
831
+ // -------------------------------------------------------------------------
832
+ /** Set the background painter (grid, fills, beforeData references, zoom clip). */
833
+ setBackground(painter) {
834
+ this._bgPainter = painter;
835
+ }
836
+ /** Set the foreground painter (afterData references, axes, brackets, annotations). */
837
+ setForeground(painter) {
838
+ this._fgPainter = painter;
839
+ }
840
+ // -------------------------------------------------------------------------
841
+ // Composited repaint
842
+ // -------------------------------------------------------------------------
843
+ /**
844
+ * Repaint the entire canvas in correct z-order:
845
+ * 1. Clear
846
+ * 2. Background
847
+ * 3. Data layers sorted by order
848
+ * 4. Foreground
849
+ * All painting is synchronous within this call (no interleaved repaints).
850
+ */
851
+ repaint(ctx) {
852
+ const canvas = ctx.canvas;
853
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
854
+ if (this._bgPainter) this._bgPainter(ctx);
855
+ if (this._sortDirty) {
856
+ this._sortedLayers = Array.from(this._layers.values()).sort((a, b) => a.order - b.order);
857
+ this._sortDirty = false;
858
+ }
859
+ for (let i = 0; i < this._sortedLayers.length; i++) {
860
+ if (this._layers.has(this._sortedLayers[i].id)) {
861
+ this._sortedLayers[i].paint(ctx);
862
+ }
863
+ }
864
+ if (this._fgPainter) this._fgPainter(ctx);
865
+ }
866
+ };
867
+
868
+ // src/animations/property-store.ts
869
+ var AnimatedPropertyStore = class {
870
+ constructor() {
871
+ this.values = /* @__PURE__ */ new Map();
872
+ }
873
+ set(key, value) {
874
+ this.values.set(key, value);
875
+ }
876
+ get(key) {
877
+ return this.values.get(key);
878
+ }
879
+ /**
880
+ * Remove a single key. Called by `setupPropertyAnimations`' `onComplete`
881
+ * hook so a finished animation stops contributing an override value.
882
+ * Returns true if the key existed.
883
+ */
884
+ delete(key) {
885
+ return this.values.delete(key);
886
+ }
887
+ clear() {
888
+ this.values.clear();
889
+ }
890
+ destroy() {
891
+ this.clear();
892
+ }
893
+ };
894
+
895
+ export { AXIS_SETTLED_THRESHOLD, AXIS_SMOOTHING, AnimatedPropertyStore, AnimationRegistry, AxisTransitionState, CanvasCompositor, advanceCategoryLerp, advanceDomainLerp, advanceTimeDomainLerp, initCategoryLerp, initDomainLerp, initDomainLerpTickFade, initTimeDomainLerp, snapCategoryLerp, snapDomainLerp, snapTimeDomainLerp };