@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,568 @@
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 { SwapText } from "../lib/swap-text.js";
6
+ import { MORPH, live, retarget } from "../lib/spring-tween.js";
7
+ import { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react";
8
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
+ //#region src/slope-chart/slope-chart.tsx
10
+ /** Space between labels, around the plot (so dots never touch an edge) and for the column headings, in pixels. */
11
+ const LABEL_GAP = 20;
12
+ const PAD = 14;
13
+ const HEAD = 28;
14
+ const clamp = (value, low, high) => Math.min(high, Math.max(low, value));
15
+ const GROUPED = new Intl.NumberFormat("en-US", { maximumFractionDigits: 1 });
16
+ /** Moves labels apart just enough to stop overlaps: touching labels form a group centred on where its members want to be. */
17
+ function spread(wanted, gap, low, high) {
18
+ let groups = wanted.map((y, index) => ({
19
+ y,
20
+ index
21
+ })).sort((a, b) => a.y - b.y).map((entry) => ({
22
+ members: [entry],
23
+ top: entry.y
24
+ }));
25
+ for (let changed = true; changed;) {
26
+ changed = false;
27
+ const next = [];
28
+ for (const group of groups) {
29
+ const prev = next[next.length - 1];
30
+ if (prev && prev.top + prev.members.length * gap > group.top) {
31
+ const members = [...prev.members, ...group.members];
32
+ next[next.length - 1] = {
33
+ members,
34
+ top: members.reduce((sum, member, k) => sum + member.y - k * gap, 0) / members.length
35
+ };
36
+ changed = true;
37
+ } else next.push(group);
38
+ }
39
+ groups = next.map((group) => ({
40
+ ...group,
41
+ top: clamp(group.top, low, Math.max(low, high - (group.members.length - 1) * gap))
42
+ }));
43
+ }
44
+ const out = new Array(wanted.length);
45
+ groups.forEach((group) => group.members.forEach((member, k) => out[member.index] = group.top + k * gap));
46
+ return out;
47
+ }
48
+ /** Rank change: an arrow and the number of places, or "=" when level. The number rises or drops in when it changes. */
49
+ function Rank({ move }) {
50
+ const text = move === 0 ? "=" : `${Math.abs(move)}`;
51
+ return /* @__PURE__ */ jsxs("span", {
52
+ "data-move": move > 0 ? "up" : move < 0 ? "down" : "level",
53
+ "aria-hidden": "true",
54
+ className: "slope-chart-rank",
55
+ children: [move !== 0 ? /* @__PURE__ */ jsx("svg", {
56
+ width: "8",
57
+ height: "8",
58
+ viewBox: "0 0 8 8",
59
+ fill: "none",
60
+ stroke: "currentColor",
61
+ strokeWidth: "1.3",
62
+ strokeLinecap: "round",
63
+ strokeLinejoin: "round",
64
+ children: /* @__PURE__ */ jsx("path", { d: move > 0 ? "M4 7V1M1.5 3.5 4 1l2.5 2.5" : "M4 1v6M1.5 4.5 4 7l2.5-2.5" })
65
+ }) : null, /* @__PURE__ */ jsx(SwapText, {
66
+ swapKey: text,
67
+ dir: move >= 0 ? 1 : -1,
68
+ motion: "rise",
69
+ children: text
70
+ })]
71
+ });
72
+ }
73
+ const SlopeChart = forwardRef(function SlopeChart({ data, label, startLabel, endLabel, formatValue, formatChange, height, highlightKey = null, activeKey, onActiveChange, ranks = true, emptyLabel = "No data", className }, ref) {
74
+ const figure = useRef(null);
75
+ const refs = useMemo(() => mergeRefs(ref, figure), [ref]);
76
+ const stage = useRef(null);
77
+ const plot = useRef(null);
78
+ const tip = useRef(null);
79
+ const empty = data.length === 0;
80
+ const plotHeight = height ?? Math.max(200, data.length * 44);
81
+ const [width, setWidth] = useState(0);
82
+ useIsomorphicLayoutEffect(() => {
83
+ const node = stage.current;
84
+ if (!node) return;
85
+ const read = () => setWidth(node.clientWidth);
86
+ read();
87
+ if (typeof ResizeObserver === "undefined") return;
88
+ const observer = new ResizeObserver(read);
89
+ observer.observe(node);
90
+ return () => observer.disconnect();
91
+ }, []);
92
+ const ready = width > 0;
93
+ const narrow = width < 440;
94
+ const leftRoom = narrow ? width < 300 ? 116 : 132 : 168;
95
+ const rightRoom = ranks ? narrow ? 76 : 96 : narrow ? 52 : 64;
96
+ const x0 = leftRoom;
97
+ const x1 = Math.max(x0 + 40, width - rightRoom);
98
+ const values = data.flatMap((item) => [item.start, item.end]);
99
+ let lo = Math.min(...values);
100
+ let hi = Math.max(...values);
101
+ if (!Number.isFinite(lo)) {
102
+ lo = 0;
103
+ hi = 1;
104
+ }
105
+ if (hi - lo < 1e-9) {
106
+ lo -= 1;
107
+ hi += 1;
108
+ }
109
+ const yOf = (value) => PAD + (1 - (value - lo) / (hi - lo)) * (plotHeight - 28);
110
+ const rankOf = (field) => {
111
+ const sorted = [...data].sort((a, b) => b[field] - a[field]);
112
+ return (item) => sorted.indexOf(item) + 1;
113
+ };
114
+ const r0 = rankOf("start");
115
+ const r1 = rankOf("end");
116
+ const l0 = spread(data.map((item) => yOf(item.start)), LABEL_GAP, 8, plotHeight - 8);
117
+ const l1 = spread(data.map((item) => yOf(item.end)), LABEL_GAP, 8, plotHeight - 8);
118
+ const rows = data.map((item, i) => ({
119
+ item,
120
+ y0: yOf(item.start),
121
+ y1: yOf(item.end),
122
+ l0: l0[i],
123
+ l1: l1[i],
124
+ rank0: r0(item),
125
+ rank1: r1(item),
126
+ order: 0
127
+ }));
128
+ const byEnd = [...rows].sort((a, b) => a.rank1 - b.rank1);
129
+ byEnd.forEach((row, k) => {
130
+ row.order = k;
131
+ });
132
+ const lives = useRef(/* @__PURE__ */ new Map());
133
+ const box = useRef({
134
+ x0,
135
+ x1
136
+ });
137
+ const paint = useCallback(() => {
138
+ const root = plot.current;
139
+ if (!root) return;
140
+ const { x0, x1 } = box.current;
141
+ for (const node of root.querySelectorAll("[data-row]")) {
142
+ const at = lives.current.get(node.dataset.row);
143
+ if (!at) continue;
144
+ const line = node.querySelector("[data-part=line]");
145
+ line?.setAttribute("y1", String(at.y0.value));
146
+ line?.setAttribute("y2", String(at.y1.value));
147
+ node.querySelector("[data-part=dot0]")?.setAttribute("cy", String(at.y0.value));
148
+ node.querySelector("[data-part=dot1]")?.setAttribute("cy", String(at.y1.value));
149
+ node.querySelector("[data-part=lead0]")?.setAttribute("d", `M${x0 - 6},${at.l0.value}L${x0 - 1},${at.y0.value}`);
150
+ node.querySelector("[data-part=lead1]")?.setAttribute("d", `M${x1 + 6},${at.l1.value}L${x1 + 1},${at.y1.value}`);
151
+ }
152
+ for (const node of root.querySelectorAll("[data-label]")) {
153
+ const at = lives.current.get(node.dataset.label);
154
+ if (at) node.style.translate = `0 ${node.dataset.side === "end" ? at.l1.value : at.l0.value}px`;
155
+ }
156
+ }, []);
157
+ useIsomorphicLayoutEffect(() => {
158
+ box.current = {
159
+ x0,
160
+ x1
161
+ };
162
+ paint();
163
+ });
164
+ const signature = rows.map((row) => [
165
+ row.item.key,
166
+ row.y0,
167
+ row.y1,
168
+ row.l0,
169
+ row.l1
170
+ ].map((part) => typeof part === "number" ? Math.round(part * 100) : part).join(":")).join("|");
171
+ const latest = useRef(rows);
172
+ useIsomorphicLayoutEffect(() => {
173
+ latest.current = rows;
174
+ });
175
+ useIsomorphicLayoutEffect(() => {
176
+ const current = latest.current;
177
+ const keys = new Set(current.map((row) => row.item.key));
178
+ for (const key of [...lives.current.keys()]) {
179
+ if (keys.has(key)) continue;
180
+ const gone = lives.current.get(key);
181
+ for (const value of Object.values(gone)) value.stop();
182
+ lives.current.delete(key);
183
+ }
184
+ for (const row of current) {
185
+ const at = lives.current.get(row.item.key);
186
+ if (!at) {
187
+ lives.current.set(row.item.key, {
188
+ y0: live(row.y0),
189
+ y1: live(row.y1),
190
+ l0: live(row.l0),
191
+ l1: live(row.l1)
192
+ });
193
+ continue;
194
+ }
195
+ retarget(at.y0, row.y0, MORPH, paint);
196
+ retarget(at.y1, row.y1, MORPH, paint);
197
+ retarget(at.l0, row.l0, MORPH, paint);
198
+ retarget(at.l1, row.l1, MORPH, paint);
199
+ }
200
+ paint();
201
+ }, [
202
+ signature,
203
+ paint,
204
+ ready
205
+ ]);
206
+ useEffect(() => () => {
207
+ for (const at of lives.current.values()) for (const value of Object.values(at)) value.stop();
208
+ }, []);
209
+ const [drawn, setDrawn] = useState(false);
210
+ useEffect(() => {
211
+ const node = figure.current;
212
+ if (!node || prefersReducedMotion() || typeof IntersectionObserver === "undefined") {
213
+ setDrawn(true);
214
+ return;
215
+ }
216
+ const observer = new IntersectionObserver(([entry]) => {
217
+ if (!entry?.isIntersecting) return;
218
+ observer.disconnect();
219
+ setDrawn(true);
220
+ }, { threshold: .3 });
221
+ observer.observe(node);
222
+ return () => observer.disconnect();
223
+ }, []);
224
+ const [ownActive, setOwnActive] = useState(null);
225
+ const wanted = activeKey !== void 0 ? activeKey : ownActive;
226
+ const active = wanted && data.some((item) => item.key === wanted) ? wanted : null;
227
+ const setActive = (key) => {
228
+ if (activeKey === void 0) setOwnActive(key);
229
+ if (key !== active) onActiveChange?.(key);
230
+ };
231
+ const activeRow = rows.find((row) => row.item.key === active) ?? null;
232
+ const [shownKey, setShownKey] = useState(null);
233
+ if (active && active !== shownKey) setShownKey(active);
234
+ const tipRow = activeRow ?? rows.find((row) => row.item.key === shownKey) ?? null;
235
+ const shownBefore = useRef(false);
236
+ useIsomorphicLayoutEffect(() => {
237
+ const node = tip.current;
238
+ if (!activeRow || !node || !width) {
239
+ shownBefore.current = false;
240
+ return;
241
+ }
242
+ const tw = node.offsetWidth;
243
+ const th = node.offsetHeight;
244
+ const mid = (activeRow.y0 + activeRow.y1) / 2;
245
+ const above = mid - th - 16 >= 0;
246
+ const left = clamp((x0 + x1) / 2 - tw / 2, 0, Math.max(0, width - tw));
247
+ const top = clamp(HEAD + (above ? mid - th - 16 : mid + 16), 0, Math.max(0, plotHeight + HEAD - th));
248
+ if (!shownBefore.current) node.style.transition = "none";
249
+ node.style.translate = `${left}px ${top}px`;
250
+ if (!shownBefore.current) {
251
+ node.offsetWidth;
252
+ node.style.transition = "";
253
+ }
254
+ shownBefore.current = true;
255
+ });
256
+ const nearest = (clientX, clientY) => {
257
+ const rect = stage.current?.getBoundingClientRect();
258
+ if (!rect || empty) return null;
259
+ const px = clientX - rect.left;
260
+ const y = clientY - rect.top - HEAD;
261
+ const t = (clamp(px, x0, x1) - x0) / Math.max(1, x1 - x0);
262
+ let best = null;
263
+ let distance = Infinity;
264
+ for (const row of rows) {
265
+ const inLine = Math.abs(row.y0 + (row.y1 - row.y0) * t - y);
266
+ const onLabel = px < x0 ? Math.abs(row.l0 - y) : px > x1 ? Math.abs(row.l1 - y) : Infinity;
267
+ const d = Math.min(inLine, onLabel);
268
+ if (d < distance) {
269
+ distance = d;
270
+ best = row;
271
+ }
272
+ }
273
+ return distance <= 22 ? best?.item.key ?? null : null;
274
+ };
275
+ const onKeyDown = (event) => {
276
+ if (empty) return;
277
+ if (event.key === "Escape" && active) {
278
+ event.preventDefault();
279
+ setActive(null);
280
+ return;
281
+ }
282
+ const at = activeRow ? activeRow.order : -1;
283
+ const moves = {
284
+ ArrowDown: at + 1,
285
+ ArrowRight: at + 1,
286
+ ArrowUp: at < 0 ? 0 : at - 1,
287
+ ArrowLeft: at < 0 ? 0 : at - 1,
288
+ Home: 0,
289
+ End: byEnd.length - 1
290
+ };
291
+ if (!(event.key in moves)) return;
292
+ event.preventDefault();
293
+ setActive(byEnd[clamp(moves[event.key], 0, byEnd.length - 1)].item.key);
294
+ };
295
+ const format = (value) => formatValue ? formatValue(value) : GROUPED.format(value);
296
+ const change = (item) => formatChange ? formatChange(item.end - item.start, item) : `${item.end >= item.start ? "+" : "−"}${format(Math.abs(item.end - item.start))}`;
297
+ const rankText = (row) => row.rank0 === row.rank1 ? "same rank" : row.rank1 < row.rank0 ? `up ${row.rank0 - row.rank1} to rank ${row.rank1}` : `down ${row.rank1 - row.rank0} to rank ${row.rank1}`;
298
+ const describe = (row) => `${row.item.label}, ${startLabel} ${format(row.item.start)}, ${endLabel} ${format(row.item.end)}, ${change(row.item)}, ${rankText(row)}`;
299
+ const summary = empty ? `${label}. ${emptyLabel}.` : `${label}, ${startLabel} to ${endLabel}. ${byEnd.map((row) => `${row.item.label} ${format(row.item.start)} to ${format(row.item.end)}`).join(", ")}.`;
300
+ return /* @__PURE__ */ jsxs("figure", {
301
+ ref: refs,
302
+ "data-slot": "slope-chart",
303
+ "data-drawn": drawn || void 0,
304
+ "data-scrubbing": active !== null || void 0,
305
+ "aria-label": label,
306
+ className: cn("slope-chart box-border font-sans text-foreground", className),
307
+ children: [
308
+ /* @__PURE__ */ jsxs("div", {
309
+ ref: stage,
310
+ "data-slot": "slope-chart-stage",
311
+ "data-narrow": narrow || void 0,
312
+ "data-active": active ? "" : void 0,
313
+ role: empty ? void 0 : "slider",
314
+ tabIndex: empty ? void 0 : 0,
315
+ "aria-label": empty ? void 0 : `${label}, explore items in ${endLabel} order`,
316
+ "aria-valuemin": empty ? void 0 : 1,
317
+ "aria-valuemax": empty ? void 0 : data.length,
318
+ "aria-valuenow": empty ? void 0 : (activeRow ? activeRow.order : 0) + 1,
319
+ "aria-valuetext": empty ? void 0 : activeRow ? describe(activeRow) : summary,
320
+ className: "slope-chart-stage",
321
+ onPointerMove: (event) => {
322
+ if (event.pointerType === "mouse" || event.buttons) setActive(nearest(event.clientX, event.clientY));
323
+ },
324
+ onPointerDown: (event) => {
325
+ if (event.pointerType === "mouse") return;
326
+ event.currentTarget.setPointerCapture?.(event.pointerId);
327
+ setActive(nearest(event.clientX, event.clientY));
328
+ },
329
+ onPointerUp: (event) => {
330
+ if (event.pointerType !== "mouse") setActive(null);
331
+ },
332
+ onPointerCancel: () => setActive(null),
333
+ onPointerLeave: (event) => {
334
+ if (event.pointerType === "mouse") setActive(null);
335
+ },
336
+ onKeyDown,
337
+ onBlur: () => setActive(null),
338
+ onFocus: (event) => {
339
+ if (event.currentTarget.matches(":focus-visible") && !empty && !active) setActive(byEnd[0].item.key);
340
+ },
341
+ children: [
342
+ ready && !empty ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
343
+ "aria-hidden": "true",
344
+ className: "relative h-7",
345
+ children: [/* @__PURE__ */ jsx("span", {
346
+ className: "slope-chart-column",
347
+ style: { left: x0 },
348
+ children: startLabel
349
+ }), /* @__PURE__ */ jsx("span", {
350
+ className: "slope-chart-column",
351
+ style: { left: x1 },
352
+ children: endLabel
353
+ })]
354
+ }), /* @__PURE__ */ jsxs("div", {
355
+ ref: plot,
356
+ className: "relative",
357
+ style: { height: plotHeight },
358
+ children: [/* @__PURE__ */ jsxs("svg", {
359
+ width,
360
+ height: plotHeight,
361
+ "aria-hidden": "true",
362
+ focusable: "false",
363
+ className: "block overflow-visible",
364
+ children: [
365
+ /* @__PURE__ */ jsx("line", {
366
+ className: "slope-chart-axis",
367
+ x1: x0,
368
+ x2: x0,
369
+ y1: 0,
370
+ y2: plotHeight
371
+ }),
372
+ /* @__PURE__ */ jsx("line", {
373
+ className: "slope-chart-axis",
374
+ x1,
375
+ x2: x1,
376
+ y1: 0,
377
+ y2: plotHeight
378
+ }),
379
+ rows.map((row, i) => {
380
+ const key = row.item.key;
381
+ return /* @__PURE__ */ jsxs("g", {
382
+ "data-row": key,
383
+ "data-on": active === key || void 0,
384
+ "data-accent": highlightKey === key || void 0,
385
+ "data-dim": active !== null && active !== key || void 0,
386
+ className: "slope-chart-item motion-safe:animate-fade-in",
387
+ style: { "--delay": `${i * 50}ms` },
388
+ children: [
389
+ /* @__PURE__ */ jsx("path", {
390
+ "data-part": "lead0",
391
+ className: "slope-chart-leader",
392
+ d: `M${x0 - 6},${row.l0}L${x0 - 1},${row.y0}`
393
+ }),
394
+ /* @__PURE__ */ jsx("path", {
395
+ "data-part": "lead1",
396
+ className: "slope-chart-leader",
397
+ d: `M${x1 + 6},${row.l1}L${x1 + 1},${row.y1}`
398
+ }),
399
+ /* @__PURE__ */ jsx("line", {
400
+ "data-part": "line",
401
+ className: "slope-chart-line",
402
+ x1: x0,
403
+ x2: x1,
404
+ y1: row.y0,
405
+ y2: row.y1,
406
+ pathLength: 1
407
+ }),
408
+ /* @__PURE__ */ jsx("circle", {
409
+ "data-part": "dot0",
410
+ className: "slope-chart-dot",
411
+ cx: x0,
412
+ cy: row.y0,
413
+ r: 4
414
+ }),
415
+ /* @__PURE__ */ jsx("circle", {
416
+ "data-part": "dot1",
417
+ "data-end": "",
418
+ className: "slope-chart-dot",
419
+ cx: x1,
420
+ cy: row.y1,
421
+ r: 4
422
+ })
423
+ ]
424
+ }, key);
425
+ })
426
+ ]
427
+ }), rows.map((row, i) => {
428
+ const key = row.item.key;
429
+ const props = {
430
+ "data-label": key,
431
+ "data-on": active === key || void 0,
432
+ "data-accent": highlightKey === key || void 0,
433
+ className: "slope-chart-label"
434
+ };
435
+ const delay = { "--delay": `${i * 50}ms` };
436
+ return /* @__PURE__ */ jsxs("div", {
437
+ "aria-hidden": "true",
438
+ children: [/* @__PURE__ */ jsxs("span", {
439
+ ...props,
440
+ "data-side": "start",
441
+ style: {
442
+ ...delay,
443
+ right: width - x0 + 10,
444
+ maxWidth: x0 - 10
445
+ },
446
+ children: [/* @__PURE__ */ jsx("span", {
447
+ className: "slope-chart-name",
448
+ children: row.item.label
449
+ }), /* @__PURE__ */ jsx("span", {
450
+ className: "slope-chart-value",
451
+ children: format(row.item.start)
452
+ })]
453
+ }), /* @__PURE__ */ jsxs("span", {
454
+ ...props,
455
+ "data-side": "end",
456
+ style: {
457
+ ...delay,
458
+ left: x1 + 10
459
+ },
460
+ children: [/* @__PURE__ */ jsx("span", {
461
+ className: "slope-chart-value",
462
+ children: format(row.item.end)
463
+ }), ranks ? /* @__PURE__ */ jsx(Rank, { move: row.rank0 - row.rank1 }) : null]
464
+ })]
465
+ }, key);
466
+ })]
467
+ })] }) : null,
468
+ /* @__PURE__ */ jsxs("div", {
469
+ ref: tip,
470
+ "aria-hidden": "true",
471
+ "data-slot": "slope-chart-tooltip",
472
+ className: "line-chart-tooltip",
473
+ children: [
474
+ /* @__PURE__ */ jsx("p", {
475
+ className: "m-0 mb-0.5 whitespace-nowrap text-sm font-medium",
476
+ children: tipRow?.item.label ?? ""
477
+ }),
478
+ /* @__PURE__ */ jsxs("p", {
479
+ className: "m-0 flex items-center justify-between gap-3 text-sm",
480
+ children: [/* @__PURE__ */ jsx("span", {
481
+ className: "text-text-secondary",
482
+ children: startLabel
483
+ }), /* @__PURE__ */ jsx("span", {
484
+ className: "font-medium tabular-nums",
485
+ children: tipRow ? format(tipRow.item.start) : ""
486
+ })]
487
+ }),
488
+ /* @__PURE__ */ jsxs("p", {
489
+ className: "m-0 flex items-center justify-between gap-3 text-sm",
490
+ children: [/* @__PURE__ */ jsx("span", {
491
+ className: "text-text-secondary",
492
+ children: endLabel
493
+ }), /* @__PURE__ */ jsx("span", {
494
+ className: "font-medium tabular-nums",
495
+ children: tipRow ? format(tipRow.item.end) : ""
496
+ })]
497
+ }),
498
+ /* @__PURE__ */ jsx("p", {
499
+ className: "m-0 mt-0.5 text-xs tabular-nums text-muted-foreground",
500
+ children: tipRow ? `${change(tipRow.item)}, ${rankText(tipRow)}` : ""
501
+ })
502
+ ]
503
+ }),
504
+ empty ? /* @__PURE__ */ jsx("p", {
505
+ className: "m-0 grid min-h-40 place-items-center text-sm text-muted-foreground",
506
+ children: emptyLabel
507
+ }) : null
508
+ ]
509
+ }),
510
+ /* @__PURE__ */ jsx("p", {
511
+ className: "sr-only",
512
+ children: summary
513
+ }),
514
+ /* @__PURE__ */ jsx("p", {
515
+ className: "sr-only",
516
+ "aria-live": "polite",
517
+ "aria-atomic": "true",
518
+ children: activeRow ? describe(activeRow) : ""
519
+ }),
520
+ empty ? null : /* @__PURE__ */ jsx("div", {
521
+ className: "sr-only",
522
+ children: /* @__PURE__ */ jsxs("table", { children: [
523
+ /* @__PURE__ */ jsx("caption", { children: label }),
524
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
525
+ /* @__PURE__ */ jsx("th", {
526
+ scope: "col",
527
+ children: "Item"
528
+ }),
529
+ /* @__PURE__ */ jsx("th", {
530
+ scope: "col",
531
+ children: startLabel
532
+ }),
533
+ /* @__PURE__ */ jsx("th", {
534
+ scope: "col",
535
+ children: endLabel
536
+ }),
537
+ /* @__PURE__ */ jsx("th", {
538
+ scope: "col",
539
+ children: "Change"
540
+ }),
541
+ /* @__PURE__ */ jsx("th", {
542
+ scope: "col",
543
+ children: "Rank"
544
+ })
545
+ ] }) }),
546
+ /* @__PURE__ */ jsx("tbody", { children: byEnd.map((row) => /* @__PURE__ */ jsxs("tr", { children: [
547
+ /* @__PURE__ */ jsx("th", {
548
+ scope: "row",
549
+ children: row.item.label
550
+ }),
551
+ /* @__PURE__ */ jsx("td", { children: format(row.item.start) }),
552
+ /* @__PURE__ */ jsx("td", { children: format(row.item.end) }),
553
+ /* @__PURE__ */ jsx("td", { children: change(row.item) }),
554
+ /* @__PURE__ */ jsxs("td", { children: [
555
+ row.rank0,
556
+ " to ",
557
+ row.rank1
558
+ ] })
559
+ ] }, row.item.key)) })
560
+ ] })
561
+ })
562
+ ]
563
+ });
564
+ });
565
+ //#endregion
566
+ export { SlopeChart };
567
+
568
+ //# sourceMappingURL=slope-chart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slope-chart.js","names":[],"sources":["../../src/slope-chart/slope-chart.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n type PointerEvent,\n} from \"react\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { mergeRefs } from \"../lib/merge-refs.js\";\nimport { prefersReducedMotion, useIsomorphicLayoutEffect } from \"../lib/motion.js\";\nimport { live, MORPH, retarget, type Live } from \"../lib/spring-tween.js\";\nimport { SwapText } from \"../lib/swap-text.js\";\n\n/**\n * SlopeChart: how several items changed between exactly two moments, and how\n * their order changed. Each item is one line from its first value to its second\n * on a shared axis, with its name and value at each end and the change in rank\n * beside the second value.\n *\n * The lines draw left to right once the chart is in view (a beat apart), the end\n * dots land as each pen arrives, and the labels fade in behind them. New data\n * moves every line, dot, leader and label from where it is on screen. Hovering,\n * touching or the arrow keys bring one item forward, fade the others' lines and\n * show its numbers; the arrow keys walk the items in the second period's order.\n *\n * Plain SVG written straight to the DOM by one small spring tween; labels are\n * real text (they truncate), so they sit beside the SVG and move with it.\n */\nexport interface SlopeItem {\n /** Stable identity. An item keeps its line across datasets, so switching morphs it. */\n key: string;\n /** Name beside the start value, in the tooltip and in the table. */\n label: string;\n /** Value in the first period. */\n start: number;\n /** Value in the second period. */\n end: number;\n}\n\nexport interface SlopeChartProps {\n data: SlopeItem[];\n /** What is measured, such as \"Conversion rate by channel\". Names the chart for assistive technology. */\n label: string;\n /** Heading of the first column, such as \"Q1\". */\n startLabel: string;\n /** Heading of the second column, such as \"Q2\". */\n endLabel: string;\n formatValue?: (value: number) => string;\n /** Formats the change in the tooltip. Defaults to the difference, in formatValue's terms. */\n formatChange?: (change: number, item: SlopeItem) => string;\n /** Plot height in pixels. Defaults to 44 pixels per item, and at least 200. */\n height?: number;\n /** The item drawn in the accent, such as the one the story is about. */\n highlightKey?: string | null;\n /** Controlled item in focus. The others' lines fade while one is in focus. */\n activeKey?: string | null;\n onActiveChange?: (key: string | null) => void;\n /** Rank movement beside each end value. @default true */\n ranks?: boolean;\n /** @default \"No data\" */\n emptyLabel?: string;\n /** Extra classes for the root. Merged last. */\n className?: string;\n}\n\ntype Row = { item: SlopeItem; y0: number; y1: number; l0: number; l1: number; rank0: number; rank1: number; order: number };\ntype RowLive = { y0: Live; y1: Live; l0: Live; l1: Live };\n\n/** Space between labels, around the plot (so dots never touch an edge) and for the column headings, in pixels. */\nconst LABEL_GAP = 20;\nconst PAD = 14;\nconst HEAD = 28;\nconst clamp = (value: number, low: number, high: number) => Math.min(high, Math.max(low, value));\nconst GROUPED = new Intl.NumberFormat(\"en-US\", { maximumFractionDigits: 1 });\n\n/** Moves labels apart just enough to stop overlaps: touching labels form a group centred on where its members want to be. */\nfunction spread(wanted: number[], gap: number, low: number, high: number): number[] {\n const order = wanted.map((y, index) => ({ y, index })).sort((a, b) => a.y - b.y);\n let groups = order.map((entry) => ({ members: [entry], top: entry.y }));\n for (let changed = true; changed; ) {\n changed = false;\n const next: typeof groups = [];\n for (const group of groups) {\n const prev = next[next.length - 1];\n if (prev && prev.top + prev.members.length * gap > group.top) {\n const members = [...prev.members, ...group.members];\n next[next.length - 1] = { members, top: members.reduce((sum, member, k) => sum + member.y - k * gap, 0) / members.length };\n changed = true;\n } else next.push(group);\n }\n groups = next.map((group) => ({ ...group, top: clamp(group.top, low, Math.max(low, high - (group.members.length - 1) * gap)) }));\n }\n const out = new Array<number>(wanted.length);\n groups.forEach((group) => group.members.forEach((member, k) => (out[member.index] = group.top + k * gap)));\n return out;\n}\n\n/** Rank change: an arrow and the number of places, or \"=\" when level. The number rises or drops in when it changes. */\nfunction Rank({ move }: { move: number }) {\n const text = move === 0 ? \"=\" : `${Math.abs(move)}`;\n return (\n <span data-move={move > 0 ? \"up\" : move < 0 ? \"down\" : \"level\"} aria-hidden=\"true\" className=\"slope-chart-rank\">\n {move !== 0 ? (\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d={move > 0 ? \"M4 7V1M1.5 3.5 4 1l2.5 2.5\" : \"M4 1v6M1.5 4.5 4 7l2.5-2.5\"} />\n </svg>\n ) : null}\n <SwapText swapKey={text} dir={move >= 0 ? 1 : -1} motion=\"rise\">\n {text}\n </SwapText>\n </span>\n );\n}\n\nexport const SlopeChart = forwardRef<HTMLElement, SlopeChartProps>(function SlopeChart(\n {\n data,\n label,\n startLabel,\n endLabel,\n formatValue,\n formatChange,\n height,\n highlightKey = null,\n activeKey,\n onActiveChange,\n ranks = true,\n emptyLabel = \"No data\",\n className,\n },\n ref,\n) {\n const figure = useRef<HTMLElement | null>(null);\n const refs = useMemo(() => mergeRefs(ref, figure), [ref]);\n const stage = useRef<HTMLDivElement>(null);\n const plot = useRef<HTMLDivElement>(null);\n const tip = useRef<HTMLDivElement>(null);\n const empty = data.length === 0;\n const plotHeight = height ?? Math.max(200, data.length * 44);\n\n const [width, setWidth] = useState(0);\n useIsomorphicLayoutEffect(() => {\n const node = stage.current;\n if (!node) return;\n const read = () => setWidth(node.clientWidth);\n read();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(read);\n observer.observe(node);\n return () => observer.disconnect();\n }, []);\n const ready = width > 0;\n const narrow = width < 440;\n const leftRoom = narrow ? (width < 300 ? 116 : 132) : 168;\n const rightRoom = ranks ? (narrow ? 76 : 96) : narrow ? 52 : 64;\n const x0 = leftRoom;\n const x1 = Math.max(x0 + 40, width - rightRoom);\n\n // One shared value axis for both columns.\n const values = data.flatMap((item) => [item.start, item.end]);\n let lo = Math.min(...values);\n let hi = Math.max(...values);\n if (!Number.isFinite(lo)) {\n lo = 0;\n hi = 1;\n }\n if (hi - lo < 1e-9) {\n lo -= 1;\n hi += 1;\n }\n const yOf = (value: number) => PAD + (1 - (value - lo) / (hi - lo)) * (plotHeight - PAD * 2);\n const rankOf = (field: \"start\" | \"end\") => {\n const sorted = [...data].sort((a, b) => b[field] - a[field]);\n return (item: SlopeItem) => sorted.indexOf(item) + 1;\n };\n const r0 = rankOf(\"start\");\n const r1 = rankOf(\"end\");\n const l0 = spread(data.map((item) => yOf(item.start)), LABEL_GAP, 8, plotHeight - 8);\n const l1 = spread(data.map((item) => yOf(item.end)), LABEL_GAP, 8, plotHeight - 8);\n const rows: Row[] = data.map((item, i) => ({\n item,\n y0: yOf(item.start),\n y1: yOf(item.end),\n l0: l0[i]!,\n l1: l1[i]!,\n rank0: r0(item),\n rank1: r1(item),\n order: 0,\n }));\n const byEnd = [...rows].sort((a, b) => a.rank1 - b.rank1);\n byEnd.forEach((row, k) => {\n row.order = k;\n });\n\n // The chart draws in its own pixels; the lives hold each row's four heights, moved by one spring and written by paint().\n const lives = useRef(new Map<string, RowLive>());\n const box = useRef({ x0, x1 });\n const paint = useCallback(() => {\n const root = plot.current;\n if (!root) return;\n const { x0, x1 } = box.current;\n for (const node of root.querySelectorAll<SVGGElement>(\"[data-row]\")) {\n const at = lives.current.get(node.dataset.row!);\n if (!at) continue;\n const line = node.querySelector(\"[data-part=line]\");\n line?.setAttribute(\"y1\", String(at.y0.value));\n line?.setAttribute(\"y2\", String(at.y1.value));\n node.querySelector(\"[data-part=dot0]\")?.setAttribute(\"cy\", String(at.y0.value));\n node.querySelector(\"[data-part=dot1]\")?.setAttribute(\"cy\", String(at.y1.value));\n node.querySelector(\"[data-part=lead0]\")?.setAttribute(\"d\", `M${x0 - 6},${at.l0.value}L${x0 - 1},${at.y0.value}`);\n node.querySelector(\"[data-part=lead1]\")?.setAttribute(\"d\", `M${x1 + 6},${at.l1.value}L${x1 + 1},${at.y1.value}`);\n }\n for (const node of root.querySelectorAll<HTMLElement>(\"[data-label]\")) {\n const at = lives.current.get(node.dataset.label!);\n if (at) node.style.translate = `0 ${node.dataset.side === \"end\" ? at.l1.value : at.l0.value}px`;\n }\n }, []);\n useIsomorphicLayoutEffect(() => {\n box.current = { x0, x1 };\n paint();\n });\n\n // New data moves every line, dot, leader and label from wherever it is on screen; a new item starts where it belongs.\n const signature = rows.map((row) => [row.item.key, row.y0, row.y1, row.l0, row.l1].map((part) => (typeof part === \"number\" ? Math.round(part * 100) : part)).join(\":\")).join(\"|\");\n const latest = useRef(rows);\n useIsomorphicLayoutEffect(() => {\n latest.current = rows;\n });\n useIsomorphicLayoutEffect(() => {\n const current = latest.current;\n const keys = new Set(current.map((row) => row.item.key));\n for (const key of [...lives.current.keys()]) {\n if (keys.has(key)) continue;\n const gone = lives.current.get(key)!;\n for (const value of Object.values(gone)) value.stop();\n lives.current.delete(key);\n }\n for (const row of current) {\n const at = lives.current.get(row.item.key);\n if (!at) {\n lives.current.set(row.item.key, { y0: live(row.y0), y1: live(row.y1), l0: live(row.l0), l1: live(row.l1) });\n continue;\n }\n retarget(at.y0, row.y0, MORPH, paint);\n retarget(at.y1, row.y1, MORPH, paint);\n retarget(at.l0, row.l0, MORPH, paint);\n retarget(at.l1, row.l1, MORPH, paint);\n }\n paint();\n // The signature stands for the rows; ready is the first width.\n \n }, [signature, paint, ready]);\n useEffect(\n () => () => {\n for (const at of lives.current.values()) for (const value of Object.values(at)) value.stop();\n },\n [],\n );\n\n // The lines draw once a third of the chart is in view.\n const [drawn, setDrawn] = useState(false);\n useEffect(() => {\n const node = figure.current;\n if (!node || prefersReducedMotion() || typeof IntersectionObserver === \"undefined\") {\n setDrawn(true);\n return;\n }\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (!entry?.isIntersecting) return;\n observer.disconnect();\n setDrawn(true);\n },\n { threshold: 0.3 },\n );\n observer.observe(node);\n return () => observer.disconnect();\n }, []);\n\n const [ownActive, setOwnActive] = useState<string | null>(null);\n const wanted = activeKey !== undefined ? activeKey : ownActive;\n const active = wanted && data.some((item) => item.key === wanted) ? wanted : null;\n const setActive = (key: string | null) => {\n if (activeKey === undefined) setOwnActive(key);\n if (key !== active) onActiveChange?.(key);\n };\n const activeRow = rows.find((row) => row.item.key === active) ?? null;\n // The tooltip keeps the last item's content while it fades out, so it never collapses to an empty box mid-fade.\n const [shownKey, setShownKey] = useState<string | null>(null);\n if (active && active !== shownKey) setShownKey(active);\n const tipRow = activeRow ?? rows.find((row) => row.item.key === shownKey) ?? null;\n\n // The tooltip sits over the middle of the line in focus and stays inside the chart; it glides between items once showing.\n const shownBefore = useRef(false);\n useIsomorphicLayoutEffect(() => {\n const node = tip.current;\n if (!activeRow || !node || !width) {\n shownBefore.current = false;\n return;\n }\n const tw = node.offsetWidth;\n const th = node.offsetHeight;\n const mid = (activeRow.y0 + activeRow.y1) / 2;\n const above = mid - th - 16 >= 0;\n const left = clamp((x0 + x1) / 2 - tw / 2, 0, Math.max(0, width - tw));\n const top = clamp(HEAD + (above ? mid - th - 16 : mid + 16), 0, Math.max(0, plotHeight + HEAD - th));\n if (!shownBefore.current) node.style.transition = \"none\";\n node.style.translate = `${left}px ${top}px`;\n if (!shownBefore.current) {\n void node.offsetWidth;\n node.style.transition = \"\";\n }\n shownBefore.current = true;\n });\n\n // The line nearest the pointer, measured at the pointer's position along the plot; a label counts as its end of the line.\n const nearest = (clientX: number, clientY: number) => {\n const rect = stage.current?.getBoundingClientRect();\n if (!rect || empty) return null;\n const px = clientX - rect.left;\n const y = clientY - rect.top - HEAD;\n const t = (clamp(px, x0, x1) - x0) / Math.max(1, x1 - x0);\n let best: Row | null = null;\n let distance = Infinity;\n for (const row of rows) {\n const inLine = Math.abs(row.y0 + (row.y1 - row.y0) * t - y);\n const onLabel = px < x0 ? Math.abs(row.l0 - y) : px > x1 ? Math.abs(row.l1 - y) : Infinity;\n const d = Math.min(inLine, onLabel);\n if (d < distance) {\n distance = d;\n best = row;\n }\n }\n return distance <= 22 ? (best?.item.key ?? null) : null;\n };\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (empty) return;\n if (event.key === \"Escape\" && active) {\n event.preventDefault();\n setActive(null);\n return;\n }\n const at = activeRow ? activeRow.order : -1;\n const moves: Record<string, number> = {\n ArrowDown: at + 1,\n ArrowRight: at + 1,\n ArrowUp: at < 0 ? 0 : at - 1,\n ArrowLeft: at < 0 ? 0 : at - 1,\n Home: 0,\n End: byEnd.length - 1,\n };\n if (!(event.key in moves)) return;\n event.preventDefault();\n setActive(byEnd[clamp(moves[event.key]!, 0, byEnd.length - 1)]!.item.key);\n };\n\n const format = (value: number) => (formatValue ? formatValue(value) : GROUPED.format(value));\n const change = (item: SlopeItem) =>\n formatChange ? formatChange(item.end - item.start, item) : `${item.end >= item.start ? \"+\" : \"−\"}${format(Math.abs(item.end - item.start))}`;\n const rankText = (row: Row) =>\n row.rank0 === row.rank1 ? \"same rank\" : row.rank1 < row.rank0 ? `up ${row.rank0 - row.rank1} to rank ${row.rank1}` : `down ${row.rank1 - row.rank0} to rank ${row.rank1}`;\n const describe = (row: Row) => `${row.item.label}, ${startLabel} ${format(row.item.start)}, ${endLabel} ${format(row.item.end)}, ${change(row.item)}, ${rankText(row)}`;\n const summary = empty\n ? `${label}. ${emptyLabel}.`\n : `${label}, ${startLabel} to ${endLabel}. ${byEnd.map((row) => `${row.item.label} ${format(row.item.start)} to ${format(row.item.end)}`).join(\", \")}.`;\n\n return (\n <figure\n ref={refs}\n data-slot=\"slope-chart\"\n data-drawn={drawn || undefined}\n data-scrubbing={active !== null || undefined}\n aria-label={label}\n className={cn(\"slope-chart box-border font-sans text-foreground\", className)}\n >\n <div\n ref={stage}\n data-slot=\"slope-chart-stage\"\n data-narrow={narrow || undefined}\n data-active={active ? \"\" : undefined}\n role={empty ? undefined : \"slider\"}\n tabIndex={empty ? undefined : 0}\n aria-label={empty ? undefined : `${label}, explore items in ${endLabel} order`}\n aria-valuemin={empty ? undefined : 1}\n aria-valuemax={empty ? undefined : data.length}\n aria-valuenow={empty ? undefined : (activeRow ? activeRow.order : 0) + 1}\n aria-valuetext={empty ? undefined : activeRow ? describe(activeRow) : summary}\n className=\"slope-chart-stage\"\n onPointerMove={(event: PointerEvent<HTMLDivElement>) => {\n if (event.pointerType === \"mouse\" || event.buttons) setActive(nearest(event.clientX, event.clientY));\n }}\n onPointerDown={(event: PointerEvent<HTMLDivElement>) => {\n if (event.pointerType === \"mouse\") return;\n event.currentTarget.setPointerCapture?.(event.pointerId);\n setActive(nearest(event.clientX, event.clientY));\n }}\n onPointerUp={(event) => {\n if (event.pointerType !== \"mouse\") setActive(null);\n }}\n onPointerCancel={() => setActive(null)}\n onPointerLeave={(event) => {\n if (event.pointerType === \"mouse\") setActive(null);\n }}\n onKeyDown={onKeyDown}\n onBlur={() => setActive(null)}\n onFocus={(event) => {\n if (event.currentTarget.matches(\":focus-visible\") && !empty && !active) setActive(byEnd[0]!.item.key);\n }}\n >\n {ready && !empty ? (\n <>\n <div aria-hidden=\"true\" className=\"relative h-7\">\n <span className=\"slope-chart-column\" style={{ left: x0 }}>\n {startLabel}\n </span>\n <span className=\"slope-chart-column\" style={{ left: x1 }}>\n {endLabel}\n </span>\n </div>\n <div ref={plot} className=\"relative\" style={{ height: plotHeight }}>\n <svg width={width} height={plotHeight} aria-hidden=\"true\" focusable=\"false\" className=\"block overflow-visible\">\n <line className=\"slope-chart-axis\" x1={x0} x2={x0} y1={0} y2={plotHeight} />\n <line className=\"slope-chart-axis\" x1={x1} x2={x1} y1={0} y2={plotHeight} />\n {rows.map((row, i) => {\n const key = row.item.key;\n return (\n <g\n key={key}\n data-row={key}\n data-on={active === key || undefined}\n data-accent={highlightKey === key || undefined}\n data-dim={(active !== null && active !== key) || undefined}\n className=\"slope-chart-item motion-safe:animate-fade-in\"\n style={{ \"--delay\": `${i * 50}ms` } as CSSProperties}\n >\n <path data-part=\"lead0\" className=\"slope-chart-leader\" d={`M${x0 - 6},${row.l0}L${x0 - 1},${row.y0}`} />\n <path data-part=\"lead1\" className=\"slope-chart-leader\" d={`M${x1 + 6},${row.l1}L${x1 + 1},${row.y1}`} />\n <line data-part=\"line\" className=\"slope-chart-line\" x1={x0} x2={x1} y1={row.y0} y2={row.y1} pathLength={1} />\n <circle data-part=\"dot0\" className=\"slope-chart-dot\" cx={x0} cy={row.y0} r={4} />\n <circle data-part=\"dot1\" data-end=\"\" className=\"slope-chart-dot\" cx={x1} cy={row.y1} r={4} />\n </g>\n );\n })}\n </svg>\n {rows.map((row, i) => {\n const key = row.item.key;\n const props = {\n \"data-label\": key,\n \"data-on\": active === key || undefined,\n \"data-accent\": highlightKey === key || undefined,\n className: \"slope-chart-label\",\n };\n const delay = { \"--delay\": `${i * 50}ms` };\n return (\n <div key={key} aria-hidden=\"true\">\n <span {...props} data-side=\"start\" style={{ ...delay, right: width - x0 + 10, maxWidth: x0 - 10 }}>\n <span className=\"slope-chart-name\">{row.item.label}</span>\n <span className=\"slope-chart-value\">{format(row.item.start)}</span>\n </span>\n <span {...props} data-side=\"end\" style={{ ...delay, left: x1 + 10 }}>\n <span className=\"slope-chart-value\">{format(row.item.end)}</span>\n {ranks ? <Rank move={row.rank0 - row.rank1} /> : null}\n </span>\n </div>\n );\n })}\n </div>\n </>\n ) : null}\n <div ref={tip} aria-hidden=\"true\" data-slot=\"slope-chart-tooltip\" className=\"line-chart-tooltip\">\n <p className=\"m-0 mb-0.5 whitespace-nowrap text-sm font-medium\">{tipRow?.item.label ?? \"\"}</p>\n <p className=\"m-0 flex items-center justify-between gap-3 text-sm\">\n <span className=\"text-text-secondary\">{startLabel}</span>\n <span className=\"font-medium tabular-nums\">{tipRow ? format(tipRow.item.start) : \"\"}</span>\n </p>\n <p className=\"m-0 flex items-center justify-between gap-3 text-sm\">\n <span className=\"text-text-secondary\">{endLabel}</span>\n <span className=\"font-medium tabular-nums\">{tipRow ? format(tipRow.item.end) : \"\"}</span>\n </p>\n <p className=\"m-0 mt-0.5 text-xs tabular-nums text-muted-foreground\">{tipRow ? `${change(tipRow.item)}, ${rankText(tipRow)}` : \"\"}</p>\n </div>\n {empty ? <p className=\"m-0 grid min-h-40 place-items-center text-sm text-muted-foreground\">{emptyLabel}</p> : null}\n </div>\n <p className=\"sr-only\">{summary}</p>\n <p className=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\">\n {activeRow ? describe(activeRow) : \"\"}\n </p>\n {empty ? null : (\n <div className=\"sr-only\">\n <table>\n <caption>{label}</caption>\n <thead>\n <tr>\n <th scope=\"col\">Item</th>\n <th scope=\"col\">{startLabel}</th>\n <th scope=\"col\">{endLabel}</th>\n <th scope=\"col\">Change</th>\n <th scope=\"col\">Rank</th>\n </tr>\n </thead>\n <tbody>\n {byEnd.map((row) => (\n <tr key={row.item.key}>\n <th scope=\"row\">{row.item.label}</th>\n <td>{format(row.item.start)}</td>\n <td>{format(row.item.end)}</td>\n <td>{change(row.item)}</td>\n <td>\n {row.rank0} to {row.rank1}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </figure>\n );\n});\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { SPARKLINE_DRAW_MS, Sparkline, SparklineProps, SparklineTone, sparklineVariants } from "./sparkline.js";
2
+ export { SPARKLINE_DRAW_MS, Sparkline, type SparklineProps, type SparklineTone, sparklineVariants };
@@ -0,0 +1,2 @@
1
+ import { SPARKLINE_DRAW_MS, Sparkline, sparklineVariants } from "./sparkline.js";
2
+ export { SPARKLINE_DRAW_MS, Sparkline, sparklineVariants };