@voila.dev/chart 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/README.md +85 -0
  2. package/dist/brush/brush-layer.d.ts +16 -0
  3. package/dist/brush/brush-layer.d.ts.map +1 -0
  4. package/dist/brush/brush-layer.js +137 -0
  5. package/dist/brush/brush-layer.js.map +7 -0
  6. package/dist/brush/index.d.ts +10 -0
  7. package/dist/brush/index.d.ts.map +1 -0
  8. package/dist/brush/index.js +8 -0
  9. package/dist/brush/index.js.map +7 -0
  10. package/dist/canvas/canvas-renderer.d.ts +11 -0
  11. package/dist/canvas/canvas-renderer.d.ts.map +1 -0
  12. package/dist/canvas/canvas-renderer.js +49 -0
  13. package/dist/canvas/canvas-renderer.js.map +7 -0
  14. package/dist/canvas/index.d.ts +2 -0
  15. package/dist/canvas/index.d.ts.map +1 -0
  16. package/dist/canvas/index.js +5 -0
  17. package/dist/canvas/index.js.map +7 -0
  18. package/dist/canvas/paint-scene.d.ts +4 -0
  19. package/dist/canvas/paint-scene.d.ts.map +1 -0
  20. package/dist/canvas/paint-scene.js +130 -0
  21. package/dist/canvas/paint-scene.js.map +7 -0
  22. package/dist/canvas/resolve-color.d.ts +18 -0
  23. package/dist/canvas/resolve-color.d.ts.map +1 -0
  24. package/dist/canvas/resolve-color.js +52 -0
  25. package/dist/canvas/resolve-color.js.map +7 -0
  26. package/dist/contour/density.d.ts +20 -0
  27. package/dist/contour/density.d.ts.map +1 -0
  28. package/dist/contour/density.js +59 -0
  29. package/dist/contour/density.js.map +7 -0
  30. package/dist/contour/index.d.ts +2 -0
  31. package/dist/contour/index.d.ts.map +1 -0
  32. package/dist/contour/index.js +5 -0
  33. package/dist/contour/index.js.map +7 -0
  34. package/dist/core/channel.d.ts +11 -0
  35. package/dist/core/channel.d.ts.map +1 -0
  36. package/dist/core/channel.js +44 -0
  37. package/dist/core/channel.js.map +7 -0
  38. package/dist/core/compile.d.ts +22 -0
  39. package/dist/core/compile.d.ts.map +1 -0
  40. package/dist/core/compile.js +295 -0
  41. package/dist/core/compile.js.map +7 -0
  42. package/dist/core/define-chart.d.ts +96 -0
  43. package/dist/core/define-chart.d.ts.map +1 -0
  44. package/dist/core/define-chart.js +7 -0
  45. package/dist/core/define-chart.js.map +7 -0
  46. package/dist/core/facet.d.ts +7 -0
  47. package/dist/core/facet.d.ts.map +1 -0
  48. package/dist/core/facet.js +134 -0
  49. package/dist/core/facet.js.map +7 -0
  50. package/dist/core/format.d.ts +37 -0
  51. package/dist/core/format.d.ts.map +1 -0
  52. package/dist/core/format.js +108 -0
  53. package/dist/core/format.js.map +7 -0
  54. package/dist/core/guides/axes.d.ts +25 -0
  55. package/dist/core/guides/axes.d.ts.map +1 -0
  56. package/dist/core/guides/axes.js +204 -0
  57. package/dist/core/guides/axes.js.map +7 -0
  58. package/dist/core/marks/area.d.ts +23 -0
  59. package/dist/core/marks/area.d.ts.map +1 -0
  60. package/dist/core/marks/area.js +187 -0
  61. package/dist/core/marks/area.js.map +7 -0
  62. package/dist/core/marks/bar.d.ts +26 -0
  63. package/dist/core/marks/bar.d.ts.map +1 -0
  64. package/dist/core/marks/bar.js +200 -0
  65. package/dist/core/marks/bar.js.map +7 -0
  66. package/dist/core/marks/cell.d.ts +16 -0
  67. package/dist/core/marks/cell.d.ts.map +1 -0
  68. package/dist/core/marks/cell.js +98 -0
  69. package/dist/core/marks/cell.js.map +7 -0
  70. package/dist/core/marks/dot.d.ts +17 -0
  71. package/dist/core/marks/dot.d.ts.map +1 -0
  72. package/dist/core/marks/dot.js +125 -0
  73. package/dist/core/marks/dot.js.map +7 -0
  74. package/dist/core/marks/funnel-layout.d.ts +37 -0
  75. package/dist/core/marks/funnel-layout.d.ts.map +1 -0
  76. package/dist/core/marks/funnel-layout.js +61 -0
  77. package/dist/core/marks/funnel-layout.js.map +7 -0
  78. package/dist/core/marks/funnel.d.ts +19 -0
  79. package/dist/core/marks/funnel.d.ts.map +1 -0
  80. package/dist/core/marks/funnel.js +143 -0
  81. package/dist/core/marks/funnel.js.map +7 -0
  82. package/dist/core/marks/line.d.ts +17 -0
  83. package/dist/core/marks/line.d.ts.map +1 -0
  84. package/dist/core/marks/line.js +150 -0
  85. package/dist/core/marks/line.js.map +7 -0
  86. package/dist/core/marks/polar.d.ts +61 -0
  87. package/dist/core/marks/polar.d.ts.map +1 -0
  88. package/dist/core/marks/polar.js +436 -0
  89. package/dist/core/marks/polar.js.map +7 -0
  90. package/dist/core/marks/rect.d.ts +22 -0
  91. package/dist/core/marks/rect.d.ts.map +1 -0
  92. package/dist/core/marks/rect.js +119 -0
  93. package/dist/core/marks/rect.js.map +7 -0
  94. package/dist/core/marks/rule.d.ts +17 -0
  95. package/dist/core/marks/rule.d.ts.map +1 -0
  96. package/dist/core/marks/rule.js +73 -0
  97. package/dist/core/marks/rule.js.map +7 -0
  98. package/dist/core/marks/shared.d.ts +41 -0
  99. package/dist/core/marks/shared.d.ts.map +1 -0
  100. package/dist/core/marks/shared.js +74 -0
  101. package/dist/core/marks/shared.js.map +7 -0
  102. package/dist/core/marks/stack.d.ts +13 -0
  103. package/dist/core/marks/stack.d.ts.map +1 -0
  104. package/dist/core/marks/stack.js +28 -0
  105. package/dist/core/marks/stack.js.map +7 -0
  106. package/dist/core/marks/stats/difference.d.ts +20 -0
  107. package/dist/core/marks/stats/difference.d.ts.map +1 -0
  108. package/dist/core/marks/stats/difference.js +168 -0
  109. package/dist/core/marks/stats/difference.js.map +7 -0
  110. package/dist/core/marks/stats/distribution.d.ts +41 -0
  111. package/dist/core/marks/stats/distribution.d.ts.map +1 -0
  112. package/dist/core/marks/stats/distribution.js +354 -0
  113. package/dist/core/marks/stats/distribution.js.map +7 -0
  114. package/dist/core/marks/stats/dodge.d.ts +16 -0
  115. package/dist/core/marks/stats/dodge.d.ts.map +1 -0
  116. package/dist/core/marks/stats/dodge.js +104 -0
  117. package/dist/core/marks/stats/dodge.js.map +7 -0
  118. package/dist/core/marks/stats/hexbin.d.ts +26 -0
  119. package/dist/core/marks/stats/hexbin.d.ts.map +1 -0
  120. package/dist/core/marks/stats/hexbin.js +113 -0
  121. package/dist/core/marks/stats/hexbin.js.map +7 -0
  122. package/dist/core/marks/stats/histogram.d.ts +27 -0
  123. package/dist/core/marks/stats/histogram.d.ts.map +1 -0
  124. package/dist/core/marks/stats/histogram.js +70 -0
  125. package/dist/core/marks/stats/histogram.js.map +7 -0
  126. package/dist/core/marks/stats/regression.d.ts +13 -0
  127. package/dist/core/marks/stats/regression.d.ts.map +1 -0
  128. package/dist/core/marks/stats/regression.js +80 -0
  129. package/dist/core/marks/stats/regression.js.map +7 -0
  130. package/dist/core/marks/stats/statistics.d.ts +34 -0
  131. package/dist/core/marks/stats/statistics.d.ts.map +1 -0
  132. package/dist/core/marks/stats/statistics.js +111 -0
  133. package/dist/core/marks/stats/statistics.js.map +7 -0
  134. package/dist/core/marks/stats/waffle.d.ts +18 -0
  135. package/dist/core/marks/stats/waffle.d.ts.map +1 -0
  136. package/dist/core/marks/stats/waffle.js +117 -0
  137. package/dist/core/marks/stats/waffle.js.map +7 -0
  138. package/dist/core/marks/text.d.ts +19 -0
  139. package/dist/core/marks/text.d.ts.map +1 -0
  140. package/dist/core/marks/text.js +60 -0
  141. package/dist/core/marks/text.js.map +7 -0
  142. package/dist/core/motion/tween.d.ts +6 -0
  143. package/dist/core/motion/tween.d.ts.map +1 -0
  144. package/dist/core/motion/tween.js +98 -0
  145. package/dist/core/motion/tween.js.map +7 -0
  146. package/dist/core/nearest.d.ts +25 -0
  147. package/dist/core/nearest.d.ts.map +1 -0
  148. package/dist/core/nearest.js +151 -0
  149. package/dist/core/nearest.js.map +7 -0
  150. package/dist/core/paths.d.ts +65 -0
  151. package/dist/core/paths.d.ts.map +1 -0
  152. package/dist/core/paths.js +192 -0
  153. package/dist/core/paths.js.map +7 -0
  154. package/dist/core/scales/color.d.ts +11 -0
  155. package/dist/core/scales/color.d.ts.map +1 -0
  156. package/dist/core/scales/color.js +35 -0
  157. package/dist/core/scales/color.js.map +7 -0
  158. package/dist/core/scales/continuous.d.ts +18 -0
  159. package/dist/core/scales/continuous.d.ts.map +1 -0
  160. package/dist/core/scales/continuous.js +82 -0
  161. package/dist/core/scales/continuous.js.map +7 -0
  162. package/dist/core/scales/discrete.d.ts +22 -0
  163. package/dist/core/scales/discrete.d.ts.map +1 -0
  164. package/dist/core/scales/discrete.js +103 -0
  165. package/dist/core/scales/discrete.js.map +7 -0
  166. package/dist/core/scales/resolve.d.ts +18 -0
  167. package/dist/core/scales/resolve.d.ts.map +1 -0
  168. package/dist/core/scales/resolve.js +112 -0
  169. package/dist/core/scales/resolve.js.map +7 -0
  170. package/dist/core/scales/time.d.ts +4 -0
  171. package/dist/core/scales/time.d.ts.map +1 -0
  172. package/dist/core/scales/time.js +140 -0
  173. package/dist/core/scales/time.js.map +7 -0
  174. package/dist/core/text.d.ts +3 -0
  175. package/dist/core/text.d.ts.map +1 -0
  176. package/dist/core/text.js +29 -0
  177. package/dist/core/text.js.map +7 -0
  178. package/dist/core/theme.d.ts +8 -0
  179. package/dist/core/theme.d.ts.map +1 -0
  180. package/dist/core/theme.js +21 -0
  181. package/dist/core/theme.js.map +7 -0
  182. package/dist/core/ticks.d.ts +27 -0
  183. package/dist/core/ticks.d.ts.map +1 -0
  184. package/dist/core/ticks.js +76 -0
  185. package/dist/core/ticks.js.map +7 -0
  186. package/dist/core/types.d.ts +305 -0
  187. package/dist/core/types.d.ts.map +1 -0
  188. package/dist/core/types.js +1 -0
  189. package/dist/core/types.js.map +7 -0
  190. package/dist/force/force.d.ts +30 -0
  191. package/dist/force/force.d.ts.map +1 -0
  192. package/dist/force/force.js +143 -0
  193. package/dist/force/force.js.map +7 -0
  194. package/dist/force/index.d.ts +2 -0
  195. package/dist/force/index.d.ts.map +1 -0
  196. package/dist/force/index.js +7 -0
  197. package/dist/force/index.js.map +7 -0
  198. package/dist/geo/geo.d.ts +59 -0
  199. package/dist/geo/geo.d.ts.map +1 -0
  200. package/dist/geo/geo.js +231 -0
  201. package/dist/geo/geo.js.map +7 -0
  202. package/dist/geo/index.d.ts +2 -0
  203. package/dist/geo/index.d.ts.map +1 -0
  204. package/dist/geo/index.js +13 -0
  205. package/dist/geo/index.js.map +7 -0
  206. package/dist/hierarchy/hierarchy.d.ts +24 -0
  207. package/dist/hierarchy/hierarchy.d.ts.map +1 -0
  208. package/dist/hierarchy/hierarchy.js +279 -0
  209. package/dist/hierarchy/hierarchy.js.map +7 -0
  210. package/dist/hierarchy/index.d.ts +2 -0
  211. package/dist/hierarchy/index.d.ts.map +1 -0
  212. package/dist/hierarchy/index.js +11 -0
  213. package/dist/hierarchy/index.js.map +7 -0
  214. package/dist/index.d.ts +29 -0
  215. package/dist/index.d.ts.map +1 -0
  216. package/dist/index.js +96 -0
  217. package/dist/index.js.map +7 -0
  218. package/dist/react/brush-contract.d.ts +23 -0
  219. package/dist/react/brush-contract.d.ts.map +1 -0
  220. package/dist/react/brush-contract.js +7 -0
  221. package/dist/react/brush-contract.js.map +7 -0
  222. package/dist/react/chart-data-table.d.ts +18 -0
  223. package/dist/react/chart-data-table.d.ts.map +1 -0
  224. package/dist/react/chart-data-table.js +55 -0
  225. package/dist/react/chart-data-table.js.map +7 -0
  226. package/dist/react/chart-legend.d.ts +17 -0
  227. package/dist/react/chart-legend.d.ts.map +1 -0
  228. package/dist/react/chart-legend.js +126 -0
  229. package/dist/react/chart-legend.js.map +7 -0
  230. package/dist/react/chart-tooltip.d.ts +18 -0
  231. package/dist/react/chart-tooltip.d.ts.map +1 -0
  232. package/dist/react/chart-tooltip.js +95 -0
  233. package/dist/react/chart-tooltip.js.map +7 -0
  234. package/dist/react/chart.d.ts +45 -0
  235. package/dist/react/chart.d.ts.map +1 -0
  236. package/dist/react/chart.js +383 -0
  237. package/dist/react/chart.js.map +7 -0
  238. package/dist/react/focus-overlay.d.ts +14 -0
  239. package/dist/react/focus-overlay.d.ts.map +1 -0
  240. package/dist/react/focus-overlay.js +147 -0
  241. package/dist/react/focus-overlay.js.map +7 -0
  242. package/dist/react/index.d.ts +7 -0
  243. package/dist/react/index.d.ts.map +1 -0
  244. package/dist/react/index.js +11 -0
  245. package/dist/react/index.js.map +7 -0
  246. package/dist/react/messages.d.ts +16 -0
  247. package/dist/react/messages.d.ts.map +1 -0
  248. package/dist/react/messages.js +33 -0
  249. package/dist/react/messages.js.map +7 -0
  250. package/dist/react/renderer.d.ts +14 -0
  251. package/dist/react/renderer.d.ts.map +1 -0
  252. package/dist/react/renderer.js +1 -0
  253. package/dist/react/renderer.js.map +7 -0
  254. package/dist/react/sr-only.d.ts +4 -0
  255. package/dist/react/sr-only.d.ts.map +1 -0
  256. package/dist/react/sr-only.js +15 -0
  257. package/dist/react/sr-only.js.map +7 -0
  258. package/dist/react/svg-renderer.d.ts +4 -0
  259. package/dist/react/svg-renderer.d.ts.map +1 -0
  260. package/dist/react/svg-renderer.js +20 -0
  261. package/dist/react/svg-renderer.js.map +7 -0
  262. package/dist/react/svg-scene.d.ts +8 -0
  263. package/dist/react/svg-scene.d.ts.map +1 -0
  264. package/dist/react/svg-scene.js +121 -0
  265. package/dist/react/svg-scene.js.map +7 -0
  266. package/dist/react/use-animated-scene.d.ts +10 -0
  267. package/dist/react/use-animated-scene.d.ts.map +1 -0
  268. package/dist/react/use-animated-scene.js +41 -0
  269. package/dist/react/use-animated-scene.js.map +7 -0
  270. package/dist/react/use-chart-focus.d.ts +29 -0
  271. package/dist/react/use-chart-focus.d.ts.map +1 -0
  272. package/dist/react/use-chart-focus.js +180 -0
  273. package/dist/react/use-chart-focus.js.map +7 -0
  274. package/dist/react/use-chart-width.d.ts +12 -0
  275. package/dist/react/use-chart-width.d.ts.map +1 -0
  276. package/dist/react/use-chart-width.js +23 -0
  277. package/dist/react/use-chart-width.js.map +7 -0
  278. package/dist/react/use-chart-zoom.d.ts +13 -0
  279. package/dist/react/use-chart-zoom.d.ts.map +1 -0
  280. package/dist/react/use-chart-zoom.js +52 -0
  281. package/dist/react/use-chart-zoom.js.map +7 -0
  282. package/dist/react/use-text-measurer.d.ts +8 -0
  283. package/dist/react/use-text-measurer.d.ts.map +1 -0
  284. package/dist/react/use-text-measurer.js +44 -0
  285. package/dist/react/use-text-measurer.js.map +7 -0
  286. package/dist/sankey/index.d.ts +2 -0
  287. package/dist/sankey/index.d.ts.map +1 -0
  288. package/dist/sankey/index.js +7 -0
  289. package/dist/sankey/index.js.map +7 -0
  290. package/dist/sankey/sankey.d.ts +29 -0
  291. package/dist/sankey/sankey.d.ts.map +1 -0
  292. package/dist/sankey/sankey.js +127 -0
  293. package/dist/sankey/sankey.js.map +7 -0
  294. package/dist/voronoi/index.d.ts +2 -0
  295. package/dist/voronoi/index.d.ts.map +1 -0
  296. package/dist/voronoi/index.js +5 -0
  297. package/dist/voronoi/index.js.map +7 -0
  298. package/dist/voronoi/voronoi.d.ts +16 -0
  299. package/dist/voronoi/voronoi.d.ts.map +1 -0
  300. package/dist/voronoi/voronoi.js +62 -0
  301. package/dist/voronoi/voronoi.js.map +7 -0
  302. package/package.json +74 -0
  303. package/src/brush/brush-layer.tsx +174 -0
  304. package/src/brush/index.ts +14 -0
  305. package/src/canvas/canvas-renderer.tsx +56 -0
  306. package/src/canvas/index.ts +1 -0
  307. package/src/canvas/paint-scene.ts +152 -0
  308. package/src/canvas/resolve-color.ts +65 -0
  309. package/src/contour/density.ts +90 -0
  310. package/src/contour/index.ts +1 -0
  311. package/src/core/channel.ts +53 -0
  312. package/src/core/compile.ts +436 -0
  313. package/src/core/define-chart.ts +128 -0
  314. package/src/core/facet.ts +189 -0
  315. package/src/core/format.ts +163 -0
  316. package/src/core/guides/axes.ts +283 -0
  317. package/src/core/marks/area.ts +238 -0
  318. package/src/core/marks/bar.ts +278 -0
  319. package/src/core/marks/cell.ts +123 -0
  320. package/src/core/marks/dot.ts +157 -0
  321. package/src/core/marks/funnel-layout.ts +113 -0
  322. package/src/core/marks/funnel.ts +172 -0
  323. package/src/core/marks/line.ts +206 -0
  324. package/src/core/marks/polar.ts +568 -0
  325. package/src/core/marks/rect.ts +156 -0
  326. package/src/core/marks/rule.ts +104 -0
  327. package/src/core/marks/shared.ts +134 -0
  328. package/src/core/marks/stack.ts +42 -0
  329. package/src/core/marks/stats/difference.ts +205 -0
  330. package/src/core/marks/stats/distribution.ts +425 -0
  331. package/src/core/marks/stats/dodge.ts +136 -0
  332. package/src/core/marks/stats/hexbin.ts +152 -0
  333. package/src/core/marks/stats/histogram.ts +108 -0
  334. package/src/core/marks/stats/regression.ts +108 -0
  335. package/src/core/marks/stats/statistics.ts +153 -0
  336. package/src/core/marks/stats/waffle.ts +141 -0
  337. package/src/core/marks/text.ts +97 -0
  338. package/src/core/motion/tween.ts +131 -0
  339. package/src/core/nearest.ts +223 -0
  340. package/src/core/paths.ts +323 -0
  341. package/src/core/scales/color.ts +51 -0
  342. package/src/core/scales/continuous.ts +111 -0
  343. package/src/core/scales/discrete.ts +156 -0
  344. package/src/core/scales/resolve.ts +158 -0
  345. package/src/core/scales/time.ts +180 -0
  346. package/src/core/text.ts +42 -0
  347. package/src/core/theme.ts +26 -0
  348. package/src/core/ticks.ts +118 -0
  349. package/src/core/types.ts +358 -0
  350. package/src/force/force.ts +200 -0
  351. package/src/force/index.ts +6 -0
  352. package/src/geo/geo.ts +346 -0
  353. package/src/geo/index.ts +10 -0
  354. package/src/hierarchy/hierarchy.ts +377 -0
  355. package/src/hierarchy/index.ts +6 -0
  356. package/src/index.ts +70 -0
  357. package/src/react/brush-contract.ts +35 -0
  358. package/src/react/chart-data-table.tsx +98 -0
  359. package/src/react/chart-legend.tsx +130 -0
  360. package/src/react/chart-tooltip.tsx +111 -0
  361. package/src/react/chart.tsx +489 -0
  362. package/src/react/focus-overlay.tsx +164 -0
  363. package/src/react/index.ts +9 -0
  364. package/src/react/messages.ts +49 -0
  365. package/src/react/renderer.ts +15 -0
  366. package/src/react/sr-only.ts +14 -0
  367. package/src/react/svg-renderer.tsx +18 -0
  368. package/src/react/svg-scene.tsx +146 -0
  369. package/src/react/use-animated-scene.ts +57 -0
  370. package/src/react/use-chart-focus.ts +245 -0
  371. package/src/react/use-chart-width.ts +27 -0
  372. package/src/react/use-chart-zoom.ts +67 -0
  373. package/src/react/use-text-measurer.ts +49 -0
  374. package/src/sankey/index.ts +6 -0
  375. package/src/sankey/sankey.ts +179 -0
  376. package/src/voronoi/index.ts +1 -0
  377. package/src/voronoi/voronoi.ts +84 -0
