@seekalfred/primitives 0.6.0 → 0.7.3

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 (346) hide show
  1. package/README.md +214 -15
  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 +53 -4
  8. package/dist/alert/alert.js +100 -11
  9. package/dist/alert/alert.js.map +1 -1
  10. package/dist/alert/index.d.ts +2 -2
  11. package/dist/alert/index.js +2 -2
  12. package/dist/alert-dialog/alert-dialog.d.ts +58 -18
  13. package/dist/alert-dialog/alert-dialog.js +152 -9
  14. package/dist/alert-dialog/alert-dialog.js.map +1 -1
  15. package/dist/alert-dialog/index.d.ts +2 -2
  16. package/dist/alert-dialog/index.js +2 -2
  17. package/dist/animated-counter/animated-counter.d.ts +38 -0
  18. package/dist/animated-counter/animated-counter.js +230 -0
  19. package/dist/animated-counter/animated-counter.js.map +1 -0
  20. package/dist/animated-counter/index.d.ts +2 -0
  21. package/dist/animated-counter/index.js +2 -0
  22. package/dist/announcement-bar/announcement-bar.d.ts +67 -0
  23. package/dist/announcement-bar/announcement-bar.js +364 -0
  24. package/dist/announcement-bar/announcement-bar.js.map +1 -0
  25. package/dist/announcement-bar/index.d.ts +2 -0
  26. package/dist/announcement-bar/index.js +2 -0
  27. package/dist/badge/badge.d.ts +1 -1
  28. package/dist/bar-chart/bar-chart.d.ts +51 -0
  29. package/dist/bar-chart/bar-chart.js +565 -0
  30. package/dist/bar-chart/bar-chart.js.map +1 -0
  31. package/dist/bar-chart/index.d.ts +2 -0
  32. package/dist/bar-chart/index.js +2 -0
  33. package/dist/breadcrumb/breadcrumb.d.ts +2 -2
  34. package/dist/breadcrumb/breadcrumb.js +12 -3
  35. package/dist/breadcrumb/breadcrumb.js.map +1 -1
  36. package/dist/brush-chart/brush-chart.d.ts +64 -0
  37. package/dist/brush-chart/brush-chart.js +1056 -0
  38. package/dist/brush-chart/brush-chart.js.map +1 -0
  39. package/dist/brush-chart/index.d.ts +2 -0
  40. package/dist/brush-chart/index.js +2 -0
  41. package/dist/button/button.d.ts +1 -1
  42. package/dist/button/button.js +31 -21
  43. package/dist/button/button.js.map +1 -1
  44. package/dist/button-group/button-group.js +3 -4
  45. package/dist/button-group/button-group.js.map +1 -1
  46. package/dist/calendar/calendar.d.ts +1 -1
  47. package/dist/card/card.d.ts +22 -1
  48. package/dist/card/card.js +60 -7
  49. package/dist/card/card.js.map +1 -1
  50. package/dist/card-stack/card-stack.d.ts +54 -0
  51. package/dist/card-stack/card-stack.js +492 -0
  52. package/dist/card-stack/card-stack.js.map +1 -0
  53. package/dist/card-stack/index.d.ts +2 -0
  54. package/dist/card-stack/index.js +2 -0
  55. package/dist/carousel/carousel.d.ts +77 -0
  56. package/dist/carousel/carousel.js +415 -0
  57. package/dist/carousel/carousel.js.map +1 -0
  58. package/dist/carousel/index.d.ts +2 -0
  59. package/dist/carousel/index.js +2 -0
  60. package/dist/checkbox/checkbox.js +4 -4
  61. package/dist/checkbox/checkbox.js.map +1 -1
  62. package/dist/chip-group/chip-group.d.ts +37 -0
  63. package/dist/chip-group/chip-group.js +148 -0
  64. package/dist/chip-group/chip-group.js.map +1 -0
  65. package/dist/chip-group/index.d.ts +2 -0
  66. package/dist/chip-group/index.js +2 -0
  67. package/dist/copy-button/copy-button.d.ts +18 -2
  68. package/dist/copy-button/copy-button.js +29 -8
  69. package/dist/copy-button/copy-button.js.map +1 -1
  70. package/dist/countdown/countdown.d.ts +45 -0
  71. package/dist/countdown/countdown.js +298 -0
  72. package/dist/countdown/countdown.js.map +1 -0
  73. package/dist/countdown/index.d.ts +2 -0
  74. package/dist/countdown/index.js +2 -0
  75. package/dist/date-picker/picker-parts.js +1 -1
  76. package/dist/date-picker/picker-parts.js.map +1 -1
  77. package/dist/dialog/dialog.js +1 -1
  78. package/dist/dialog/dialog.js.map +1 -1
  79. package/dist/donut-chart/donut-chart.d.ts +86 -0
  80. package/dist/donut-chart/donut-chart.js +593 -0
  81. package/dist/donut-chart/donut-chart.js.map +1 -0
  82. package/dist/donut-chart/index.d.ts +2 -0
  83. package/dist/donut-chart/index.js +2 -0
  84. package/dist/empty-state/empty-state.d.ts +42 -10
  85. package/dist/empty-state/empty-state.js +44 -26
  86. package/dist/empty-state/empty-state.js.map +1 -1
  87. package/dist/empty-state/index.d.ts +2 -2
  88. package/dist/empty-state/index.js +2 -2
  89. package/dist/file-drop-zone/file-drop-zone.js +1 -1
  90. package/dist/file-drop-zone/file-drop-zone.js.map +1 -1
  91. package/dist/filter-bar/filter-bar.d.ts +50 -26
  92. package/dist/filter-bar/filter-bar.js +317 -157
  93. package/dist/filter-bar/filter-bar.js.map +1 -1
  94. package/dist/gauge/gauge.d.ts +45 -0
  95. package/dist/gauge/gauge.js +219 -0
  96. package/dist/gauge/gauge.js.map +1 -0
  97. package/dist/gauge/index.d.ts +2 -0
  98. package/dist/gauge/index.js +2 -0
  99. package/dist/in-view-title/in-view-title.d.ts +33 -0
  100. package/dist/in-view-title/in-view-title.js +119 -0
  101. package/dist/in-view-title/in-view-title.js.map +1 -0
  102. package/dist/in-view-title/index.d.ts +2 -0
  103. package/dist/in-view-title/index.js +2 -0
  104. package/dist/index.d.ts +53 -10
  105. package/dist/index.js +52 -12
  106. package/dist/input/input.js +4 -4
  107. package/dist/input/input.js.map +1 -1
  108. package/dist/lib/cn.js +11 -1
  109. package/dist/lib/cn.js.map +1 -1
  110. package/dist/lib/field-message.js +28 -10
  111. package/dist/lib/field-message.js.map +1 -1
  112. package/dist/lib/field-shell.js +10 -3
  113. package/dist/lib/field-shell.js.map +1 -1
  114. package/dist/lib/field-surface.js +31 -9
  115. package/dist/lib/field-surface.js.map +1 -1
  116. package/dist/lib/flag-emoji.js +50 -0
  117. package/dist/lib/flag-emoji.js.map +1 -0
  118. package/dist/lib/flip.js +11 -3
  119. package/dist/lib/flip.js.map +1 -1
  120. package/dist/lib/menu-highlight.js +64 -0
  121. package/dist/lib/menu-highlight.js.map +1 -0
  122. package/dist/lib/motion.js +9 -2
  123. package/dist/lib/motion.js.map +1 -1
  124. package/dist/lib/rolling-value.js +1 -1
  125. package/dist/lib/rolling-value.js.map +1 -1
  126. package/dist/lib/spring-tween.js +500 -0
  127. package/dist/lib/spring-tween.js.map +1 -0
  128. package/dist/lib/swap-text.js +3 -1
  129. package/dist/lib/swap-text.js.map +1 -1
  130. package/dist/lib/use-copy-feedback.js +17 -3
  131. package/dist/lib/use-copy-feedback.js.map +1 -1
  132. package/dist/line-chart/index.d.ts +2 -0
  133. package/dist/line-chart/index.js +2 -0
  134. package/dist/line-chart/line-chart.d.ts +116 -0
  135. package/dist/line-chart/line-chart.js +740 -0
  136. package/dist/line-chart/line-chart.js.map +1 -0
  137. package/dist/mention-input/index.d.ts +2 -0
  138. package/dist/mention-input/index.js +2 -0
  139. package/dist/mention-input/mention-input.d.ts +98 -0
  140. package/dist/mention-input/mention-input.js +576 -0
  141. package/dist/mention-input/mention-input.js.map +1 -0
  142. package/dist/menu/menu.d.ts +2 -0
  143. package/dist/menu/menu.js +23 -12
  144. package/dist/menu/menu.js.map +1 -1
  145. package/dist/money-input/index.d.ts +2 -0
  146. package/dist/money-input/index.js +2 -0
  147. package/dist/money-input/money-input.d.ts +86 -0
  148. package/dist/money-input/money-input.js +613 -0
  149. package/dist/money-input/money-input.js.map +1 -0
  150. package/dist/morph-select/index.d.ts +2 -0
  151. package/dist/morph-select/index.js +2 -0
  152. package/dist/morph-select/morph-select.d.ts +89 -0
  153. package/dist/morph-select/morph-select.js +712 -0
  154. package/dist/morph-select/morph-select.js.map +1 -0
  155. package/dist/multi-select/index.d.ts +2 -0
  156. package/dist/multi-select/index.js +2 -0
  157. package/dist/multi-select/multi-select.d.ts +77 -0
  158. package/dist/multi-select/multi-select.js +209 -0
  159. package/dist/multi-select/multi-select.js.map +1 -0
  160. package/dist/number-field/index.d.ts +2 -0
  161. package/dist/number-field/index.js +2 -0
  162. package/dist/number-field/number-field.d.ts +42 -0
  163. package/dist/number-field/number-field.js +199 -0
  164. package/dist/number-field/number-field.js.map +1 -0
  165. package/dist/onboarding-checklist/index.d.ts +2 -0
  166. package/dist/onboarding-checklist/index.js +2 -0
  167. package/dist/onboarding-checklist/onboarding-checklist.d.ts +55 -0
  168. package/dist/onboarding-checklist/onboarding-checklist.js +577 -0
  169. package/dist/onboarding-checklist/onboarding-checklist.js.map +1 -0
  170. package/dist/password-field/password-field.d.ts +16 -0
  171. package/dist/password-field/password-field.js +39 -10
  172. package/dist/password-field/password-field.js.map +1 -1
  173. package/dist/phone-input/index.d.ts +3 -0
  174. package/dist/phone-input/index.js +3 -0
  175. package/dist/phone-input/phone-countries.d.ts +29 -0
  176. package/dist/phone-input/phone-countries.js +170 -0
  177. package/dist/phone-input/phone-countries.js.map +1 -0
  178. package/dist/phone-input/phone-input.d.ts +66 -0
  179. package/dist/phone-input/phone-input.js +440 -0
  180. package/dist/phone-input/phone-input.js.map +1 -0
  181. package/dist/popover/index.d.ts +2 -2
  182. package/dist/popover/index.js +2 -2
  183. package/dist/popover/popover.d.ts +51 -2
  184. package/dist/popover/popover.js +59 -8
  185. package/dist/popover/popover.js.map +1 -1
  186. package/dist/progress/progress.d.ts +16 -2
  187. package/dist/progress/progress.js +16 -9
  188. package/dist/progress/progress.js.map +1 -1
  189. package/dist/radio-group/index.d.ts +2 -2
  190. package/dist/radio-group/index.js +2 -2
  191. package/dist/radio-group/radio-group.d.ts +33 -3
  192. package/dist/radio-group/radio-group.js +110 -10
  193. package/dist/radio-group/radio-group.js.map +1 -1
  194. package/dist/reactions/index.d.ts +2 -0
  195. package/dist/reactions/index.js +2 -0
  196. package/dist/reactions/reactions.d.ts +50 -0
  197. package/dist/reactions/reactions.js +315 -0
  198. package/dist/reactions/reactions.js.map +1 -0
  199. package/dist/rich-text-editor/index.d.ts +3 -0
  200. package/dist/rich-text-editor/index.js +2 -0
  201. package/dist/rich-text-editor/rich-text-editor.d.ts +70 -0
  202. package/dist/rich-text-editor/rich-text-editor.js +909 -0
  203. package/dist/rich-text-editor/rich-text-editor.js.map +1 -0
  204. package/dist/rich-text-editor/rich-text-engine.d.ts +16 -0
  205. package/dist/rich-text-editor/rich-text-engine.js +366 -0
  206. package/dist/rich-text-editor/rich-text-engine.js.map +1 -0
  207. package/dist/rich-text-editor/rich-text-html.js +174 -0
  208. package/dist/rich-text-editor/rich-text-html.js.map +1 -0
  209. package/dist/rich-text-editor/rich-text-icons.js +43 -0
  210. package/dist/rich-text-editor/rich-text-icons.js.map +1 -0
  211. package/dist/ridgeline/index.d.ts +2 -0
  212. package/dist/ridgeline/index.js +2 -0
  213. package/dist/ridgeline/ridgeline.d.ts +55 -0
  214. package/dist/ridgeline/ridgeline.js +701 -0
  215. package/dist/ridgeline/ridgeline.js.map +1 -0
  216. package/dist/scroll-area/index.d.ts +2 -2
  217. package/dist/scroll-area/index.js +2 -2
  218. package/dist/scroll-area/scroll-area.d.ts +68 -31
  219. package/dist/scroll-area/scroll-area.js +212 -62
  220. package/dist/scroll-area/scroll-area.js.map +1 -1
  221. package/dist/scrub-input/evaluate.d.ts +14 -0
  222. package/dist/scrub-input/evaluate.js +72 -0
  223. package/dist/scrub-input/evaluate.js.map +1 -0
  224. package/dist/scrub-input/index.d.ts +3 -0
  225. package/dist/scrub-input/index.js +3 -0
  226. package/dist/scrub-input/scrub-input.d.ts +74 -0
  227. package/dist/scrub-input/scrub-input.js +486 -0
  228. package/dist/scrub-input/scrub-input.js.map +1 -0
  229. package/dist/search-field/search-field.d.ts +24 -2
  230. package/dist/search-field/search-field.js +24 -9
  231. package/dist/search-field/search-field.js.map +1 -1
  232. package/dist/select/select.d.ts +3 -1
  233. package/dist/select/select.js +28 -14
  234. package/dist/select/select.js.map +1 -1
  235. package/dist/separator/separator.d.ts +22 -10
  236. package/dist/separator/separator.js +33 -11
  237. package/dist/separator/separator.js.map +1 -1
  238. package/dist/sheet/sheet.js +2 -1
  239. package/dist/sheet/sheet.js.map +1 -1
  240. package/dist/shortcut-recorder/index.d.ts +3 -0
  241. package/dist/shortcut-recorder/index.js +3 -0
  242. package/dist/shortcut-recorder/shortcut-model.d.ts +27 -0
  243. package/dist/shortcut-recorder/shortcut-model.js +206 -0
  244. package/dist/shortcut-recorder/shortcut-model.js.map +1 -0
  245. package/dist/shortcut-recorder/shortcut-recorder.d.ts +93 -0
  246. package/dist/shortcut-recorder/shortcut-recorder.js +489 -0
  247. package/dist/shortcut-recorder/shortcut-recorder.js.map +1 -0
  248. package/dist/slider/index.d.ts +2 -2
  249. package/dist/slider/slider.d.ts +46 -14
  250. package/dist/slider/slider.js +151 -67
  251. package/dist/slider/slider.js.map +1 -1
  252. package/dist/slope-chart/index.d.ts +2 -0
  253. package/dist/slope-chart/index.js +2 -0
  254. package/dist/slope-chart/slope-chart.d.ts +54 -0
  255. package/dist/slope-chart/slope-chart.js +568 -0
  256. package/dist/slope-chart/slope-chart.js.map +1 -0
  257. package/dist/sparkline/index.d.ts +2 -0
  258. package/dist/sparkline/index.js +2 -0
  259. package/dist/sparkline/sparkline.d.ts +46 -0
  260. package/dist/sparkline/sparkline.js +390 -0
  261. package/dist/sparkline/sparkline.js.map +1 -0
  262. package/dist/split-bar/index.d.ts +2 -0
  263. package/dist/split-bar/index.js +2 -0
  264. package/dist/split-bar/split-bar.d.ts +62 -0
  265. package/dist/split-bar/split-bar.js +513 -0
  266. package/dist/split-bar/split-bar.js.map +1 -0
  267. package/dist/split-button/split-button.d.ts +1 -1
  268. package/dist/split-button/split-button.js +12 -11
  269. package/dist/split-button/split-button.js.map +1 -1
  270. package/dist/stat-card/index.d.ts +2 -2
  271. package/dist/stat-card/index.js +2 -2
  272. package/dist/stat-card/stat-card.d.ts +58 -5
  273. package/dist/stat-card/stat-card.js +144 -17
  274. package/dist/stat-card/stat-card.js.map +1 -1
  275. package/dist/stepper/index.d.ts +2 -0
  276. package/dist/stepper/index.js +2 -0
  277. package/dist/stepper/stepper.d.ts +51 -0
  278. package/dist/stepper/stepper.js +215 -0
  279. package/dist/stepper/stepper.js.map +1 -0
  280. package/dist/streamgraph/index.d.ts +2 -0
  281. package/dist/streamgraph/index.js +2 -0
  282. package/dist/streamgraph/streamgraph.d.ts +70 -0
  283. package/dist/streamgraph/streamgraph.js +613 -0
  284. package/dist/streamgraph/streamgraph.js.map +1 -0
  285. package/dist/styles.css +1 -1
  286. package/dist/swipe-actions/index.d.ts +2 -0
  287. package/dist/swipe-actions/index.js +2 -0
  288. package/dist/swipe-actions/swipe-actions.d.ts +67 -0
  289. package/dist/swipe-actions/swipe-actions.js +552 -0
  290. package/dist/swipe-actions/swipe-actions.js.map +1 -0
  291. package/dist/switch/switch.js +2 -2
  292. package/dist/switch/switch.js.map +1 -1
  293. package/dist/table/index.d.ts +2 -2
  294. package/dist/table/index.js +2 -2
  295. package/dist/table/table.d.ts +55 -3
  296. package/dist/table/table.js +340 -165
  297. package/dist/table/table.js.map +1 -1
  298. package/dist/tabs/tabs.js +2 -2
  299. package/dist/tabs/tabs.js.map +1 -1
  300. package/dist/tag-input/index.d.ts +2 -0
  301. package/dist/tag-input/index.js +2 -0
  302. package/dist/tag-input/tag-input.d.ts +40 -0
  303. package/dist/tag-input/tag-input.js +269 -0
  304. package/dist/tag-input/tag-input.js.map +1 -0
  305. package/dist/text-morph/index.d.ts +2 -0
  306. package/dist/text-morph/index.js +2 -0
  307. package/dist/text-morph/text-morph.d.ts +23 -0
  308. package/dist/text-morph/text-morph.js +21 -0
  309. package/dist/text-morph/text-morph.js.map +1 -0
  310. package/dist/text-reveal/index.d.ts +2 -0
  311. package/dist/text-reveal/index.js +2 -0
  312. package/dist/text-reveal/text-reveal.d.ts +27 -0
  313. package/dist/text-reveal/text-reveal.js +51 -0
  314. package/dist/text-reveal/text-reveal.js.map +1 -0
  315. package/dist/text-shimmer/index.d.ts +2 -0
  316. package/dist/text-shimmer/index.js +2 -0
  317. package/dist/text-shimmer/text-shimmer.d.ts +29 -0
  318. package/dist/text-shimmer/text-shimmer.js +29 -0
  319. package/dist/text-shimmer/text-shimmer.js.map +1 -0
  320. package/dist/time-picker/time-picker.d.ts +36 -1
  321. package/dist/time-picker/time-picker.js +35 -7
  322. package/dist/time-picker/time-picker.js.map +1 -1
  323. package/dist/toast/index.d.ts +2 -2
  324. package/dist/toast/index.js +2 -2
  325. package/dist/toast/toast.d.ts +7 -1
  326. package/dist/toast/toast.js +82 -40
  327. package/dist/toast/toast.js.map +1 -1
  328. package/dist/tooltip/tooltip.d.ts +9 -2
  329. package/dist/tooltip/tooltip.js +7 -7
  330. package/dist/tooltip/tooltip.js.map +1 -1
  331. package/dist/treemap/index.d.ts +2 -0
  332. package/dist/treemap/index.js +2 -0
  333. package/dist/treemap/treemap.d.ts +53 -0
  334. package/dist/treemap/treemap.js +699 -0
  335. package/dist/treemap/treemap.js.map +1 -0
  336. package/dist/usage-meter/index.d.ts +2 -0
  337. package/dist/usage-meter/index.js +2 -0
  338. package/dist/usage-meter/usage-meter.d.ts +80 -0
  339. package/dist/usage-meter/usage-meter.js +458 -0
  340. package/dist/usage-meter/usage-meter.js.map +1 -0
  341. package/dist/waffle-chart/index.d.ts +2 -0
  342. package/dist/waffle-chart/index.js +2 -0
  343. package/dist/waffle-chart/waffle-chart.d.ts +57 -0
  344. package/dist/waffle-chart/waffle-chart.js +426 -0
  345. package/dist/waffle-chart/waffle-chart.js.map +1 -0
  346. package/package.json +165 -3
