@cdx-ui/components 0.3.5 → 0.3.6

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 (278) hide show
  1. package/README.md +1 -1
  2. package/coverage.svg +1 -1
  3. package/docs/components/bar-chart/content.md +703 -0
  4. package/docs/components/content.md +9 -1
  5. package/docs/components/line-chart/content.md +567 -0
  6. package/docs/components/pie-chart/content.md +493 -0
  7. package/docs/components/progress-segmented/content.md +1 -1
  8. package/docs/components/stepper/content.md +599 -0
  9. package/docs/components/system-alert/content.md +533 -0
  10. package/docs/foundations/styles/tokens/all-tokens/content.md +2 -1
  11. package/docs/llms.txt +9 -0
  12. package/docs/patterns/content.md +1 -0
  13. package/docs/patterns/dashboard/content.md +423 -19
  14. package/docs/patterns/insights/content.md +590 -0
  15. package/docs/resources/release-notes/0.3.5/content.md +7 -0
  16. package/docs/resources/release-notes/content.md +1 -0
  17. package/lib/commonjs/components/BarChart/geometry.js +1130 -0
  18. package/lib/commonjs/components/BarChart/geometry.js.map +1 -0
  19. package/lib/commonjs/components/BarChart/index.js +942 -0
  20. package/lib/commonjs/components/BarChart/index.js.map +1 -0
  21. package/lib/commonjs/components/BarChart/styles.js +26 -0
  22. package/lib/commonjs/components/BarChart/styles.js.map +1 -0
  23. package/lib/commonjs/components/Button/index.js +2 -2
  24. package/lib/commonjs/components/Button/index.js.map +1 -1
  25. package/lib/commonjs/components/LineChart/geometry.js +698 -0
  26. package/lib/commonjs/components/LineChart/geometry.js.map +1 -0
  27. package/lib/commonjs/components/LineChart/index.js +747 -0
  28. package/lib/commonjs/components/LineChart/index.js.map +1 -0
  29. package/lib/commonjs/components/LineChart/styles.js +25 -0
  30. package/lib/commonjs/components/LineChart/styles.js.map +1 -0
  31. package/lib/commonjs/components/PieChart/geometry.js +216 -0
  32. package/lib/commonjs/components/PieChart/geometry.js.map +1 -0
  33. package/lib/commonjs/components/PieChart/index.js +476 -0
  34. package/lib/commonjs/components/PieChart/index.js.map +1 -0
  35. package/lib/commonjs/components/PieChart/styles.js +88 -0
  36. package/lib/commonjs/components/PieChart/styles.js.map +1 -0
  37. package/lib/commonjs/components/ProgressCircle/ProgressCircleRing.js +9 -31
  38. package/lib/commonjs/components/ProgressCircle/ProgressCircleRing.js.map +1 -1
  39. package/lib/commonjs/components/ProgressCircle/ProgressRing.js +52 -0
  40. package/lib/commonjs/components/ProgressCircle/ProgressRing.js.map +1 -0
  41. package/lib/commonjs/components/ScrollShadow/useScrollShadow.js +8 -7
  42. package/lib/commonjs/components/ScrollShadow/useScrollShadow.js.map +1 -1
  43. package/lib/commonjs/components/Stepper/index.js +369 -0
  44. package/lib/commonjs/components/Stepper/index.js.map +1 -0
  45. package/lib/commonjs/components/Stepper/styles.js +211 -0
  46. package/lib/commonjs/components/Stepper/styles.js.map +1 -0
  47. package/lib/commonjs/components/Stepper/useStepperLabelFit.js +22 -0
  48. package/lib/commonjs/components/Stepper/useStepperLabelFit.js.map +1 -0
  49. package/lib/commonjs/components/Stepper/useStepperLabelFit.web.js +52 -0
  50. package/lib/commonjs/components/Stepper/useStepperLabelFit.web.js.map +1 -0
  51. package/lib/commonjs/components/Stepper/useStepperRingColors.js +31 -0
  52. package/lib/commonjs/components/Stepper/useStepperRingColors.js.map +1 -0
  53. package/lib/commonjs/components/SystemAlert/animation.js +218 -0
  54. package/lib/commonjs/components/SystemAlert/animation.js.map +1 -0
  55. package/lib/commonjs/components/SystemAlert/index.js +525 -0
  56. package/lib/commonjs/components/SystemAlert/index.js.map +1 -0
  57. package/lib/commonjs/components/SystemAlert/styles.js +178 -0
  58. package/lib/commonjs/components/SystemAlert/styles.js.map +1 -0
  59. package/lib/commonjs/components/SystemAlert/useSystemAlertStatusBarStyle.js +53 -0
  60. package/lib/commonjs/components/SystemAlert/useSystemAlertStatusBarStyle.js.map +1 -0
  61. package/lib/commonjs/components/Tabs/index.js +4 -0
  62. package/lib/commonjs/components/Tabs/index.js.map +1 -1
  63. package/lib/commonjs/components/Tabs/styles.js +1 -1
  64. package/lib/commonjs/components/Tabs/styles.js.map +1 -1
  65. package/lib/commonjs/components/chart/ChartInspector.js +610 -0
  66. package/lib/commonjs/components/chart/ChartInspector.js.map +1 -0
  67. package/lib/commonjs/components/chart/format.js +93 -0
  68. package/lib/commonjs/components/chart/format.js.map +1 -0
  69. package/lib/commonjs/components/chart/index.js +2 -0
  70. package/lib/commonjs/components/chart/index.js.map +1 -0
  71. package/lib/commonjs/components/chart/motion.js +97 -0
  72. package/lib/commonjs/components/chart/motion.js.map +1 -0
  73. package/lib/commonjs/components/chart/palette.js +178 -0
  74. package/lib/commonjs/components/chart/palette.js.map +1 -0
  75. package/lib/commonjs/components/chart/size.js +34 -0
  76. package/lib/commonjs/components/chart/size.js.map +1 -0
  77. package/lib/commonjs/components/chart/ticks.js +59 -0
  78. package/lib/commonjs/components/chart/ticks.js.map +1 -0
  79. package/lib/commonjs/components/chart/types.js +6 -0
  80. package/lib/commonjs/components/chart/types.js.map +1 -0
  81. package/lib/commonjs/components/chart/useChartHostWidth.js +27 -0
  82. package/lib/commonjs/components/chart/useChartHostWidth.js.map +1 -0
  83. package/lib/commonjs/components/index.js +60 -0
  84. package/lib/commonjs/components/index.js.map +1 -1
  85. package/lib/commonjs/figma/SystemAlert.Button.figma.js +28 -0
  86. package/lib/commonjs/figma/SystemAlert.Button.figma.js.map +1 -0
  87. package/lib/commonjs/figma/SystemAlert.Close.figma.js +22 -0
  88. package/lib/commonjs/figma/SystemAlert.Close.figma.js.map +1 -0
  89. package/lib/commonjs/figma/SystemAlert.Description.figma.js +20 -0
  90. package/lib/commonjs/figma/SystemAlert.Description.figma.js.map +1 -0
  91. package/lib/commonjs/figma/SystemAlert.IconButton.figma.js +31 -0
  92. package/lib/commonjs/figma/SystemAlert.IconButton.figma.js.map +1 -0
  93. package/lib/commonjs/figma/SystemAlert.figma.js +48 -0
  94. package/lib/commonjs/figma/SystemAlert.figma.js.map +1 -0
  95. package/lib/module/components/BarChart/geometry.js +1110 -0
  96. package/lib/module/components/BarChart/geometry.js.map +1 -0
  97. package/lib/module/components/BarChart/index.js +936 -0
  98. package/lib/module/components/BarChart/index.js.map +1 -0
  99. package/lib/module/components/BarChart/styles.js +22 -0
  100. package/lib/module/components/BarChart/styles.js.map +1 -0
  101. package/lib/module/components/Button/index.js +2 -2
  102. package/lib/module/components/Button/index.js.map +1 -1
  103. package/lib/module/components/LineChart/geometry.js +685 -0
  104. package/lib/module/components/LineChart/geometry.js.map +1 -0
  105. package/lib/module/components/LineChart/index.js +741 -0
  106. package/lib/module/components/LineChart/index.js.map +1 -0
  107. package/lib/module/components/LineChart/styles.js +21 -0
  108. package/lib/module/components/LineChart/styles.js.map +1 -0
  109. package/lib/module/components/PieChart/geometry.js +209 -0
  110. package/lib/module/components/PieChart/geometry.js.map +1 -0
  111. package/lib/module/components/PieChart/index.js +471 -0
  112. package/lib/module/components/PieChart/index.js.map +1 -0
  113. package/lib/module/components/PieChart/styles.js +84 -0
  114. package/lib/module/components/PieChart/styles.js.map +1 -0
  115. package/lib/module/components/ProgressCircle/ProgressCircleRing.js +10 -32
  116. package/lib/module/components/ProgressCircle/ProgressCircleRing.js.map +1 -1
  117. package/lib/module/components/ProgressCircle/ProgressRing.js +48 -0
  118. package/lib/module/components/ProgressCircle/ProgressRing.js.map +1 -0
  119. package/lib/module/components/ScrollShadow/useScrollShadow.js +8 -7
  120. package/lib/module/components/ScrollShadow/useScrollShadow.js.map +1 -1
  121. package/lib/module/components/Stepper/index.js +360 -0
  122. package/lib/module/components/Stepper/index.js.map +1 -0
  123. package/lib/module/components/Stepper/styles.js +206 -0
  124. package/lib/module/components/Stepper/styles.js.map +1 -0
  125. package/lib/module/components/Stepper/useStepperLabelFit.js +18 -0
  126. package/lib/module/components/Stepper/useStepperLabelFit.js.map +1 -0
  127. package/lib/module/components/Stepper/useStepperLabelFit.web.js +48 -0
  128. package/lib/module/components/Stepper/useStepperLabelFit.web.js.map +1 -0
  129. package/lib/module/components/Stepper/useStepperRingColors.js +28 -0
  130. package/lib/module/components/Stepper/useStepperRingColors.js.map +1 -0
  131. package/lib/module/components/SystemAlert/animation.js +213 -0
  132. package/lib/module/components/SystemAlert/animation.js.map +1 -0
  133. package/lib/module/components/SystemAlert/index.js +515 -0
  134. package/lib/module/components/SystemAlert/index.js.map +1 -0
  135. package/lib/module/components/SystemAlert/styles.js +174 -0
  136. package/lib/module/components/SystemAlert/styles.js.map +1 -0
  137. package/lib/module/components/SystemAlert/useSystemAlertStatusBarStyle.js +49 -0
  138. package/lib/module/components/SystemAlert/useSystemAlertStatusBarStyle.js.map +1 -0
  139. package/lib/module/components/Tabs/index.js +4 -0
  140. package/lib/module/components/Tabs/index.js.map +1 -1
  141. package/lib/module/components/Tabs/styles.js +1 -1
  142. package/lib/module/components/Tabs/styles.js.map +1 -1
  143. package/lib/module/components/chart/ChartInspector.js +600 -0
  144. package/lib/module/components/chart/ChartInspector.js.map +1 -0
  145. package/lib/module/components/chart/format.js +84 -0
  146. package/lib/module/components/chart/format.js.map +1 -0
  147. package/lib/module/components/chart/index.js +2 -0
  148. package/lib/module/components/chart/index.js.map +1 -0
  149. package/lib/module/components/chart/motion.js +89 -0
  150. package/lib/module/components/chart/motion.js.map +1 -0
  151. package/lib/module/components/chart/palette.js +168 -0
  152. package/lib/module/components/chart/palette.js.map +1 -0
  153. package/lib/module/components/chart/size.js +29 -0
  154. package/lib/module/components/chart/size.js.map +1 -0
  155. package/lib/module/components/chart/ticks.js +55 -0
  156. package/lib/module/components/chart/ticks.js.map +1 -0
  157. package/lib/module/components/chart/types.js +4 -0
  158. package/lib/module/components/chart/types.js.map +1 -0
  159. package/lib/module/components/chart/useChartHostWidth.js +23 -0
  160. package/lib/module/components/chart/useChartHostWidth.js.map +1 -0
  161. package/lib/module/components/index.js +5 -0
  162. package/lib/module/components/index.js.map +1 -1
  163. package/lib/module/figma/SystemAlert.Button.figma.js +22 -0
  164. package/lib/module/figma/SystemAlert.Button.figma.js.map +1 -0
  165. package/lib/module/figma/SystemAlert.Close.figma.js +18 -0
  166. package/lib/module/figma/SystemAlert.Close.figma.js.map +1 -0
  167. package/lib/module/figma/SystemAlert.Description.figma.js +14 -0
  168. package/lib/module/figma/SystemAlert.Description.figma.js.map +1 -0
  169. package/lib/module/figma/SystemAlert.IconButton.figma.js +25 -0
  170. package/lib/module/figma/SystemAlert.IconButton.figma.js.map +1 -0
  171. package/lib/module/figma/SystemAlert.figma.js +42 -0
  172. package/lib/module/figma/SystemAlert.figma.js.map +1 -0
  173. package/lib/typescript/components/BarChart/geometry.d.ts +236 -0
  174. package/lib/typescript/components/BarChart/geometry.d.ts.map +1 -0
  175. package/lib/typescript/components/BarChart/index.d.ts +193 -0
  176. package/lib/typescript/components/BarChart/index.d.ts.map +1 -0
  177. package/lib/typescript/components/BarChart/styles.d.ts +32 -0
  178. package/lib/typescript/components/BarChart/styles.d.ts.map +1 -0
  179. package/lib/typescript/components/LineChart/geometry.d.ts +248 -0
  180. package/lib/typescript/components/LineChart/geometry.d.ts.map +1 -0
  181. package/lib/typescript/components/LineChart/index.d.ts +105 -0
  182. package/lib/typescript/components/LineChart/index.d.ts.map +1 -0
  183. package/lib/typescript/components/LineChart/styles.d.ts +12 -0
  184. package/lib/typescript/components/LineChart/styles.d.ts.map +1 -0
  185. package/lib/typescript/components/PieChart/geometry.d.ts +43 -0
  186. package/lib/typescript/components/PieChart/geometry.d.ts.map +1 -0
  187. package/lib/typescript/components/PieChart/index.d.ts +147 -0
  188. package/lib/typescript/components/PieChart/index.d.ts.map +1 -0
  189. package/lib/typescript/components/PieChart/styles.d.ts +27 -0
  190. package/lib/typescript/components/PieChart/styles.d.ts.map +1 -0
  191. package/lib/typescript/components/ProgressCircle/ProgressCircleRing.d.ts.map +1 -1
  192. package/lib/typescript/components/ProgressCircle/ProgressRing.d.ts +17 -0
  193. package/lib/typescript/components/ProgressCircle/ProgressRing.d.ts.map +1 -0
  194. package/lib/typescript/components/ScrollShadow/useScrollShadow.d.ts.map +1 -1
  195. package/lib/typescript/components/Stepper/index.d.ts +68 -0
  196. package/lib/typescript/components/Stepper/index.d.ts.map +1 -0
  197. package/lib/typescript/components/Stepper/styles.d.ts +46 -0
  198. package/lib/typescript/components/Stepper/styles.d.ts.map +1 -0
  199. package/lib/typescript/components/Stepper/useStepperLabelFit.d.ts +15 -0
  200. package/lib/typescript/components/Stepper/useStepperLabelFit.d.ts.map +1 -0
  201. package/lib/typescript/components/Stepper/useStepperLabelFit.web.d.ts +10 -0
  202. package/lib/typescript/components/Stepper/useStepperLabelFit.web.d.ts.map +1 -0
  203. package/lib/typescript/components/Stepper/useStepperRingColors.d.ts +6 -0
  204. package/lib/typescript/components/Stepper/useStepperRingColors.d.ts.map +1 -0
  205. package/lib/typescript/components/SystemAlert/animation.d.ts +56 -0
  206. package/lib/typescript/components/SystemAlert/animation.d.ts.map +1 -0
  207. package/lib/typescript/components/SystemAlert/index.d.ts +110 -0
  208. package/lib/typescript/components/SystemAlert/index.d.ts.map +1 -0
  209. package/lib/typescript/components/SystemAlert/styles.d.ts +38 -0
  210. package/lib/typescript/components/SystemAlert/styles.d.ts.map +1 -0
  211. package/lib/typescript/components/SystemAlert/useSystemAlertStatusBarStyle.d.ts +14 -0
  212. package/lib/typescript/components/SystemAlert/useSystemAlertStatusBarStyle.d.ts.map +1 -0
  213. package/lib/typescript/components/Tabs/index.d.ts.map +1 -1
  214. package/lib/typescript/components/chart/ChartInspector.d.ts +101 -0
  215. package/lib/typescript/components/chart/ChartInspector.d.ts.map +1 -0
  216. package/lib/typescript/components/chart/format.d.ts +16 -0
  217. package/lib/typescript/components/chart/format.d.ts.map +1 -0
  218. package/lib/typescript/components/chart/index.d.ts +3 -0
  219. package/lib/typescript/components/chart/index.d.ts.map +1 -0
  220. package/lib/typescript/components/chart/motion.d.ts +27 -0
  221. package/lib/typescript/components/chart/motion.d.ts.map +1 -0
  222. package/lib/typescript/components/chart/palette.d.ts +44 -0
  223. package/lib/typescript/components/chart/palette.d.ts.map +1 -0
  224. package/lib/typescript/components/chart/size.d.ts +25 -0
  225. package/lib/typescript/components/chart/size.d.ts.map +1 -0
  226. package/lib/typescript/components/chart/ticks.d.ts +3 -0
  227. package/lib/typescript/components/chart/ticks.d.ts.map +1 -0
  228. package/lib/typescript/components/chart/types.d.ts +163 -0
  229. package/lib/typescript/components/chart/types.d.ts.map +1 -0
  230. package/lib/typescript/components/chart/useChartHostWidth.d.ts +9 -0
  231. package/lib/typescript/components/chart/useChartHostWidth.d.ts.map +1 -0
  232. package/lib/typescript/components/index.d.ts +5 -0
  233. package/lib/typescript/components/index.d.ts.map +1 -1
  234. package/lib/typescript/figma/SystemAlert.Button.figma.d.ts +11 -0
  235. package/lib/typescript/figma/SystemAlert.Button.figma.d.ts.map +1 -0
  236. package/lib/typescript/figma/SystemAlert.Close.figma.d.ts +11 -0
  237. package/lib/typescript/figma/SystemAlert.Close.figma.d.ts.map +1 -0
  238. package/lib/typescript/figma/SystemAlert.Description.figma.d.ts +8 -0
  239. package/lib/typescript/figma/SystemAlert.Description.figma.d.ts.map +1 -0
  240. package/lib/typescript/figma/SystemAlert.IconButton.figma.d.ts +11 -0
  241. package/lib/typescript/figma/SystemAlert.IconButton.figma.d.ts.map +1 -0
  242. package/lib/typescript/figma/SystemAlert.figma.d.ts +8 -0
  243. package/lib/typescript/figma/SystemAlert.figma.d.ts.map +1 -0
  244. package/package.json +5 -5
  245. package/src/components/BarChart/geometry.ts +1469 -0
  246. package/src/components/BarChart/index.tsx +1424 -0
  247. package/src/components/BarChart/styles.ts +31 -0
  248. package/src/components/Button/index.tsx +1 -1
  249. package/src/components/LineChart/geometry.ts +957 -0
  250. package/src/components/LineChart/index.tsx +1109 -0
  251. package/src/components/LineChart/styles.ts +26 -0
  252. package/src/components/PieChart/geometry.ts +295 -0
  253. package/src/components/PieChart/index.tsx +715 -0
  254. package/src/components/PieChart/styles.ts +101 -0
  255. package/src/components/ProgressCircle/ProgressCircleRing.tsx +10 -39
  256. package/src/components/ProgressCircle/ProgressRing.tsx +60 -0
  257. package/src/components/ScrollShadow/useScrollShadow.ts +12 -11
  258. package/src/components/Stepper/index.tsx +452 -0
  259. package/src/components/Stepper/styles.ts +234 -0
  260. package/src/components/Stepper/useStepperLabelFit.ts +21 -0
  261. package/src/components/Stepper/useStepperLabelFit.web.ts +53 -0
  262. package/src/components/Stepper/useStepperRingColors.ts +29 -0
  263. package/src/components/SystemAlert/animation.ts +252 -0
  264. package/src/components/SystemAlert/index.tsx +684 -0
  265. package/src/components/SystemAlert/styles.ts +212 -0
  266. package/src/components/SystemAlert/useSystemAlertStatusBarStyle.ts +57 -0
  267. package/src/components/Tabs/index.tsx +4 -0
  268. package/src/components/Tabs/styles.ts +1 -1
  269. package/src/components/chart/ChartInspector.tsx +726 -0
  270. package/src/components/chart/format.ts +95 -0
  271. package/src/components/chart/index.ts +24 -0
  272. package/src/components/chart/motion.ts +98 -0
  273. package/src/components/chart/palette.tsx +247 -0
  274. package/src/components/chart/size.ts +21 -0
  275. package/src/components/chart/ticks.ts +53 -0
  276. package/src/components/chart/types.ts +183 -0
  277. package/src/components/chart/useChartHostWidth.ts +26 -0
  278. package/src/components/index.ts +5 -0
