@adminiumjs/charts 0.1.0-rc.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 (327) hide show
  1. package/LICENSE +661 -0
  2. package/dist/components/AnomalyChart.d.ts +30 -0
  3. package/dist/components/AnomalyChart.d.ts.map +1 -0
  4. package/dist/components/AnomalyChart.js +32 -0
  5. package/dist/components/AnomalyChart.js.map +1 -0
  6. package/dist/components/BarChart.d.ts +33 -0
  7. package/dist/components/BarChart.d.ts.map +1 -0
  8. package/dist/components/BarChart.js +40 -0
  9. package/dist/components/BarChart.js.map +1 -0
  10. package/dist/components/BoxPlotChart.d.ts +23 -0
  11. package/dist/components/BoxPlotChart.d.ts.map +1 -0
  12. package/dist/components/BoxPlotChart.js +24 -0
  13. package/dist/components/BoxPlotChart.js.map +1 -0
  14. package/dist/components/BulletChart.d.ts +27 -0
  15. package/dist/components/BulletChart.d.ts.map +1 -0
  16. package/dist/components/BulletChart.js +24 -0
  17. package/dist/components/BulletChart.js.map +1 -0
  18. package/dist/components/BumpChart.d.ts +27 -0
  19. package/dist/components/BumpChart.d.ts.map +1 -0
  20. package/dist/components/BumpChart.js +17 -0
  21. package/dist/components/BumpChart.js.map +1 -0
  22. package/dist/components/CandlestickChart.d.ts +26 -0
  23. package/dist/components/CandlestickChart.d.ts.map +1 -0
  24. package/dist/components/CandlestickChart.js +22 -0
  25. package/dist/components/CandlestickChart.js.map +1 -0
  26. package/dist/components/ChartSurface.d.ts +52 -0
  27. package/dist/components/ChartSurface.d.ts.map +1 -0
  28. package/dist/components/ChartSurface.js +15 -0
  29. package/dist/components/ChartSurface.js.map +1 -0
  30. package/dist/components/Chord.d.ts +30 -0
  31. package/dist/components/Chord.d.ts.map +1 -0
  32. package/dist/components/Chord.js +14 -0
  33. package/dist/components/Chord.js.map +1 -0
  34. package/dist/components/ChoroplethGridChart.d.ts +32 -0
  35. package/dist/components/ChoroplethGridChart.d.ts.map +1 -0
  36. package/dist/components/ChoroplethGridChart.js +15 -0
  37. package/dist/components/ChoroplethGridChart.js.map +1 -0
  38. package/dist/components/CohortMatrixChart.d.ts +30 -0
  39. package/dist/components/CohortMatrixChart.d.ts.map +1 -0
  40. package/dist/components/CohortMatrixChart.js +13 -0
  41. package/dist/components/CohortMatrixChart.js.map +1 -0
  42. package/dist/components/CorrelationMatrixChart.d.ts +24 -0
  43. package/dist/components/CorrelationMatrixChart.d.ts.map +1 -0
  44. package/dist/components/CorrelationMatrixChart.js +29 -0
  45. package/dist/components/CorrelationMatrixChart.js.map +1 -0
  46. package/dist/components/DonutChart.d.ts +31 -0
  47. package/dist/components/DonutChart.d.ts.map +1 -0
  48. package/dist/components/DonutChart.js +19 -0
  49. package/dist/components/DonutChart.js.map +1 -0
  50. package/dist/components/ForecastChart.d.ts +37 -0
  51. package/dist/components/ForecastChart.d.ts.map +1 -0
  52. package/dist/components/ForecastChart.js +39 -0
  53. package/dist/components/ForecastChart.js.map +1 -0
  54. package/dist/components/Funnel.d.ts +27 -0
  55. package/dist/components/Funnel.d.ts.map +1 -0
  56. package/dist/components/Funnel.js +25 -0
  57. package/dist/components/Funnel.js.map +1 -0
  58. package/dist/components/HeatCalendarChart.d.ts +39 -0
  59. package/dist/components/HeatCalendarChart.d.ts.map +1 -0
  60. package/dist/components/HeatCalendarChart.js +37 -0
  61. package/dist/components/HeatCalendarChart.js.map +1 -0
  62. package/dist/components/HeatMonthChart.d.ts +30 -0
  63. package/dist/components/HeatMonthChart.d.ts.map +1 -0
  64. package/dist/components/HeatMonthChart.js +14 -0
  65. package/dist/components/HeatMonthChart.js.map +1 -0
  66. package/dist/components/HexbinChart.d.ts +22 -0
  67. package/dist/components/HexbinChart.d.ts.map +1 -0
  68. package/dist/components/HexbinChart.js +31 -0
  69. package/dist/components/HexbinChart.js.map +1 -0
  70. package/dist/components/LineAreaChart.d.ts +26 -0
  71. package/dist/components/LineAreaChart.d.ts.map +1 -0
  72. package/dist/components/LineAreaChart.js +62 -0
  73. package/dist/components/LineAreaChart.js.map +1 -0
  74. package/dist/components/MarimekkoChart.d.ts +24 -0
  75. package/dist/components/MarimekkoChart.d.ts.map +1 -0
  76. package/dist/components/MarimekkoChart.js +20 -0
  77. package/dist/components/MarimekkoChart.js.map +1 -0
  78. package/dist/components/MultiLineChart.d.ts +36 -0
  79. package/dist/components/MultiLineChart.d.ts.map +1 -0
  80. package/dist/components/MultiLineChart.js +62 -0
  81. package/dist/components/MultiLineChart.js.map +1 -0
  82. package/dist/components/ParallelCoordinatesChart.d.ts +22 -0
  83. package/dist/components/ParallelCoordinatesChart.d.ts.map +1 -0
  84. package/dist/components/ParallelCoordinatesChart.js +16 -0
  85. package/dist/components/ParallelCoordinatesChart.js.map +1 -0
  86. package/dist/components/ParetoChart.d.ts +26 -0
  87. package/dist/components/ParetoChart.d.ts.map +1 -0
  88. package/dist/components/ParetoChart.js +26 -0
  89. package/dist/components/ParetoChart.js.map +1 -0
  90. package/dist/components/Radar.d.ts +27 -0
  91. package/dist/components/Radar.d.ts.map +1 -0
  92. package/dist/components/Radar.js +19 -0
  93. package/dist/components/Radar.js.map +1 -0
  94. package/dist/components/RadialBar.d.ts +25 -0
  95. package/dist/components/RadialBar.d.ts.map +1 -0
  96. package/dist/components/RadialBar.js +12 -0
  97. package/dist/components/RadialBar.js.map +1 -0
  98. package/dist/components/RankingBars.d.ts +27 -0
  99. package/dist/components/RankingBars.d.ts.map +1 -0
  100. package/dist/components/RankingBars.js +25 -0
  101. package/dist/components/RankingBars.js.map +1 -0
  102. package/dist/components/RidgelineChart.d.ts +23 -0
  103. package/dist/components/RidgelineChart.d.ts.map +1 -0
  104. package/dist/components/RidgelineChart.js +20 -0
  105. package/dist/components/RidgelineChart.js.map +1 -0
  106. package/dist/components/SankeyChart.d.ts +29 -0
  107. package/dist/components/SankeyChart.d.ts.map +1 -0
  108. package/dist/components/SankeyChart.js +21 -0
  109. package/dist/components/SankeyChart.js.map +1 -0
  110. package/dist/components/ScatterBubbleChart.d.ts +26 -0
  111. package/dist/components/ScatterBubbleChart.d.ts.map +1 -0
  112. package/dist/components/ScatterBubbleChart.js +31 -0
  113. package/dist/components/ScatterBubbleChart.js.map +1 -0
  114. package/dist/components/SlopeChart.d.ts +28 -0
  115. package/dist/components/SlopeChart.d.ts.map +1 -0
  116. package/dist/components/SlopeChart.js +18 -0
  117. package/dist/components/SlopeChart.js.map +1 -0
  118. package/dist/components/Sparkline.d.ts +15 -0
  119. package/dist/components/Sparkline.d.ts.map +1 -0
  120. package/dist/components/Sparkline.js +27 -0
  121. package/dist/components/Sparkline.js.map +1 -0
  122. package/dist/components/StackedBar100.d.ts +30 -0
  123. package/dist/components/StackedBar100.d.ts.map +1 -0
  124. package/dist/components/StackedBar100.js +21 -0
  125. package/dist/components/StackedBar100.js.map +1 -0
  126. package/dist/components/StreamChart.d.ts +23 -0
  127. package/dist/components/StreamChart.d.ts.map +1 -0
  128. package/dist/components/StreamChart.js +56 -0
  129. package/dist/components/StreamChart.js.map +1 -0
  130. package/dist/components/Sunburst.d.ts +24 -0
  131. package/dist/components/Sunburst.d.ts.map +1 -0
  132. package/dist/components/Sunburst.js +13 -0
  133. package/dist/components/Sunburst.js.map +1 -0
  134. package/dist/components/TimelineLanesChart.d.ts +25 -0
  135. package/dist/components/TimelineLanesChart.d.ts.map +1 -0
  136. package/dist/components/TimelineLanesChart.js +41 -0
  137. package/dist/components/TimelineLanesChart.js.map +1 -0
  138. package/dist/components/Treemap.d.ts +28 -0
  139. package/dist/components/Treemap.d.ts.map +1 -0
  140. package/dist/components/Treemap.js +22 -0
  141. package/dist/components/Treemap.js.map +1 -0
  142. package/dist/components/ViolinChart.d.ts +22 -0
  143. package/dist/components/ViolinChart.d.ts.map +1 -0
  144. package/dist/components/ViolinChart.js +21 -0
  145. package/dist/components/ViolinChart.js.map +1 -0
  146. package/dist/components/WaterfallChart.d.ts +23 -0
  147. package/dist/components/WaterfallChart.d.ts.map +1 -0
  148. package/dist/components/WaterfallChart.js +29 -0
  149. package/dist/components/WaterfallChart.js.map +1 -0
  150. package/dist/components/WordCloud.d.ts +24 -0
  151. package/dist/components/WordCloud.d.ts.map +1 -0
  152. package/dist/components/WordCloud.js +22 -0
  153. package/dist/components/WordCloud.js.map +1 -0
  154. package/dist/demo/barsRanking.d.ts +26 -0
  155. package/dist/demo/barsRanking.d.ts.map +1 -0
  156. package/dist/demo/barsRanking.js +80 -0
  157. package/dist/demo/barsRanking.js.map +1 -0
  158. package/dist/demo/generators.d.ts +44 -0
  159. package/dist/demo/generators.d.ts.map +1 -0
  160. package/dist/demo/generators.js +72 -0
  161. package/dist/demo/generators.js.map +1 -0
  162. package/dist/demo/mulberry32.d.ts +10 -0
  163. package/dist/demo/mulberry32.d.ts.map +1 -0
  164. package/dist/demo/mulberry32.js +26 -0
  165. package/dist/demo/mulberry32.js.map +1 -0
  166. package/dist/geometry/anomaly.d.ts +22 -0
  167. package/dist/geometry/anomaly.d.ts.map +1 -0
  168. package/dist/geometry/anomaly.js +52 -0
  169. package/dist/geometry/anomaly.js.map +1 -0
  170. package/dist/geometry/bars.d.ts +46 -0
  171. package/dist/geometry/bars.d.ts.map +1 -0
  172. package/dist/geometry/bars.js +68 -0
  173. package/dist/geometry/bars.js.map +1 -0
  174. package/dist/geometry/bullet.d.ts +53 -0
  175. package/dist/geometry/bullet.d.ts.map +1 -0
  176. package/dist/geometry/bullet.js +67 -0
  177. package/dist/geometry/bullet.js.map +1 -0
  178. package/dist/geometry/bump.d.ts +42 -0
  179. package/dist/geometry/bump.d.ts.map +1 -0
  180. package/dist/geometry/bump.js +29 -0
  181. package/dist/geometry/bump.js.map +1 -0
  182. package/dist/geometry/candles.d.ts +39 -0
  183. package/dist/geometry/candles.d.ts.map +1 -0
  184. package/dist/geometry/candles.js +42 -0
  185. package/dist/geometry/candles.js.map +1 -0
  186. package/dist/geometry/chord.d.ts +53 -0
  187. package/dist/geometry/chord.d.ts.map +1 -0
  188. package/dist/geometry/chord.js +111 -0
  189. package/dist/geometry/chord.js.map +1 -0
  190. package/dist/geometry/choropleth.d.ts +58 -0
  191. package/dist/geometry/choropleth.d.ts.map +1 -0
  192. package/dist/geometry/choropleth.js +101 -0
  193. package/dist/geometry/choropleth.js.map +1 -0
  194. package/dist/geometry/cohort.d.ts +54 -0
  195. package/dist/geometry/cohort.d.ts.map +1 -0
  196. package/dist/geometry/cohort.js +70 -0
  197. package/dist/geometry/cohort.js.map +1 -0
  198. package/dist/geometry/correlation.d.ts +138 -0
  199. package/dist/geometry/correlation.d.ts.map +1 -0
  200. package/dist/geometry/correlation.js +161 -0
  201. package/dist/geometry/correlation.js.map +1 -0
  202. package/dist/geometry/distribution.d.ts +115 -0
  203. package/dist/geometry/distribution.d.ts.map +1 -0
  204. package/dist/geometry/distribution.js +131 -0
  205. package/dist/geometry/distribution.js.map +1 -0
  206. package/dist/geometry/donut.d.ts +37 -0
  207. package/dist/geometry/donut.d.ts.map +1 -0
  208. package/dist/geometry/donut.js +46 -0
  209. package/dist/geometry/donut.js.map +1 -0
  210. package/dist/geometry/forecast.d.ts +30 -0
  211. package/dist/geometry/forecast.d.ts.map +1 -0
  212. package/dist/geometry/forecast.js +75 -0
  213. package/dist/geometry/forecast.js.map +1 -0
  214. package/dist/geometry/funnel.d.ts +37 -0
  215. package/dist/geometry/funnel.d.ts.map +1 -0
  216. package/dist/geometry/funnel.js +42 -0
  217. package/dist/geometry/funnel.js.map +1 -0
  218. package/dist/geometry/heat.d.ts +34 -0
  219. package/dist/geometry/heat.d.ts.map +1 -0
  220. package/dist/geometry/heat.js +50 -0
  221. package/dist/geometry/heat.js.map +1 -0
  222. package/dist/geometry/heatCalendar.d.ts +43 -0
  223. package/dist/geometry/heatCalendar.d.ts.map +1 -0
  224. package/dist/geometry/heatCalendar.js +82 -0
  225. package/dist/geometry/heatCalendar.js.map +1 -0
  226. package/dist/geometry/heatMonth.d.ts +47 -0
  227. package/dist/geometry/heatMonth.d.ts.map +1 -0
  228. package/dist/geometry/heatMonth.js +72 -0
  229. package/dist/geometry/heatMonth.js.map +1 -0
  230. package/dist/geometry/lineArea.d.ts +17 -0
  231. package/dist/geometry/lineArea.d.ts.map +1 -0
  232. package/dist/geometry/lineArea.js +37 -0
  233. package/dist/geometry/lineArea.js.map +1 -0
  234. package/dist/geometry/marimekko.d.ts +43 -0
  235. package/dist/geometry/marimekko.d.ts.map +1 -0
  236. package/dist/geometry/marimekko.js +45 -0
  237. package/dist/geometry/marimekko.js.map +1 -0
  238. package/dist/geometry/multiLine.d.ts +19 -0
  239. package/dist/geometry/multiLine.d.ts.map +1 -0
  240. package/dist/geometry/multiLine.js +25 -0
  241. package/dist/geometry/multiLine.js.map +1 -0
  242. package/dist/geometry/pareto.d.ts +44 -0
  243. package/dist/geometry/pareto.d.ts.map +1 -0
  244. package/dist/geometry/pareto.js +65 -0
  245. package/dist/geometry/pareto.js.map +1 -0
  246. package/dist/geometry/radar.d.ts +60 -0
  247. package/dist/geometry/radar.d.ts.map +1 -0
  248. package/dist/geometry/radar.js +67 -0
  249. package/dist/geometry/radar.js.map +1 -0
  250. package/dist/geometry/radialBar.d.ts +31 -0
  251. package/dist/geometry/radialBar.d.ts.map +1 -0
  252. package/dist/geometry/radialBar.js +53 -0
  253. package/dist/geometry/radialBar.js.map +1 -0
  254. package/dist/geometry/ranking.d.ts +48 -0
  255. package/dist/geometry/ranking.d.ts.map +1 -0
  256. package/dist/geometry/ranking.js +42 -0
  257. package/dist/geometry/ranking.js.map +1 -0
  258. package/dist/geometry/sankey.d.ts +60 -0
  259. package/dist/geometry/sankey.d.ts.map +1 -0
  260. package/dist/geometry/sankey.js +130 -0
  261. package/dist/geometry/sankey.js.map +1 -0
  262. package/dist/geometry/scales.d.ts +14 -0
  263. package/dist/geometry/scales.d.ts.map +1 -0
  264. package/dist/geometry/scales.js +33 -0
  265. package/dist/geometry/scales.js.map +1 -0
  266. package/dist/geometry/slope.d.ts +34 -0
  267. package/dist/geometry/slope.d.ts.map +1 -0
  268. package/dist/geometry/slope.js +44 -0
  269. package/dist/geometry/slope.js.map +1 -0
  270. package/dist/geometry/sparkline.d.ts +20 -0
  271. package/dist/geometry/sparkline.d.ts.map +1 -0
  272. package/dist/geometry/sparkline.js +43 -0
  273. package/dist/geometry/sparkline.js.map +1 -0
  274. package/dist/geometry/stacked100.d.ts +33 -0
  275. package/dist/geometry/stacked100.d.ts.map +1 -0
  276. package/dist/geometry/stacked100.js +34 -0
  277. package/dist/geometry/stacked100.js.map +1 -0
  278. package/dist/geometry/streamStack.d.ts +32 -0
  279. package/dist/geometry/streamStack.d.ts.map +1 -0
  280. package/dist/geometry/streamStack.js +56 -0
  281. package/dist/geometry/streamStack.js.map +1 -0
  282. package/dist/geometry/sunburst.d.ts +37 -0
  283. package/dist/geometry/sunburst.d.ts.map +1 -0
  284. package/dist/geometry/sunburst.js +84 -0
  285. package/dist/geometry/sunburst.js.map +1 -0
  286. package/dist/geometry/timelineLanes.d.ts +46 -0
  287. package/dist/geometry/timelineLanes.d.ts.map +1 -0
  288. package/dist/geometry/timelineLanes.js +52 -0
  289. package/dist/geometry/timelineLanes.js.map +1 -0
  290. package/dist/geometry/treemap.d.ts +42 -0
  291. package/dist/geometry/treemap.d.ts.map +1 -0
  292. package/dist/geometry/treemap.js +134 -0
  293. package/dist/geometry/treemap.js.map +1 -0
  294. package/dist/geometry/waterfall.d.ts +40 -0
  295. package/dist/geometry/waterfall.d.ts.map +1 -0
  296. package/dist/geometry/waterfall.js +80 -0
  297. package/dist/geometry/waterfall.js.map +1 -0
  298. package/dist/geometry/wordcloud.d.ts +46 -0
  299. package/dist/geometry/wordcloud.d.ts.map +1 -0
  300. package/dist/geometry/wordcloud.js +79 -0
  301. package/dist/geometry/wordcloud.js.map +1 -0
  302. package/dist/hooks/useChartSize.d.ts +6 -0
  303. package/dist/hooks/useChartSize.d.ts.map +1 -0
  304. package/dist/hooks/useChartSize.js +32 -0
  305. package/dist/hooks/useChartSize.js.map +1 -0
  306. package/dist/hooks/useMountAnimation.d.ts +4 -0
  307. package/dist/hooks/useMountAnimation.d.ts.map +1 -0
  308. package/dist/hooks/useMountAnimation.js +40 -0
  309. package/dist/hooks/useMountAnimation.js.map +1 -0
  310. package/dist/hooks/useRtl.d.ts +7 -0
  311. package/dist/hooks/useRtl.d.ts.map +1 -0
  312. package/dist/hooks/useRtl.js +18 -0
  313. package/dist/hooks/useRtl.js.map +1 -0
  314. package/dist/index.d.ts +110 -0
  315. package/dist/index.d.ts.map +1 -0
  316. package/dist/index.js +79 -0
  317. package/dist/index.js.map +1 -0
  318. package/dist/utils/format.d.ts +5 -0
  319. package/dist/utils/format.d.ts.map +1 -0
  320. package/dist/utils/format.js +24 -0
  321. package/dist/utils/format.js.map +1 -0
  322. package/dist/utils/stats.d.ts +23 -0
  323. package/dist/utils/stats.d.ts.map +1 -0
  324. package/dist/utils/stats.js +82 -0
  325. package/dist/utils/stats.js.map +1 -0
  326. package/package.json +36 -0
  327. package/src/styles.css +205 -0
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Streamgraph stacking geometry (`chart-stream`, research/widget-registry.md
3
+ * §2): centered ("silhouette") stacked bands over time. Pure + DOM-free; the
4
+ * component supplies the pixel x/y scales, this returns value-space band edges
5
+ * and a golden-testable pixel area-path builder.
6
+ */
7
+ import { area, curveBasis, curveLinear } from 'd3-shape';
8
+ /**
9
+ * Stack series into bands. `silhouette` centers the total thickness on zero at
10
+ * each x (the classic streamgraph); `zero` stacks upward from a flat baseline.
11
+ * Negative inputs are clamped to zero (thicknesses are non-negative).
12
+ */
13
+ export function stackStream(series, offset = 'silhouette') {
14
+ const n = series.reduce((max, s) => Math.max(max, s.values.length), 0);
15
+ const bands = series.map((s) => ({
16
+ key: s.key,
17
+ label: s.label,
18
+ low: Array.from({ length: n }, () => 0),
19
+ high: Array.from({ length: n }, () => 0),
20
+ }));
21
+ let min = 0;
22
+ let max = 0;
23
+ for (let i = 0; i < n; i += 1) {
24
+ const total = series.reduce((sum, s) => sum + Math.max(0, s.values[i] ?? 0), 0);
25
+ let running = offset === 'silhouette' ? -total / 2 : 0;
26
+ for (let s = 0; s < series.length; s += 1) {
27
+ const value = Math.max(0, series[s]?.values[i] ?? 0);
28
+ const band = bands[s];
29
+ if (band === undefined)
30
+ continue;
31
+ const low = running;
32
+ running += value;
33
+ band.low[i] = low;
34
+ band.high[i] = running;
35
+ if (running > max)
36
+ max = running;
37
+ if (low < min)
38
+ min = low;
39
+ }
40
+ }
41
+ return { bands, min, max };
42
+ }
43
+ /**
44
+ * Closed area path between per-index lower/upper PIXEL edges. `xs`, `low`,
45
+ * `high` are parallel pixel arrays; `smooth` uses a basis spline for the
46
+ * organic stream look.
47
+ */
48
+ export function bandAreaPath(xs, low, high, smooth = true) {
49
+ const generator = area()
50
+ .x((_, i) => xs[i] ?? 0)
51
+ .y0((_, i) => low[i] ?? 0)
52
+ .y1((_, i) => high[i] ?? 0)
53
+ .curve(smooth ? curveBasis : curveLinear);
54
+ return generator(high.map(() => 0));
55
+ }
56
+ //# sourceMappingURL=streamStack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamStack.js","sourceRoot":"","sources":["../../src/geometry/streamStack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ export interface SunburstChildInput {
2
+ label: string;
3
+ value: number;
4
+ }
5
+ export interface SunburstParentInput {
6
+ label: string;
7
+ children: readonly SunburstChildInput[];
8
+ }
9
+ export interface SunburstArc {
10
+ label: string;
11
+ parentLabel?: string;
12
+ value: number;
13
+ /** Fraction of the grand total, 0..1. */
14
+ share: number;
15
+ depth: 0 | 1;
16
+ startAngle: number;
17
+ endAngle: number;
18
+ path: string;
19
+ colorVar: string;
20
+ }
21
+ export interface SunburstLayout {
22
+ arcs: SunburstArc[];
23
+ total: number;
24
+ }
25
+ export interface SunburstOptions {
26
+ size: number;
27
+ /** Ring thickness in px (default derived from size). */
28
+ ringThickness?: number;
29
+ /** Radius of the empty center hole (default 0). */
30
+ innerRadius?: number;
31
+ }
32
+ /**
33
+ * Two-ring sunburst arcs (parents then their children, in input order). Empty
34
+ * parents (no positive children) are skipped; a non-positive total yields [].
35
+ */
36
+ export declare function sunburstArcs(parents: readonly SunburstParentInput[], options: SunburstOptions): SunburstLayout;
37
+ //# sourceMappingURL=sunburst.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sunburst.d.ts","sourceRoot":"","sources":["../../src/geometry/sunburst.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAWD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,EAAE,OAAO,EAAE,eAAe,GAAG,cAAc,CAiE9G"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Pure sunburst geometry (`chart-sunburst`, research/widget-registry.md §2): two
3
+ * nested rings from a 2-level hierarchy — inner ring = parents (angle ∝ subtree
4
+ * total), outer ring = children (angle ∝ child value within the parent span).
5
+ * Arcs sweep clockwise from 12 o'clock and do NOT mirror in RTL (rotation is
6
+ * direction-neutral, §7.4). DOM-free + deterministic (04 §7.1).
7
+ */
8
+ import { arc } from 'd3-shape';
9
+ const TAU = Math.PI * 2;
10
+ function vizColor(index) {
11
+ return `var(--viz-${(index % 8) + 1})`;
12
+ }
13
+ /** Blend a parent color toward the surface for its children (lighter band). */
14
+ function childColor(index) {
15
+ return `color-mix(in srgb, var(--viz-${(index % 8) + 1}) 62%, var(--surface))`;
16
+ }
17
+ /**
18
+ * Two-ring sunburst arcs (parents then their children, in input order). Empty
19
+ * parents (no positive children) are skipped; a non-positive total yields [].
20
+ */
21
+ export function sunburstArcs(parents, options) {
22
+ const { size } = options;
23
+ const outer = Math.max(0, size / 2);
24
+ const innerHole = options.innerRadius ?? 0;
25
+ const band = options.ringThickness ?? (outer - innerHole) / 2;
26
+ if (outer <= 0)
27
+ return { arcs: [], total: 0 };
28
+ const normalized = parents.map((p, i) => {
29
+ const children = p.children
30
+ .map((c) => ({ label: c.label, value: Number.isFinite(c.value) ? Math.max(0, c.value) : 0 }))
31
+ .filter((c) => c.value > 0);
32
+ const total = children.reduce((s, c) => s + c.value, 0);
33
+ return { label: p.label, index: i, children, total };
34
+ });
35
+ const grandTotal = normalized.reduce((s, p) => s + p.total, 0);
36
+ if (grandTotal <= 0)
37
+ return { arcs: [], total: 0 };
38
+ const innerArc = arc()
39
+ .innerRadius(innerHole)
40
+ .outerRadius(innerHole + band);
41
+ const outerArc = arc()
42
+ .innerRadius(innerHole + band)
43
+ .outerRadius(outer);
44
+ const arcs = [];
45
+ let angle = 0;
46
+ for (const parent of normalized) {
47
+ if (parent.total <= 0)
48
+ continue;
49
+ const parentSpan = (parent.total / grandTotal) * TAU;
50
+ const parentStart = angle;
51
+ const parentEnd = angle + parentSpan;
52
+ arcs.push({
53
+ label: parent.label,
54
+ value: parent.total,
55
+ share: parent.total / grandTotal,
56
+ depth: 0,
57
+ startAngle: parentStart,
58
+ endAngle: parentEnd,
59
+ path: innerArc({ startAngle: parentStart, endAngle: parentEnd }) ?? '',
60
+ colorVar: vizColor(parent.index),
61
+ });
62
+ let childAngle = parentStart;
63
+ for (const child of parent.children) {
64
+ const childSpan = (child.value / grandTotal) * TAU;
65
+ const cStart = childAngle;
66
+ const cEnd = childAngle + childSpan;
67
+ childAngle = cEnd;
68
+ arcs.push({
69
+ label: child.label,
70
+ parentLabel: parent.label,
71
+ value: child.value,
72
+ share: child.value / grandTotal,
73
+ depth: 1,
74
+ startAngle: cStart,
75
+ endAngle: cEnd,
76
+ path: outerArc({ startAngle: cStart, endAngle: cEnd }) ?? '',
77
+ colorVar: childColor(parent.index),
78
+ });
79
+ }
80
+ angle = parentEnd;
81
+ }
82
+ return { arcs, total: grandTotal };
83
+ }
84
+ //# sourceMappingURL=sunburst.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sunburst.js","sourceRoot":"","sources":["../../src/geometry/sunburst.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Swimlane timeline geometry (`chart-timeline-lanes`, research/widget-registry.md
3
+ * §2): stacked horizontal lanes with events positioned along a shared time
4
+ * axis. The time axis is an LTR island (04 §7.4 — time axes never mirror), so
5
+ * event x-positions are LTR here; the component flips only the lane-label
6
+ * gutter side under RTL. Pure + DOM-free.
7
+ */
8
+ export interface LaneEvent {
9
+ lane: string;
10
+ /** Normalized position along the time axis, 0 (oldest) … 1 (newest). */
11
+ position: number;
12
+ label: string;
13
+ tone?: string;
14
+ }
15
+ export interface PositionedEvent {
16
+ x: number;
17
+ label: string;
18
+ tone?: string | undefined;
19
+ }
20
+ export interface LaneRow {
21
+ lane: string;
22
+ index: number;
23
+ /** Top y of the lane band. */
24
+ y: number;
25
+ height: number;
26
+ /** Vertical center — the event pill baseline. */
27
+ centerY: number;
28
+ events: PositionedEvent[];
29
+ }
30
+ export interface LaneLayoutOptions {
31
+ /** Vertical gap between lane bands (px, default 8). */
32
+ laneGap?: number;
33
+ }
34
+ /**
35
+ * One row per lane (in the given order), each carrying its events at pixel x =
36
+ * `clamp(position, 0, 1) · width`. Events keep input order within a lane.
37
+ */
38
+ export declare function layoutLanes(lanes: readonly string[], events: readonly LaneEvent[], width: number, height: number, options?: LaneLayoutOptions): LaneRow[];
39
+ /** Normalize timestamped events to lane positions over a [min, max] time span. */
40
+ export declare function positionByTime(events: readonly {
41
+ lane: string;
42
+ ms: number;
43
+ label: string;
44
+ tone?: string | undefined;
45
+ }[]): LaneEvent[];
46
+ //# sourceMappingURL=timelineLanes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timelineLanes.d.ts","sourceRoot":"","sources":["../../src/geometry/timelineLanes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,MAAM,EAAE,SAAS,SAAS,EAAE,EAC5B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,iBAAsB,GAC9B,OAAO,EAAE,CAwBX;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAC5B,MAAM,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,EAAE,GACxF,SAAS,EAAE,CAYb"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Swimlane timeline geometry (`chart-timeline-lanes`, research/widget-registry.md
3
+ * §2): stacked horizontal lanes with events positioned along a shared time
4
+ * axis. The time axis is an LTR island (04 §7.4 — time axes never mirror), so
5
+ * event x-positions are LTR here; the component flips only the lane-label
6
+ * gutter side under RTL. Pure + DOM-free.
7
+ */
8
+ /**
9
+ * One row per lane (in the given order), each carrying its events at pixel x =
10
+ * `clamp(position, 0, 1) · width`. Events keep input order within a lane.
11
+ */
12
+ export function layoutLanes(lanes, events, width, height, options = {}) {
13
+ const { laneGap = 8 } = options;
14
+ const count = lanes.length;
15
+ if (count === 0)
16
+ return [];
17
+ const laneHeight = Math.max(0, (height - laneGap * (count - 1)) / count);
18
+ return lanes.map((lane, index) => {
19
+ const y = index * (laneHeight + laneGap);
20
+ const laneEvents = events
21
+ .filter((event) => event.lane === lane)
22
+ .map((event) => ({
23
+ x: Math.min(1, Math.max(0, event.position)) * width,
24
+ label: event.label,
25
+ tone: event.tone,
26
+ }));
27
+ return {
28
+ lane,
29
+ index,
30
+ y,
31
+ height: laneHeight,
32
+ centerY: y + laneHeight / 2,
33
+ events: laneEvents,
34
+ };
35
+ });
36
+ }
37
+ /** Normalize timestamped events to lane positions over a [min, max] time span. */
38
+ export function positionByTime(events) {
39
+ if (events.length === 0)
40
+ return [];
41
+ const times = events.map((event) => event.ms);
42
+ const min = Math.min(...times);
43
+ const max = Math.max(...times);
44
+ const span = max - min || 1;
45
+ return events.map((event) => ({
46
+ lane: event.lane,
47
+ position: (event.ms - min) / span,
48
+ label: event.label,
49
+ ...(event.tone !== undefined ? { tone: event.tone } : {}),
50
+ }));
51
+ }
52
+ //# sourceMappingURL=timelineLanes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timelineLanes.js","sourceRoot":"","sources":["../../src/geometry/timelineLanes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgCH;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,KAAwB,EACxB,MAA4B,EAC5B,KAAa,EACb,MAAc,EACd,UAA6B,EAAE;IAE/B,MAAM,EAAE,OAAO,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IAChC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3B,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,GAAG,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;IAEzE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC/B,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,UAAU,GAAG,OAAO,CAAC,CAAC;QACzC,MAAM,UAAU,GAAsB,MAAM;aACzC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;aACtC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACf,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,KAAK;YACnD,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,IAAI,EAAE,KAAK,CAAC,IAAI;SACjB,CAAC,CAAC,CAAC;QACN,OAAO;YACL,IAAI;YACJ,KAAK;YACL,CAAC;YACD,MAAM,EAAE,UAAU;YAClB,OAAO,EAAE,CAAC,GAAG,UAAU,GAAG,CAAC;YAC3B,MAAM,EAAE,UAAU;SACnB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAC5B,MAAyF;IAEzF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;IAC5B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,IAAI;QACjC,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1D,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Pure treemap geometry (`chart-treemap`, research/widget-registry.md §2):
3
+ * squarified slice-and-dice layout (Bruls/Huizing/van Wijk) over a flat,
4
+ * value-weighted category list. DOM-free and deterministic so scheduled-report
5
+ * workers rasterize the identical layout the browser renders (04 §7.1).
6
+ *
7
+ * RTL: the caller mirrors the x axis (`mirrorTiles`) — the layout math itself
8
+ * stays orientation-neutral (categorical part-to-whole mirrors per §7.4).
9
+ */
10
+ export interface TreemapInput {
11
+ label: string;
12
+ value: number;
13
+ }
14
+ export interface TreemapTile {
15
+ label: string;
16
+ value: number;
17
+ /** Fraction of the total, 0..1. */
18
+ share: number;
19
+ x: number;
20
+ y: number;
21
+ width: number;
22
+ height: number;
23
+ /** `var(--viz-N)` cycling by input order. */
24
+ colorVar: string;
25
+ /** Sequential alpha ramp step for area intensity (var(--viz-ramp-N)). */
26
+ rampVar: string;
27
+ }
28
+ export interface TreemapOptions {
29
+ width: number;
30
+ height: number;
31
+ /** Slices beyond this fold into a trailing "other" tile (default Infinity). */
32
+ maxTiles?: number;
33
+ otherLabel?: string;
34
+ }
35
+ /**
36
+ * Squarified treemap tiles in input order (color cycles by order; area alpha
37
+ * ramps by value rank). Non-positive and non-finite values are dropped.
38
+ */
39
+ export declare function treemapTiles(input: readonly TreemapInput[], options: TreemapOptions): TreemapTile[];
40
+ /** Mirror tiles across the vertical axis for RTL rendering. */
41
+ export declare function mirrorTiles(tiles: readonly TreemapTile[], width: number): TreemapTile[];
42
+ //# sourceMappingURL=treemap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treemap.d.ts","sourceRoot":"","sources":["../../src/geometry/treemap.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAmCD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,OAAO,EAAE,cAAc,GACtB,WAAW,EAAE,CA4Ff;AAED,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAEvF"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Pure treemap geometry (`chart-treemap`, research/widget-registry.md §2):
3
+ * squarified slice-and-dice layout (Bruls/Huizing/van Wijk) over a flat,
4
+ * value-weighted category list. DOM-free and deterministic so scheduled-report
5
+ * workers rasterize the identical layout the browser renders (04 §7.1).
6
+ *
7
+ * RTL: the caller mirrors the x axis (`mirrorTiles`) — the layout math itself
8
+ * stays orientation-neutral (categorical part-to-whole mirrors per §7.4).
9
+ */
10
+ function vizColor(index) {
11
+ return `var(--viz-${(index % 8) + 1})`;
12
+ }
13
+ /** Ramp step 1..6 by descending rank (largest tile = strongest). */
14
+ function rampColor(rank, count) {
15
+ if (count <= 1)
16
+ return 'var(--viz-ramp-6)';
17
+ const step = 6 - Math.round((rank / (count - 1)) * 5); // rank 0 → 6, last → 1
18
+ return `var(--viz-ramp-${Math.min(6, Math.max(1, step))})`;
19
+ }
20
+ function worstRatio(row, length) {
21
+ if (length <= 0 || row.length === 0)
22
+ return Infinity;
23
+ let min = Infinity;
24
+ let max = -Infinity;
25
+ let sum = 0;
26
+ for (const area of row) {
27
+ if (area < min)
28
+ min = area;
29
+ if (area > max)
30
+ max = area;
31
+ sum += area;
32
+ }
33
+ const side2 = length * length;
34
+ const sum2 = sum * sum;
35
+ return Math.max((side2 * max) / sum2, sum2 / (side2 * min));
36
+ }
37
+ /**
38
+ * Squarified treemap tiles in input order (color cycles by order; area alpha
39
+ * ramps by value rank). Non-positive and non-finite values are dropped.
40
+ */
41
+ export function treemapTiles(input, options) {
42
+ const { width, height, maxTiles = Infinity, otherLabel = 'Other' } = options;
43
+ if (width <= 0 || height <= 0)
44
+ return [];
45
+ // Fold overflow into an "other" tile, preserving input order/color indices.
46
+ let items = input.filter((d) => Number.isFinite(d.value) && d.value > 0);
47
+ const colorIndex = new Map();
48
+ items.forEach((item, i) => colorIndex.set(item, i));
49
+ if (Number.isFinite(maxTiles) && items.length > maxTiles) {
50
+ const kept = items.slice(0, maxTiles);
51
+ const rest = items.slice(maxTiles).reduce((sum, d) => sum + d.value, 0);
52
+ const other = { label: otherLabel, value: rest };
53
+ colorIndex.set(other, maxTiles);
54
+ items = [...kept, other];
55
+ }
56
+ const total = items.reduce((sum, d) => sum + d.value, 0);
57
+ if (total <= 0)
58
+ return [];
59
+ const area = width * height;
60
+ // Descending scaled areas drive squarify; original index rides along for order.
61
+ const scaled = items
62
+ .map((item, index) => ({ item, index, area: (item.value / total) * area }))
63
+ .sort((a, b) => b.area - a.area || a.index - b.index);
64
+ const placed = [];
65
+ const cursor = { x: 0, y: 0, width, height };
66
+ let row = [];
67
+ const shortSide = () => Math.min(cursor.width, cursor.height);
68
+ const layoutRow = () => {
69
+ if (row.length === 0)
70
+ return;
71
+ const rowArea = row.reduce((sum, r) => sum + r.area, 0);
72
+ const horizontal = cursor.width >= cursor.height;
73
+ if (horizontal) {
74
+ const rowWidth = rowArea / cursor.height;
75
+ let offset = cursor.y;
76
+ for (const cell of row) {
77
+ const cellHeight = (cell.area / rowArea) * cursor.height;
78
+ placed.push({ index: cell.index, x: cursor.x, y: offset, width: rowWidth, height: cellHeight });
79
+ offset += cellHeight;
80
+ }
81
+ cursor.x += rowWidth;
82
+ cursor.width -= rowWidth;
83
+ }
84
+ else {
85
+ const rowHeight = rowArea / cursor.width;
86
+ let offset = cursor.x;
87
+ for (const cell of row) {
88
+ const cellWidth = (cell.area / rowArea) * cursor.width;
89
+ placed.push({ index: cell.index, x: offset, y: cursor.y, width: cellWidth, height: rowHeight });
90
+ offset += cellWidth;
91
+ }
92
+ cursor.y += rowHeight;
93
+ cursor.height -= rowHeight;
94
+ }
95
+ row = [];
96
+ };
97
+ for (const cell of scaled) {
98
+ const length = shortSide();
99
+ const current = row.map((r) => r.area);
100
+ const withCell = [...current, cell.area];
101
+ if (row.length === 0 || worstRatio(withCell, length) <= worstRatio(current, length)) {
102
+ row.push({ index: cell.index, area: cell.area });
103
+ }
104
+ else {
105
+ layoutRow();
106
+ row.push({ index: cell.index, area: cell.area });
107
+ }
108
+ }
109
+ layoutRow();
110
+ // Rank by value (descending) for the alpha ramp.
111
+ const rankByIndex = new Map();
112
+ [...scaled].forEach((cell, rank) => rankByIndex.set(cell.index, rank));
113
+ return placed
114
+ .sort((a, b) => a.index - b.index)
115
+ .map((p) => {
116
+ const source = items[p.index];
117
+ return {
118
+ label: source.label,
119
+ value: source.value,
120
+ share: source.value / total,
121
+ x: p.x,
122
+ y: p.y,
123
+ width: p.width,
124
+ height: p.height,
125
+ colorVar: vizColor(colorIndex.get(source) ?? p.index),
126
+ rampVar: rampColor(rankByIndex.get(p.index) ?? 0, placed.length),
127
+ };
128
+ });
129
+ }
130
+ /** Mirror tiles across the vertical axis for RTL rendering. */
131
+ export function mirrorTiles(tiles, width) {
132
+ return tiles.map((tile) => ({ ...tile, x: width - tile.x - tile.width }));
133
+ }
134
+ //# sourceMappingURL=treemap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"treemap.js","sourceRoot":"","sources":["../../src/geometry/treemap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ export type WaterfallStepType = 'up' | 'down' | 'total';
2
+ export interface WaterfallInput {
3
+ label: string;
4
+ /** Magnitude (non-negative). Sign is implied by `type`. */
5
+ value: number;
6
+ type: WaterfallStepType;
7
+ }
8
+ export interface WaterfallBar {
9
+ index: number;
10
+ label: string;
11
+ value: number;
12
+ type: WaterfallStepType;
13
+ /** Running level after this step (the connector level to the next bar). */
14
+ exitLevel: number;
15
+ x: number;
16
+ y: number;
17
+ width: number;
18
+ height: number;
19
+ centerX: number;
20
+ }
21
+ export interface WaterfallConnector {
22
+ fromIndex: number;
23
+ x1: number;
24
+ x2: number;
25
+ y: number;
26
+ }
27
+ export interface WaterfallLayout {
28
+ bars: WaterfallBar[];
29
+ connectors: WaterfallConnector[];
30
+ yTicks: number[];
31
+ yFor: (value: number) => number;
32
+ }
33
+ export interface WaterfallLayoutOptions {
34
+ width: number;
35
+ height: number;
36
+ rtl: boolean;
37
+ tickCount?: number;
38
+ }
39
+ export declare function layoutWaterfall(items: readonly WaterfallInput[], options: WaterfallLayoutOptions): WaterfallLayout;
40
+ //# sourceMappingURL=waterfall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waterfall.d.ts","sourceRoot":"","sources":["../../src/geometry/waterfall.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,MAAM,GAAG,OAAO,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,iBAAiB,CAAC;IACxB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,EAAE,OAAO,EAAE,sBAAsB,GAAG,eAAe,CA6ElH"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Pure waterfall / bridge layout (`chart-waterfall`, research/widget-registry.md
3
+ * §2): floating bars for signed steps plus total anchors, with connector
4
+ * segments riding the running level. DOM-free. Categorical x mirrors in RTL
5
+ * (band-scale flip); connectors bridge adjacent bars on the correct logical
6
+ * side so they read left→right in LTR and right→left in RTL.
7
+ */
8
+ import { categoricalBandScale } from './scales.js';
9
+ import { niceTicks } from '../utils/stats.js';
10
+ export function layoutWaterfall(items, options) {
11
+ const { width, height, rtl, tickCount = 3 } = options;
12
+ if (items.length === 0 || width <= 0 || height <= 0) {
13
+ return { bars: [], connectors: [], yTicks: [], yFor: () => 0 };
14
+ }
15
+ // First pass in value-space: resolve each bar's low/high band and exit level.
16
+ let running = 0;
17
+ const spans = items.map((item) => {
18
+ const magnitude = Math.max(0, item.value);
19
+ let low;
20
+ let high;
21
+ if (item.type === 'total') {
22
+ running = item.value;
23
+ low = Math.min(0, item.value);
24
+ high = Math.max(0, item.value);
25
+ }
26
+ else if (item.type === 'down') {
27
+ high = running;
28
+ running -= magnitude;
29
+ low = running;
30
+ }
31
+ else {
32
+ low = running;
33
+ running += magnitude;
34
+ high = running;
35
+ }
36
+ return { low, high, exitLevel: running };
37
+ });
38
+ const highest = spans.reduce((m, s) => Math.max(m, s.high), 0);
39
+ const lowest = spans.reduce((m, s) => Math.min(m, s.low), 0);
40
+ const ticks = niceTicks(Math.min(0, lowest), Math.max(1, highest), tickCount);
41
+ const domainLo = ticks[0] ?? Math.min(0, lowest);
42
+ const domainHi = ticks.at(-1) ?? Math.max(1, highest);
43
+ const span = domainHi - domainLo || 1;
44
+ const yFor = (value) => height - ((value - domainLo) / span) * height;
45
+ const band = categoricalBandScale(items.map((item) => item.label), width, rtl, { paddingInner: 0.34, paddingOuter: 0.18 });
46
+ const bandwidth = band.bandwidth();
47
+ const bars = items.map((item, index) => {
48
+ const s = spans[index] ?? { low: 0, high: 0, exitLevel: 0 };
49
+ const x = band(item.label) ?? 0;
50
+ const yHigh = yFor(s.high);
51
+ const yLow = yFor(s.low);
52
+ return {
53
+ index,
54
+ label: item.label,
55
+ value: item.value,
56
+ type: item.type,
57
+ exitLevel: s.exitLevel,
58
+ x,
59
+ y: Math.min(yHigh, yLow),
60
+ width: bandwidth,
61
+ height: Math.max(0, Math.abs(yLow - yHigh)),
62
+ centerX: x + bandwidth / 2,
63
+ };
64
+ });
65
+ const connectors = [];
66
+ for (let i = 0; i < bars.length - 1; i += 1) {
67
+ const a = bars[i];
68
+ const b = bars[i + 1];
69
+ if (a === undefined || b === undefined)
70
+ continue;
71
+ connectors.push({
72
+ fromIndex: i,
73
+ x1: rtl ? a.x : a.x + a.width,
74
+ x2: rtl ? b.x + b.width : b.x,
75
+ y: yFor(a.exitLevel),
76
+ });
77
+ }
78
+ return { bars, connectors, yTicks: ticks, yFor };
79
+ }
80
+ //# sourceMappingURL=waterfall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waterfall.js","sourceRoot":"","sources":["../../src/geometry/waterfall.ts"],"names":[],"mappings":"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"}