@@ -0,0 +1,415 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { mergeRefs } from "../lib/merge-refs.js";
4
+ import { useIsomorphicLayoutEffect, useReducedMotion } from "../lib/motion.js";
5
+ import { Children, forwardRef, isValidElement, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/carousel/carousel.tsx
8
+ /** Movement before a mouse press is read as a drag. */
9
+ const SLOP = 6;
10
+ /** Release speed in px/s that always moves at least one slide. */
11
+ const FLICK = 360;
12
+ /**
13
+ * How long a glide may take before the carousel stops waiting for it: one slide,
14
+ * plus more per extra slide (a `loop` wrap crosses them all), capped.
15
+ */
16
+ const BACKSTOP = {
17
+ base: 1e3,
18
+ perSlide: 250,
19
+ max: 3e3
20
+ };
21
+ /** Where a flick would come to rest: velocity (px/s) projected with a paging deceleration rate. */
22
+ const project = (velocity, rate = .995) => velocity / 1e3 * rate / (1 - rate);
23
+ const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
24
+ const defaultSlideLabel = (index, count) => `${index + 1} of ${count}`;
25
+ const PlayGlyph = () => /* @__PURE__ */ jsx("svg", {
26
+ width: 15,
27
+ height: 15,
28
+ viewBox: "0 0 16 16",
29
+ fill: "currentColor",
30
+ "aria-hidden": "true",
31
+ children: /* @__PURE__ */ jsx("path", { d: "M4.5 2.8v10.4a.6.6 0 0 0 .9.5l8.2-5.2a.6.6 0 0 0 0-1L5.4 2.3a.6.6 0 0 0-.9.5Z" })
32
+ });
33
+ const PauseGlyph = () => /* @__PURE__ */ jsxs("svg", {
34
+ width: 15,
35
+ height: 15,
36
+ viewBox: "0 0 16 16",
37
+ fill: "currentColor",
38
+ "aria-hidden": "true",
39
+ children: [/* @__PURE__ */ jsx("rect", {
40
+ x: "3.5",
41
+ y: "2.5",
42
+ width: "3.2",
43
+ height: "11",
44
+ rx: "1"
45
+ }), /* @__PURE__ */ jsx("rect", {
46
+ x: "9.3",
47
+ y: "2.5",
48
+ width: "3.2",
49
+ height: "11",
50
+ rx: "1"
51
+ })]
52
+ });
53
+ const Chevron = ({ back }) => /* @__PURE__ */ jsx("svg", {
54
+ width: 18,
55
+ height: 18,
56
+ viewBox: "0 0 16 16",
57
+ fill: "none",
58
+ stroke: "currentColor",
59
+ strokeWidth: 1.75,
60
+ strokeLinecap: "round",
61
+ strokeLinejoin: "round",
62
+ "aria-hidden": "true",
63
+ children: /* @__PURE__ */ jsx("path", { d: back ? "M10 3.5 5.5 8l4.5 4.5" : "M6 3.5 10.5 8 6 12.5" })
64
+ });
65
+ const Carousel = forwardRef(function Carousel({ label, children, index: controlledIndex, defaultIndex = 0, onIndexChange, slideSize, slideLabel = defaultSlideLabel, interval, autoplay = false, loop = false, peek = true, labels, className }, ref) {
66
+ const slides = Children.toArray(children);
67
+ const count = slides.length;
68
+ const last = Math.max(0, count - 1);
69
+ const id = useId();
70
+ const reduced = useReducedMotion();
71
+ const [ownIndex, setOwnIndex] = useState(() => clamp(defaultIndex, 0, last));
72
+ const index = clamp(controlledIndex ?? ownIndex, 0, last);
73
+ const [playing, setPlaying] = useState(autoplay);
74
+ const [hovered, setHovered] = useState(false);
75
+ const [touching, setTouching] = useState(false);
76
+ const [focusPaused, setFocusPaused] = useState(false);
77
+ const [inView, setInView] = useState(true);
78
+ const [pageVisible, setPageVisible] = useState(true);
79
+ const [announcement, setAnnouncement] = useState("");
80
+ const root = useRef(null);
81
+ const rootRef = useMemo(() => mergeRefs(ref, root), [ref]);
82
+ const viewport = useRef(null);
83
+ const track = useRef(null);
84
+ const play = useRef(null);
85
+ const tabs = useRef([]);
86
+ const target = useRef(index);
87
+ const travelling = useRef(null);
88
+ const backstop = useRef(void 0);
89
+ const drag = useRef(null);
90
+ const swallowClick = useRef(false);
91
+ const canRotate = Boolean(interval) && count > 1 && !reduced;
92
+ const running = canRotate && playing && !hovered && !touching && !focusPaused && inView && pageVisible;
93
+ const step = () => {
94
+ const [first, second] = Array.from(track.current?.children ?? []);
95
+ return first && second ? second.offsetLeft - first.offsetLeft : first?.offsetWidth ?? 0;
96
+ };
97
+ /** The scroll position that centres slide `i`. */
98
+ const leftOf = (i) => {
99
+ const node = track.current?.children[i];
100
+ const box = viewport.current;
101
+ return node && box ? node.offsetLeft - (box.clientWidth - node.offsetWidth) / 2 : 0;
102
+ };
103
+ /** Writes how far each slide and indicator is from the centre, straight from the scroll position. Returns the position in slides. */
104
+ const paint = useCallback(() => {
105
+ const box = viewport.current;
106
+ const size = step();
107
+ if (!box || !size) return target.current;
108
+ const position = box.scrollLeft / size;
109
+ Array.from(track.current?.children ?? []).forEach((slide, i) => {
110
+ slide.style.setProperty("--d", String(Math.min(1, Math.abs(position - i))));
111
+ });
112
+ tabs.current.forEach((tab, i) => {
113
+ const dot = tab?.firstElementChild;
114
+ if (dot instanceof HTMLElement) dot.style.setProperty("--e", String(Math.max(0, 1 - Math.abs(clamp(position, 0, last) - i))));
115
+ });
116
+ return position;
117
+ }, [last]);
118
+ function scrollToIndex(i, smooth) {
119
+ const box = viewport.current;
120
+ if (!box) return;
121
+ const left = leftOf(i);
122
+ if (!smooth || reduced || Math.abs(box.scrollLeft - left) < 1) {
123
+ travelling.current = null;
124
+ box.scrollTo({
125
+ left,
126
+ behavior: "auto"
127
+ });
128
+ paint();
129
+ return;
130
+ }
131
+ travelling.current = i;
132
+ clearTimeout(backstop.current);
133
+ const distance = Math.abs(box.scrollLeft - left) / (step() || 1);
134
+ const wait = Math.min(BACKSTOP.max, BACKSTOP.base + BACKSTOP.perSlide * Math.max(0, distance - 1));
135
+ backstop.current = setTimeout(() => travelling.current = null, wait);
136
+ box.scrollTo({
137
+ left,
138
+ behavior: "smooth"
139
+ });
140
+ }
141
+ function commit(next, announce) {
142
+ target.current = next;
143
+ if (controlledIndex === void 0) setOwnIndex(next);
144
+ onIndexChange?.(next);
145
+ if (announce) setAnnouncement(slideLabel(next, count));
146
+ }
147
+ function select(to, announce = true) {
148
+ const next = clamp(to, 0, last);
149
+ if (next !== target.current) commit(next, announce);
150
+ scrollToIndex(next, true);
151
+ }
152
+ useIsomorphicLayoutEffect(() => {
153
+ scrollToIndex(target.current, false);
154
+ const box = viewport.current;
155
+ if (!box || typeof ResizeObserver === "undefined") return;
156
+ const observer = new ResizeObserver(() => {
157
+ if (!drag.current && travelling.current === null) scrollToIndex(target.current, false);
158
+ });
159
+ observer.observe(box);
160
+ return () => observer.disconnect();
161
+ }, []);
162
+ useIsomorphicLayoutEffect(() => {
163
+ Array.from(track.current?.children ?? []).forEach((slide, i) => slide.toggleAttribute("inert", i !== index));
164
+ }, [index, count]);
165
+ useEffect(() => {
166
+ if (target.current !== index) {
167
+ target.current = index;
168
+ scrollToIndex(index, true);
169
+ }
170
+ }, [index]);
171
+ useEffect(() => () => clearTimeout(backstop.current), []);
172
+ useEffect(() => {
173
+ const box = viewport.current;
174
+ if (!box) return;
175
+ const onScrollEnd = () => {
176
+ if (travelling.current === null) return;
177
+ travelling.current = null;
178
+ clearTimeout(backstop.current);
179
+ };
180
+ box.addEventListener("scrollend", onScrollEnd);
181
+ return () => box.removeEventListener("scrollend", onScrollEnd);
182
+ }, []);
183
+ function onScroll() {
184
+ const position = paint();
185
+ const box = viewport.current;
186
+ if (!box || drag.current?.locked) return;
187
+ if (travelling.current !== null) {
188
+ if (Math.abs(box.scrollLeft - leftOf(travelling.current)) < 2) travelling.current = null;
189
+ return;
190
+ }
191
+ const next = clamp(Math.round(position), 0, last);
192
+ if (next !== target.current) commit(next, true);
193
+ }
194
+ const advance = () => select(index >= last ? 0 : index + 1, false);
195
+ /** The slide `by` steps from `from`: clamped at the ends, or around them with `loop`. */
196
+ const stepFrom = (from, by) => loop ? (from + by + count) % count : clamp(from + by, 0, last);
197
+ useEffect(() => {
198
+ const node = root.current;
199
+ if (!interval || !node) return;
200
+ const observer = typeof IntersectionObserver === "undefined" ? null : new IntersectionObserver(([entry]) => entry && setInView(entry.isIntersecting));
201
+ observer?.observe(node);
202
+ const onVisibility = () => setPageVisible(document.visibilityState !== "hidden");
203
+ document.addEventListener("visibilitychange", onVisibility);
204
+ return () => {
205
+ observer?.disconnect();
206
+ document.removeEventListener("visibilitychange", onVisibility);
207
+ };
208
+ }, [interval]);
209
+ function onPointerDown(event) {
210
+ if (count < 2 || drag.current || event.pointerType !== "mouse" || event.button !== 0) return;
211
+ swallowClick.current = false;
212
+ drag.current = {
213
+ pointer: event.pointerId,
214
+ startX: event.clientX,
215
+ startLeft: event.currentTarget.scrollLeft,
216
+ from: target.current,
217
+ locked: false,
218
+ samples: []
219
+ };
220
+ }
221
+ function onPointerMove(event) {
222
+ const current = drag.current;
223
+ if (!current || current.pointer !== event.pointerId) return;
224
+ const box = event.currentTarget;
225
+ if (!current.locked) {
226
+ if (Math.abs(event.clientX - current.startX) < SLOP) return;
227
+ current.locked = true;
228
+ current.startX = event.clientX;
229
+ travelling.current = null;
230
+ try {
231
+ box.setPointerCapture(event.pointerId);
232
+ } catch {}
233
+ box.dataset.dragging = "";
234
+ }
235
+ box.scrollLeft = current.startLeft - (event.clientX - current.startX);
236
+ current.samples.push([event.timeStamp, box.scrollLeft]);
237
+ if (current.samples.length > 16) current.samples.shift();
238
+ }
239
+ function finish(event, cancelled) {
240
+ const current = drag.current;
241
+ if (!current || current.pointer !== event.pointerId) return;
242
+ drag.current = null;
243
+ if (!current.locked) return;
244
+ const box = event.currentTarget;
245
+ delete box.dataset.dragging;
246
+ swallowClick.current = true;
247
+ const recent = current.samples.filter(([time]) => event.timeStamp - time <= 90);
248
+ const first = recent[0];
249
+ const lastSample = recent[recent.length - 1];
250
+ const velocity = !cancelled && first && lastSample && recent.length > 1 && event.timeStamp - lastSample[0] <= 50 && lastSample[0] > first[0] ? (lastSample[1] - first[1]) / (lastSample[0] - first[0]) * 1e3 : 0;
251
+ const size = step() || 1;
252
+ let to = Math.round((box.scrollLeft + project(velocity)) / size);
253
+ if (Math.abs(velocity) > FLICK) {
254
+ const direction = velocity > 0 ? 1 : -1;
255
+ if ((to - current.from) * direction < 1) to = current.from + direction;
256
+ }
257
+ select(to);
258
+ }
259
+ /** A tap on a neighbour brings it to the centre; a click that ends a drag is not a tap. */
260
+ function onClick(event) {
261
+ if (swallowClick.current) {
262
+ swallowClick.current = false;
263
+ event.preventDefault();
264
+ event.stopPropagation();
265
+ return;
266
+ }
267
+ const hit = Array.from(track.current?.children ?? []).findIndex((slide) => {
268
+ const rect = slide.getBoundingClientRect();
269
+ return event.clientX >= rect.left && event.clientX <= rect.right;
270
+ });
271
+ if (hit >= 0 && hit !== target.current) select(hit);
272
+ }
273
+ function onKeyDown(event) {
274
+ if (event.altKey || event.ctrlKey || event.metaKey || count < 2) return;
275
+ const node = event.target;
276
+ if (node.closest("input, textarea, select, [contenteditable]")) return;
277
+ const from = target.current;
278
+ const to = event.key === "ArrowLeft" ? stepFrom(from, -1) : event.key === "ArrowRight" ? stepFrom(from, 1) : event.key === "Home" ? 0 : event.key === "End" ? last : null;
279
+ if (to === null) return;
280
+ event.preventDefault();
281
+ const next = clamp(to, 0, last);
282
+ select(next);
283
+ if (node.getAttribute("role") === "tab") tabs.current[next]?.focus({ preventScroll: true });
284
+ else if (track.current?.contains(node)) viewport.current?.focus({ preventScroll: true });
285
+ }
286
+ const text = {
287
+ previous: "Previous slide",
288
+ next: "Next slide",
289
+ play: "Start slide rotation",
290
+ pause: "Pause slide rotation",
291
+ slides: "Choose a slide",
292
+ ...labels
293
+ };
294
+ return /* @__PURE__ */ jsxs("section", {
295
+ ref: rootRef,
296
+ "data-slot": "carousel",
297
+ "aria-roledescription": "carousel",
298
+ "aria-label": label,
299
+ "data-loop": loop || void 0,
300
+ "data-peek": peek ? void 0 : "false",
301
+ className: cn("carousel", className),
302
+ style: slideSize && peek ? { "--carousel-slide-size": slideSize } : void 0,
303
+ onKeyDown,
304
+ onFocus: (event) => setFocusPaused(event.target !== play.current && event.target.matches(":focus-visible")),
305
+ onBlur: (event) => {
306
+ if (!event.currentTarget.contains(event.relatedTarget)) setFocusPaused(false);
307
+ },
308
+ children: [
309
+ /* @__PURE__ */ jsx("div", {
310
+ ref: viewport,
311
+ role: "region",
312
+ "aria-label": "Slides",
313
+ tabIndex: 0,
314
+ "data-slot": "carousel-viewport",
315
+ className: "carousel-viewport",
316
+ onScroll,
317
+ onPointerDown,
318
+ onPointerMove,
319
+ onPointerUp: (event) => finish(event, false),
320
+ onPointerCancel: (event) => finish(event, true),
321
+ onPointerEnter: (event) => event.pointerType === "mouse" && setHovered(true),
322
+ onPointerLeave: () => setHovered(false),
323
+ onTouchStart: () => setTouching(true),
324
+ onTouchEnd: () => setTouching(false),
325
+ onTouchCancel: () => setTouching(false),
326
+ onClickCapture: onClick,
327
+ onDragStart: (event) => event.preventDefault(),
328
+ children: /* @__PURE__ */ jsx("div", {
329
+ ref: track,
330
+ className: "carousel-track",
331
+ children: slides.map((slide, i) => /* @__PURE__ */ jsx("div", {
332
+ id: `${id}-slide-${i}`,
333
+ role: "tabpanel",
334
+ "aria-roledescription": "slide",
335
+ "aria-label": slideLabel(i, count),
336
+ "data-active": i === index || void 0,
337
+ className: "carousel-slide",
338
+ children: slide
339
+ }, isValidElement(slide) && slide.key != null ? slide.key : i))
340
+ })
341
+ }),
342
+ count > 1 ? /* @__PURE__ */ jsxs("div", {
343
+ className: "carousel-controls",
344
+ children: [
345
+ canRotate ? /* @__PURE__ */ jsx("button", {
346
+ ref: play,
347
+ type: "button",
348
+ "aria-label": playing ? text.pause : text.play,
349
+ className: "carousel-control",
350
+ onClick: () => setPlaying(!playing),
351
+ children: playing ? /* @__PURE__ */ jsx(PauseGlyph, {}) : /* @__PURE__ */ jsx(PlayGlyph, {})
352
+ }) : null,
353
+ /* @__PURE__ */ jsx("div", {
354
+ role: "tablist",
355
+ "aria-label": text.slides,
356
+ className: "carousel-tabs",
357
+ children: slides.map((_, i) => /* @__PURE__ */ jsx("button", {
358
+ ref: (node) => {
359
+ tabs.current[i] = node;
360
+ },
361
+ type: "button",
362
+ role: "tab",
363
+ "aria-selected": i === index,
364
+ "aria-controls": `${id}-slide-${i}`,
365
+ "aria-label": slideLabel(i, count),
366
+ tabIndex: i === index ? 0 : -1,
367
+ className: "carousel-tab",
368
+ onClick: () => select(i),
369
+ children: /* @__PURE__ */ jsxs("span", {
370
+ "aria-hidden": "true",
371
+ className: "carousel-dot",
372
+ children: [/* @__PURE__ */ jsx("span", { className: "carousel-dot-fill" }), canRotate && playing && i === index ? /* @__PURE__ */ jsx("span", {
373
+ className: "carousel-drain",
374
+ style: {
375
+ animationDuration: `${interval}ms`,
376
+ animationPlayState: running ? "running" : "paused"
377
+ },
378
+ onAnimationEnd: advance
379
+ }, index) : null]
380
+ })
381
+ }, i))
382
+ }),
383
+ /* @__PURE__ */ jsxs("div", {
384
+ className: "carousel-arrows",
385
+ children: [/* @__PURE__ */ jsx("button", {
386
+ type: "button",
387
+ "aria-label": text.previous,
388
+ "aria-disabled": !loop && index === 0,
389
+ className: "carousel-control",
390
+ onClick: () => (loop || target.current > 0) && select(stepFrom(target.current, -1)),
391
+ children: /* @__PURE__ */ jsx(Chevron, { back: true })
392
+ }), /* @__PURE__ */ jsx("button", {
393
+ type: "button",
394
+ "aria-label": text.next,
395
+ "aria-disabled": !loop && index === last,
396
+ className: "carousel-control",
397
+ onClick: () => (loop || target.current < last) && select(stepFrom(target.current, 1)),
398
+ children: /* @__PURE__ */ jsx(Chevron, {})
399
+ })]
400
+ })
401
+ ]
402
+ }) : null,
403
+ /* @__PURE__ */ jsx("span", {
404
+ className: "sr-only",
405
+ "aria-live": "polite",
406
+ "aria-atomic": "true",
407
+ children: announcement
408
+ })
409
+ ]
410
+ });
411
+ });
412
+ //#endregion
413
+ export { Carousel };
414
+
415
+ //# sourceMappingURL=carousel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"carousel.js","names":[],"sources":["../../src/carousel/carousel.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Children,\n forwardRef,\n isValidElement,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n type MouseEvent,\n type PointerEvent,\n type ReactNode,\n} from \"react\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { mergeRefs } from \"../lib/merge-refs.js\";\nimport { useIsomorphicLayoutEffect, useReducedMotion } from \"../lib/motion.js\";\n\n/**\n * Carousel: a row of slides people browse by swiping, a trackpad, dragging\n * with a mouse, the arrow keys, or the controls below it. Use it for a short,\n * ordered set of peers such as products or case studies, where the neighbours\n * stay in view as a hint that there is more.\n *\n * The slides sit on a native scroll-snap track, so touch and trackpad swipes\n * are the browser's own. The active slide is centred; its neighbours shrink and\n * dim with their distance, and each page indicator stretches into a pill as the\n * track nears its slide, all written straight from the scroll position without a\n * re-render. A mouse can drag the track, and a flick carries on to the next\n * slide. Arrow keys, Home and End move between slides from the track or the\n * indicators. `interval` adds a play control that rotates through the slides;\n * rotation pauses on hover, keyboard focus and touch, while the carousel is off\n * screen or the tab is hidden, and is unavailable under reduced motion (where\n * scrolling also jumps instead of gliding).\n *\n * `loop` wraps the ends: next on the last slide goes to the first, previous on\n * the first to the last, from the controls and the arrow keys alike (a swipe\n * or drag still stops at the end of the track). `peek={false}` shows one slide\n * at a time across the full width, with no neighbours in view, for a viewer\n * such as a single creative asset.\n */\nexport interface CarouselProps {\n /** Names the carousel for assistive technology, such as \"From the Harbour suites\". */\n label: string;\n /** One child per slide. */\n children: ReactNode;\n /** Controlled active slide. Pair with `onIndexChange`. */\n index?: number;\n /** @default 0 */\n defaultIndex?: number;\n onIndexChange?: (index: number) => void;\n /** Width of one slide as a CSS length; `cqw` is a share of the carousel's width. @default \"min(80cqw, 340px)\" */\n slideSize?: string;\n /** Names each slide and its indicator. @default (index, count) => `${index + 1} of ${count}` */\n slideLabel?: (index: number, count: number) => string;\n /** Milliseconds per slide. Adds a play control that rotates through the slides. */\n interval?: number;\n /** Starts rotating on mount. Off by default, so motion begins with the viewer. @default false */\n autoplay?: boolean;\n /**\n * Wraps around at the ends: next on the last slide goes to the first and\n * previous on the first goes to the last, from the controls and the arrow\n * keys. The controls are then never disabled. Home and End still go to the\n * first and last slide; a swipe or drag stops at the end of the track.\n * @default false\n */\n loop?: boolean;\n /**\n * Neighbouring slides peek in at the sides. `false` shows one slide at a\n * time across the full width (`slideSize` is ignored), with the controls\n * spanning it too.\n * @default true\n */\n peek?: boolean;\n /** Names of the controls, for translation. */\n labels?: {\n /** @default \"Previous slide\" */\n previous?: string;\n /** @default \"Next slide\" */\n next?: string;\n /** @default \"Start slide rotation\" */\n play?: string;\n /** @default \"Pause slide rotation\" */\n pause?: string;\n /** Names the group of indicators. @default \"Choose a slide\" */\n slides?: string;\n };\n /** Extra classes for the carousel. Merged last. */\n className?: string;\n}\n\n/** Movement before a mouse press is read as a drag. */\nconst SLOP = 6;\n/** Release speed in px/s that always moves at least one slide. */\nconst FLICK = 360;\n/**\n * How long a glide may take before the carousel stops waiting for it: one slide,\n * plus more per extra slide (a `loop` wrap crosses them all), capped.\n */\nconst BACKSTOP = { base: 1000, perSlide: 250, max: 3000 };\n/** Where a flick would come to rest: velocity (px/s) projected with a paging deceleration rate. */\nconst project = (velocity: number, rate = 0.995) => ((velocity / 1000) * rate) / (1 - rate);\nconst clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));\nconst defaultSlideLabel = (index: number, count: number) => `${index + 1} of ${count}`;\n\nconst PlayGlyph = () => (\n <svg width={15} height={15} viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M4.5 2.8v10.4a.6.6 0 0 0 .9.5l8.2-5.2a.6.6 0 0 0 0-1L5.4 2.3a.6.6 0 0 0-.9.5Z\" />\n </svg>\n);\nconst PauseGlyph = () => (\n <svg width={15} height={15} viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\n <rect x=\"3.5\" y=\"2.5\" width=\"3.2\" height=\"11\" rx=\"1\" />\n <rect x=\"9.3\" y=\"2.5\" width=\"3.2\" height=\"11\" rx=\"1\" />\n </svg>\n);\nconst Chevron = ({ back }: { back?: boolean }) => (\n <svg width={18} height={18} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.75} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d={back ? \"M10 3.5 5.5 8l4.5 4.5\" : \"M6 3.5 10.5 8 6 12.5\"} />\n </svg>\n);\n\ntype Drag = { pointer: number; startX: number; startLeft: number; from: number; locked: boolean; samples: [number, number][] };\n\nexport const Carousel = forwardRef<HTMLElement, CarouselProps>(function Carousel(\n {\n label,\n children,\n index: controlledIndex,\n defaultIndex = 0,\n onIndexChange,\n slideSize,\n slideLabel = defaultSlideLabel,\n interval,\n autoplay = false,\n loop = false,\n peek = true,\n labels,\n className,\n },\n ref,\n) {\n const slides = Children.toArray(children);\n const count = slides.length;\n const last = Math.max(0, count - 1);\n const id = useId();\n const reduced = useReducedMotion();\n const [ownIndex, setOwnIndex] = useState(() => clamp(defaultIndex, 0, last));\n const index = clamp(controlledIndex ?? ownIndex, 0, last);\n const [playing, setPlaying] = useState(autoplay);\n const [hovered, setHovered] = useState(false);\n const [touching, setTouching] = useState(false);\n const [focusPaused, setFocusPaused] = useState(false);\n const [inView, setInView] = useState(true);\n const [pageVisible, setPageVisible] = useState(true);\n const [announcement, setAnnouncement] = useState(\"\");\n\n const root = useRef<HTMLElement | null>(null);\n const rootRef = useMemo(() => mergeRefs(ref, root), [ref]);\n const viewport = useRef<HTMLDivElement>(null);\n const track = useRef<HTMLDivElement>(null);\n const play = useRef<HTMLButtonElement>(null);\n const tabs = useRef<(HTMLButtonElement | null)[]>([]);\n // The slide the carousel is on, as the component last decided it (state lags a render behind).\n const target = useRef(index);\n // Set while a scroll we started is in flight, so the in-between slides are not reported as the viewer's choice.\n const travelling = useRef<number | null>(null);\n const backstop = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const drag = useRef<Drag | null>(null);\n const swallowClick = useRef(false);\n\n const canRotate = Boolean(interval) && count > 1 && !reduced;\n const running = canRotate && playing && !hovered && !touching && !focusPaused && inView && pageVisible;\n\n const step = () => {\n const [first, second] = Array.from(track.current?.children ?? []) as HTMLElement[];\n return first && second ? second.offsetLeft - first.offsetLeft : (first?.offsetWidth ?? 0);\n };\n /** The scroll position that centres slide `i`. */\n const leftOf = (i: number) => {\n const node = track.current?.children[i] as HTMLElement | undefined;\n const box = viewport.current;\n return node && box ? node.offsetLeft - (box.clientWidth - node.offsetWidth) / 2 : 0;\n };\n\n /** Writes how far each slide and indicator is from the centre, straight from the scroll position. Returns the position in slides. */\n const paint = useCallback(() => {\n const box = viewport.current;\n const size = step();\n if (!box || !size) return target.current;\n const position = box.scrollLeft / size;\n Array.from(track.current?.children ?? []).forEach((slide, i) => {\n (slide as HTMLElement).style.setProperty(\"--d\", String(Math.min(1, Math.abs(position - i))));\n });\n tabs.current.forEach((tab, i) => {\n const dot = tab?.firstElementChild;\n if (dot instanceof HTMLElement) dot.style.setProperty(\"--e\", String(Math.max(0, 1 - Math.abs(clamp(position, 0, last) - i))));\n });\n return position;\n }, [last]);\n\n function scrollToIndex(i: number, smooth: boolean) {\n const box = viewport.current;\n if (!box) return;\n const left = leftOf(i);\n if (!smooth || reduced || Math.abs(box.scrollLeft - left) < 1) {\n travelling.current = null;\n box.scrollTo({ left, behavior: \"auto\" });\n paint();\n return;\n }\n travelling.current = i;\n clearTimeout(backstop.current);\n // A scroll that never reports arriving (a resize mid-flight) must not hold the carousel deaf to the viewer's own swipes.\n // The glide normally ends on `scrollend`; this timer is the fallback, scaled to the\n // distance so a long wrap is not cut short.\n const distance = Math.abs(box.scrollLeft - left) / (step() || 1);\n const wait = Math.min(\n BACKSTOP.max,\n BACKSTOP.base + BACKSTOP.perSlide * Math.max(0, distance - 1),\n );\n backstop.current = setTimeout(() => (travelling.current = null), wait);\n box.scrollTo({ left, behavior: \"smooth\" });\n }\n\n function commit(next: number, announce: boolean) {\n target.current = next;\n if (controlledIndex === undefined) setOwnIndex(next);\n onIndexChange?.(next);\n if (announce) setAnnouncement(slideLabel(next, count));\n }\n\n function select(to: number, announce = true) {\n const next = clamp(to, 0, last);\n if (next !== target.current) commit(next, announce);\n scrollToIndex(next, true);\n }\n\n // The start slide is in place before first paint, so nothing glides on mount; later resizes keep the carousel on its slide.\n useIsomorphicLayoutEffect(() => {\n scrollToIndex(target.current, false);\n const box = viewport.current;\n if (!box || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => {\n if (!drag.current && travelling.current === null) scrollToIndex(target.current, false);\n });\n observer.observe(box);\n return () => observer.disconnect();\n }, []);\n\n // The viewer's own slides, inert unless active, are the only ones in the tab order or the accessibility tree's reach.\n useIsomorphicLayoutEffect(() => {\n Array.from(track.current?.children ?? []).forEach((slide, i) => slide.toggleAttribute(\"inert\", i !== index));\n }, [index, count]);\n\n // A controlled index that moves by itself brings the carousel along.\n useEffect(() => {\n if (target.current !== index) {\n target.current = index;\n scrollToIndex(index, true);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- only a changed index matters\n }, [index]);\n\n useEffect(() => () => clearTimeout(backstop.current), []);\n\n // A glide is over when the browser says the scroll has ended, however long it took.\n useEffect(() => {\n const box = viewport.current;\n if (!box) return;\n const onScrollEnd = () => {\n if (travelling.current === null) return;\n travelling.current = null;\n clearTimeout(backstop.current);\n };\n box.addEventListener(\"scrollend\", onScrollEnd);\n return () => box.removeEventListener(\"scrollend\", onScrollEnd);\n }, []);\n\n function onScroll() {\n const position = paint();\n const box = viewport.current;\n if (!box || drag.current?.locked) return;\n if (travelling.current !== null) {\n if (Math.abs(box.scrollLeft - leftOf(travelling.current)) < 2) travelling.current = null;\n return;\n }\n const next = clamp(Math.round(position), 0, last);\n if (next !== target.current) commit(next, true);\n }\n\n const advance = () => select(index >= last ? 0 : index + 1, false);\n /** The slide `by` steps from `from`: clamped at the ends, or around them with `loop`. */\n const stepFrom = (from: number, by: number) => (loop ? (from + by + count) % count : clamp(from + by, 0, last));\n\n useEffect(() => {\n const node = root.current;\n if (!interval || !node) return;\n const observer = typeof IntersectionObserver === \"undefined\" ? null : new IntersectionObserver(([entry]) => entry && setInView(entry.isIntersecting));\n observer?.observe(node);\n const onVisibility = () => setPageVisible(document.visibilityState !== \"hidden\");\n document.addEventListener(\"visibilitychange\", onVisibility);\n return () => {\n observer?.disconnect();\n document.removeEventListener(\"visibilitychange\", onVisibility);\n };\n }, [interval]);\n\n function onPointerDown(event: PointerEvent<HTMLDivElement>) {\n if (count < 2 || drag.current || event.pointerType !== \"mouse\" || event.button !== 0) return;\n swallowClick.current = false;\n drag.current = { pointer: event.pointerId, startX: event.clientX, startLeft: event.currentTarget.scrollLeft, from: target.current, locked: false, samples: [] };\n }\n\n function onPointerMove(event: PointerEvent<HTMLDivElement>) {\n const current = drag.current;\n if (!current || current.pointer !== event.pointerId) return;\n const box = event.currentTarget;\n if (!current.locked) {\n if (Math.abs(event.clientX - current.startX) < SLOP) return;\n // The slop is consumed, so the track starts moving from the pointer without a jump. Snapping is off while it is held.\n current.locked = true;\n current.startX = event.clientX;\n travelling.current = null;\n try {\n box.setPointerCapture(event.pointerId);\n } catch {\n // The pointer already ended; the drag simply stops following it.\n }\n box.dataset.dragging = \"\";\n }\n box.scrollLeft = current.startLeft - (event.clientX - current.startX);\n current.samples.push([event.timeStamp, box.scrollLeft]);\n if (current.samples.length > 16) current.samples.shift();\n }\n\n function finish(event: PointerEvent<HTMLDivElement>, cancelled: boolean) {\n const current = drag.current;\n if (!current || current.pointer !== event.pointerId) return;\n drag.current = null;\n if (!current.locked) return;\n const box = event.currentTarget;\n delete box.dataset.dragging;\n swallowClick.current = true;\n const recent = current.samples.filter(([time]) => event.timeStamp - time <= 90);\n const first = recent[0];\n const lastSample = recent[recent.length - 1];\n const velocity =\n !cancelled && first && lastSample && recent.length > 1 && event.timeStamp - lastSample[0] <= 50 && lastSample[0] > first[0]\n ? ((lastSample[1] - first[1]) / (lastSample[0] - first[0])) * 1000\n : 0;\n const size = step() || 1;\n // The landing slide comes from where the flick would carry the track, not from where the pointer let go.\n let to = Math.round((box.scrollLeft + project(velocity)) / size);\n if (Math.abs(velocity) > FLICK) {\n const direction = velocity > 0 ? 1 : -1;\n if ((to - current.from) * direction < 1) to = current.from + direction;\n }\n select(to);\n }\n\n /** A tap on a neighbour brings it to the centre; a click that ends a drag is not a tap. */\n function onClick(event: MouseEvent<HTMLDivElement>) {\n if (swallowClick.current) {\n swallowClick.current = false;\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n const hit = Array.from(track.current?.children ?? []).findIndex((slide) => {\n const rect = slide.getBoundingClientRect();\n return event.clientX >= rect.left && event.clientX <= rect.right;\n });\n if (hit >= 0 && hit !== target.current) select(hit);\n }\n\n function onKeyDown(event: KeyboardEvent<HTMLElement>) {\n if (event.altKey || event.ctrlKey || event.metaKey || count < 2) return;\n const node = event.target as HTMLElement;\n if (node.closest(\"input, textarea, select, [contenteditable]\")) return;\n const from = target.current;\n const to =\n event.key === \"ArrowLeft\" ? stepFrom(from, -1) : event.key === \"ArrowRight\" ? stepFrom(from, 1) : event.key === \"Home\" ? 0 : event.key === \"End\" ? last : null;\n if (to === null) return;\n event.preventDefault();\n const next = clamp(to, 0, last);\n select(next);\n if (node.getAttribute(\"role\") === \"tab\") tabs.current[next]?.focus({ preventScroll: true });\n else if (track.current?.contains(node)) viewport.current?.focus({ preventScroll: true });\n }\n\n const text = { previous: \"Previous slide\", next: \"Next slide\", play: \"Start slide rotation\", pause: \"Pause slide rotation\", slides: \"Choose a slide\", ...labels };\n\n return (\n <section\n ref={rootRef}\n data-slot=\"carousel\"\n aria-roledescription=\"carousel\"\n aria-label={label}\n data-loop={loop || undefined}\n data-peek={peek ? undefined : \"false\"}\n className={cn(\"carousel\", className)}\n style={slideSize && peek ? ({ \"--carousel-slide-size\": slideSize } as CSSProperties) : undefined}\n onKeyDown={onKeyDown}\n onFocus={(event) => setFocusPaused(event.target !== play.current && event.target.matches(\":focus-visible\"))}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget)) setFocusPaused(false);\n }}\n >\n <div\n ref={viewport}\n role=\"region\"\n aria-label=\"Slides\"\n tabIndex={0}\n data-slot=\"carousel-viewport\"\n className=\"carousel-viewport\"\n onScroll={onScroll}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={(event) => finish(event, false)}\n onPointerCancel={(event) => finish(event, true)}\n onPointerEnter={(event) => event.pointerType === \"mouse\" && setHovered(true)}\n onPointerLeave={() => setHovered(false)}\n onTouchStart={() => setTouching(true)}\n onTouchEnd={() => setTouching(false)}\n onTouchCancel={() => setTouching(false)}\n onClickCapture={onClick}\n onDragStart={(event) => event.preventDefault()}\n >\n <div ref={track} className=\"carousel-track\">\n {slides.map((slide, i) => (\n <div\n key={isValidElement(slide) && slide.key != null ? slide.key : i}\n id={`${id}-slide-${i}`}\n role=\"tabpanel\"\n aria-roledescription=\"slide\"\n aria-label={slideLabel(i, count)}\n data-active={i === index || undefined}\n className=\"carousel-slide\"\n >\n {slide}\n </div>\n ))}\n </div>\n </div>\n {count > 1 ? (\n <div className=\"carousel-controls\">\n {canRotate ? (\n <button\n ref={play}\n type=\"button\"\n aria-label={playing ? text.pause : text.play}\n className=\"carousel-control\"\n onClick={() => setPlaying(!playing)}\n >\n {playing ? <PauseGlyph /> : <PlayGlyph />}\n </button>\n ) : null}\n <div role=\"tablist\" aria-label={text.slides} className=\"carousel-tabs\">\n {slides.map((_, i) => (\n <button\n key={i}\n ref={(node) => {\n tabs.current[i] = node;\n }}\n type=\"button\"\n role=\"tab\"\n aria-selected={i === index}\n aria-controls={`${id}-slide-${i}`}\n aria-label={slideLabel(i, count)}\n tabIndex={i === index ? 0 : -1}\n className=\"carousel-tab\"\n onClick={() => select(i)}\n >\n <span aria-hidden=\"true\" className=\"carousel-dot\">\n <span className=\"carousel-dot-fill\" />\n {canRotate && playing && i === index ? (\n <span\n key={index}\n className=\"carousel-drain\"\n style={{ animationDuration: `${interval}ms`, animationPlayState: running ? \"running\" : \"paused\" }}\n onAnimationEnd={advance}\n />\n ) : null}\n </span>\n </button>\n ))}\n </div>\n <div className=\"carousel-arrows\">\n <button\n type=\"button\"\n aria-label={text.previous}\n aria-disabled={!loop && index === 0}\n className=\"carousel-control\"\n onClick={() => (loop || target.current > 0) && select(stepFrom(target.current, -1))}\n >\n <Chevron back />\n </button>\n <button\n type=\"button\"\n aria-label={text.next}\n aria-disabled={!loop && index === last}\n className=\"carousel-control\"\n onClick={() => (loop || target.current < last) && select(stepFrom(target.current, 1))}\n >\n <Chevron />\n </button>\n </div>\n </div>\n ) : null}\n <span className=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\">\n {announcement}\n </span>\n </section>\n );\n});\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Carousel, CarouselProps } from "./carousel.js";
2
+ export { Carousel, type CarouselProps };
@@ -0,0 +1,2 @@
1
+ import { Carousel } from "./carousel.js";
2
+ export { Carousel };
@@ -43,10 +43,10 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
43
43
  */
44
44
  const checkboxVariants = cva([selectionLabelVariants()]);
45
45
  const checkboxBoxVariants = cva([
46
- "inline-flex size-4 shrink-0 items-center justify-center",
47
- "rounded-2xs border-(length:--border-width)",
46
+ "inline-flex size-4.5 shrink-0 items-center justify-center",
47
+ "rounded-checkbox border-(length:--border-width)",
48
48
  "box-border",
49
- "bg-background border-border text-primary-foreground",
49
+ "bg-surface border-control-edge text-primary-foreground",
50
50
  "checkbox-box",
51
51
  "group-data-[selected]:border-primary-strong",
52
52
  "group-data-[indeterminate]:border-primary-strong",
@@ -71,7 +71,7 @@ const Checkbox$1 = forwardRef(function Checkbox$2({ className, children, ...prop
71
71
  "data-mark": isIndeterminate ? "indeterminate" : isSelected ? "check" : void 0,
72
72
  viewBox: "0 0 18 18",
73
73
  fill: "none",
74
- className: "absolute -inset-px size-4 overflow-visible",
74
+ className: "absolute -inset-px size-4.5 overflow-visible",
75
75
  children: /* @__PURE__ */ jsx("path", {
76
76
  className: "checkbox-mark",
77
77
  pathLength: "1",
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.js","names":["Checkbox","AriaCheckbox"],"sources":["../../src/checkbox/checkbox.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport {\n Checkbox as AriaCheckbox,\n type CheckboxProps as AriaCheckboxProps,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { selectionLabelVariants, selectionRingVariants } from \"../lib/selection-control.js\";\n\n/**\n * Checkbox, rebuilt on React Aria.\n *\n * THE CENSUS FOUND ZERO CALL SITES. It is ported anyway because forms and\n * table row selection are unbuildable without it, but that fact changes what\n * this is: with no usage to be faithful to and no call site to break, it is a\n * rewrite rather than a restyling. Four things the legacy component got\n * wrong are therefore simply fixed rather than carried:\n *\n * - **No accessible name.** It rendered a bare `<input type=\"checkbox\">` with\n * no label, no `aria-label` and no `id`, so every use was an axe `label`\n * violation. Here the label is `children`, and React Aria wraps the input\n * in it.\n * - **The fill never showed.** `checked:bg-primary` on a native input with no\n * `appearance-none` is painted over by the user-agent checkbox.\n * - **`border-primary` cannot be a boundary.** Brand orange is 2.44:1 on\n * white, under even the 3:1 non-text floor (WCAG 1.4.11).\n * - **`focus-visible:ring-2` is a box-shadow**, which forced-colors discards,\n * taking the only focus indication with it.\n *\n * React Aria renders a `<label>` around a visually-hidden real `<input>` and\n * NOTHING else -- there is no visual box in the box. Drawing one, and keeping\n * it in step with `data-selected` / `data-indeterminate`, is what this\n * component owns.\n *\n * Every string in the cva blocks below is a STATIC literal. Tailwind scans\n * source text, so a class assembled at runtime is invisible to it and would\n * simply never be emitted.\n */\n/**\n * The label geometry now lives in lib/selection-control.ts, shared with\n * Radio and Switch. Three controls with the same 24px target and the same\n * typography is the Rule of Three, and this migration has twice found a\n * legacy pair that styled one surface twice and silently drifted.\n */\nexport const checkboxVariants = cva([selectionLabelVariants()]);\n\nexport const checkboxBoxVariants = cva([\n \"inline-flex size-4 shrink-0 items-center justify-center\",\n \"rounded-2xs border-(length:--border-width)\",\n\n // box-border: the size is the whole square, border included.\n \"box-border\",\n\n \"bg-background border-border text-primary-foreground\",\n\n // Border colour eases, the square presses to .95 and springs back (see checkbox-box).\n \"checkbox-box\",\n\n // The border takes the strong tone once chosen; the colour itself is the fill below.\n \"group-data-[selected]:border-primary-strong\",\n \"group-data-[indeterminate]:border-primary-strong\",\n // Hover darkens an unchosen box's border.\n \"group-data-[hovered]:not-group-data-[selected]:not-group-data-[indeterminate]:border-muted-foreground\",\n\n selectionRingVariants(),\n]);\n\nexport interface CheckboxProps\n extends Omit<AriaCheckboxProps, \"className\" | \"style\" | \"children\"> {\n /**\n * The label, and the control's accessible name.\n *\n * Omit it only for a genuinely label-less checkbox -- a table row selector\n * -- and pass `aria-label` instead. A checkbox with neither has no\n * accessible name, which is what every legacy call site would have been.\n */\n children?: ReactNode;\n /** Extra classes for the label. Merged last, so they win conflicts. */\n className?: string;\n}\n\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n { className, children, ...props },\n ref,\n) {\n return (\n <AriaCheckbox\n {...props}\n // inputRef, not ref: AriaCheckbox's own ref targets the label it\n // renders around a visually-hidden native input, and a label cannot\n // be focused -- ref.current.focus() would silently no-op. inputRef is\n // React Aria's own escape hatch to the real control.\n inputRef={ref}\n data-slot=\"checkbox\"\n // `group` is load-bearing: React Aria puts data-selected,\n // data-indeterminate and data-focus-visible on the LABEL, and CSS\n // cannot look upward from the box to them.\n className={cn(checkboxVariants(), className)}\n >\n {({ isSelected, isIndeterminate }) => (\n <>\n {/*\n aria-hidden: the real <input> already carries the state. A\n decorative box announced as well would say everything twice.\n */}\n <span aria-hidden=\"true\" data-slot=\"checkbox-box\" className={checkboxBoxVariants()}>\n <span data-slot=\"checkbox-fill\" className=\"checkbox-fill\" />\n {/*\n One mark, always rendered: the state decides what it shows. Both\n states can be true at once (a \"select all\" box that has been\n partially cleared) and indeterminate wins, which the path's\n `d` carries in CSS -- the same precedence the old two-glyph\n branch pinned in JS.\n */}\n <svg\n data-slot=\"checkbox-mark\"\n data-mark={isIndeterminate ? \"indeterminate\" : isSelected ? \"check\" : undefined}\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n className=\"absolute -inset-px size-4 overflow-visible\"\n >\n <path\n className=\"checkbox-mark\"\n pathLength=\"1\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </span>\n {children == null ? null : <span data-slot=\"checkbox-label\">{children}</span>}\n </>\n )}\n </AriaCheckbox>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,MAAa,mBAAmB,IAAI,CAAC,uBAAuB,CAAC,CAAC;AAE9D,MAAa,sBAAsB,IAAI;CACrC;CACA;CAGA;CAEA;CAGA;CAGA;CACA;CAEA;CAEA,sBAAsB;AACxB,CAAC;AAgBD,MAAaA,aAAW,WAA4C,SAASA,WAC3E,EAAE,WAAW,UAAU,GAAG,SAC1B,KACA;CACA,OACE,oBAACC,UAAD;EACE,GAAI;EAKJ,UAAU;EACV,aAAU;EAIV,WAAW,GAAG,iBAAiB,GAAG,SAAS;EAEzC,WAAA,EAAE,YAAY,sBACd,qBAAA,YAAA,EAAA,UAAA,CAKE,qBAAC,QAAD;GAAM,eAAY;GAAO,aAAU;GAAe,WAAW,oBAAoB;GAAjF,UAAA,CACE,oBAAC,QAAD;IAAM,aAAU;IAAgB,WAAU;GAAiB,CAAA,GAQ3D,oBAAC,OAAD;IACE,aAAU;IACV,aAAW,kBAAkB,kBAAkB,aAAa,UAAU,KAAA;IACtE,SAAQ;IACR,MAAK;IACL,WAAU;IAEV,UAAA,oBAAC,QAAD;KACE,WAAU;KACV,YAAW;KACX,QAAO;KACP,aAAY;KACZ,eAAc;KACd,gBAAe;IAChB,CAAA;GACE,CAAA,CACD;EACL,CAAA,GAAA,YAAY,OAAO,OAAO,oBAAC,QAAD;GAAM,aAAU;GAAkB;EAAe,CAAA,CAC5E,EAAA,CAAA;CAEQ,CAAA;AAElB,CAAC"}
1
+ {"version":3,"file":"checkbox.js","names":["Checkbox","AriaCheckbox"],"sources":["../../src/checkbox/checkbox.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport {\n Checkbox as AriaCheckbox,\n type CheckboxProps as AriaCheckboxProps,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { selectionLabelVariants, selectionRingVariants } from \"../lib/selection-control.js\";\n\n/**\n * Checkbox, rebuilt on React Aria.\n *\n * THE CENSUS FOUND ZERO CALL SITES. It is ported anyway because forms and\n * table row selection are unbuildable without it, but that fact changes what\n * this is: with no usage to be faithful to and no call site to break, it is a\n * rewrite rather than a restyling. Four things the legacy component got\n * wrong are therefore simply fixed rather than carried:\n *\n * - **No accessible name.** It rendered a bare `<input type=\"checkbox\">` with\n * no label, no `aria-label` and no `id`, so every use was an axe `label`\n * violation. Here the label is `children`, and React Aria wraps the input\n * in it.\n * - **The fill never showed.** `checked:bg-primary` on a native input with no\n * `appearance-none` is painted over by the user-agent checkbox.\n * - **`border-primary` cannot be a boundary.** Brand orange is 2.44:1 on\n * white, under even the 3:1 non-text floor (WCAG 1.4.11).\n * - **`focus-visible:ring-2` is a box-shadow**, which forced-colors discards,\n * taking the only focus indication with it.\n *\n * React Aria renders a `<label>` around a visually-hidden real `<input>` and\n * NOTHING else -- there is no visual box in the box. Drawing one, and keeping\n * it in step with `data-selected` / `data-indeterminate`, is what this\n * component owns.\n *\n * Every string in the cva blocks below is a STATIC literal. Tailwind scans\n * source text, so a class assembled at runtime is invisible to it and would\n * simply never be emitted.\n */\n/**\n * The label geometry now lives in lib/selection-control.ts, shared with\n * Radio and Switch. Three controls with the same 24px target and the same\n * typography is the Rule of Three, and this migration has twice found a\n * legacy pair that styled one surface twice and silently drifted.\n */\nexport const checkboxVariants = cva([selectionLabelVariants()]);\n\nexport const checkboxBoxVariants = cva([\n \"inline-flex size-4.5 shrink-0 items-center justify-center\",\n \"rounded-checkbox border-(length:--border-width)\",\n\n // box-border: the size is the whole square, border included.\n \"box-border\",\n\n \"bg-surface border-control-edge text-primary-foreground\",\n\n // Border colour eases, the square presses to .95 and springs back (see checkbox-box).\n \"checkbox-box\",\n\n // The border takes the strong tone once chosen; the colour itself is the fill below.\n \"group-data-[selected]:border-primary-strong\",\n \"group-data-[indeterminate]:border-primary-strong\",\n // Hover darkens an unchosen box's border.\n \"group-data-[hovered]:not-group-data-[selected]:not-group-data-[indeterminate]:border-muted-foreground\",\n\n selectionRingVariants(),\n]);\n\nexport interface CheckboxProps\n extends Omit<AriaCheckboxProps, \"className\" | \"style\" | \"children\"> {\n /**\n * The label, and the control's accessible name.\n *\n * Omit it only for a genuinely label-less checkbox -- a table row selector\n * -- and pass `aria-label` instead. A checkbox with neither has no\n * accessible name, which is what every legacy call site would have been.\n */\n children?: ReactNode;\n /** Extra classes for the label. Merged last, so they win conflicts. */\n className?: string;\n}\n\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n { className, children, ...props },\n ref,\n) {\n return (\n <AriaCheckbox\n {...props}\n // inputRef, not ref: AriaCheckbox's own ref targets the label it\n // renders around a visually-hidden native input, and a label cannot\n // be focused -- ref.current.focus() would silently no-op. inputRef is\n // React Aria's own escape hatch to the real control.\n inputRef={ref}\n data-slot=\"checkbox\"\n // `group` is load-bearing: React Aria puts data-selected,\n // data-indeterminate and data-focus-visible on the LABEL, and CSS\n // cannot look upward from the box to them.\n className={cn(checkboxVariants(), className)}\n >\n {({ isSelected, isIndeterminate }) => (\n <>\n {/*\n aria-hidden: the real <input> already carries the state. A\n decorative box announced as well would say everything twice.\n */}\n <span aria-hidden=\"true\" data-slot=\"checkbox-box\" className={checkboxBoxVariants()}>\n <span data-slot=\"checkbox-fill\" className=\"checkbox-fill\" />\n {/*\n One mark, always rendered: the state decides what it shows. Both\n states can be true at once (a \"select all\" box that has been\n partially cleared) and indeterminate wins, which the path's\n `d` carries in CSS -- the same precedence the old two-glyph\n branch pinned in JS.\n */}\n <svg\n data-slot=\"checkbox-mark\"\n data-mark={isIndeterminate ? \"indeterminate\" : isSelected ? \"check\" : undefined}\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n className=\"absolute -inset-px size-4.5 overflow-visible\"\n >\n <path\n className=\"checkbox-mark\"\n pathLength=\"1\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </span>\n {children == null ? null : <span data-slot=\"checkbox-label\">{children}</span>}\n </>\n )}\n </AriaCheckbox>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,MAAa,mBAAmB,IAAI,CAAC,uBAAuB,CAAC,CAAC;AAE9D,MAAa,sBAAsB,IAAI;CACrC;CACA;CAGA;CAEA;CAGA;CAGA;CACA;CAEA;CAEA,sBAAsB;AACxB,CAAC;AAgBD,MAAaA,aAAW,WAA4C,SAASA,WAC3E,EAAE,WAAW,UAAU,GAAG,SAC1B,KACA;CACA,OACE,oBAACC,UAAD;EACE,GAAI;EAKJ,UAAU;EACV,aAAU;EAIV,WAAW,GAAG,iBAAiB,GAAG,SAAS;EAEzC,WAAA,EAAE,YAAY,sBACd,qBAAA,YAAA,EAAA,UAAA,CAKE,qBAAC,QAAD;GAAM,eAAY;GAAO,aAAU;GAAe,WAAW,oBAAoB;GAAjF,UAAA,CACE,oBAAC,QAAD;IAAM,aAAU;IAAgB,WAAU;GAAiB,CAAA,GAQ3D,oBAAC,OAAD;IACE,aAAU;IACV,aAAW,kBAAkB,kBAAkB,aAAa,UAAU,KAAA;IACtE,SAAQ;IACR,MAAK;IACL,WAAU;IAEV,UAAA,oBAAC,QAAD;KACE,WAAU;KACV,YAAW;KACX,QAAO;KACP,aAAY;KACZ,eAAc;KACd,gBAAe;IAChB,CAAA;GACE,CAAA,CACD;EACL,CAAA,GAAA,YAAY,OAAO,OAAO,oBAAC,QAAD;GAAM,aAAU;GAAkB;EAAe,CAAA,CAC5E,EAAA,CAAA;CAEQ,CAAA;AAElB,CAAC"}
@@ -0,0 +1,37 @@
1
+ //#region src/chip-group/chip-group.d.ts
2
+ /**
3
+ * ChipGroup: selectable filter chips for narrowing a list by facets people
4
+ * toggle often, such as topics, statuses or tags.
5
+ *
6
+ * Selecting a chip grows a check in at its start (it draws itself as it
7
+ * scales up from a soft blur), the label slides over, the chip widens on the
8
+ * morph spring, and its neighbours glide to their new places, even across
9
+ * lines. The row follows its own height. Long sets fold behind a "+N more"
10
+ * chip; opening it grows the hidden chips in one after another. Arrow keys move
11
+ * between chips, Space or Enter toggles, and each chip is a pressed or
12
+ * unpressed button. Selected reads as a tint plus the check, never colour alone.
13
+ */
14
+ export interface ChipOption {
15
+ value: string;
16
+ label: string;
17
+ }
18
+ export interface ChipGroupProps {
19
+ options: ChipOption[];
20
+ value: string[];
21
+ onValueChange: (value: string[]) => void;
22
+ /** Accessible name of the group, such as "Topics". */
23
+ label: string;
24
+ /** Allow several chips at once. In single mode the selected chip can still be cleared. @default true */
25
+ multiple?: boolean;
26
+ /** Chips shown before the rest fold behind a "+N more" chip. Chips selected when it folds stay in view. */
27
+ maxVisible?: number;
28
+ /** Text of the overflow chip. @default (hidden) => `+${hidden} more` */
29
+ moreLabel?: (hidden: number) => string;
30
+ /** @default "Show less" */
31
+ lessLabel?: string;
32
+ /** Extra classes for the group. Merged last. */
33
+ className?: string;
34
+ }
35
+ export declare const ChipGroup: import("react").ForwardRefExoticComponent<ChipGroupProps & import("react").RefAttributes<HTMLDivElement>>;
36
+ //#endregion
37
+ //# sourceMappingURL=chip-group.d.ts.map