@@ -0,0 +1,192 @@
1
+ const PATH_PRECISION = 2;
2
+ const MONOTONE_SLOPE_LIMIT = 9;
3
+ function round(value) {
4
+ const factor = 10 ** PATH_PRECISION;
5
+ return Math.round(value * factor) / factor;
6
+ }
7
+ function point(x, y) {
8
+ return `${round(x)},${round(y)}`;
9
+ }
10
+ function monotoneTangents(points) {
11
+ const count = points.length;
12
+ const secants = [];
13
+ for (let index = 0; index < count - 1; index += 1) {
14
+ const run = points[index + 1].x - points[index].x;
15
+ secants.push(run === 0 ? 0 : (points[index + 1].y - points[index].y) / run);
16
+ }
17
+ const tangents = [secants[0] ?? 0];
18
+ for (let index = 1; index < count - 1; index += 1) {
19
+ tangents.push((secants[index - 1] + secants[index]) / 2);
20
+ }
21
+ tangents.push(secants[count - 2] ?? 0);
22
+ for (let index = 0; index < secants.length; index += 1) {
23
+ const secant = secants[index];
24
+ if (secant === 0) {
25
+ tangents[index] = 0;
26
+ tangents[index + 1] = 0;
27
+ continue;
28
+ }
29
+ const before = tangents[index] / secant;
30
+ const after = tangents[index + 1] / secant;
31
+ const magnitude = before * before + after * after;
32
+ if (magnitude > MONOTONE_SLOPE_LIMIT) {
33
+ const scale = 3 / Math.sqrt(magnitude);
34
+ tangents[index] = scale * before * secant;
35
+ tangents[index + 1] = scale * after * secant;
36
+ }
37
+ }
38
+ return tangents;
39
+ }
40
+ function monotoneSegments(points) {
41
+ const tangents = monotoneTangents(points);
42
+ const segments = [];
43
+ for (let index = 0; index < points.length - 1; index += 1) {
44
+ const from = points[index];
45
+ const to = points[index + 1];
46
+ const third = (to.x - from.x) / 3;
47
+ segments.push(
48
+ `C${point(from.x + third, from.y + tangents[index] * third)} ${point(
49
+ to.x - third,
50
+ to.y - tangents[index + 1] * third
51
+ )} ${point(to.x, to.y)}`
52
+ );
53
+ }
54
+ return segments.join("");
55
+ }
56
+ function stepSegments(points) {
57
+ const segments = [];
58
+ for (let index = 0; index < points.length - 1; index += 1) {
59
+ const from = points[index];
60
+ const to = points[index + 1];
61
+ const middle = (from.x + to.x) / 2;
62
+ segments.push(
63
+ `L${point(middle, from.y)}L${point(middle, to.y)}L${point(to.x, to.y)}`
64
+ );
65
+ }
66
+ return segments.join("");
67
+ }
68
+ function linearSegments(points) {
69
+ return points.slice(1).map((current) => `L${point(current.x, current.y)}`).join("");
70
+ }
71
+ const segmentBuilders = {
72
+ linear: linearSegments,
73
+ monotone: monotoneSegments,
74
+ step: stepSegments
75
+ };
76
+ function linePath(points, curve = "linear") {
77
+ if (points.length < 2) {
78
+ return "";
79
+ }
80
+ return `M${point(points[0].x, points[0].y)}${segmentBuilders[curve](points)}`;
81
+ }
82
+ function areaPath(top, bottom, curve = "linear") {
83
+ const upper = linePath(top, curve);
84
+ if (upper === "" || bottom.length === 0) {
85
+ return "";
86
+ }
87
+ const lower = [...bottom].reverse();
88
+ return `${upper}L${point(lower[0].x, lower[0].y)}${segmentBuilders[curve](lower)}Z`;
89
+ }
90
+ function polygonPath(points) {
91
+ if (points.length === 0) {
92
+ return "";
93
+ }
94
+ const [head, ...rest] = points;
95
+ const tail = rest.map((current) => `L${point(current.x, current.y)}`).join("");
96
+ return `M${point(head.x, head.y)}${tail}Z`;
97
+ }
98
+ function cornerRadii(radius, width, height) {
99
+ const raw = typeof radius === "number" ? [radius, radius, radius, radius] : radius;
100
+ const limit = Math.min(Math.abs(width), Math.abs(height)) / 2;
101
+ return [
102
+ Math.max(0, Math.min(raw[0], limit)),
103
+ Math.max(0, Math.min(raw[1], limit)),
104
+ Math.max(0, Math.min(raw[2], limit)),
105
+ Math.max(0, Math.min(raw[3], limit))
106
+ ];
107
+ }
108
+ function roundedBarPath(options) {
109
+ const { x, y, width, height, radius = 0 } = options;
110
+ if (width <= 0 || height <= 0) {
111
+ return "";
112
+ }
113
+ const [topLeft, topRight, bottomRight, bottomLeft] = cornerRadii(
114
+ radius,
115
+ width,
116
+ height
117
+ );
118
+ const right = x + width;
119
+ const bottom = y + height;
120
+ return [
121
+ `M${point(x + topLeft, y)}`,
122
+ `H${round(right - topRight)}`,
123
+ topRight > 0 ? `A${round(topRight)},${round(topRight)} 0 0 1 ${point(right, y + topRight)}` : "",
124
+ `V${round(bottom - bottomRight)}`,
125
+ bottomRight > 0 ? `A${round(bottomRight)},${round(bottomRight)} 0 0 1 ${point(right - bottomRight, bottom)}` : "",
126
+ `H${round(x + bottomLeft)}`,
127
+ bottomLeft > 0 ? `A${round(bottomLeft)},${round(bottomLeft)} 0 0 1 ${point(x, bottom - bottomLeft)}` : "",
128
+ `V${round(y + topLeft)}`,
129
+ topLeft > 0 ? `A${round(topLeft)},${round(topLeft)} 0 0 1 ${point(x + topLeft, y)}` : "",
130
+ "Z"
131
+ ].join("");
132
+ }
133
+ const DEGREES_TO_RADIANS = Math.PI / 180;
134
+ function polarToCartesian(cx, cy, radius, angle) {
135
+ const radians = angle * DEGREES_TO_RADIANS;
136
+ return {
137
+ x: cx + radius * Math.sin(radians),
138
+ y: cy - radius * Math.cos(radians)
139
+ };
140
+ }
141
+ function arcPath(options) {
142
+ const { cx, cy, innerRadius, outerRadius, startAngle, endAngle } = options;
143
+ const sweep = endAngle - startAngle;
144
+ if (sweep <= 0 || outerRadius <= 0) {
145
+ return "";
146
+ }
147
+ if (sweep >= 360) {
148
+ const half = startAngle + 180;
149
+ return `${arcPath({ ...options, endAngle: half })}${arcPath({
150
+ ...options,
151
+ startAngle: half,
152
+ endAngle: startAngle + 359.99
153
+ })}`;
154
+ }
155
+ const largeArc = sweep > 180 ? 1 : 0;
156
+ const outerStart = polarToCartesian(cx, cy, outerRadius, startAngle);
157
+ const outerEnd = polarToCartesian(cx, cy, outerRadius, endAngle);
158
+ if (innerRadius <= 0) {
159
+ return [
160
+ `M${point(cx, cy)}`,
161
+ `L${point(outerStart.x, outerStart.y)}`,
162
+ `A${round(outerRadius)},${round(outerRadius)} 0 ${largeArc} 1 ${point(outerEnd.x, outerEnd.y)}`,
163
+ "Z"
164
+ ].join("");
165
+ }
166
+ const innerEnd = polarToCartesian(cx, cy, innerRadius, endAngle);
167
+ const innerStart = polarToCartesian(cx, cy, innerRadius, startAngle);
168
+ return [
169
+ `M${point(outerStart.x, outerStart.y)}`,
170
+ `A${round(outerRadius)},${round(outerRadius)} 0 ${largeArc} 1 ${point(outerEnd.x, outerEnd.y)}`,
171
+ `L${point(innerEnd.x, innerEnd.y)}`,
172
+ `A${round(innerRadius)},${round(innerRadius)} 0 ${largeArc} 0 ${point(innerStart.x, innerStart.y)}`,
173
+ "Z"
174
+ ].join("");
175
+ }
176
+ function multiPolygonPath(polygons, offsetX = 0, offsetY = 0) {
177
+ return polygons.flatMap(
178
+ (rings) => rings.map(
179
+ (ring) => ring.length === 0 ? "" : `M${ring.map(([x, y]) => point(x + offsetX, y + offsetY)).join("L")}Z`
180
+ )
181
+ ).join("");
182
+ }
183
+ export {
184
+ arcPath,
185
+ areaPath,
186
+ linePath,
187
+ multiPolygonPath,
188
+ polarToCartesian,
189
+ polygonPath,
190
+ roundedBarPath
191
+ };
192
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/core/paths.ts"],
4
+ "sourcesContent": ["import type { ChartCorners, ChartCurve } from \"#/core/types.ts\";\n\n/** A point in chart pixels. */\nexport interface ChartXY {\n\treadonly x: number;\n\treadonly y: number;\n}\n\n/**\n * Path builders. Everything is SVG path data, which both renderers read: SVG\n * sets it as `d`, Canvas hands it to `Path2D`. Everything It is rounded to `PATH_PRECISION` decimals so the\n * emitted `d` attributes stay short, stable across runs and pleasant to assert\n * on in tests.\n */\n\nconst PATH_PRECISION = 2;\n/** Fritsch-Carlson clamps the tangent when the slope ratio exceeds this. */\nconst MONOTONE_SLOPE_LIMIT = 9;\n\nfunction round(value: number): number {\n\tconst factor = 10 ** PATH_PRECISION;\n\treturn Math.round(value * factor) / factor;\n}\n\nfunction point(x: number, y: number): string {\n\treturn `${round(x)},${round(y)}`;\n}\n\n/**\n * Per-point tangents for a monotone cubic spline (Fritsch-Carlson): the curve\n * bends through the data without the overshoot a plain cubic gives you, so a\n * series that never goes negative never dips below the axis.\n */\nfunction monotoneTangents(points: ReadonlyArray<ChartXY>): number[] {\n\tconst count = points.length;\n\tconst secants: number[] = [];\n\tfor (let index = 0; index < count - 1; index += 1) {\n\t\tconst run = points[index + 1].x - points[index].x;\n\t\tsecants.push(run === 0 ? 0 : (points[index + 1].y - points[index].y) / run);\n\t}\n\n\tconst tangents: number[] = [secants[0] ?? 0];\n\tfor (let index = 1; index < count - 1; index += 1) {\n\t\ttangents.push((secants[index - 1] + secants[index]) / 2);\n\t}\n\ttangents.push(secants[count - 2] ?? 0);\n\n\tfor (let index = 0; index < secants.length; index += 1) {\n\t\tconst secant = secants[index];\n\t\tif (secant === 0) {\n\t\t\ttangents[index] = 0;\n\t\t\ttangents[index + 1] = 0;\n\t\t\tcontinue;\n\t\t}\n\t\tconst before = tangents[index] / secant;\n\t\tconst after = tangents[index + 1] / secant;\n\t\tconst magnitude = before * before + after * after;\n\t\tif (magnitude > MONOTONE_SLOPE_LIMIT) {\n\t\t\tconst scale = 3 / Math.sqrt(magnitude);\n\t\t\ttangents[index] = scale * before * secant;\n\t\t\ttangents[index + 1] = scale * after * secant;\n\t\t}\n\t}\n\treturn tangents;\n}\n\nfunction monotoneSegments(points: ReadonlyArray<ChartXY>): string {\n\tconst tangents = monotoneTangents(points);\n\tconst segments: string[] = [];\n\tfor (let index = 0; index < points.length - 1; index += 1) {\n\t\tconst from = points[index];\n\t\tconst to = points[index + 1];\n\t\tconst third = (to.x - from.x) / 3;\n\t\tsegments.push(\n\t\t\t`C${point(from.x + third, from.y + tangents[index] * third)} ${point(\n\t\t\t\tto.x - third,\n\t\t\t\tto.y - tangents[index + 1] * third,\n\t\t\t)} ${point(to.x, to.y)}`,\n\t\t);\n\t}\n\treturn segments.join(\"\");\n}\n\n/** Midpoint step: hold the value, jump halfway between the two categories. */\nfunction stepSegments(points: ReadonlyArray<ChartXY>): string {\n\tconst segments: string[] = [];\n\tfor (let index = 0; index < points.length - 1; index += 1) {\n\t\tconst from = points[index];\n\t\tconst to = points[index + 1];\n\t\tconst middle = (from.x + to.x) / 2;\n\t\tsegments.push(\n\t\t\t`L${point(middle, from.y)}L${point(middle, to.y)}L${point(to.x, to.y)}`,\n\t\t);\n\t}\n\treturn segments.join(\"\");\n}\n\nfunction linearSegments(points: ReadonlyArray<ChartXY>): string {\n\treturn points\n\t\t.slice(1)\n\t\t.map((current) => `L${point(current.x, current.y)}`)\n\t\t.join(\"\");\n}\n\nconst segmentBuilders: Record<\n\tChartCurve,\n\t(points: ReadonlyArray<ChartXY>) => string\n> = {\n\tlinear: linearSegments,\n\tmonotone: monotoneSegments,\n\tstep: stepSegments,\n};\n\n/**\n * An open path through `points`. Returns `\"\"` for fewer than two points, which\n * renders as nothing rather than as a stray dot.\n */\nexport function linePath(\n\tpoints: ReadonlyArray<ChartXY>,\n\tcurve: ChartCurve = \"linear\",\n): string {\n\tif (points.length < 2) {\n\t\treturn \"\";\n\t}\n\treturn `M${point(points[0].x, points[0].y)}${segmentBuilders[curve](points)}`;\n}\n\n/**\n * A closed band between a top edge and a bottom edge, both drawn with the same\n * curve, so an area and its outline never disagree. The bottom edge runs under\n * the same x positions as the top: a flat baseline, or the series below it in\n * a stack.\n */\nexport function areaPath(\n\ttop: ReadonlyArray<ChartXY>,\n\tbottom: ReadonlyArray<ChartXY>,\n\tcurve: ChartCurve = \"linear\",\n): string {\n\tconst upper = linePath(top, curve);\n\tif (upper === \"\" || bottom.length === 0) {\n\t\treturn \"\";\n\t}\n\tconst lower = [...bottom].reverse();\n\treturn `${upper}L${point(lower[0].x, lower[0].y)}${segmentBuilders[curve](lower)}Z`;\n}\n\n/** A closed polygon \u2014 the radar mark's outline. */\nexport function polygonPath(points: ReadonlyArray<ChartXY>): string {\n\tif (points.length === 0) {\n\t\treturn \"\";\n\t}\n\tconst [head, ...rest] = points;\n\tconst tail = rest\n\t\t.map((current) => `L${point(current.x, current.y)}`)\n\t\t.join(\"\");\n\treturn `M${point(head.x, head.y)}${tail}Z`;\n}\n\nfunction cornerRadii(\n\tradius: number | ChartCorners,\n\twidth: number,\n\theight: number,\n): readonly [number, number, number, number] {\n\tconst raw: readonly [number, number, number, number] =\n\t\ttypeof radius === \"number\" ? [radius, radius, radius, radius] : radius;\n\tconst limit = Math.min(Math.abs(width), Math.abs(height)) / 2;\n\treturn [\n\t\tMath.max(0, Math.min(raw[0], limit)),\n\t\tMath.max(0, Math.min(raw[1], limit)),\n\t\tMath.max(0, Math.min(raw[2], limit)),\n\t\tMath.max(0, Math.min(raw[3], limit)),\n\t];\n}\n\nexport interface RoundedBarOptions {\n\treadonly x: number;\n\treadonly y: number;\n\treadonly width: number;\n\treadonly height: number;\n\t/** One radius, or `[topLeft, topRight, bottomRight, bottomLeft]`. */\n\treadonly radius?: number | ChartCorners;\n}\n\n/**\n * A rectangle with independently rounded corners \u2014 stacked bars round only the\n * outer end of the stack, so the inner joins stay square.\n */\nexport function roundedBarPath(options: RoundedBarOptions): string {\n\tconst { x, y, width, height, radius = 0 } = options;\n\tif (width <= 0 || height <= 0) {\n\t\treturn \"\";\n\t}\n\tconst [topLeft, topRight, bottomRight, bottomLeft] = cornerRadii(\n\t\tradius,\n\t\twidth,\n\t\theight,\n\t);\n\tconst right = x + width;\n\tconst bottom = y + height;\n\treturn [\n\t\t`M${point(x + topLeft, y)}`,\n\t\t`H${round(right - topRight)}`,\n\t\ttopRight > 0\n\t\t\t? `A${round(topRight)},${round(topRight)} 0 0 1 ${point(right, y + topRight)}`\n\t\t\t: \"\",\n\t\t`V${round(bottom - bottomRight)}`,\n\t\tbottomRight > 0\n\t\t\t? `A${round(bottomRight)},${round(bottomRight)} 0 0 1 ${point(right - bottomRight, bottom)}`\n\t\t\t: \"\",\n\t\t`H${round(x + bottomLeft)}`,\n\t\tbottomLeft > 0\n\t\t\t? `A${round(bottomLeft)},${round(bottomLeft)} 0 0 1 ${point(x, bottom - bottomLeft)}`\n\t\t\t: \"\",\n\t\t`V${round(y + topLeft)}`,\n\t\ttopLeft > 0\n\t\t\t? `A${round(topLeft)},${round(topLeft)} 0 0 1 ${point(x + topLeft, y)}`\n\t\t\t: \"\",\n\t\t\"Z\",\n\t].join(\"\");\n}\n\nconst DEGREES_TO_RADIANS = Math.PI / 180;\n\n/**\n * Angles are degrees, clockwise, zero at twelve o'clock: the way a pie chart\n * is described out loud.\n */\nexport function polarToCartesian(\n\tcx: number,\n\tcy: number,\n\tradius: number,\n\tangle: number,\n): ChartXY {\n\tconst radians = angle * DEGREES_TO_RADIANS;\n\treturn {\n\t\tx: cx + radius * Math.sin(radians),\n\t\ty: cy - radius * Math.cos(radians),\n\t};\n}\n\nexport interface ArcOptions {\n\t/** Centre of the circle the arc is cut from, in plot coordinates. */\n\treadonly cx: number;\n\t/** Centre of the circle the arc is cut from, in plot coordinates. */\n\treadonly cy: number;\n\t/** Inner edge. `0` makes the arc a pie wedge rather than a donut segment. */\n\treadonly innerRadius: number;\n\t/** Outer edge, in pixels from the centre. */\n\treadonly outerRadius: number;\n\t/** Degrees clockwise from twelve o'clock. */\n\treadonly startAngle: number;\n\t/** Degrees clockwise from twelve o'clock. A 360-degree sweep draws a full ring. */\n\treadonly endAngle: number;\n}\n\n/**\n * A pie wedge (`innerRadius` 0) or a donut segment. A sweep of 360 degrees or\n * more is drawn as two half arcs, because a single arc back to its own start\n * point renders as nothing at all.\n */\nexport function arcPath(options: ArcOptions): string {\n\tconst { cx, cy, innerRadius, outerRadius, startAngle, endAngle } = options;\n\tconst sweep = endAngle - startAngle;\n\tif (sweep <= 0 || outerRadius <= 0) {\n\t\treturn \"\";\n\t}\n\tif (sweep >= 360) {\n\t\tconst half = startAngle + 180;\n\t\treturn `${arcPath({ ...options, endAngle: half })}${arcPath({\n\t\t\t...options,\n\t\t\tstartAngle: half,\n\t\t\tendAngle: startAngle + 359.99,\n\t\t})}`;\n\t}\n\n\tconst largeArc = sweep > 180 ? 1 : 0;\n\tconst outerStart = polarToCartesian(cx, cy, outerRadius, startAngle);\n\tconst outerEnd = polarToCartesian(cx, cy, outerRadius, endAngle);\n\n\tif (innerRadius <= 0) {\n\t\treturn [\n\t\t\t`M${point(cx, cy)}`,\n\t\t\t`L${point(outerStart.x, outerStart.y)}`,\n\t\t\t`A${round(outerRadius)},${round(outerRadius)} 0 ${largeArc} 1 ${point(outerEnd.x, outerEnd.y)}`,\n\t\t\t\"Z\",\n\t\t].join(\"\");\n\t}\n\n\tconst innerEnd = polarToCartesian(cx, cy, innerRadius, endAngle);\n\tconst innerStart = polarToCartesian(cx, cy, innerRadius, startAngle);\n\treturn [\n\t\t`M${point(outerStart.x, outerStart.y)}`,\n\t\t`A${round(outerRadius)},${round(outerRadius)} 0 ${largeArc} 1 ${point(outerEnd.x, outerEnd.y)}`,\n\t\t`L${point(innerEnd.x, innerEnd.y)}`,\n\t\t`A${round(innerRadius)},${round(innerRadius)} 0 ${largeArc} 0 ${point(innerStart.x, innerStart.y)}`,\n\t\t\"Z\",\n\t].join(\"\");\n}\n\n/**\n * Path data for GeoJSON polygon rings already in chart pixels (what\n * d3-contour returns): every ring closed, holes drawn with the even-odd rule\n * the renderers default to.\n */\nexport function multiPolygonPath(\n\tpolygons: ReadonlyArray<\n\t\tReadonlyArray<\n\t\t\tReadonlyArray<readonly [number, number] | ReadonlyArray<number>>\n\t\t>\n\t>,\n\toffsetX = 0,\n\toffsetY = 0,\n): string {\n\treturn polygons\n\t\t.flatMap((rings) =>\n\t\t\trings.map((ring) =>\n\t\t\t\tring.length === 0\n\t\t\t\t\t? \"\"\n\t\t\t\t\t: `M${ring.map(([x, y]) => point(x + offsetX, y + offsetY)).join(\"L\")}Z`,\n\t\t\t),\n\t\t)\n\t\t.join(\"\");\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,11 @@
1
+ import type { ChartColorScale, ChartValue } from "../types.js";
2
+ /**
3
+ * Colours stay CSS strings all the way to the renderer (`var(--chart-2)`,
4
+ * `color-mix(…)`): SVG resolves them itself, and the Canvas renderer resolves
5
+ * them against the page, so a theme switch needs no recompute.
6
+ */
7
+ /** One palette colour per category, cycling when there are more categories than colours. */
8
+ export declare function ordinalColorScale(domain: ReadonlyArray<ChartValue>, palette: ReadonlyArray<string>): ChartColorScale;
9
+ /** A ramp between two colours, mixed by the browser in OKLab so the steps look even. */
10
+ export declare function sequentialColorScale(domain: readonly [number, number], [from, to]: readonly [string, string]): ChartColorScale;
11
+ //# sourceMappingURL=color.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../../src/core/scales/color.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEnE;;;;GAIG;AAEH,4FAA4F;AAC5F,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,EACjC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAC5B,eAAe,CAcjB;AAID,wFAAwF;AACxF,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,EACjC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,eAAe,CAcjB"}
@@ -0,0 +1,35 @@
1
+ import { toNumber } from "./continuous.js";
2
+ import { categoryKey } from "./discrete.js";
3
+ function ordinalColorScale(domain, palette) {
4
+ const indexByKey = /* @__PURE__ */ new Map();
5
+ for (const value of domain) {
6
+ const key = categoryKey(value);
7
+ if (!indexByKey.has(key)) {
8
+ indexByKey.set(key, indexByKey.size);
9
+ }
10
+ }
11
+ return {
12
+ kind: "ordinal",
13
+ domain,
14
+ map: (value) => palette[(indexByKey.get(categoryKey(value)) ?? 0) % palette.length]
15
+ };
16
+ }
17
+ const PERCENT_PRECISION = 10;
18
+ function sequentialColorScale(domain, [from, to]) {
19
+ const [low, high] = domain;
20
+ const span = high - low;
21
+ return {
22
+ kind: "sequential",
23
+ domain,
24
+ map: (value) => {
25
+ const share = span === 0 ? 1 : (toNumber(value) - low) / span;
26
+ const percent = Math.round(Math.min(1, Math.max(0, share)) * 100 * PERCENT_PRECISION) / PERCENT_PRECISION;
27
+ return `color-mix(in oklab, ${to} ${percent}%, ${from})`;
28
+ }
29
+ };
30
+ }
31
+ export {
32
+ ordinalColorScale,
33
+ sequentialColorScale
34
+ };
35
+ //# sourceMappingURL=color.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/core/scales/color.ts"],
4
+ "sourcesContent": ["import { toNumber } from \"#/core/scales/continuous.ts\";\nimport { categoryKey } from \"#/core/scales/discrete.ts\";\nimport type { ChartColorScale, ChartValue } from \"#/core/types.ts\";\n\n/**\n * Colours stay CSS strings all the way to the renderer (`var(--chart-2)`,\n * `color-mix(\u2026)`): SVG resolves them itself, and the Canvas renderer resolves\n * them against the page, so a theme switch needs no recompute.\n */\n\n/** One palette colour per category, cycling when there are more categories than colours. */\nexport function ordinalColorScale(\n\tdomain: ReadonlyArray<ChartValue>,\n\tpalette: ReadonlyArray<string>,\n): ChartColorScale {\n\tconst indexByKey = new Map<string, number>();\n\tfor (const value of domain) {\n\t\tconst key = categoryKey(value);\n\t\tif (!indexByKey.has(key)) {\n\t\t\tindexByKey.set(key, indexByKey.size);\n\t\t}\n\t}\n\treturn {\n\t\tkind: \"ordinal\",\n\t\tdomain,\n\t\tmap: (value) =>\n\t\t\tpalette[(indexByKey.get(categoryKey(value)) ?? 0) % palette.length],\n\t};\n}\n\nconst PERCENT_PRECISION = 10;\n\n/** A ramp between two colours, mixed by the browser in OKLab so the steps look even. */\nexport function sequentialColorScale(\n\tdomain: readonly [number, number],\n\t[from, to]: readonly [string, string],\n): ChartColorScale {\n\tconst [low, high] = domain;\n\tconst span = high - low;\n\treturn {\n\t\tkind: \"sequential\",\n\t\tdomain,\n\t\tmap: (value) => {\n\t\t\tconst share = span === 0 ? 1 : (toNumber(value) - low) / span;\n\t\t\tconst percent =\n\t\t\t\tMath.round(Math.min(1, Math.max(0, share)) * 100 * PERCENT_PRECISION) /\n\t\t\t\tPERCENT_PRECISION;\n\t\t\treturn `color-mix(in oklab, ${to} ${percent}%, ${from})`;\n\t\t},\n\t};\n}\n"],
5
+ "mappings": "AAAA,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAUrB,SAAS,kBACf,QACA,SACkB;AAClB,QAAM,aAAa,oBAAI,IAAoB;AAC3C,aAAW,SAAS,QAAQ;AAC3B,UAAM,MAAM,YAAY,KAAK;AAC7B,QAAI,CAAC,WAAW,IAAI,GAAG,GAAG;AACzB,iBAAW,IAAI,KAAK,WAAW,IAAI;AAAA,IACpC;AAAA,EACD;AACA,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA,KAAK,CAAC,UACL,SAAS,WAAW,IAAI,YAAY,KAAK,CAAC,KAAK,KAAK,QAAQ,MAAM;AAAA,EACpE;AACD;AAEA,MAAM,oBAAoB;AAGnB,SAAS,qBACf,QACA,CAAC,MAAM,EAAE,GACS;AAClB,QAAM,CAAC,KAAK,IAAI,IAAI;AACpB,QAAM,OAAO,OAAO;AACpB,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA,KAAK,CAAC,UAAU;AACf,YAAM,QAAQ,SAAS,IAAI,KAAK,SAAS,KAAK,IAAI,OAAO;AACzD,YAAM,UACL,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC,IAAI,MAAM,iBAAiB,IACpE;AACD,aAAO,uBAAuB,EAAE,IAAI,OAAO,MAAM,IAAI;AAAA,IACtD;AAAA,EACD;AACD;",
6
+ "names": []
7
+ }
@@ -0,0 +1,18 @@
1
+ import type { ChartPositionScale, ChartValue } from "../types.js";
2
+ export interface ContinuousScaleOptions {
3
+ readonly domain: readonly [number, number];
4
+ readonly range: readonly [number, number];
5
+ readonly locale: string;
6
+ /** How many ticks the axis has room for. */
7
+ readonly tickCount: number;
8
+ }
9
+ export declare function toNumber(value: ChartValue): number;
10
+ /** Numbers in, pixels out, linearly. */
11
+ export declare function linearScale(options: ContinuousScaleOptions): ChartPositionScale;
12
+ /**
13
+ * Orders of magnitude, for data that spans several of them. Values at or
14
+ * below zero have no logarithm: they are clamped onto the bottom of the scale
15
+ * rather than drawn at minus infinity.
16
+ */
17
+ export declare function logScale(options: ContinuousScaleOptions): ChartPositionScale;
18
+ //# sourceMappingURL=continuous.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"continuous.d.ts","sourceRoot":"","sources":["../../../src/core/scales/continuous.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEtE,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAKlD;AAsBD,wCAAwC;AACxC,wBAAgB,WAAW,CAC1B,OAAO,EAAE,sBAAsB,GAC7B,kBAAkB,CAoBpB;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,kBAAkB,CAyC5E"}
@@ -0,0 +1,82 @@
1
+ import { formatCompactNumber, formatTickValue } from "../format.js";
2
+ import { niceTicks } from "../ticks.js";
3
+ function toNumber(value) {
4
+ if (value instanceof Date) {
5
+ return value.getTime();
6
+ }
7
+ return typeof value === "number" ? value : Number(value);
8
+ }
9
+ function interpolator([domainStart, domainEnd], [rangeStart, rangeEnd]) {
10
+ const domainSpan = domainEnd - domainStart;
11
+ const rangeSpan = rangeEnd - rangeStart;
12
+ return {
13
+ // A zero-width domain collapses to the middle of the range: a flat series
14
+ // draws a centred line instead of dividing by zero.
15
+ forward: (value) => domainSpan === 0 ? rangeStart + rangeSpan / 2 : rangeStart + (value - domainStart) / domainSpan * rangeSpan,
16
+ backward: (pixel) => rangeSpan === 0 ? domainStart : domainStart + (pixel - rangeStart) / rangeSpan * domainSpan
17
+ };
18
+ }
19
+ function linearScale(options) {
20
+ const { domain, range, locale, tickCount } = options;
21
+ const { forward, backward } = interpolator(domain, range);
22
+ const map = (value) => forward(toNumber(value));
23
+ return {
24
+ kind: "linear",
25
+ domain,
26
+ range,
27
+ bandwidth: 0,
28
+ map,
29
+ center: map,
30
+ invert: backward,
31
+ ticks: (count = tickCount) => niceTicks(
32
+ Math.min(domain[0], domain[1]),
33
+ Math.max(domain[0], domain[1]),
34
+ count
35
+ ),
36
+ format: (value) => formatTickValue(toNumber(value), locale)
37
+ };
38
+ }
39
+ function logScale(options) {
40
+ const { range, locale, tickCount } = options;
41
+ const low = Math.max(Number.MIN_VALUE, Math.min(...options.domain));
42
+ const high = Math.max(low, ...options.domain);
43
+ const logDomain = [
44
+ Math.log10(low),
45
+ Math.log10(high)
46
+ ];
47
+ const { forward, backward } = interpolator(logDomain, range);
48
+ const map = (value) => forward(Math.log10(Math.max(low, toNumber(value))));
49
+ function ticks(count = tickCount) {
50
+ const first = Math.floor(logDomain[0]);
51
+ const last = Math.ceil(logDomain[1]);
52
+ const decades = last - first;
53
+ const multiples = decades * 3 <= count ? [1, 2, 5] : [1];
54
+ const values = [];
55
+ for (let power = first; power <= last; power += 1) {
56
+ for (const multiple of multiples) {
57
+ const value = multiple * 10 ** power;
58
+ if (value >= low && value <= high) {
59
+ values.push(value);
60
+ }
61
+ }
62
+ }
63
+ return values;
64
+ }
65
+ return {
66
+ kind: "log",
67
+ domain: [low, high],
68
+ range,
69
+ bandwidth: 0,
70
+ map,
71
+ center: map,
72
+ invert: (pixel) => 10 ** backward(pixel),
73
+ ticks,
74
+ format: (value) => formatCompactNumber(toNumber(value), locale)
75
+ };
76
+ }
77
+ export {
78
+ linearScale,
79
+ logScale,
80
+ toNumber
81
+ };
82
+ //# sourceMappingURL=continuous.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/core/scales/continuous.ts"],
4
+ "sourcesContent": ["import { formatCompactNumber, formatTickValue } from \"#/core/format.ts\";\nimport { niceTicks } from \"#/core/ticks.ts\";\nimport type { ChartPositionScale, ChartValue } from \"#/core/types.ts\";\n\nexport interface ContinuousScaleOptions {\n\treadonly domain: readonly [number, number];\n\treadonly range: readonly [number, number];\n\treadonly locale: string;\n\t/** How many ticks the axis has room for. */\n\treadonly tickCount: number;\n}\n\nexport function toNumber(value: ChartValue): number {\n\tif (value instanceof Date) {\n\t\treturn value.getTime();\n\t}\n\treturn typeof value === \"number\" ? value : Number(value);\n}\n\nfunction interpolator(\n\t[domainStart, domainEnd]: readonly [number, number],\n\t[rangeStart, rangeEnd]: readonly [number, number],\n) {\n\tconst domainSpan = domainEnd - domainStart;\n\tconst rangeSpan = rangeEnd - rangeStart;\n\treturn {\n\t\t// A zero-width domain collapses to the middle of the range: a flat series\n\t\t// draws a centred line instead of dividing by zero.\n\t\tforward: (value: number) =>\n\t\t\tdomainSpan === 0\n\t\t\t\t? rangeStart + rangeSpan / 2\n\t\t\t\t: rangeStart + ((value - domainStart) / domainSpan) * rangeSpan,\n\t\tbackward: (pixel: number) =>\n\t\t\trangeSpan === 0\n\t\t\t\t? domainStart\n\t\t\t\t: domainStart + ((pixel - rangeStart) / rangeSpan) * domainSpan,\n\t};\n}\n\n/** Numbers in, pixels out, linearly. */\nexport function linearScale(\n\toptions: ContinuousScaleOptions,\n): ChartPositionScale {\n\tconst { domain, range, locale, tickCount } = options;\n\tconst { forward, backward } = interpolator(domain, range);\n\tconst map = (value: ChartValue) => forward(toNumber(value));\n\treturn {\n\t\tkind: \"linear\",\n\t\tdomain,\n\t\trange,\n\t\tbandwidth: 0,\n\t\tmap,\n\t\tcenter: map,\n\t\tinvert: backward,\n\t\tticks: (count = tickCount) =>\n\t\t\tniceTicks(\n\t\t\t\tMath.min(domain[0], domain[1]),\n\t\t\t\tMath.max(domain[0], domain[1]),\n\t\t\t\tcount,\n\t\t\t),\n\t\tformat: (value) => formatTickValue(toNumber(value), locale),\n\t};\n}\n\n/**\n * Orders of magnitude, for data that spans several of them. Values at or\n * below zero have no logarithm: they are clamped onto the bottom of the scale\n * rather than drawn at minus infinity.\n */\nexport function logScale(options: ContinuousScaleOptions): ChartPositionScale {\n\tconst { range, locale, tickCount } = options;\n\tconst low = Math.max(Number.MIN_VALUE, Math.min(...options.domain));\n\tconst high = Math.max(low, ...options.domain);\n\tconst logDomain: readonly [number, number] = [\n\t\tMath.log10(low),\n\t\tMath.log10(high),\n\t];\n\tconst { forward, backward } = interpolator(logDomain, range);\n\tconst map = (value: ChartValue) =>\n\t\tforward(Math.log10(Math.max(low, toNumber(value))));\n\n\tfunction ticks(count = tickCount): ReadonlyArray<number> {\n\t\tconst first = Math.floor(logDomain[0]);\n\t\tconst last = Math.ceil(logDomain[1]);\n\t\tconst decades = last - first;\n\t\t// Few decades leave room for 2 and 5 between the powers of ten.\n\t\tconst multiples = decades * 3 <= count ? [1, 2, 5] : [1];\n\t\tconst values: number[] = [];\n\t\tfor (let power = first; power <= last; power += 1) {\n\t\t\tfor (const multiple of multiples) {\n\t\t\t\tconst value = multiple * 10 ** power;\n\t\t\t\tif (value >= low && value <= high) {\n\t\t\t\t\tvalues.push(value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn values;\n\t}\n\n\treturn {\n\t\tkind: \"log\",\n\t\tdomain: [low, high],\n\t\trange,\n\t\tbandwidth: 0,\n\t\tmap,\n\t\tcenter: map,\n\t\tinvert: (pixel) => 10 ** backward(pixel),\n\t\tticks,\n\t\tformat: (value) => formatCompactNumber(toNumber(value), locale),\n\t};\n}\n"],
5
+ "mappings": "AAAA,SAAS,qBAAqB,uBAAuB;AACrD,SAAS,iBAAiB;AAWnB,SAAS,SAAS,OAA2B;AACnD,MAAI,iBAAiB,MAAM;AAC1B,WAAO,MAAM,QAAQ;AAAA,EACtB;AACA,SAAO,OAAO,UAAU,WAAW,QAAQ,OAAO,KAAK;AACxD;AAEA,SAAS,aACR,CAAC,aAAa,SAAS,GACvB,CAAC,YAAY,QAAQ,GACpB;AACD,QAAM,aAAa,YAAY;AAC/B,QAAM,YAAY,WAAW;AAC7B,SAAO;AAAA;AAAA;AAAA,IAGN,SAAS,CAAC,UACT,eAAe,IACZ,aAAa,YAAY,IACzB,cAAe,QAAQ,eAAe,aAAc;AAAA,IACxD,UAAU,CAAC,UACV,cAAc,IACX,cACA,eAAgB,QAAQ,cAAc,YAAa;AAAA,EACxD;AACD;AAGO,SAAS,YACf,SACqB;AACrB,QAAM,EAAE,QAAQ,OAAO,QAAQ,UAAU,IAAI;AAC7C,QAAM,EAAE,SAAS,SAAS,IAAI,aAAa,QAAQ,KAAK;AACxD,QAAM,MAAM,CAAC,UAAsB,QAAQ,SAAS,KAAK,CAAC;AAC1D,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO,CAAC,QAAQ,cACf;AAAA,MACC,KAAK,IAAI,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AAAA,MAC7B,KAAK,IAAI,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AAAA,MAC7B;AAAA,IACD;AAAA,IACD,QAAQ,CAAC,UAAU,gBAAgB,SAAS,KAAK,GAAG,MAAM;AAAA,EAC3D;AACD;AAOO,SAAS,SAAS,SAAqD;AAC7E,QAAM,EAAE,OAAO,QAAQ,UAAU,IAAI;AACrC,QAAM,MAAM,KAAK,IAAI,OAAO,WAAW,KAAK,IAAI,GAAG,QAAQ,MAAM,CAAC;AAClE,QAAM,OAAO,KAAK,IAAI,KAAK,GAAG,QAAQ,MAAM;AAC5C,QAAM,YAAuC;AAAA,IAC5C,KAAK,MAAM,GAAG;AAAA,IACd,KAAK,MAAM,IAAI;AAAA,EAChB;AACA,QAAM,EAAE,SAAS,SAAS,IAAI,aAAa,WAAW,KAAK;AAC3D,QAAM,MAAM,CAAC,UACZ,QAAQ,KAAK,MAAM,KAAK,IAAI,KAAK,SAAS,KAAK,CAAC,CAAC,CAAC;AAEnD,WAAS,MAAM,QAAQ,WAAkC;AACxD,UAAM,QAAQ,KAAK,MAAM,UAAU,CAAC,CAAC;AACrC,UAAM,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC;AACnC,UAAM,UAAU,OAAO;AAEvB,UAAM,YAAY,UAAU,KAAK,QAAQ,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;AACvD,UAAM,SAAmB,CAAC;AAC1B,aAAS,QAAQ,OAAO,SAAS,MAAM,SAAS,GAAG;AAClD,iBAAW,YAAY,WAAW;AACjC,cAAM,QAAQ,WAAW,MAAM;AAC/B,YAAI,SAAS,OAAO,SAAS,MAAM;AAClC,iBAAO,KAAK,KAAK;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAEA,SAAO;AAAA,IACN,MAAM;AAAA,IACN,QAAQ,CAAC,KAAK,IAAI;AAAA,IAClB;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ,CAAC,UAAU,MAAM,SAAS,KAAK;AAAA,IACvC;AAAA,IACA,QAAQ,CAAC,UAAU,oBAAoB,SAAS,KAAK,GAAG,MAAM;AAAA,EAC/D;AACD;",
6
+ "names": []
7
+ }
@@ -0,0 +1,22 @@
1
+ import type { ChartPositionScale, ChartValue } from "../types.js";
2
+ /**
3
+ * Categories in, slots out. `band` gives each category a slot of `bandwidth`
4
+ * pixels (what bars sit on), `point` a position with no width (what lines sit
5
+ * on, first and last touching the plot edges).
6
+ */
7
+ export interface DiscreteScaleOptions {
8
+ readonly domain: ReadonlyArray<ChartValue>;
9
+ readonly range: readonly [number, number];
10
+ readonly locale: string;
11
+ /** Share of a step left empty between two bands. 0 = touching bars. */
12
+ readonly paddingInner?: number;
13
+ /** Share of a step left empty before the first and after the last slot. */
14
+ readonly paddingOuter?: number;
15
+ }
16
+ /** A category's identity: two equal dates are one category. */
17
+ export declare function categoryKey(value: ChartValue): string;
18
+ /** A category as a label. A year stays "2026", never "2 026". */
19
+ export declare function formatCategory(value: ChartValue, locale: string): string;
20
+ export declare function bandScale(options: DiscreteScaleOptions): ChartPositionScale;
21
+ export declare function pointScale(options: DiscreteScaleOptions): ChartPositionScale;
22
+ //# sourceMappingURL=discrete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discrete.d.ts","sourceRoot":"","sources":["../../../src/core/scales/discrete.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEtE;;;;GAIG;AAEH,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC3C,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,uEAAuE;IACvE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAC/B;AAKD,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAErD;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAExE;AAyDD,wBAAgB,SAAS,CAAC,OAAO,EAAE,oBAAoB,GAAG,kBAAkB,CAsC3E;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,oBAAoB,GAAG,kBAAkB,CA4B5E"}
@@ -0,0 +1,103 @@
1
+ import { dateFormat, formatDate } from "../format.js";
2
+ const DEFAULT_BAND_PADDING_INNER = 0.2;
3
+ const DEFAULT_BAND_PADDING_OUTER = 0.1;
4
+ function categoryKey(value) {
5
+ return value instanceof Date ? `${value.getTime()}` : String(value);
6
+ }
7
+ function formatCategory(value, locale) {
8
+ return value instanceof Date ? formatDate(value, locale) : String(value);
9
+ }
10
+ function dateCategoryFormatter(domain, locale) {
11
+ const dates = domain.filter((value) => value instanceof Date);
12
+ if (dates.length === 0 || dates.length !== domain.length) {
13
+ return void 0;
14
+ }
15
+ const midnight = dates.every((date) => date.getTime() % 864e5 === 0);
16
+ const firstOfMonth = midnight && dates.every((date) => date.getUTCDate() === 1);
17
+ const newYear = firstOfMonth && dates.every((date) => date.getUTCMonth() === 0);
18
+ if (newYear) {
19
+ const year = dateFormat(locale, { year: "numeric" });
20
+ return (value) => year.format(value);
21
+ }
22
+ if (firstOfMonth) {
23
+ const month = dateFormat(locale, { month: "short" });
24
+ const monthYear = dateFormat(locale, { month: "short", year: "numeric" });
25
+ const first = dates[0].getTime();
26
+ return (value) => {
27
+ const date = value;
28
+ return date.getUTCMonth() === 0 || date.getTime() === first ? monthYear.format(date) : month.format(date);
29
+ };
30
+ }
31
+ if (midnight) {
32
+ const day = dateFormat(locale, { day: "numeric", month: "short" });
33
+ return (value) => day.format(value);
34
+ }
35
+ return void 0;
36
+ }
37
+ function clamp(value, low, high) {
38
+ return Math.min(Math.max(value, low), high);
39
+ }
40
+ function indexer(domain) {
41
+ const indexByKey = /* @__PURE__ */ new Map();
42
+ for (const [index, value] of domain.entries()) {
43
+ const key = categoryKey(value);
44
+ if (!indexByKey.has(key)) {
45
+ indexByKey.set(key, index);
46
+ }
47
+ }
48
+ return (value) => indexByKey.get(categoryKey(value)) ?? 0;
49
+ }
50
+ function bandScale(options) {
51
+ const {
52
+ domain,
53
+ range,
54
+ locale,
55
+ paddingInner = DEFAULT_BAND_PADDING_INNER,
56
+ paddingOuter = DEFAULT_BAND_PADDING_OUTER
57
+ } = options;
58
+ const [start, end] = range;
59
+ const count = domain.length;
60
+ const step = (end - start) / Math.max(1, count - paddingInner + paddingOuter * 2);
61
+ const bandwidth = Math.abs(step * (1 - paddingInner));
62
+ const origin = start + step * paddingOuter;
63
+ const indexOf = indexer(domain);
64
+ const map = (value) => origin + step * indexOf(value) - (step < 0 ? bandwidth : 0);
65
+ return {
66
+ kind: "band",
67
+ domain,
68
+ range,
69
+ bandwidth,
70
+ map,
71
+ center: (value) => map(value) + bandwidth / 2,
72
+ invert: (pixel) => domain[count === 0 ? 0 : clamp(Math.floor((pixel - origin) / step), 0, count - 1)],
73
+ ticks: () => domain,
74
+ format: dateCategoryFormatter(domain, locale) ?? ((value) => formatCategory(value, locale))
75
+ };
76
+ }
77
+ function pointScale(options) {
78
+ const { domain, range, locale, paddingOuter = 0 } = options;
79
+ const [start, end] = range;
80
+ const count = domain.length;
81
+ const step = (end - start) / Math.max(1, count - 1 + paddingOuter * 2);
82
+ const origin = start + step * paddingOuter;
83
+ const indexOf = indexer(domain);
84
+ const map = (value) => count <= 1 ? start + (end - start) / 2 : origin + step * indexOf(value);
85
+ return {
86
+ kind: "point",
87
+ domain,
88
+ range,
89
+ bandwidth: 0,
90
+ map,
91
+ center: map,
92
+ invert: (pixel) => domain[count === 0 ? 0 : clamp(Math.round((pixel - origin) / step), 0, count - 1)],
93
+ ticks: () => domain,
94
+ format: dateCategoryFormatter(domain, locale) ?? ((value) => formatCategory(value, locale))
95
+ };
96
+ }
97
+ export {
98
+ bandScale,
99
+ categoryKey,
100
+ formatCategory,
101
+ pointScale
102
+ };
103
+ //# sourceMappingURL=discrete.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/core/scales/discrete.ts"],
4
+ "sourcesContent": ["import { dateFormat, formatDate } from \"#/core/format.ts\";\nimport type { ChartPositionScale, ChartValue } from \"#/core/types.ts\";\n\n/**\n * Categories in, slots out. `band` gives each category a slot of `bandwidth`\n * pixels (what bars sit on), `point` a position with no width (what lines sit\n * on, first and last touching the plot edges).\n */\n\nexport interface DiscreteScaleOptions {\n\treadonly domain: ReadonlyArray<ChartValue>;\n\treadonly range: readonly [number, number];\n\treadonly locale: string;\n\t/** Share of a step left empty between two bands. 0 = touching bars. */\n\treadonly paddingInner?: number;\n\t/** Share of a step left empty before the first and after the last slot. */\n\treadonly paddingOuter?: number;\n}\n\nconst DEFAULT_BAND_PADDING_INNER = 0.2;\nconst DEFAULT_BAND_PADDING_OUTER = 0.1;\n\n/** A category's identity: two equal dates are one category. */\nexport function categoryKey(value: ChartValue): string {\n\treturn value instanceof Date ? `${value.getTime()}` : String(value);\n}\n\n/** A category as a label. A year stays \"2026\", never \"2 026\". */\nexport function formatCategory(value: ChartValue, locale: string): string {\n\treturn value instanceof Date ? formatDate(value, locale) : String(value);\n}\n\n/**\n * Labels for a row of date categories, as short as the dates allow: years\n * when every date is a New Year, months when every date is a first of the\n * month (with the year where it turns), days when every date is a midnight.\n */\nfunction dateCategoryFormatter(\n\tdomain: ReadonlyArray<ChartValue>,\n\tlocale: string,\n): ((value: ChartValue) => string) | undefined {\n\tconst dates = domain.filter((value): value is Date => value instanceof Date);\n\tif (dates.length === 0 || dates.length !== domain.length) {\n\t\treturn undefined;\n\t}\n\tconst midnight = dates.every((date) => date.getTime() % 86_400_000 === 0);\n\tconst firstOfMonth =\n\t\tmidnight && dates.every((date) => date.getUTCDate() === 1);\n\tconst newYear =\n\t\tfirstOfMonth && dates.every((date) => date.getUTCMonth() === 0);\n\tif (newYear) {\n\t\tconst year = dateFormat(locale, { year: \"numeric\" });\n\t\treturn (value) => year.format(value as Date);\n\t}\n\tif (firstOfMonth) {\n\t\tconst month = dateFormat(locale, { month: \"short\" });\n\t\tconst monthYear = dateFormat(locale, { month: \"short\", year: \"numeric\" });\n\t\tconst first = dates[0].getTime();\n\t\treturn (value) => {\n\t\t\tconst date = value as Date;\n\t\t\treturn date.getUTCMonth() === 0 || date.getTime() === first\n\t\t\t\t? monthYear.format(date)\n\t\t\t\t: month.format(date);\n\t\t};\n\t}\n\tif (midnight) {\n\t\tconst day = dateFormat(locale, { day: \"numeric\", month: \"short\" });\n\t\treturn (value) => day.format(value as Date);\n\t}\n\treturn undefined;\n}\n\nfunction clamp(value: number, low: number, high: number): number {\n\treturn Math.min(Math.max(value, low), high);\n}\n\nfunction indexer(domain: ReadonlyArray<ChartValue>) {\n\tconst indexByKey = new Map<string, number>();\n\tfor (const [index, value] of domain.entries()) {\n\t\tconst key = categoryKey(value);\n\t\tif (!indexByKey.has(key)) {\n\t\t\tindexByKey.set(key, index);\n\t\t}\n\t}\n\treturn (value: ChartValue) => indexByKey.get(categoryKey(value)) ?? 0;\n}\n\nexport function bandScale(options: DiscreteScaleOptions): ChartPositionScale {\n\tconst {\n\t\tdomain,\n\t\trange,\n\t\tlocale,\n\t\tpaddingInner = DEFAULT_BAND_PADDING_INNER,\n\t\tpaddingOuter = DEFAULT_BAND_PADDING_OUTER,\n\t} = options;\n\tconst [start, end] = range;\n\tconst count = domain.length;\n\tconst step =\n\t\t(end - start) / Math.max(1, count - paddingInner + paddingOuter * 2);\n\tconst bandwidth = Math.abs(step * (1 - paddingInner));\n\tconst origin = start + step * paddingOuter;\n\tconst indexOf = indexer(domain);\n\t// A reversed range (a y band running top to bottom is not, but a flipped\n\t// one is) still opens each band towards larger pixels.\n\tconst map = (value: ChartValue) =>\n\t\torigin + step * indexOf(value) - (step < 0 ? bandwidth : 0);\n\n\treturn {\n\t\tkind: \"band\",\n\t\tdomain,\n\t\trange,\n\t\tbandwidth,\n\t\tmap,\n\t\tcenter: (value) => map(value) + bandwidth / 2,\n\t\tinvert: (pixel) =>\n\t\t\tdomain[\n\t\t\t\tcount === 0\n\t\t\t\t\t? 0\n\t\t\t\t\t: clamp(Math.floor((pixel - origin) / step), 0, count - 1)\n\t\t\t],\n\t\tticks: () => domain,\n\t\tformat:\n\t\t\tdateCategoryFormatter(domain, locale) ??\n\t\t\t((value) => formatCategory(value, locale)),\n\t};\n}\n\nexport function pointScale(options: DiscreteScaleOptions): ChartPositionScale {\n\tconst { domain, range, locale, paddingOuter = 0 } = options;\n\tconst [start, end] = range;\n\tconst count = domain.length;\n\tconst step = (end - start) / Math.max(1, count - 1 + paddingOuter * 2);\n\tconst origin = start + step * paddingOuter;\n\tconst indexOf = indexer(domain);\n\tconst map = (value: ChartValue) =>\n\t\tcount <= 1 ? start + (end - start) / 2 : origin + step * indexOf(value);\n\n\treturn {\n\t\tkind: \"point\",\n\t\tdomain,\n\t\trange,\n\t\tbandwidth: 0,\n\t\tmap,\n\t\tcenter: map,\n\t\tinvert: (pixel) =>\n\t\t\tdomain[\n\t\t\t\tcount === 0\n\t\t\t\t\t? 0\n\t\t\t\t\t: clamp(Math.round((pixel - origin) / step), 0, count - 1)\n\t\t\t],\n\t\tticks: () => domain,\n\t\tformat:\n\t\t\tdateCategoryFormatter(domain, locale) ??\n\t\t\t((value) => formatCategory(value, locale)),\n\t};\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,18 @@
1
+ import type { ChartPositionScaleOptions } from "../define-chart.js";
2
+ import type { ChartChannel, ChartPositionScale, ChartPositionScaleKind, ChartValue } from "../types.js";
3
+ /**
4
+ * What a scale will be once the plot size is known: its kind and its domain,
5
+ * read off every channel the marks put on it. Split from the range so the
6
+ * axes can measure their tick labels before the plot rectangle exists.
7
+ */
8
+ export interface ScalePlan {
9
+ readonly kind: ChartPositionScaleKind;
10
+ readonly domain: ReadonlyArray<ChartValue>;
11
+ readonly label: string | undefined;
12
+ /** The band padding a mark asked for, when the options name none. */
13
+ readonly padding?: number;
14
+ readonly paddingOuter?: number;
15
+ }
16
+ export declare function planScale(channels: ReadonlyArray<ChartChannel>, options: ChartPositionScaleOptions | undefined, axis: "x" | "y"): ScalePlan | undefined;
17
+ export declare function buildScale(plan: ScalePlan, options: ChartPositionScaleOptions | undefined, range: readonly [number, number], locale: string, tickCount: number): ChartPositionScale;
18
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/core/scales/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAKxE,OAAO,KAAK,EACX,YAAY,EACZ,kBAAkB,EAClB,sBAAsB,EACtB,UAAU,EACV,MAAM,iBAAiB,CAAC;AAEzB;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACzB,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,qEAAqE;IACrE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAC/B;AA6DD,wBAAgB,SAAS,CACxB,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,EACrC,OAAO,EAAE,yBAAyB,GAAG,SAAS,EAC9C,IAAI,EAAE,GAAG,GAAG,GAAG,GACb,SAAS,GAAG,SAAS,CAoCvB;AAED,wBAAgB,UAAU,CACzB,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,yBAAyB,GAAG,SAAS,EAC9C,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GACf,kBAAkB,CAwBpB"}