@seekalfred/primitives 0.6.0 → 0.7.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 (322) hide show
  1. package/README.md +19 -11
  2. package/dist/activity-heatmap/activity-heatmap.d.ts +92 -0
  3. package/dist/activity-heatmap/activity-heatmap.js +699 -0
  4. package/dist/activity-heatmap/activity-heatmap.js.map +1 -0
  5. package/dist/activity-heatmap/index.d.ts +2 -0
  6. package/dist/activity-heatmap/index.js +2 -0
  7. package/dist/alert/alert.d.ts +5 -1
  8. package/dist/alert/alert.js +68 -7
  9. package/dist/alert/alert.js.map +1 -1
  10. package/dist/alert-dialog/alert-dialog.d.ts +45 -18
  11. package/dist/alert-dialog/alert-dialog.js +128 -9
  12. package/dist/alert-dialog/alert-dialog.js.map +1 -1
  13. package/dist/alert-dialog/index.d.ts +2 -2
  14. package/dist/alert-dialog/index.js +2 -2
  15. package/dist/animated-counter/animated-counter.d.ts +38 -0
  16. package/dist/animated-counter/animated-counter.js +230 -0
  17. package/dist/animated-counter/animated-counter.js.map +1 -0
  18. package/dist/animated-counter/index.d.ts +2 -0
  19. package/dist/animated-counter/index.js +2 -0
  20. package/dist/announcement-bar/announcement-bar.d.ts +67 -0
  21. package/dist/announcement-bar/announcement-bar.js +364 -0
  22. package/dist/announcement-bar/announcement-bar.js.map +1 -0
  23. package/dist/announcement-bar/index.d.ts +2 -0
  24. package/dist/announcement-bar/index.js +2 -0
  25. package/dist/badge/badge.d.ts +1 -1
  26. package/dist/bar-chart/bar-chart.d.ts +51 -0
  27. package/dist/bar-chart/bar-chart.js +565 -0
  28. package/dist/bar-chart/bar-chart.js.map +1 -0
  29. package/dist/bar-chart/index.d.ts +2 -0
  30. package/dist/bar-chart/index.js +2 -0
  31. package/dist/breadcrumb/breadcrumb.d.ts +2 -2
  32. package/dist/breadcrumb/breadcrumb.js +12 -3
  33. package/dist/breadcrumb/breadcrumb.js.map +1 -1
  34. package/dist/brush-chart/brush-chart.d.ts +64 -0
  35. package/dist/brush-chart/brush-chart.js +1056 -0
  36. package/dist/brush-chart/brush-chart.js.map +1 -0
  37. package/dist/brush-chart/index.d.ts +2 -0
  38. package/dist/brush-chart/index.js +2 -0
  39. package/dist/button/button.d.ts +2 -2
  40. package/dist/button/button.js +31 -21
  41. package/dist/button/button.js.map +1 -1
  42. package/dist/button-group/button-group.js +3 -4
  43. package/dist/button-group/button-group.js.map +1 -1
  44. package/dist/card/card.js +1 -1
  45. package/dist/card/card.js.map +1 -1
  46. package/dist/card-stack/card-stack.d.ts +54 -0
  47. package/dist/card-stack/card-stack.js +492 -0
  48. package/dist/card-stack/card-stack.js.map +1 -0
  49. package/dist/card-stack/index.d.ts +2 -0
  50. package/dist/card-stack/index.js +2 -0
  51. package/dist/carousel/carousel.d.ts +56 -0
  52. package/dist/carousel/carousel.js +389 -0
  53. package/dist/carousel/carousel.js.map +1 -0
  54. package/dist/carousel/index.d.ts +2 -0
  55. package/dist/carousel/index.js +2 -0
  56. package/dist/checkbox/checkbox.js +4 -4
  57. package/dist/checkbox/checkbox.js.map +1 -1
  58. package/dist/chip-group/chip-group.d.ts +37 -0
  59. package/dist/chip-group/chip-group.js +148 -0
  60. package/dist/chip-group/chip-group.js.map +1 -0
  61. package/dist/chip-group/index.d.ts +2 -0
  62. package/dist/chip-group/index.js +2 -0
  63. package/dist/countdown/countdown.d.ts +45 -0
  64. package/dist/countdown/countdown.js +298 -0
  65. package/dist/countdown/countdown.js.map +1 -0
  66. package/dist/countdown/index.d.ts +2 -0
  67. package/dist/countdown/index.js +2 -0
  68. package/dist/date-picker/picker-parts.js +1 -1
  69. package/dist/date-picker/picker-parts.js.map +1 -1
  70. package/dist/dialog/dialog.js +1 -1
  71. package/dist/dialog/dialog.js.map +1 -1
  72. package/dist/donut-chart/donut-chart.d.ts +64 -0
  73. package/dist/donut-chart/donut-chart.js +576 -0
  74. package/dist/donut-chart/donut-chart.js.map +1 -0
  75. package/dist/donut-chart/index.d.ts +2 -0
  76. package/dist/donut-chart/index.js +2 -0
  77. package/dist/empty-state/empty-state.d.ts +21 -10
  78. package/dist/empty-state/empty-state.js +32 -26
  79. package/dist/empty-state/empty-state.js.map +1 -1
  80. package/dist/empty-state/index.d.ts +2 -2
  81. package/dist/empty-state/index.js +2 -2
  82. package/dist/file-drop-zone/file-drop-zone.js +1 -1
  83. package/dist/file-drop-zone/file-drop-zone.js.map +1 -1
  84. package/dist/filter-bar/filter-bar.d.ts +47 -26
  85. package/dist/filter-bar/filter-bar.js +272 -156
  86. package/dist/filter-bar/filter-bar.js.map +1 -1
  87. package/dist/gauge/gauge.d.ts +45 -0
  88. package/dist/gauge/gauge.js +219 -0
  89. package/dist/gauge/gauge.js.map +1 -0
  90. package/dist/gauge/index.d.ts +2 -0
  91. package/dist/gauge/index.js +2 -0
  92. package/dist/in-view-title/in-view-title.d.ts +33 -0
  93. package/dist/in-view-title/in-view-title.js +119 -0
  94. package/dist/in-view-title/in-view-title.js.map +1 -0
  95. package/dist/in-view-title/index.d.ts +2 -0
  96. package/dist/in-view-title/index.js +2 -0
  97. package/dist/index.d.ts +49 -6
  98. package/dist/index.js +48 -8
  99. package/dist/lib/cn.js +11 -1
  100. package/dist/lib/cn.js.map +1 -1
  101. package/dist/lib/field-message.js +28 -10
  102. package/dist/lib/field-message.js.map +1 -1
  103. package/dist/lib/field-surface.js +9 -8
  104. package/dist/lib/field-surface.js.map +1 -1
  105. package/dist/lib/flag-emoji.js +50 -0
  106. package/dist/lib/flag-emoji.js.map +1 -0
  107. package/dist/lib/flip.js +11 -3
  108. package/dist/lib/flip.js.map +1 -1
  109. package/dist/lib/menu-highlight.js +64 -0
  110. package/dist/lib/menu-highlight.js.map +1 -0
  111. package/dist/lib/motion.js +9 -2
  112. package/dist/lib/motion.js.map +1 -1
  113. package/dist/lib/rolling-value.js +1 -1
  114. package/dist/lib/rolling-value.js.map +1 -1
  115. package/dist/lib/spring-tween.js +500 -0
  116. package/dist/lib/spring-tween.js.map +1 -0
  117. package/dist/lib/swap-text.js +3 -1
  118. package/dist/lib/swap-text.js.map +1 -1
  119. package/dist/line-chart/index.d.ts +2 -0
  120. package/dist/line-chart/index.js +2 -0
  121. package/dist/line-chart/line-chart.d.ts +76 -0
  122. package/dist/line-chart/line-chart.js +611 -0
  123. package/dist/line-chart/line-chart.js.map +1 -0
  124. package/dist/mention-input/index.d.ts +2 -0
  125. package/dist/mention-input/index.js +2 -0
  126. package/dist/mention-input/mention-input.d.ts +98 -0
  127. package/dist/mention-input/mention-input.js +576 -0
  128. package/dist/mention-input/mention-input.js.map +1 -0
  129. package/dist/menu/menu.d.ts +2 -0
  130. package/dist/menu/menu.js +23 -12
  131. package/dist/menu/menu.js.map +1 -1
  132. package/dist/money-input/index.d.ts +2 -0
  133. package/dist/money-input/index.js +2 -0
  134. package/dist/money-input/money-input.d.ts +65 -0
  135. package/dist/money-input/money-input.js +607 -0
  136. package/dist/money-input/money-input.js.map +1 -0
  137. package/dist/morph-select/index.d.ts +2 -0
  138. package/dist/morph-select/index.js +2 -0
  139. package/dist/morph-select/morph-select.d.ts +71 -0
  140. package/dist/morph-select/morph-select.js +693 -0
  141. package/dist/morph-select/morph-select.js.map +1 -0
  142. package/dist/multi-select/index.d.ts +2 -0
  143. package/dist/multi-select/index.js +2 -0
  144. package/dist/multi-select/multi-select.d.ts +36 -0
  145. package/dist/multi-select/multi-select.js +152 -0
  146. package/dist/multi-select/multi-select.js.map +1 -0
  147. package/dist/number-field/index.d.ts +2 -0
  148. package/dist/number-field/index.js +2 -0
  149. package/dist/number-field/number-field.d.ts +42 -0
  150. package/dist/number-field/number-field.js +199 -0
  151. package/dist/number-field/number-field.js.map +1 -0
  152. package/dist/onboarding-checklist/index.d.ts +2 -0
  153. package/dist/onboarding-checklist/index.js +2 -0
  154. package/dist/onboarding-checklist/onboarding-checklist.d.ts +55 -0
  155. package/dist/onboarding-checklist/onboarding-checklist.js +577 -0
  156. package/dist/onboarding-checklist/onboarding-checklist.js.map +1 -0
  157. package/dist/password-field/password-field.js +2 -2
  158. package/dist/password-field/password-field.js.map +1 -1
  159. package/dist/phone-input/index.d.ts +3 -0
  160. package/dist/phone-input/index.js +3 -0
  161. package/dist/phone-input/phone-countries.d.ts +29 -0
  162. package/dist/phone-input/phone-countries.js +170 -0
  163. package/dist/phone-input/phone-countries.js.map +1 -0
  164. package/dist/phone-input/phone-input.d.ts +66 -0
  165. package/dist/phone-input/phone-input.js +440 -0
  166. package/dist/phone-input/phone-input.js.map +1 -0
  167. package/dist/popover/popover.d.ts +12 -0
  168. package/dist/popover/popover.js +31 -7
  169. package/dist/popover/popover.js.map +1 -1
  170. package/dist/progress/progress.js +1 -1
  171. package/dist/radio-group/radio-group.js +1 -1
  172. package/dist/radio-group/radio-group.js.map +1 -1
  173. package/dist/reactions/index.d.ts +2 -0
  174. package/dist/reactions/index.js +2 -0
  175. package/dist/reactions/reactions.d.ts +50 -0
  176. package/dist/reactions/reactions.js +315 -0
  177. package/dist/reactions/reactions.js.map +1 -0
  178. package/dist/rich-text-editor/index.d.ts +3 -0
  179. package/dist/rich-text-editor/index.js +2 -0
  180. package/dist/rich-text-editor/rich-text-editor.d.ts +70 -0
  181. package/dist/rich-text-editor/rich-text-editor.js +909 -0
  182. package/dist/rich-text-editor/rich-text-editor.js.map +1 -0
  183. package/dist/rich-text-editor/rich-text-engine.d.ts +16 -0
  184. package/dist/rich-text-editor/rich-text-engine.js +366 -0
  185. package/dist/rich-text-editor/rich-text-engine.js.map +1 -0
  186. package/dist/rich-text-editor/rich-text-html.js +174 -0
  187. package/dist/rich-text-editor/rich-text-html.js.map +1 -0
  188. package/dist/rich-text-editor/rich-text-icons.js +43 -0
  189. package/dist/rich-text-editor/rich-text-icons.js.map +1 -0
  190. package/dist/ridgeline/index.d.ts +2 -0
  191. package/dist/ridgeline/index.js +2 -0
  192. package/dist/ridgeline/ridgeline.d.ts +55 -0
  193. package/dist/ridgeline/ridgeline.js +701 -0
  194. package/dist/ridgeline/ridgeline.js.map +1 -0
  195. package/dist/scroll-area/index.d.ts +2 -2
  196. package/dist/scroll-area/index.js +2 -2
  197. package/dist/scroll-area/scroll-area.d.ts +68 -31
  198. package/dist/scroll-area/scroll-area.js +208 -59
  199. package/dist/scroll-area/scroll-area.js.map +1 -1
  200. package/dist/scrub-input/evaluate.d.ts +14 -0
  201. package/dist/scrub-input/evaluate.js +72 -0
  202. package/dist/scrub-input/evaluate.js.map +1 -0
  203. package/dist/scrub-input/index.d.ts +3 -0
  204. package/dist/scrub-input/index.js +3 -0
  205. package/dist/scrub-input/scrub-input.d.ts +74 -0
  206. package/dist/scrub-input/scrub-input.js +486 -0
  207. package/dist/scrub-input/scrub-input.js.map +1 -0
  208. package/dist/search-field/search-field.d.ts +2 -1
  209. package/dist/search-field/search-field.js +4 -4
  210. package/dist/search-field/search-field.js.map +1 -1
  211. package/dist/select/select.d.ts +3 -1
  212. package/dist/select/select.js +20 -8
  213. package/dist/select/select.js.map +1 -1
  214. package/dist/separator/separator.d.ts +1 -1
  215. package/dist/sheet/sheet.js +2 -1
  216. package/dist/sheet/sheet.js.map +1 -1
  217. package/dist/shortcut-recorder/index.d.ts +3 -0
  218. package/dist/shortcut-recorder/index.js +3 -0
  219. package/dist/shortcut-recorder/shortcut-model.d.ts +27 -0
  220. package/dist/shortcut-recorder/shortcut-model.js +206 -0
  221. package/dist/shortcut-recorder/shortcut-model.js.map +1 -0
  222. package/dist/shortcut-recorder/shortcut-recorder.d.ts +93 -0
  223. package/dist/shortcut-recorder/shortcut-recorder.js +489 -0
  224. package/dist/shortcut-recorder/shortcut-recorder.js.map +1 -0
  225. package/dist/slider/index.d.ts +2 -2
  226. package/dist/slider/slider.d.ts +46 -14
  227. package/dist/slider/slider.js +151 -67
  228. package/dist/slider/slider.js.map +1 -1
  229. package/dist/slope-chart/index.d.ts +2 -0
  230. package/dist/slope-chart/index.js +2 -0
  231. package/dist/slope-chart/slope-chart.d.ts +54 -0
  232. package/dist/slope-chart/slope-chart.js +568 -0
  233. package/dist/slope-chart/slope-chart.js.map +1 -0
  234. package/dist/sparkline/index.d.ts +2 -0
  235. package/dist/sparkline/index.js +2 -0
  236. package/dist/sparkline/sparkline.d.ts +46 -0
  237. package/dist/sparkline/sparkline.js +390 -0
  238. package/dist/sparkline/sparkline.js.map +1 -0
  239. package/dist/split-bar/index.d.ts +2 -0
  240. package/dist/split-bar/index.js +2 -0
  241. package/dist/split-bar/split-bar.d.ts +62 -0
  242. package/dist/split-bar/split-bar.js +513 -0
  243. package/dist/split-bar/split-bar.js.map +1 -0
  244. package/dist/split-button/split-button.d.ts +1 -1
  245. package/dist/split-button/split-button.js +12 -11
  246. package/dist/split-button/split-button.js.map +1 -1
  247. package/dist/stat-card/index.d.ts +2 -2
  248. package/dist/stat-card/index.js +2 -2
  249. package/dist/stat-card/stat-card.d.ts +24 -4
  250. package/dist/stat-card/stat-card.js +114 -17
  251. package/dist/stat-card/stat-card.js.map +1 -1
  252. package/dist/stepper/index.d.ts +2 -0
  253. package/dist/stepper/index.js +2 -0
  254. package/dist/stepper/stepper.d.ts +51 -0
  255. package/dist/stepper/stepper.js +215 -0
  256. package/dist/stepper/stepper.js.map +1 -0
  257. package/dist/streamgraph/index.d.ts +2 -0
  258. package/dist/streamgraph/index.js +2 -0
  259. package/dist/streamgraph/streamgraph.d.ts +70 -0
  260. package/dist/streamgraph/streamgraph.js +613 -0
  261. package/dist/streamgraph/streamgraph.js.map +1 -0
  262. package/dist/styles.css +1 -1
  263. package/dist/swipe-actions/index.d.ts +2 -0
  264. package/dist/swipe-actions/index.js +2 -0
  265. package/dist/swipe-actions/swipe-actions.d.ts +67 -0
  266. package/dist/swipe-actions/swipe-actions.js +552 -0
  267. package/dist/swipe-actions/swipe-actions.js.map +1 -0
  268. package/dist/switch/switch.js +2 -2
  269. package/dist/switch/switch.js.map +1 -1
  270. package/dist/table/index.d.ts +2 -2
  271. package/dist/table/index.js +2 -2
  272. package/dist/table/table.d.ts +56 -4
  273. package/dist/table/table.js +340 -165
  274. package/dist/table/table.js.map +1 -1
  275. package/dist/tabs/tabs.js +2 -2
  276. package/dist/tabs/tabs.js.map +1 -1
  277. package/dist/tag-input/index.d.ts +2 -0
  278. package/dist/tag-input/index.js +2 -0
  279. package/dist/tag-input/tag-input.d.ts +40 -0
  280. package/dist/tag-input/tag-input.js +269 -0
  281. package/dist/tag-input/tag-input.js.map +1 -0
  282. package/dist/text-morph/index.d.ts +2 -0
  283. package/dist/text-morph/index.js +2 -0
  284. package/dist/text-morph/text-morph.d.ts +23 -0
  285. package/dist/text-morph/text-morph.js +21 -0
  286. package/dist/text-morph/text-morph.js.map +1 -0
  287. package/dist/text-reveal/index.d.ts +2 -0
  288. package/dist/text-reveal/index.js +2 -0
  289. package/dist/text-reveal/text-reveal.d.ts +27 -0
  290. package/dist/text-reveal/text-reveal.js +51 -0
  291. package/dist/text-reveal/text-reveal.js.map +1 -0
  292. package/dist/text-shimmer/index.d.ts +2 -0
  293. package/dist/text-shimmer/index.js +2 -0
  294. package/dist/text-shimmer/text-shimmer.d.ts +29 -0
  295. package/dist/text-shimmer/text-shimmer.js +29 -0
  296. package/dist/text-shimmer/text-shimmer.js.map +1 -0
  297. package/dist/time-picker/time-picker.js +2 -2
  298. package/dist/time-picker/time-picker.js.map +1 -1
  299. package/dist/toast/index.d.ts +2 -2
  300. package/dist/toast/index.js +2 -2
  301. package/dist/toast/toast.d.ts +6 -0
  302. package/dist/toast/toast.js +82 -40
  303. package/dist/toast/toast.js.map +1 -1
  304. package/dist/tooltip/tooltip.d.ts +9 -2
  305. package/dist/tooltip/tooltip.js +7 -7
  306. package/dist/tooltip/tooltip.js.map +1 -1
  307. package/dist/treemap/index.d.ts +2 -0
  308. package/dist/treemap/index.js +2 -0
  309. package/dist/treemap/treemap.d.ts +53 -0
  310. package/dist/treemap/treemap.js +699 -0
  311. package/dist/treemap/treemap.js.map +1 -0
  312. package/dist/usage-meter/index.d.ts +2 -0
  313. package/dist/usage-meter/index.js +2 -0
  314. package/dist/usage-meter/usage-meter.d.ts +50 -0
  315. package/dist/usage-meter/usage-meter.js +440 -0
  316. package/dist/usage-meter/usage-meter.js.map +1 -0
  317. package/dist/waffle-chart/index.d.ts +2 -0
  318. package/dist/waffle-chart/index.js +2 -0
  319. package/dist/waffle-chart/waffle-chart.d.ts +57 -0
  320. package/dist/waffle-chart/waffle-chart.js +426 -0
  321. package/dist/waffle-chart/waffle-chart.js.map +1 -0
  322. package/package.json +165 -3