@@ -0,0 +1,26 @@
1
+ import { cva, type VariantProps } from '@cdx-ui/utils';
2
+
3
+ export const lineChartRootVariants = cva('w-full max-w-full items-center gap-4');
4
+
5
+ export const lineChartLegendVariants = cva(
6
+ 'max-w-full flex-row flex-wrap items-center justify-center gap-x-4 gap-y-2',
7
+ );
8
+
9
+ export const lineChartLegendItemVariants = cva('flex-row items-center gap-1.5');
10
+
11
+ export const lineChartLegendLabelVariants = cva('body-sm text-content-primary', {
12
+ variants: {
13
+ selected: {
14
+ true: 'font-medium text-content-primary',
15
+ false: '',
16
+ },
17
+ },
18
+ defaultVariants: {
19
+ selected: false,
20
+ },
21
+ });
22
+
23
+ export type LineChartLegendLabelVariantProps = VariantProps<typeof lineChartLegendLabelVariants>;
24
+ export const LINE_STROKE_WIDTH = 2;
25
+ export const LINE_DOT_RADIUS = 3;
26
+ export const LINE_ACTIVE_DOT_RADIUS = 5;
@@ -0,0 +1,295 @@
1
+ export interface PieSliceInput {
2
+ readonly id: string;
3
+ readonly label: string;
4
+ readonly value: number;
5
+ }
6
+
7
+ export interface PieSliceLayout {
8
+ readonly id: string;
9
+ readonly index: number;
10
+ readonly label: string;
11
+ readonly value: number;
12
+ readonly percentage: number;
13
+ readonly startAngle: number;
14
+ readonly endAngle: number;
15
+ readonly path: string;
16
+ }
17
+
18
+ export interface PieRadii {
19
+ readonly cx: number;
20
+ readonly cy: number;
21
+ readonly outerRadius: number;
22
+ readonly innerRadius: number;
23
+ }
24
+
25
+ export interface SlicePathOptions extends PieRadii {
26
+ readonly startAngle: number;
27
+ readonly endAngle: number;
28
+ readonly cornerRadius?: number;
29
+ }
30
+
31
+ const FULL_CIRCLE = 359.999;
32
+ const MAX_INNER_RADIUS_RATIO = 0.85;
33
+
34
+ function clamp(value: number, min: number, max: number): number {
35
+ return Math.min(max, Math.max(min, value));
36
+ }
37
+
38
+ function formatCoordinate(value: number): string {
39
+ 'worklet';
40
+ const rounded = Math.round(value * 100) / 100;
41
+ return Object.is(rounded, -0) ? '0' : String(rounded);
42
+ }
43
+
44
+ function point(cx: number, cy: number, radius: number, angleFromTop: number) {
45
+ 'worklet';
46
+ const radians = ((angleFromTop - 90) * Math.PI) / 180;
47
+ return {
48
+ x: cx + radius * Math.cos(radians),
49
+ y: cy + radius * Math.sin(radians),
50
+ };
51
+ }
52
+
53
+ function moveTo(x: number, y: number): string {
54
+ 'worklet';
55
+ return `M ${formatCoordinate(x)} ${formatCoordinate(y)}`;
56
+ }
57
+
58
+ function lineTo(x: number, y: number): string {
59
+ 'worklet';
60
+ return `L ${formatCoordinate(x)} ${formatCoordinate(y)}`;
61
+ }
62
+
63
+ function arcTo(
64
+ radius: number,
65
+ end: { readonly x: number; readonly y: number },
66
+ largeArc: 0 | 1,
67
+ sweep: 0 | 1,
68
+ ): string {
69
+ 'worklet';
70
+ return `A ${formatCoordinate(radius)} ${formatCoordinate(radius)} 0 ${String(largeArc)} ${String(sweep)} ${formatCoordinate(end.x)} ${formatCoordinate(end.y)}`;
71
+ }
72
+
73
+ /**
74
+ * SVG arc commands cannot draw a 360° sweep in one segment, so a full ring is
75
+ * two semicircles.
76
+ */
77
+ export function slicePath({
78
+ cx,
79
+ cy,
80
+ outerRadius,
81
+ innerRadius,
82
+ startAngle,
83
+ endAngle,
84
+ cornerRadius = 0,
85
+ }: SlicePathOptions): string {
86
+ 'worklet';
87
+ const sweep = endAngle - startAngle;
88
+ if (sweep <= 0 || outerRadius <= 0) {
89
+ return '';
90
+ }
91
+
92
+ const isFullCircle = sweep >= FULL_CIRCLE;
93
+ const drawEnd = isFullCircle ? startAngle + FULL_CIRCLE : endAngle;
94
+ const largeArc: 0 | 1 = sweep > 180 ? 1 : 0;
95
+
96
+ if (innerRadius <= 0) {
97
+ if (isFullCircle) {
98
+ const start = point(cx, cy, outerRadius, startAngle);
99
+ const mid = point(cx, cy, outerRadius, startAngle + 180);
100
+ return [
101
+ moveTo(start.x, start.y),
102
+ arcTo(outerRadius, mid, 1, 1),
103
+ arcTo(outerRadius, start, 1, 1),
104
+ 'Z',
105
+ ].join(' ');
106
+ }
107
+
108
+ if (cornerRadius > 0) {
109
+ const sweepRad = (sweep * Math.PI) / 180;
110
+ const half = Math.sin(Math.min(sweepRad / 2, Math.PI / 2));
111
+ const maxRcByAngle = (outerRadius * half) / (1 + half) - 0.5;
112
+ const rc = Math.max(0, Math.min(cornerRadius, outerRadius / 2 - 0.5, maxRcByAngle));
113
+ if (rc >= 0.5) {
114
+ const alphaDeg = (Math.asin(rc / (outerRadius - rc)) * 180) / Math.PI;
115
+ const outerArcSweep = sweep - 2 * alphaDeg;
116
+ if (outerArcSweep > 0) {
117
+ const along = Math.sqrt((outerRadius - rc) ** 2 - rc ** 2);
118
+ const p1 = point(cx, cy, along, startAngle);
119
+ const p2 = point(cx, cy, outerRadius, startAngle + alphaDeg);
120
+ const p3 = point(cx, cy, outerRadius, endAngle - alphaDeg);
121
+ const p4 = point(cx, cy, along, endAngle);
122
+ return [
123
+ moveTo(cx, cy),
124
+ lineTo(p1.x, p1.y),
125
+ arcTo(rc, p2, 0, 1),
126
+ arcTo(outerRadius, p3, outerArcSweep > 180 ? 1 : 0, 1),
127
+ arcTo(rc, p4, 0, 1),
128
+ 'Z',
129
+ ].join(' ');
130
+ }
131
+ }
132
+ }
133
+
134
+ const start = point(cx, cy, outerRadius, startAngle);
135
+ const end = point(cx, cy, outerRadius, drawEnd);
136
+ return [
137
+ moveTo(cx, cy),
138
+ lineTo(start.x, start.y),
139
+ arcTo(outerRadius, end, largeArc, 1),
140
+ 'Z',
141
+ ].join(' ');
142
+ }
143
+
144
+ if (isFullCircle) {
145
+ const outerStart = point(cx, cy, outerRadius, startAngle);
146
+ const outerMid = point(cx, cy, outerRadius, startAngle + 180);
147
+ const innerStart = point(cx, cy, innerRadius, startAngle);
148
+ const innerMid = point(cx, cy, innerRadius, startAngle + 180);
149
+ return [
150
+ moveTo(outerStart.x, outerStart.y),
151
+ arcTo(outerRadius, outerMid, 1, 1),
152
+ arcTo(outerRadius, outerStart, 1, 1),
153
+ lineTo(innerStart.x, innerStart.y),
154
+ arcTo(innerRadius, innerMid, 1, 0),
155
+ arcTo(innerRadius, innerStart, 1, 0),
156
+ 'Z',
157
+ ].join(' ');
158
+ }
159
+
160
+ // Rounded corner donut slice
161
+ if (cornerRadius > 0) {
162
+ const maxRcByThickness = (outerRadius - innerRadius) / 2 - 0.5;
163
+ const sweepRad = (sweep * Math.PI) / 180;
164
+ const maxSin = Math.sin(Math.min(sweepRad / 2.5, Math.PI / 2 - 0.05));
165
+ const maxRcByAngle = maxSin < 0.99 ? (innerRadius * maxSin) / (1 - maxSin) : maxRcByThickness;
166
+ const rc = Math.max(0, Math.min(cornerRadius, maxRcByThickness, maxRcByAngle));
167
+
168
+ if (rc >= 0.5) {
169
+ const alphaRad = Math.asin(rc / (outerRadius - rc));
170
+ const betaRad = Math.asin(rc / (innerRadius + rc));
171
+ const alphaDeg = (alphaRad * 180) / Math.PI;
172
+ const betaDeg = (betaRad * 180) / Math.PI;
173
+
174
+ const outerArcSweep = sweep - 2 * alphaDeg;
175
+ const innerArcSweep = sweep - 2 * betaDeg;
176
+
177
+ if (outerArcSweep > 0 && innerArcSweep > 0) {
178
+ const L_out = Math.sqrt((outerRadius - rc) ** 2 - rc ** 2);
179
+ const L_in = Math.sqrt((innerRadius + rc) ** 2 - rc ** 2);
180
+
181
+ const p1 = point(cx, cy, L_out, startAngle);
182
+ const p2 = point(cx, cy, outerRadius, startAngle + alphaDeg);
183
+ const p3 = point(cx, cy, outerRadius, endAngle - alphaDeg);
184
+ const p4 = point(cx, cy, L_out, endAngle);
185
+ const p5 = point(cx, cy, L_in, endAngle);
186
+ const p6 = point(cx, cy, innerRadius, endAngle - betaDeg);
187
+ const p7 = point(cx, cy, innerRadius, startAngle + betaDeg);
188
+ const p8 = point(cx, cy, L_in, startAngle);
189
+
190
+ return [
191
+ moveTo(p1.x, p1.y),
192
+ arcTo(rc, p2, 0, 1),
193
+ arcTo(outerRadius, p3, outerArcSweep > 180 ? 1 : 0, 1),
194
+ arcTo(rc, p4, 0, 1),
195
+ lineTo(p5.x, p5.y),
196
+ arcTo(rc, p6, 0, 1),
197
+ arcTo(innerRadius, p7, innerArcSweep > 180 ? 1 : 0, 0),
198
+ arcTo(rc, p8, 0, 1),
199
+ 'Z',
200
+ ].join(' ');
201
+ }
202
+ }
203
+ }
204
+
205
+ const outerStart = point(cx, cy, outerRadius, startAngle);
206
+ const outerEnd = point(cx, cy, outerRadius, drawEnd);
207
+ const innerEnd = point(cx, cy, innerRadius, drawEnd);
208
+ const innerStart = point(cx, cy, innerRadius, startAngle);
209
+ return [
210
+ moveTo(outerStart.x, outerStart.y),
211
+ arcTo(outerRadius, outerEnd, largeArc, 1),
212
+ lineTo(innerEnd.x, innerEnd.y),
213
+ arcTo(innerRadius, innerStart, largeArc, 0),
214
+ 'Z',
215
+ ].join(' ');
216
+ }
217
+
218
+ export function pieRadii(size: number, innerRadiusRatio: number): PieRadii {
219
+ const outerRadius = Math.max(size / 2 - 1, 0);
220
+ return {
221
+ cx: size / 2,
222
+ cy: size / 2,
223
+ outerRadius,
224
+ innerRadius: outerRadius * clamp(innerRadiusRatio, 0, MAX_INNER_RADIUS_RATIO),
225
+ };
226
+ }
227
+
228
+ /** `innerRadius` in pixels or as a percent of the outer radius, as a 0–1 ratio. */
229
+ export function resolveInnerRadiusRatio(innerRadius: number | string, size: number): number {
230
+ const outerRadius = Math.max(size / 2 - 1, 0);
231
+ if (typeof innerRadius === 'string') {
232
+ const percent = Number.parseFloat(innerRadius);
233
+ return Number.isFinite(percent) ? percent / 100 : 0;
234
+ }
235
+ if (!Number.isFinite(innerRadius) || outerRadius <= 0) {
236
+ return 0;
237
+ }
238
+ return innerRadius / outerRadius;
239
+ }
240
+
241
+ export function layoutPieSlices({
242
+ data,
243
+ size,
244
+ innerRadiusRatio,
245
+ paddingAngle = 0,
246
+ cornerRadius,
247
+ }: {
248
+ readonly data: readonly PieSliceInput[];
249
+ readonly size: number;
250
+ readonly innerRadiusRatio: number;
251
+ /** Degrees between neighboring slices. */
252
+ readonly paddingAngle?: number;
253
+ readonly cornerRadius?: number;
254
+ }): PieSliceLayout[] {
255
+ const valid = data
256
+ .map((slice, index) => ({ slice, index }))
257
+ .filter(({ slice }) => Number.isFinite(slice.value) && slice.value > 0);
258
+
259
+ const total = valid.reduce((sum, item) => sum + item.slice.value, 0);
260
+ if (total <= 0 || size <= 0) {
261
+ return [];
262
+ }
263
+
264
+ const { cx, cy, outerRadius, innerRadius } = pieRadii(size, innerRadiusRatio);
265
+ const gap = valid.length > 1 && Number.isFinite(paddingAngle) ? Math.max(paddingAngle, 0) : 0;
266
+ let cursor = 0;
267
+
268
+ return valid.map(({ slice, index }) => {
269
+ const percentage = slice.value / total;
270
+ const sweep = percentage * 360;
271
+ const appliedGap = sweep > gap * 2 ? gap : 0;
272
+ const startAngle = cursor + appliedGap / 2;
273
+ const endAngle = cursor + sweep - appliedGap / 2;
274
+ cursor += sweep;
275
+
276
+ return {
277
+ id: slice.id,
278
+ index,
279
+ label: slice.label,
280
+ value: slice.value,
281
+ percentage,
282
+ startAngle,
283
+ endAngle,
284
+ path: slicePath({
285
+ cx,
286
+ cy,
287
+ outerRadius,
288
+ innerRadius,
289
+ startAngle,
290
+ endAngle,
291
+ cornerRadius,
292
+ }),
293
+ };
294
+ });
295
+ }