@@ -0,0 +1,576 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { mergeRefs } from "../lib/merge-refs.js";
4
+ import { prefersReducedMotion, useIsomorphicLayoutEffect } from "../lib/motion.js";
5
+ import { useCountTo } from "../lib/count-to.js";
6
+ import { REVEAL, SETTLE, SNAPPY, live, retarget } from "../lib/spring-tween.js";
7
+ import { forwardRef, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
8
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
+ //#region src/donut-chart/donut-chart.tsx
10
+ const OTHER = "__other";
11
+ const TAU = Math.PI * 2;
12
+ /** Neutral steps after the four series colours, and the quietest step for Other. */
13
+ const NEUTRAL = [
14
+ 56,
15
+ 42,
16
+ 32
17
+ ];
18
+ const seriesColor = (index) => index < 4 ? `var(--color-chart-${index + 1})` : `color-mix(in oklab, var(--color-foreground) ${NEUTRAL[(index - 4) % NEUTRAL.length]}%, var(--color-surface))`;
19
+ const OTHER_COLOR = "color-mix(in oklab, var(--color-foreground) 26%, var(--color-surface))";
20
+ /** Room outside the ring for the lift; growth, margin, the gap between segments and their corner radius, in pixels. */
21
+ const LIFT = 4;
22
+ const GROW = 2;
23
+ const MARGIN = 7;
24
+ const GAP = 3;
25
+ const CORNER = 4;
26
+ /** Stagger of the trailing edges on the first sweep. */
27
+ const STAGGER_MS = 35;
28
+ const GROUPED = new Intl.NumberFormat("en-US", { maximumFractionDigits: 1 });
29
+ const PERCENT = new Intl.NumberFormat("en-US", {
30
+ style: "percent",
31
+ maximumFractionDigits: 0
32
+ });
33
+ const shareText = (share) => share > 0 && share < .01 ? "<1%" : PERCENT.format(share);
34
+ const n2 = (value) => (Math.round(value * 100) / 100).toString();
35
+ /** Small parts join one "Other" segment, but only when at least two would; grouping a single part hides it for nothing. */
36
+ function sliceData(data, groupBelow, maxSegments, otherLabel) {
37
+ const parts = data.filter((item) => item.value > 0);
38
+ const total = parts.reduce((sum, item) => sum + item.value, 0);
39
+ if (!total) return [];
40
+ const ranked = [...parts].sort((a, b) => b.value - a.value);
41
+ const keep = new Set(ranked.filter((item, rank) => item.value / total >= groupBelow && rank < maxSegments - 1).map((item) => item.key));
42
+ const rest = parts.filter((item) => !keep.has(item.key));
43
+ if (rest.length < 2) return parts.map((item) => ({ ...item }));
44
+ return [...parts.filter((item) => keep.has(item.key)).map((item) => ({ ...item })), {
45
+ key: OTHER,
46
+ label: otherLabel,
47
+ value: rest.reduce((sum, item) => sum + item.value, 0),
48
+ members: rest
49
+ }];
50
+ }
51
+ /** Turns of the ring for each slice in data order; a hidden slice closes to a point where it sits. */
52
+ function layout(slices, hidden) {
53
+ const total = slices.reduce((sum, item) => sum + (hidden.has(item.key) ? 0 : item.value), 0) || 1;
54
+ let at = 0;
55
+ return new Map(slices.map((item) => {
56
+ const arc = {
57
+ start: at,
58
+ end: at + (hidden.has(item.key) ? 0 : item.value / total)
59
+ };
60
+ at = arc.end;
61
+ return [item.key, arc];
62
+ }));
63
+ }
64
+ /** Half the width, in pixels, of a sector's outer edge once the gap is cut; below a couple of pixels a segment fades rather than drawing a hairline. */
65
+ function breadth(R, t0, t1, gap) {
66
+ const turns = t1 - t0;
67
+ if (turns >= 1 - 1e-6) return Infinity;
68
+ return Math.sin(Math.min(turns * Math.PI, Math.PI / 2)) * R - Math.min(gap / 2, (1 - turns) * TAU * R / 2);
69
+ }
70
+ /**
71
+ * An annular sector between two turns of the ring, clockwise from the top, with
72
+ * rounded corners. Its sides run parallel to the radius at a fixed distance, so
73
+ * the gap between neighbours is the same width from the inner edge to the outer.
74
+ * A thin sector narrows to a wedge and then to nothing, so a closing one never pops.
75
+ */
76
+ function sector(c, R, r, t0, t1, gap, corner) {
77
+ const turns = t1 - t0;
78
+ if (turns <= 1e-6) return "";
79
+ const at = (radius, angle) => `${n2(c + radius * Math.cos(angle))} ${n2(c + radius * Math.sin(angle))}`;
80
+ if (turns >= 1 - 1e-6) return `M${at(R, -Math.PI / 2)}A${n2(R)} ${n2(R)} 0 1 1 ${at(R, Math.PI / 2)}A${n2(R)} ${n2(R)} 0 1 1 ${at(R, -Math.PI / 2)}ZM${at(r, -Math.PI / 2)}A${n2(r)} ${n2(r)} 0 1 0 ${at(r, Math.PI / 2)}A${n2(r)} ${n2(r)} 0 1 0 ${at(r, -Math.PI / 2)}Z`;
81
+ const p = Math.min(gap / 2, (1 - turns) * TAU * R / 2);
82
+ const a0 = t0 * TAU - Math.PI / 2;
83
+ const a1 = t1 * TAU - Math.PI / 2;
84
+ const half = (a1 - a0) / 2;
85
+ const s = Math.sin(Math.min(half, Math.PI / 2));
86
+ if (s * R <= p + 1e-6) return "";
87
+ const side = (t, angle, sign) => `${n2(c + t * Math.cos(angle) - sign * p * Math.sin(angle))} ${n2(c + t * Math.sin(angle) + sign * p * Math.cos(angle))}`;
88
+ const band = (R - r) / 2;
89
+ const ro = Math.max(0, Math.min(corner, band, s >= .9999 ? Infinity : (s * R - p) / (1 + s)));
90
+ const dO = Math.asin(Math.min(1, (p + ro) / (R - ro)));
91
+ const tO = Math.sqrt(Math.max(0, (R - ro) ** 2 - (p + ro) ** 2));
92
+ const bigO = a1 - a0 - 2 * dO > Math.PI ? 1 : 0;
93
+ let d = `M${side(tO, a0, 1)}`;
94
+ if (ro > .01) d += `A${n2(ro)} ${n2(ro)} 0 0 1 ${at(R, a0 + dO)}`;
95
+ d += `A${n2(R)} ${n2(R)} 0 ${bigO} 1 ${at(R, a1 - dO)}`;
96
+ if (ro > .01) d += `A${n2(ro)} ${n2(ro)} 0 0 1 ${side(tO, a1, -1)}`;
97
+ if (s * r > p + 1e-6 || s >= .9999) {
98
+ const ri = Math.max(0, Math.min(corner, band, s >= .9999 ? Infinity : (s * r - p) / (1 - s)));
99
+ const dI = Math.asin(Math.min(1, (p + ri) / (r + ri)));
100
+ const tI = Math.sqrt(Math.max(0, (r + ri) ** 2 - (p + ri) ** 2));
101
+ const bigI = a1 - a0 - 2 * dI > Math.PI ? 1 : 0;
102
+ d += `L${side(tI, a1, -1)}`;
103
+ if (ri > .01) d += `A${n2(ri)} ${n2(ri)} 0 0 1 ${at(r, a1 - dI)}`;
104
+ d += `A${n2(r)} ${n2(r)} 0 ${bigI} 0 ${at(r, a0 + dI)}`;
105
+ if (ri > .01) d += `A${n2(ri)} ${n2(ri)} 0 0 1 ${side(tI, a0, 1)}`;
106
+ } else d += `L${at(p / s, (a0 + a1) / 2)}`;
107
+ return `${d}Z`;
108
+ }
109
+ /**
110
+ * A number that counts to each new value on the smooth spring. useCountTo counts
111
+ * in whole steps, so a fraction (a share) is counted in ten-thousandths.
112
+ */
113
+ function Count({ value, format }) {
114
+ const fine = !Number.isInteger(value);
115
+ const shown = useCountTo(fine ? value * 1e4 : value);
116
+ return /* @__PURE__ */ jsx(Fragment$1, { children: format(fine ? shown / 1e4 : shown) });
117
+ }
118
+ const DonutChart = forwardRef(function DonutChart({ data, label, unit = "", formatValue = (value) => GROUPED.format(value), totalLabel = "Total", size = 208, thickness = 24, groupBelow = .04, maxSegments = 6, otherLabel = "Other", activeKey, defaultActiveKey = null, onActiveChange, hiddenKeys, defaultHiddenKeys, onHiddenKeysChange, legendAction = "toggle", legend = true, emptyLabel = "No data yet", className }, ref) {
119
+ const figure = useRef(null);
120
+ const refs = useMemo(() => mergeRefs(ref, figure), [ref]);
121
+ const legendId = useId();
122
+ const slices = sliceData(data, groupBelow, maxSegments, otherLabel);
123
+ const [ownHidden, setOwnHidden] = useState(defaultHiddenKeys ?? []);
124
+ const hiddenList = hiddenKeys ?? ownHidden;
125
+ const hidden = new Set(hiddenList.filter((key) => slices.some((item) => item.key === key)));
126
+ const visible = slices.filter((item) => !hidden.has(item.key));
127
+ const total = visible.reduce((sum, item) => sum + item.value, 0);
128
+ const signature = slices.map((item) => `${item.key}:${item.value}${hidden.has(item.key) ? "h" : ""}`).join("|");
129
+ const suffix = unit ? ` ${unit}` : "";
130
+ const [palette, setPalette] = useState(() => new Map(data.map((item, index) => [item.key, index])));
131
+ if (data.some((item) => !palette.has(item.key))) {
132
+ const next = new Map(palette);
133
+ for (const item of data) if (!next.has(item.key)) next.set(item.key, next.size);
134
+ setPalette(next);
135
+ }
136
+ const colorFor = (item) => item.color ?? (item.key === OTHER ? OTHER_COLOR : seriesColor(palette.get(item.key) ?? 0));
137
+ const [drawn, setDrawn] = useState(slices);
138
+ const [seen, setSeen] = useState(signature);
139
+ if (seen !== signature) {
140
+ setSeen(signature);
141
+ const next = [...slices];
142
+ drawn.forEach((item, index) => {
143
+ if (next.some((slice) => slice.key === item.key)) return;
144
+ const before = drawn.slice(0, index).reverse().find((prior) => next.some((slice) => slice.key === prior.key));
145
+ next.splice(before ? next.findIndex((slice) => slice.key === before.key) + 1 : 0, 0, {
146
+ ...item,
147
+ value: 0
148
+ });
149
+ });
150
+ setDrawn(next);
151
+ }
152
+ const [ownActive, setOwnActive] = useState(defaultActiveKey);
153
+ const selected = activeKey !== void 0 ? activeKey : ownActive;
154
+ const [preview, setPreview] = useState(null);
155
+ const select = (key) => {
156
+ if (activeKey === void 0) setOwnActive(key);
157
+ onActiveChange?.(key);
158
+ };
159
+ const current = [preview, selected].find((key) => key && visible.some((item) => item.key === key)) ?? null;
160
+ const activeSlice = visible.find((item) => item.key === current) ?? null;
161
+ const [announcement, setAnnouncement] = useState("");
162
+ const setHidden = (key) => {
163
+ const isHidden = hidden.has(key);
164
+ if (!isHidden && visible.length <= 1) return;
165
+ const next = isHidden ? hiddenList.filter((item) => item !== key) : [...hiddenList, key];
166
+ if (hiddenKeys === void 0) setOwnHidden(next);
167
+ onHiddenKeysChange?.(next);
168
+ const item = slices.find((slice) => slice.key === key);
169
+ const nextTotal = slices.reduce((sum, slice) => sum + (next.includes(slice.key) ? 0 : slice.value), 0);
170
+ if (item) setAnnouncement(`${item.label} ${isHidden ? "shown" : "hidden"}. ${totalLabel} ${formatValue(nextTotal)}${suffix}.`);
171
+ };
172
+ const c = size / 2;
173
+ const outer = c - MARGIN;
174
+ const inner = Math.max(8, outer - thickness);
175
+ const corner = Math.min(CORNER, thickness / 4);
176
+ const geometry = useRef({
177
+ c,
178
+ outer,
179
+ inner,
180
+ corner
181
+ });
182
+ const segments = useRef(/* @__PURE__ */ new Map());
183
+ const svg = useRef(null);
184
+ /** One writer: every path's shape, opacity and lift, straight onto the elements. */
185
+ const paint = useCallback(() => {
186
+ const root = svg.current;
187
+ if (!root) return;
188
+ const { c, outer, inner, corner } = geometry.current;
189
+ for (const node of root.querySelectorAll("[data-key]")) {
190
+ const segment = segments.current.get(node.dataset.key);
191
+ if (!segment) {
192
+ node.setAttribute("d", "");
193
+ continue;
194
+ }
195
+ const start = segment.start.value;
196
+ const end = segment.end.value;
197
+ const lift = Math.max(0, segment.lift.value);
198
+ const R = outer + lift * GROW;
199
+ node.setAttribute("d", sector(c, R, inner - lift * GROW * .5, start, end, GAP, corner));
200
+ node.setAttribute("fill-opacity", n2(Math.min(1, Math.max(0, (breadth(R, start, end, GAP) - 1) / 3))));
201
+ const middle = (start + end) / 2 * TAU - Math.PI / 2;
202
+ node.setAttribute("transform", `translate(${n2(Math.cos(middle) * lift * LIFT)} ${n2(Math.sin(middle) * lift * LIFT)})`);
203
+ }
204
+ }, []);
205
+ useIsomorphicLayoutEffect(() => {
206
+ geometry.current = {
207
+ c,
208
+ outer,
209
+ inner,
210
+ corner
211
+ };
212
+ paint();
213
+ });
214
+ useEffect(() => () => {
215
+ for (const segment of segments.current.values()) {
216
+ segment.start.stop();
217
+ segment.end.stop();
218
+ segment.lift.stop();
219
+ }
220
+ }, []);
221
+ const [shown, setShown] = useState(false);
222
+ useEffect(() => {
223
+ const node = figure.current;
224
+ if (!node || prefersReducedMotion() || typeof IntersectionObserver === "undefined") {
225
+ setShown(true);
226
+ return;
227
+ }
228
+ const observer = new IntersectionObserver(([entry]) => {
229
+ if (!entry?.isIntersecting) return;
230
+ observer.disconnect();
231
+ setShown(true);
232
+ }, { threshold: .35 });
233
+ observer.observe(node);
234
+ return () => observer.disconnect();
235
+ }, []);
236
+ const targets = useRef(/* @__PURE__ */ new Map());
237
+ const latest = useRef({
238
+ drawn,
239
+ slices
240
+ });
241
+ useIsomorphicLayoutEffect(() => {
242
+ latest.current = {
243
+ drawn,
244
+ slices
245
+ };
246
+ });
247
+ useEffect(() => {
248
+ if (!shown) return;
249
+ const { drawn: order, slices: now } = latest.current;
250
+ const goal = layout(now, hidden);
251
+ targets.current = goal;
252
+ const first = segments.current.size === 0;
253
+ const place = (index) => {
254
+ const before = order.slice(0, index).reverse().find((item) => goal.has(item.key));
255
+ return before ? goal.get(before.key).end : 0;
256
+ };
257
+ const drop = (key) => {
258
+ if (latest.current.slices.some((item) => item.key === key)) return;
259
+ segments.current.delete(key);
260
+ setDrawn((list) => list.filter((item) => item.key !== key));
261
+ };
262
+ order.forEach((item, index) => {
263
+ const leaving = !goal.has(item.key);
264
+ const to = goal.get(item.key) ?? {
265
+ start: place(index),
266
+ end: place(index)
267
+ };
268
+ let segment = segments.current.get(item.key);
269
+ if (!segment) {
270
+ const prior = order.slice(0, index).reverse().map((entry) => segments.current.get(entry.key)).find(Boolean);
271
+ const from = first ? 0 : prior ? prior.end.value : 0;
272
+ segment = {
273
+ start: live(from),
274
+ end: live(from),
275
+ lift: live(0)
276
+ };
277
+ segments.current.set(item.key, segment);
278
+ }
279
+ if (first) {
280
+ retarget(segment.start, to.start, REVEAL, paint);
281
+ retarget(segment.end, to.end, REVEAL, paint, 40 + index * STAGGER_MS);
282
+ return;
283
+ }
284
+ retarget(segment.start, to.start, SETTLE, paint);
285
+ retarget(segment.end, to.end, SETTLE, paint, 0, leaving ? () => drop(item.key) : void 0);
286
+ });
287
+ paint();
288
+ }, [
289
+ shown,
290
+ signature,
291
+ paint
292
+ ]);
293
+ useEffect(() => {
294
+ for (const [key, segment] of segments.current) retarget(segment.lift, key === current ? 1 : 0, SNAPPY, paint);
295
+ }, [
296
+ current,
297
+ drawn,
298
+ shown,
299
+ paint
300
+ ]);
301
+ const hit = (event) => {
302
+ const box = svg.current?.getBoundingClientRect();
303
+ if (!box?.width) return void 0;
304
+ const scale = size / box.width;
305
+ const x = (event.clientX - box.left) * scale - c;
306
+ const y = (event.clientY - box.top) * scale - c;
307
+ const radius = Math.hypot(x, y);
308
+ if (radius < inner - 6 || radius > c) return null;
309
+ let turn = (Math.atan2(y, x) + Math.PI / 2) / TAU;
310
+ if (turn < 0) turn += 1;
311
+ for (const [key, arc] of targets.current) if (arc.end > arc.start && turn >= arc.start && turn < arc.end && visible.some((item) => item.key === key)) return key;
312
+ };
313
+ const onRingMove = (event) => {
314
+ if (event.pointerType !== "mouse") return;
315
+ const key = hit(event);
316
+ if (key !== void 0 && key !== preview) setPreview(key);
317
+ };
318
+ const onRingClick = (event) => {
319
+ const key = hit(event);
320
+ if (key) select(selected === key ? null : key);
321
+ };
322
+ const format = (value) => `${formatValue(value)}${suffix}`;
323
+ const describe = (item) => `${item.label}, ${format(item.value)}, ${shareText(item.value / (total || 1))}${item.members ? `. Includes ${item.members.map((member) => member.label).join(", ")}` : ""}`;
324
+ const rows = useRef([]);
325
+ const step = (key, index, count) => {
326
+ return {
327
+ ArrowDown: index + 1,
328
+ ArrowRight: index + 1,
329
+ ArrowUp: index - 1,
330
+ ArrowLeft: index - 1,
331
+ Home: 0,
332
+ End: count - 1
333
+ }[key];
334
+ };
335
+ const onLegendKey = (event, index) => {
336
+ if (event.key === "Escape" && selected) {
337
+ event.preventDefault();
338
+ select(null);
339
+ return;
340
+ }
341
+ const next = step(event.key, index, slices.length);
342
+ if (next === void 0) return;
343
+ event.preventDefault();
344
+ rows.current[(next + slices.length) % slices.length]?.focus();
345
+ };
346
+ const onRingKey = (event) => {
347
+ if (!visible.length) return;
348
+ if (event.key === "Escape") {
349
+ event.preventDefault();
350
+ setPreview(null);
351
+ if (selected) select(null);
352
+ return;
353
+ }
354
+ if ((event.key === "Enter" || event.key === " ") && current) {
355
+ event.preventDefault();
356
+ select(selected === current ? null : current);
357
+ return;
358
+ }
359
+ const index = visible.findIndex((item) => item.key === current);
360
+ const next = step(event.key, index < 0 ? event.key.endsWith("Up") || event.key.endsWith("Left") ? 0 : -1 : index, visible.length);
361
+ if (next === void 0) return;
362
+ event.preventDefault();
363
+ const item = visible[(next + visible.length) % visible.length];
364
+ setPreview(item.key);
365
+ setAnnouncement(describe(item));
366
+ };
367
+ const onLegendBlur = (event) => {
368
+ if (!(event.relatedTarget instanceof Node && event.currentTarget.closest("ul")?.contains(event.relatedTarget))) setPreview(null);
369
+ };
370
+ const identity = activeSlice ? activeSlice.key : "__total";
371
+ const readouts = [{
372
+ key: "__total",
373
+ label: total ? totalLabel : emptyLabel,
374
+ value: total,
375
+ meta: null
376
+ }, ...slices.map((item) => ({
377
+ key: item.key,
378
+ label: item.label,
379
+ value: item.value,
380
+ meta: item
381
+ }))];
382
+ const activeIndex = Math.max(0, readouts.findIndex((item) => item.key === identity));
383
+ const summary = total ? `${label}. ${totalLabel} ${format(total)}. ${visible.map(describe).join(". ")}.` : `${label}. ${emptyLabel}.`;
384
+ const members = (item) => item.members ? item.members.length > 2 ? `${item.members.slice(0, 2).map((member) => member.label).join(", ")} and ${item.members.length - 2} more` : item.members.map((member) => member.label).join(" and ") : null;
385
+ return /* @__PURE__ */ jsxs("figure", {
386
+ ref: refs,
387
+ "data-slot": "donut-chart",
388
+ "aria-label": label,
389
+ "data-legend": legend || void 0,
390
+ className: cn("donut-chart box-border font-sans text-foreground", className),
391
+ children: [
392
+ /* @__PURE__ */ jsxs("div", {
393
+ "data-slot": "donut-chart-ring",
394
+ className: "donut-chart-ring",
395
+ style: {
396
+ width: size,
397
+ "--inner": `${inner * 2 / size * 100}%`
398
+ },
399
+ tabIndex: legend ? void 0 : 0,
400
+ role: legend ? void 0 : "application",
401
+ "aria-label": legend ? void 0 : `${label}. Use the arrow keys to read each segment.`,
402
+ onKeyDown: legend ? void 0 : onRingKey,
403
+ onBlur: legend ? void 0 : () => setPreview(null),
404
+ children: [/* @__PURE__ */ jsxs("svg", {
405
+ ref: svg,
406
+ viewBox: `0 0 ${size} ${size}`,
407
+ "aria-hidden": "true",
408
+ focusable: "false",
409
+ onPointerMove: onRingMove,
410
+ onPointerLeave: () => setPreview(null),
411
+ onClick: onRingClick,
412
+ "data-hovering": current !== null || void 0,
413
+ className: "block size-full overflow-visible data-[hovering]:cursor-pointer",
414
+ children: [/* @__PURE__ */ jsx("circle", {
415
+ className: "donut-chart-track",
416
+ cx: c,
417
+ cy: c,
418
+ r: (outer + inner) / 2,
419
+ strokeWidth: outer - inner,
420
+ "data-idle": !shown || !total || void 0
421
+ }), drawn.map((item) => /* @__PURE__ */ jsx("path", {
422
+ "data-key": item.key,
423
+ "data-active": item.key === current || void 0,
424
+ "data-dim": current !== null && item.key !== current || void 0,
425
+ className: "donut-chart-segment",
426
+ style: { "--slice": colorFor(item) }
427
+ }, item.key))]
428
+ }), /* @__PURE__ */ jsx("div", {
429
+ "aria-hidden": "true",
430
+ className: "donut-chart-center",
431
+ children: readouts.map((item, index) => /* @__PURE__ */ jsxs("span", {
432
+ "data-place": Math.sign(index - activeIndex),
433
+ className: "donut-chart-readout",
434
+ children: [
435
+ /* @__PURE__ */ jsx("span", {
436
+ className: "block w-full min-h-5 truncate text-xs text-text-secondary",
437
+ children: item.label
438
+ }),
439
+ /* @__PURE__ */ jsx("span", {
440
+ className: "block max-w-full min-h-8 truncate text-h3 font-medium tabular-nums",
441
+ children: item.value || item.meta ? /* @__PURE__ */ jsx(Count, {
442
+ value: item.value,
443
+ format: formatValue
444
+ }) : " "
445
+ }),
446
+ /* @__PURE__ */ jsx("span", {
447
+ className: "block w-full min-h-5 truncate text-xs tabular-nums text-muted-foreground",
448
+ children: item.meta ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
449
+ /* @__PURE__ */ jsx(Count, {
450
+ value: total && !hidden.has(item.key) ? item.value / total : 0,
451
+ format: shareText
452
+ }),
453
+ " of",
454
+ " ",
455
+ totalLabel.toLowerCase()
456
+ ] }) : unit || " "
457
+ })
458
+ ]
459
+ }, item.key))
460
+ })]
461
+ }),
462
+ legend && slices.length > 0 ? /* @__PURE__ */ jsx("ul", {
463
+ id: legendId,
464
+ "aria-label": `${label}, segments${legendAction === "toggle" ? ". Press a segment to show or hide it" : ""}`,
465
+ onPointerLeave: () => setPreview(null),
466
+ className: "m-0 -mb-0.5 grid list-none p-0",
467
+ children: slices.map((item, index) => {
468
+ const off = hidden.has(item.key);
469
+ return /* @__PURE__ */ jsx("li", {
470
+ className: "overflow-hidden motion-safe:animate-fade-in",
471
+ children: /* @__PURE__ */ jsxs("button", {
472
+ ref: (node) => {
473
+ rows.current[index] = node;
474
+ },
475
+ type: "button",
476
+ "data-slot": "donut-chart-row",
477
+ "aria-pressed": legendAction === "toggle" ? !off : selected === item.key,
478
+ "aria-label": off ? `${item.label}, hidden` : describe(item),
479
+ "data-active": item.key === current || void 0,
480
+ "data-pinned": selected === item.key || void 0,
481
+ "data-hidden": off || void 0,
482
+ style: { "--slice": colorFor(item) },
483
+ onClick: () => legendAction === "toggle" ? setHidden(item.key) : select(selected === item.key ? null : item.key),
484
+ onPointerEnter: (event) => {
485
+ if (event.pointerType === "mouse") setPreview(off ? null : item.key);
486
+ },
487
+ onFocus: (event) => {
488
+ if (event.currentTarget.matches(":focus-visible")) setPreview(off ? null : item.key);
489
+ },
490
+ onBlur: onLegendBlur,
491
+ onKeyDown: (event) => onLegendKey(event, index),
492
+ className: "donut-chart-row",
493
+ children: [
494
+ /* @__PURE__ */ jsx("span", {
495
+ "aria-hidden": "true",
496
+ className: "donut-chart-dot"
497
+ }),
498
+ /* @__PURE__ */ jsxs("span", {
499
+ className: "grid min-w-0",
500
+ children: [/* @__PURE__ */ jsx("span", {
501
+ className: "donut-chart-row-label truncate",
502
+ children: item.label
503
+ }), item.members ? /* @__PURE__ */ jsx("span", {
504
+ className: "truncate text-xs text-muted-foreground",
505
+ children: members(item)
506
+ }) : null]
507
+ }),
508
+ /* @__PURE__ */ jsx("span", {
509
+ "aria-hidden": "true",
510
+ className: "donut-chart-row-value justify-self-end tabular-nums text-text-secondary",
511
+ children: /* @__PURE__ */ jsx(Count, {
512
+ value: item.value,
513
+ format: formatValue
514
+ })
515
+ }),
516
+ /* @__PURE__ */ jsx("span", {
517
+ "aria-hidden": "true",
518
+ className: "donut-chart-row-value justify-self-end font-medium tabular-nums",
519
+ children: /* @__PURE__ */ jsx(Count, {
520
+ value: off || !total ? 0 : item.value / total,
521
+ format: shareText
522
+ })
523
+ })
524
+ ]
525
+ })
526
+ }, item.key);
527
+ })
528
+ }) : null,
529
+ /* @__PURE__ */ jsx("p", {
530
+ className: "sr-only",
531
+ children: summary
532
+ }),
533
+ /* @__PURE__ */ jsx("p", {
534
+ className: "sr-only",
535
+ "aria-live": "polite",
536
+ children: announcement
537
+ }),
538
+ total > 0 ? /* @__PURE__ */ jsx("div", {
539
+ className: "sr-only",
540
+ children: /* @__PURE__ */ jsxs("table", { children: [
541
+ /* @__PURE__ */ jsx("caption", { children: label }),
542
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
543
+ /* @__PURE__ */ jsx("th", {
544
+ scope: "col",
545
+ children: "Segment"
546
+ }),
547
+ /* @__PURE__ */ jsx("th", {
548
+ scope: "col",
549
+ children: "Value"
550
+ }),
551
+ /* @__PURE__ */ jsx("th", {
552
+ scope: "col",
553
+ children: "Share"
554
+ })
555
+ ] }) }),
556
+ /* @__PURE__ */ jsx("tbody", { children: visible.flatMap((item) => item.members ? item.members.map((member) => ({
557
+ key: member.key,
558
+ label: `${member.label} (${otherLabel})`,
559
+ value: member.value
560
+ })) : [item]).map((item) => /* @__PURE__ */ jsxs("tr", { children: [
561
+ /* @__PURE__ */ jsx("th", {
562
+ scope: "row",
563
+ children: item.label
564
+ }),
565
+ /* @__PURE__ */ jsx("td", { children: format(item.value) }),
566
+ /* @__PURE__ */ jsx("td", { children: shareText(item.value / total) })
567
+ ] }, item.key)) })
568
+ ] })
569
+ }) : null
570
+ ]
571
+ });
572
+ });
573
+ //#endregion
574
+ export { DonutChart };
575
+
576
+ //# sourceMappingURL=donut-chart.js.map