@seekalfred/primitives 0.5.1 → 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 (446) hide show
  1. package/README.md +682 -19
  2. package/dist/accordion/accordion.js +10 -4
  3. package/dist/accordion/accordion.js.map +1 -1
  4. package/dist/action-button/action-button.d.ts +50 -0
  5. package/dist/action-button/action-button.js +159 -0
  6. package/dist/action-button/action-button.js.map +1 -0
  7. package/dist/action-button/index.d.ts +2 -0
  8. package/dist/action-button/index.js +2 -0
  9. package/dist/activity-heatmap/activity-heatmap.d.ts +92 -0
  10. package/dist/activity-heatmap/activity-heatmap.js +699 -0
  11. package/dist/activity-heatmap/activity-heatmap.js.map +1 -0
  12. package/dist/activity-heatmap/index.d.ts +2 -0
  13. package/dist/activity-heatmap/index.js +2 -0
  14. package/dist/alert/alert.d.ts +19 -1
  15. package/dist/alert/alert.js +180 -23
  16. package/dist/alert/alert.js.map +1 -1
  17. package/dist/alert-dialog/alert-dialog.d.ts +45 -18
  18. package/dist/alert-dialog/alert-dialog.js +128 -9
  19. package/dist/alert-dialog/alert-dialog.js.map +1 -1
  20. package/dist/alert-dialog/index.d.ts +2 -2
  21. package/dist/alert-dialog/index.js +2 -2
  22. package/dist/animated-counter/animated-counter.d.ts +38 -0
  23. package/dist/animated-counter/animated-counter.js +230 -0
  24. package/dist/animated-counter/animated-counter.js.map +1 -0
  25. package/dist/animated-counter/index.d.ts +2 -0
  26. package/dist/animated-counter/index.js +2 -0
  27. package/dist/announcement-bar/announcement-bar.d.ts +67 -0
  28. package/dist/announcement-bar/announcement-bar.js +364 -0
  29. package/dist/announcement-bar/announcement-bar.js.map +1 -0
  30. package/dist/announcement-bar/index.d.ts +2 -0
  31. package/dist/announcement-bar/index.js +2 -0
  32. package/dist/avatar/avatar.d.ts +6 -0
  33. package/dist/avatar/avatar.js +47 -16
  34. package/dist/avatar/avatar.js.map +1 -1
  35. package/dist/badge/badge.d.ts +10 -3
  36. package/dist/badge/badge.js +35 -5
  37. package/dist/badge/badge.js.map +1 -1
  38. package/dist/bar-chart/bar-chart.d.ts +51 -0
  39. package/dist/bar-chart/bar-chart.js +565 -0
  40. package/dist/bar-chart/bar-chart.js.map +1 -0
  41. package/dist/bar-chart/index.d.ts +2 -0
  42. package/dist/bar-chart/index.js +2 -0
  43. package/dist/breadcrumb/breadcrumb.d.ts +2 -29
  44. package/dist/breadcrumb/breadcrumb.js +32 -9
  45. package/dist/breadcrumb/breadcrumb.js.map +1 -1
  46. package/dist/brush-chart/brush-chart.d.ts +64 -0
  47. package/dist/brush-chart/brush-chart.js +1056 -0
  48. package/dist/brush-chart/brush-chart.js.map +1 -0
  49. package/dist/brush-chart/index.d.ts +2 -0
  50. package/dist/brush-chart/index.js +2 -0
  51. package/dist/button/button.d.ts +36 -23
  52. package/dist/button/button.js +198 -45
  53. package/dist/button/button.js.map +1 -1
  54. package/dist/button-group/button-group.d.ts +76 -0
  55. package/dist/button-group/button-group.js +402 -0
  56. package/dist/button-group/button-group.js.map +1 -0
  57. package/dist/button-group/index.d.ts +2 -0
  58. package/dist/button-group/index.js +2 -0
  59. package/dist/calendar/calendar.d.ts +1 -1
  60. package/dist/calendar/calendar.js +257 -30
  61. package/dist/calendar/calendar.js.map +1 -1
  62. package/dist/card/card.d.ts +9 -2
  63. package/dist/card/card.js +16 -5
  64. package/dist/card/card.js.map +1 -1
  65. package/dist/card-stack/card-stack.d.ts +54 -0
  66. package/dist/card-stack/card-stack.js +492 -0
  67. package/dist/card-stack/card-stack.js.map +1 -0
  68. package/dist/card-stack/index.d.ts +2 -0
  69. package/dist/card-stack/index.js +2 -0
  70. package/dist/carousel/carousel.d.ts +56 -0
  71. package/dist/carousel/carousel.js +389 -0
  72. package/dist/carousel/carousel.js.map +1 -0
  73. package/dist/carousel/index.d.ts +2 -0
  74. package/dist/carousel/index.js +2 -0
  75. package/dist/checkbox/checkbox.d.ts +0 -7
  76. package/dist/checkbox/checkbox.js +26 -29
  77. package/dist/checkbox/checkbox.js.map +1 -1
  78. package/dist/chip-group/chip-group.d.ts +37 -0
  79. package/dist/chip-group/chip-group.js +148 -0
  80. package/dist/chip-group/chip-group.js.map +1 -0
  81. package/dist/chip-group/index.d.ts +2 -0
  82. package/dist/chip-group/index.js +2 -0
  83. package/dist/confirm-morph/confirm-morph.d.ts +85 -0
  84. package/dist/confirm-morph/confirm-morph.js +652 -0
  85. package/dist/confirm-morph/confirm-morph.js.map +1 -0
  86. package/dist/confirm-morph/index.d.ts +2 -0
  87. package/dist/confirm-morph/index.js +2 -0
  88. package/dist/copy-button/copy-button.d.ts +32 -0
  89. package/dist/copy-button/copy-button.js +134 -0
  90. package/dist/copy-button/copy-button.js.map +1 -0
  91. package/dist/copy-button/index.d.ts +2 -0
  92. package/dist/copy-button/index.js +2 -0
  93. package/dist/countdown/countdown.d.ts +45 -0
  94. package/dist/countdown/countdown.js +298 -0
  95. package/dist/countdown/countdown.js.map +1 -0
  96. package/dist/countdown/index.d.ts +2 -0
  97. package/dist/countdown/index.js +2 -0
  98. package/dist/date-picker/date-picker.d.ts +51 -0
  99. package/dist/date-picker/date-picker.js +241 -0
  100. package/dist/date-picker/date-picker.js.map +1 -0
  101. package/dist/date-picker/date-range-picker.d.ts +78 -0
  102. package/dist/date-picker/date-range-picker.js +1015 -0
  103. package/dist/date-picker/date-range-picker.js.map +1 -0
  104. package/dist/date-picker/index.d.ts +4 -0
  105. package/dist/date-picker/index.js +4 -0
  106. package/dist/date-picker/picker-parts.d.ts +46 -0
  107. package/dist/date-picker/picker-parts.js +135 -0
  108. package/dist/date-picker/picker-parts.js.map +1 -0
  109. package/dist/dialog/dialog.d.ts +10 -14
  110. package/dist/dialog/dialog.js +40 -12
  111. package/dist/dialog/dialog.js.map +1 -1
  112. package/dist/donut-chart/donut-chart.d.ts +64 -0
  113. package/dist/donut-chart/donut-chart.js +576 -0
  114. package/dist/donut-chart/donut-chart.js.map +1 -0
  115. package/dist/donut-chart/index.d.ts +2 -0
  116. package/dist/donut-chart/index.js +2 -0
  117. package/dist/empty-state/empty-state.d.ts +55 -0
  118. package/dist/empty-state/empty-state.js +89 -0
  119. package/dist/empty-state/empty-state.js.map +1 -0
  120. package/dist/empty-state/index.d.ts +2 -0
  121. package/dist/empty-state/index.js +2 -0
  122. package/dist/expanding-button-group/expanding-button-group.d.ts +54 -0
  123. package/dist/expanding-button-group/expanding-button-group.js +350 -0
  124. package/dist/expanding-button-group/expanding-button-group.js.map +1 -0
  125. package/dist/expanding-button-group/index.d.ts +2 -0
  126. package/dist/expanding-button-group/index.js +2 -0
  127. package/dist/file-drop-zone/file-drop-zone.d.ts +71 -0
  128. package/dist/file-drop-zone/file-drop-zone.js +116 -0
  129. package/dist/file-drop-zone/file-drop-zone.js.map +1 -0
  130. package/dist/file-drop-zone/index.d.ts +2 -0
  131. package/dist/file-drop-zone/index.js +2 -0
  132. package/dist/filter-bar/filter-bar.d.ts +142 -0
  133. package/dist/filter-bar/filter-bar.js +416 -0
  134. package/dist/filter-bar/filter-bar.js.map +1 -0
  135. package/dist/filter-bar/index.d.ts +2 -0
  136. package/dist/filter-bar/index.js +2 -0
  137. package/dist/floating-button-group/floating-button-group.d.ts +61 -0
  138. package/dist/floating-button-group/floating-button-group.js +340 -0
  139. package/dist/floating-button-group/floating-button-group.js.map +1 -0
  140. package/dist/floating-button-group/index.d.ts +2 -0
  141. package/dist/floating-button-group/index.js +2 -0
  142. package/dist/gauge/gauge.d.ts +45 -0
  143. package/dist/gauge/gauge.js +219 -0
  144. package/dist/gauge/gauge.js.map +1 -0
  145. package/dist/gauge/index.d.ts +2 -0
  146. package/dist/gauge/index.js +2 -0
  147. package/dist/icon-morph/icon-morph.d.ts +55 -0
  148. package/dist/icon-morph/icon-morph.js +331 -0
  149. package/dist/icon-morph/icon-morph.js.map +1 -0
  150. package/dist/icon-morph/index.d.ts +2 -0
  151. package/dist/icon-morph/index.js +2 -0
  152. package/dist/in-view-title/in-view-title.d.ts +33 -0
  153. package/dist/in-view-title/in-view-title.js +119 -0
  154. package/dist/in-view-title/in-view-title.js.map +1 -0
  155. package/dist/in-view-title/index.d.ts +2 -0
  156. package/dist/in-view-title/index.js +2 -0
  157. package/dist/index.d.ts +71 -6
  158. package/dist/index.js +73 -11
  159. package/dist/input/input.d.ts +22 -0
  160. package/dist/input/input.js +36 -12
  161. package/dist/input/input.js.map +1 -1
  162. package/dist/lib/cn.js +11 -1
  163. package/dist/lib/cn.js.map +1 -1
  164. package/dist/lib/count-to.js +113 -0
  165. package/dist/lib/count-to.js.map +1 -0
  166. package/dist/lib/eye-morph.js +62 -0
  167. package/dist/lib/eye-morph.js.map +1 -0
  168. package/dist/lib/field-message.js +354 -0
  169. package/dist/lib/field-message.js.map +1 -0
  170. package/dist/lib/field-shell.js +81 -0
  171. package/dist/lib/field-shell.js.map +1 -0
  172. package/dist/lib/field-surface.js +11 -8
  173. package/dist/lib/field-surface.js.map +1 -1
  174. package/dist/lib/flag-emoji.js +50 -0
  175. package/dist/lib/flag-emoji.js.map +1 -0
  176. package/dist/lib/flip.js +88 -0
  177. package/dist/lib/flip.js.map +1 -0
  178. package/dist/lib/height-follow.js +59 -0
  179. package/dist/lib/height-follow.js.map +1 -0
  180. package/dist/lib/icon-swap.js +47 -0
  181. package/dist/lib/icon-swap.js.map +1 -0
  182. package/dist/lib/leaving-list.js +57 -0
  183. package/dist/lib/leaving-list.js.map +1 -0
  184. package/dist/lib/menu-highlight.js +64 -0
  185. package/dist/lib/menu-highlight.js.map +1 -0
  186. package/dist/lib/merge-refs.js +3 -3
  187. package/dist/lib/merge-refs.js.map +1 -1
  188. package/dist/lib/morph-text.js +128 -0
  189. package/dist/lib/morph-text.js.map +1 -0
  190. package/dist/lib/motion.js +169 -0
  191. package/dist/lib/motion.js.map +1 -0
  192. package/dist/lib/pausable-timeout.js +67 -0
  193. package/dist/lib/pausable-timeout.js.map +1 -0
  194. package/dist/lib/rolling-value.js +31 -0
  195. package/dist/lib/rolling-value.js.map +1 -0
  196. package/dist/lib/spring-progress.js +114 -0
  197. package/dist/lib/spring-progress.js.map +1 -0
  198. package/dist/lib/spring-tween.js +500 -0
  199. package/dist/lib/spring-tween.js.map +1 -0
  200. package/dist/lib/svg-id.js +10 -0
  201. package/dist/lib/svg-id.js.map +1 -0
  202. package/dist/lib/swap-text.js +79 -0
  203. package/dist/lib/swap-text.js.map +1 -0
  204. package/dist/lib/use-copy-feedback.js +36 -0
  205. package/dist/lib/use-copy-feedback.js.map +1 -0
  206. package/dist/line-chart/index.d.ts +2 -0
  207. package/dist/line-chart/index.js +2 -0
  208. package/dist/line-chart/line-chart.d.ts +76 -0
  209. package/dist/line-chart/line-chart.js +611 -0
  210. package/dist/line-chart/line-chart.js.map +1 -0
  211. package/dist/mention-input/index.d.ts +2 -0
  212. package/dist/mention-input/index.js +2 -0
  213. package/dist/mention-input/mention-input.d.ts +98 -0
  214. package/dist/mention-input/mention-input.js +576 -0
  215. package/dist/mention-input/mention-input.js.map +1 -0
  216. package/dist/menu/menu.d.ts +2 -0
  217. package/dist/menu/menu.js +23 -12
  218. package/dist/menu/menu.js.map +1 -1
  219. package/dist/money-input/index.d.ts +2 -0
  220. package/dist/money-input/index.js +2 -0
  221. package/dist/money-input/money-input.d.ts +65 -0
  222. package/dist/money-input/money-input.js +607 -0
  223. package/dist/money-input/money-input.js.map +1 -0
  224. package/dist/morph-select/index.d.ts +2 -0
  225. package/dist/morph-select/index.js +2 -0
  226. package/dist/morph-select/morph-select.d.ts +71 -0
  227. package/dist/morph-select/morph-select.js +693 -0
  228. package/dist/morph-select/morph-select.js.map +1 -0
  229. package/dist/multi-select/index.d.ts +2 -0
  230. package/dist/multi-select/index.js +2 -0
  231. package/dist/multi-select/multi-select.d.ts +36 -0
  232. package/dist/multi-select/multi-select.js +152 -0
  233. package/dist/multi-select/multi-select.js.map +1 -0
  234. package/dist/number-field/index.d.ts +2 -0
  235. package/dist/number-field/index.js +2 -0
  236. package/dist/number-field/number-field.d.ts +42 -0
  237. package/dist/number-field/number-field.js +199 -0
  238. package/dist/number-field/number-field.js.map +1 -0
  239. package/dist/onboarding-checklist/index.d.ts +2 -0
  240. package/dist/onboarding-checklist/index.js +2 -0
  241. package/dist/onboarding-checklist/onboarding-checklist.d.ts +55 -0
  242. package/dist/onboarding-checklist/onboarding-checklist.js +577 -0
  243. package/dist/onboarding-checklist/onboarding-checklist.js.map +1 -0
  244. package/dist/page-header/index.d.ts +2 -0
  245. package/dist/page-header/index.js +2 -0
  246. package/dist/page-header/page-header.d.ts +75 -0
  247. package/dist/page-header/page-header.js +83 -0
  248. package/dist/page-header/page-header.js.map +1 -0
  249. package/dist/password-field/index.d.ts +2 -0
  250. package/dist/password-field/index.js +2 -0
  251. package/dist/password-field/password-field.d.ts +37 -0
  252. package/dist/password-field/password-field.js +101 -0
  253. package/dist/password-field/password-field.js.map +1 -0
  254. package/dist/password-strength/index.d.ts +2 -0
  255. package/dist/password-strength/index.js +2 -0
  256. package/dist/password-strength/password-strength.d.ts +127 -0
  257. package/dist/password-strength/password-strength.js +455 -0
  258. package/dist/password-strength/password-strength.js.map +1 -0
  259. package/dist/phone-input/index.d.ts +3 -0
  260. package/dist/phone-input/index.js +3 -0
  261. package/dist/phone-input/phone-countries.d.ts +29 -0
  262. package/dist/phone-input/phone-countries.js +170 -0
  263. package/dist/phone-input/phone-countries.js.map +1 -0
  264. package/dist/phone-input/phone-input.d.ts +66 -0
  265. package/dist/phone-input/phone-input.js +440 -0
  266. package/dist/phone-input/phone-input.js.map +1 -0
  267. package/dist/popover/popover.d.ts +20 -0
  268. package/dist/popover/popover.js +33 -9
  269. package/dist/popover/popover.js.map +1 -1
  270. package/dist/progress/progress.js +46 -5
  271. package/dist/progress/progress.js.map +1 -1
  272. package/dist/radio-group/radio-group.js +8 -7
  273. package/dist/radio-group/radio-group.js.map +1 -1
  274. package/dist/reactions/index.d.ts +2 -0
  275. package/dist/reactions/index.js +2 -0
  276. package/dist/reactions/reactions.d.ts +50 -0
  277. package/dist/reactions/reactions.js +315 -0
  278. package/dist/reactions/reactions.js.map +1 -0
  279. package/dist/rich-text-editor/index.d.ts +3 -0
  280. package/dist/rich-text-editor/index.js +2 -0
  281. package/dist/rich-text-editor/rich-text-editor.d.ts +70 -0
  282. package/dist/rich-text-editor/rich-text-editor.js +909 -0
  283. package/dist/rich-text-editor/rich-text-editor.js.map +1 -0
  284. package/dist/rich-text-editor/rich-text-engine.d.ts +16 -0
  285. package/dist/rich-text-editor/rich-text-engine.js +366 -0
  286. package/dist/rich-text-editor/rich-text-engine.js.map +1 -0
  287. package/dist/rich-text-editor/rich-text-html.js +174 -0
  288. package/dist/rich-text-editor/rich-text-html.js.map +1 -0
  289. package/dist/rich-text-editor/rich-text-icons.js +43 -0
  290. package/dist/rich-text-editor/rich-text-icons.js.map +1 -0
  291. package/dist/ridgeline/index.d.ts +2 -0
  292. package/dist/ridgeline/index.js +2 -0
  293. package/dist/ridgeline/ridgeline.d.ts +55 -0
  294. package/dist/ridgeline/ridgeline.js +701 -0
  295. package/dist/ridgeline/ridgeline.js.map +1 -0
  296. package/dist/scroll-area/index.d.ts +2 -2
  297. package/dist/scroll-area/index.js +2 -2
  298. package/dist/scroll-area/scroll-area.d.ts +75 -28
  299. package/dist/scroll-area/scroll-area.js +212 -41
  300. package/dist/scroll-area/scroll-area.js.map +1 -1
  301. package/dist/scrub-input/evaluate.d.ts +14 -0
  302. package/dist/scrub-input/evaluate.js +72 -0
  303. package/dist/scrub-input/evaluate.js.map +1 -0
  304. package/dist/scrub-input/index.d.ts +3 -0
  305. package/dist/scrub-input/index.js +3 -0
  306. package/dist/scrub-input/scrub-input.d.ts +74 -0
  307. package/dist/scrub-input/scrub-input.js +486 -0
  308. package/dist/scrub-input/scrub-input.js.map +1 -0
  309. package/dist/search-field/index.d.ts +2 -0
  310. package/dist/search-field/index.js +2 -0
  311. package/dist/search-field/search-field.d.ts +27 -0
  312. package/dist/search-field/search-field.js +155 -0
  313. package/dist/search-field/search-field.js.map +1 -0
  314. package/dist/select/select.d.ts +3 -1
  315. package/dist/select/select.js +95 -25
  316. package/dist/select/select.js.map +1 -1
  317. package/dist/separator/separator.d.ts +1 -1
  318. package/dist/sheet/sheet.js +4 -2
  319. package/dist/sheet/sheet.js.map +1 -1
  320. package/dist/shortcut-recorder/index.d.ts +3 -0
  321. package/dist/shortcut-recorder/index.js +3 -0
  322. package/dist/shortcut-recorder/shortcut-model.d.ts +27 -0
  323. package/dist/shortcut-recorder/shortcut-model.js +206 -0
  324. package/dist/shortcut-recorder/shortcut-model.js.map +1 -0
  325. package/dist/shortcut-recorder/shortcut-recorder.d.ts +93 -0
  326. package/dist/shortcut-recorder/shortcut-recorder.js +489 -0
  327. package/dist/shortcut-recorder/shortcut-recorder.js.map +1 -0
  328. package/dist/side-nav/index.d.ts +2 -0
  329. package/dist/side-nav/index.js +2 -0
  330. package/dist/side-nav/side-nav.d.ts +72 -0
  331. package/dist/side-nav/side-nav.js +142 -0
  332. package/dist/side-nav/side-nav.js.map +1 -0
  333. package/dist/skeleton/skeleton.d.ts +8 -2
  334. package/dist/skeleton/skeleton.js +6 -2
  335. package/dist/skeleton/skeleton.js.map +1 -1
  336. package/dist/slider/index.d.ts +2 -2
  337. package/dist/slider/slider.d.ts +46 -14
  338. package/dist/slider/slider.js +188 -50
  339. package/dist/slider/slider.js.map +1 -1
  340. package/dist/slope-chart/index.d.ts +2 -0
  341. package/dist/slope-chart/index.js +2 -0
  342. package/dist/slope-chart/slope-chart.d.ts +54 -0
  343. package/dist/slope-chart/slope-chart.js +568 -0
  344. package/dist/slope-chart/slope-chart.js.map +1 -0
  345. package/dist/sparkline/index.d.ts +2 -0
  346. package/dist/sparkline/index.js +2 -0
  347. package/dist/sparkline/sparkline.d.ts +46 -0
  348. package/dist/sparkline/sparkline.js +390 -0
  349. package/dist/sparkline/sparkline.js.map +1 -0
  350. package/dist/split-bar/index.d.ts +2 -0
  351. package/dist/split-bar/index.js +2 -0
  352. package/dist/split-bar/split-bar.d.ts +62 -0
  353. package/dist/split-bar/split-bar.js +513 -0
  354. package/dist/split-bar/split-bar.js.map +1 -0
  355. package/dist/split-button/index.d.ts +2 -0
  356. package/dist/split-button/index.js +2 -0
  357. package/dist/split-button/split-button.d.ts +46 -0
  358. package/dist/split-button/split-button.js +123 -0
  359. package/dist/split-button/split-button.js.map +1 -0
  360. package/dist/stat-card/index.d.ts +2 -0
  361. package/dist/stat-card/index.js +2 -0
  362. package/dist/stat-card/stat-card.d.ts +101 -0
  363. package/dist/stat-card/stat-card.js +249 -0
  364. package/dist/stat-card/stat-card.js.map +1 -0
  365. package/dist/stepper/index.d.ts +2 -0
  366. package/dist/stepper/index.js +2 -0
  367. package/dist/stepper/stepper.d.ts +51 -0
  368. package/dist/stepper/stepper.js +215 -0
  369. package/dist/stepper/stepper.js.map +1 -0
  370. package/dist/streamgraph/index.d.ts +2 -0
  371. package/dist/streamgraph/index.js +2 -0
  372. package/dist/streamgraph/streamgraph.d.ts +70 -0
  373. package/dist/streamgraph/streamgraph.js +613 -0
  374. package/dist/streamgraph/streamgraph.js.map +1 -0
  375. package/dist/styles.css +1 -1
  376. package/dist/swipe-actions/index.d.ts +2 -0
  377. package/dist/swipe-actions/index.js +2 -0
  378. package/dist/swipe-actions/swipe-actions.d.ts +67 -0
  379. package/dist/swipe-actions/swipe-actions.js +552 -0
  380. package/dist/swipe-actions/swipe-actions.js.map +1 -0
  381. package/dist/switch/switch.js +10 -9
  382. package/dist/switch/switch.js.map +1 -1
  383. package/dist/table/index.d.ts +2 -2
  384. package/dist/table/index.js +2 -2
  385. package/dist/table/table.d.ts +87 -4
  386. package/dist/table/table.js +441 -165
  387. package/dist/table/table.js.map +1 -1
  388. package/dist/tabs/tabs.js +143 -7
  389. package/dist/tabs/tabs.js.map +1 -1
  390. package/dist/tag-input/index.d.ts +2 -0
  391. package/dist/tag-input/index.js +2 -0
  392. package/dist/tag-input/tag-input.d.ts +40 -0
  393. package/dist/tag-input/tag-input.js +269 -0
  394. package/dist/tag-input/tag-input.js.map +1 -0
  395. package/dist/text-morph/index.d.ts +2 -0
  396. package/dist/text-morph/index.js +2 -0
  397. package/dist/text-morph/text-morph.d.ts +23 -0
  398. package/dist/text-morph/text-morph.js +21 -0
  399. package/dist/text-morph/text-morph.js.map +1 -0
  400. package/dist/text-reveal/index.d.ts +2 -0
  401. package/dist/text-reveal/index.js +2 -0
  402. package/dist/text-reveal/text-reveal.d.ts +27 -0
  403. package/dist/text-reveal/text-reveal.js +51 -0
  404. package/dist/text-reveal/text-reveal.js.map +1 -0
  405. package/dist/text-shimmer/index.d.ts +2 -0
  406. package/dist/text-shimmer/index.js +2 -0
  407. package/dist/text-shimmer/text-shimmer.d.ts +29 -0
  408. package/dist/text-shimmer/text-shimmer.js +29 -0
  409. package/dist/text-shimmer/text-shimmer.js.map +1 -0
  410. package/dist/textarea/textarea.d.ts +23 -0
  411. package/dist/textarea/textarea.js +24 -2
  412. package/dist/textarea/textarea.js.map +1 -1
  413. package/dist/theme-switch/index.d.ts +2 -0
  414. package/dist/theme-switch/index.js +2 -0
  415. package/dist/theme-switch/theme-switch.d.ts +37 -0
  416. package/dist/theme-switch/theme-switch.js +123 -0
  417. package/dist/theme-switch/theme-switch.js.map +1 -0
  418. package/dist/time-picker/index.d.ts +2 -0
  419. package/dist/time-picker/index.js +2 -0
  420. package/dist/time-picker/time-picker.d.ts +54 -0
  421. package/dist/time-picker/time-picker.js +201 -0
  422. package/dist/time-picker/time-picker.js.map +1 -0
  423. package/dist/toast/index.d.ts +2 -2
  424. package/dist/toast/index.js +2 -2
  425. package/dist/toast/toast.d.ts +6 -0
  426. package/dist/toast/toast.js +98 -36
  427. package/dist/toast/toast.js.map +1 -1
  428. package/dist/tooltip/tooltip.d.ts +10 -3
  429. package/dist/tooltip/tooltip.js +67 -18
  430. package/dist/tooltip/tooltip.js.map +1 -1
  431. package/dist/treemap/index.d.ts +2 -0
  432. package/dist/treemap/index.js +2 -0
  433. package/dist/treemap/treemap.d.ts +53 -0
  434. package/dist/treemap/treemap.js +699 -0
  435. package/dist/treemap/treemap.js.map +1 -0
  436. package/dist/usage-meter/index.d.ts +2 -0
  437. package/dist/usage-meter/index.js +2 -0
  438. package/dist/usage-meter/usage-meter.d.ts +50 -0
  439. package/dist/usage-meter/usage-meter.js +440 -0
  440. package/dist/usage-meter/usage-meter.js.map +1 -0
  441. package/dist/waffle-chart/index.d.ts +2 -0
  442. package/dist/waffle-chart/index.js +2 -0
  443. package/dist/waffle-chart/waffle-chart.d.ts +57 -0
  444. package/dist/waffle-chart/waffle-chart.js +426 -0
  445. package/dist/waffle-chart/waffle-chart.js.map +1 -0
  446. package/package.json +245 -3
@@ -0,0 +1,350 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { useExitBackstop, useIsomorphicLayoutEffect, useLeavingItems } from "../lib/motion.js";
4
+ import { IconSwap } from "../lib/icon-swap.js";
5
+ import { useCallback, useEffect, useRef, useState } from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/expanding-button-group/expanding-button-group.tsx
8
+ /** Geometry per size. The icon keeps the same left inset collapsed and expanded, so it never moves while the label is revealed. */
9
+ const metrics = {
10
+ sm: {
11
+ height: 28,
12
+ icon: 14,
13
+ start: 7,
14
+ gap: 5,
15
+ end: 11
16
+ },
17
+ md: {
18
+ height: 36,
19
+ icon: 16,
20
+ start: 10,
21
+ gap: 7,
22
+ end: 14
23
+ }
24
+ };
25
+ /** Pixels the pointer must travel into a neighbouring action before the expansion moves to it. */
26
+ const hysteresis = 4;
27
+ /** The confirmation tick draws itself from its short stroke. */
28
+ function DrawnCheck() {
29
+ return /* @__PURE__ */ jsx("svg", {
30
+ viewBox: "0 0 24 24",
31
+ fill: "none",
32
+ stroke: "currentColor",
33
+ strokeWidth: 2,
34
+ strokeLinecap: "round",
35
+ strokeLinejoin: "round",
36
+ "aria-hidden": "true",
37
+ children: /* @__PURE__ */ jsx("path", {
38
+ d: "M4 12.5l5 5L20 6.5",
39
+ pathLength: 1,
40
+ className: "[stroke-dasharray:1] motion-safe:animate-check-draw-quick"
41
+ })
42
+ });
43
+ }
44
+ function LeavingWord({ id, onDone, children }) {
45
+ const remove = useCallback(() => onDone(id), [onDone, id]);
46
+ useExitBackstop(true, remove);
47
+ return /* @__PURE__ */ jsx("span", {
48
+ "aria-hidden": "true",
49
+ onAnimationEnd: (event) => {
50
+ if (event.target === event.currentTarget) remove();
51
+ },
52
+ className: "col-start-1 row-start-1 whitespace-nowrap motion-safe:animate-word-out motion-reduce:animate-fade-out",
53
+ children
54
+ });
55
+ }
56
+ function Item({ item, size, expanded, done, busy, tabStop, onPointerDown, onClick, onFocus }) {
57
+ const m = metrics[size];
58
+ const labelRef = useRef(null);
59
+ const doneRef = useRef(null);
60
+ const wordRef = useRef(null);
61
+ const [text, setText] = useState(0);
62
+ useIsomorphicLayoutEffect(() => {
63
+ const measure = () => {
64
+ const next = Math.max(labelRef.current?.getBoundingClientRect().width ?? 0, doneRef.current?.getBoundingClientRect().width ?? 0);
65
+ setText((current) => Math.abs(current - next) < .5 ? current : next);
66
+ };
67
+ measure();
68
+ if (typeof ResizeObserver === "undefined") return;
69
+ let frame = 0;
70
+ const observer = new ResizeObserver(() => {
71
+ cancelAnimationFrame(frame);
72
+ frame = requestAnimationFrame(measure);
73
+ });
74
+ if (labelRef.current) observer.observe(labelRef.current);
75
+ if (doneRef.current) observer.observe(doneRef.current);
76
+ return () => {
77
+ cancelAnimationFrame(frame);
78
+ observer.disconnect();
79
+ };
80
+ }, [
81
+ item.label,
82
+ item.doneLabel,
83
+ size
84
+ ]);
85
+ const showDone = done && !!item.doneLabel;
86
+ const measured = text > 0;
87
+ const target = expanded && measured ? m.start + m.icon + m.gap + text + m.end : m.height;
88
+ const word = showDone ? item.doneLabel : item.label;
89
+ const { leaving, changed, remove } = useLeavingItems(word, word, () => wordRef.current);
90
+ return /* @__PURE__ */ jsxs("button", {
91
+ type: "button",
92
+ style: { width: target },
93
+ "data-ebg-item": "",
94
+ "data-id": item.id,
95
+ "data-tone": item.tone ?? "neutral",
96
+ "data-state": showDone ? "done" : "idle",
97
+ "data-expanded": expanded || void 0,
98
+ "data-unmeasured": measured ? void 0 : "",
99
+ "aria-label": item.label,
100
+ "aria-disabled": item.isDisabled || void 0,
101
+ "aria-busy": busy || void 0,
102
+ tabIndex: tabStop ? 0 : -1,
103
+ onPointerDown: (event) => onPointerDown(item, event),
104
+ onClick: () => onClick(item),
105
+ onFocus: (event) => onFocus(item, event),
106
+ className: "expanding-group-item focus-visible:outline-solid focus-visible:outline-(length:--focus-ring-width) focus-visible:outline-offset-(--focus-ring-offset) focus-visible:outline-(--color-ring)",
107
+ children: [/* @__PURE__ */ jsx("span", {
108
+ className: "expanding-group-icon",
109
+ "aria-hidden": "true",
110
+ children: /* @__PURE__ */ jsx(IconSwap, {
111
+ iconKey: showDone ? "done" : "icon",
112
+ tight: true,
113
+ fill: true,
114
+ className: "size-full",
115
+ children: showDone ? /* @__PURE__ */ jsx(DrawnCheck, {}) : item.icon
116
+ })
117
+ }), /* @__PURE__ */ jsxs("span", {
118
+ className: "expanding-group-label",
119
+ "aria-hidden": "true",
120
+ children: [
121
+ leaving.map((entry) => /* @__PURE__ */ jsx(LeavingWord, {
122
+ id: entry.id,
123
+ onDone: remove,
124
+ children: entry.value
125
+ }, entry.id)),
126
+ /* @__PURE__ */ jsx("span", {
127
+ ref: wordRef,
128
+ className: cn("col-start-1 row-start-1 whitespace-nowrap" + (changed ? " motion-safe:animate-word-in motion-reduce:animate-fade-in" : "")),
129
+ children: word
130
+ }, word),
131
+ /* @__PURE__ */ jsx("span", {
132
+ ref: labelRef,
133
+ className: "pointer-events-none invisible col-start-1 row-start-1 whitespace-nowrap",
134
+ children: item.label
135
+ }),
136
+ item.doneLabel ? /* @__PURE__ */ jsx("span", {
137
+ ref: doneRef,
138
+ className: "pointer-events-none invisible col-start-1 row-start-1 whitespace-nowrap",
139
+ children: item.doneLabel
140
+ }) : null
141
+ ]
142
+ })]
143
+ });
144
+ }
145
+ /**
146
+ * A compact pill of icon buttons for actions. One action always shows its label;
147
+ * the one you point at or focus takes over the label while its neighbours slide
148
+ * aside, and an action can confirm in place: the icon draws a check and the label
149
+ * becomes a past tense word. On touch, the first tap reveals the label and a
150
+ * second tap runs the action.
151
+ *
152
+ * Arrow keys move focus, Home and End jump to the ends. A disabled action stays
153
+ * focusable and still reveals its label, so people can learn what it would do.
154
+ *
155
+ * @example
156
+ * <ExpandingButtonGroup label="Message actions" items={[{ id: "archive", label: "Archive", doneLabel: "Archived", icon: <ArchiveIcon aria-hidden /> }]} />
157
+ */
158
+ function ExpandingButtonGroup({ items, label, size = "md", defaultExpanded = null, onAction, confirmDuration = 1400, className }) {
159
+ const root = useRef(null);
160
+ const [intent, setIntent] = useState(null);
161
+ const [done, setDone] = useState(null);
162
+ const [busy, setBusy] = useState(null);
163
+ const [announcement, setAnnouncement] = useState("");
164
+ const [focused, setFocused] = useState(null);
165
+ const [settled, setSettled] = useState(false);
166
+ const pointerOver = useRef(null);
167
+ const pointerAt = useRef(null);
168
+ const keyFocus = useRef(null);
169
+ const touchOpen = useRef(null);
170
+ const press = useRef(null);
171
+ const doneRef = useRef(null);
172
+ const timer = useRef(null);
173
+ const mounted = useRef(true);
174
+ const seq = useRef(0);
175
+ useEffect(() => {
176
+ mounted.current = true;
177
+ const frames = requestAnimationFrame(() => requestAnimationFrame(() => setSettled(true)));
178
+ return () => {
179
+ mounted.current = false;
180
+ cancelAnimationFrame(frames);
181
+ if (timer.current) clearTimeout(timer.current);
182
+ };
183
+ }, []);
184
+ const has = (id) => !!id && items.some((item) => item.id === id);
185
+ const firstEnabled = items.find((item) => !item.isDisabled)?.id ?? items[0]?.id ?? null;
186
+ const restId = has(defaultExpanded) ? defaultExpanded : firstEnabled;
187
+ const expandedId = has(intent) ? intent : restId;
188
+ const tabStop = has(focused) ? focused : restId;
189
+ useEffect(() => {
190
+ if (!intent || touchOpen.current !== intent) return;
191
+ const onDown = (event) => {
192
+ if (root.current?.contains(event.target)) return;
193
+ touchOpen.current = null;
194
+ setIntent(doneRef.current ?? keyFocus.current);
195
+ };
196
+ document.addEventListener("pointerdown", onDown, true);
197
+ return () => document.removeEventListener("pointerdown", onDown, true);
198
+ }, [intent]);
199
+ const confirm = useCallback((item) => {
200
+ if (timer.current) clearTimeout(timer.current);
201
+ seq.current += 1;
202
+ doneRef.current = item.id;
203
+ setDone({
204
+ id: item.id,
205
+ seq: seq.current
206
+ });
207
+ setAnnouncement((item.doneLabel ?? "") + (seq.current % 2 ? "" : "​"));
208
+ timer.current = setTimeout(() => {
209
+ doneRef.current = null;
210
+ setDone(null);
211
+ if (pointerOver.current !== item.id && keyFocus.current !== item.id) {
212
+ if (touchOpen.current === item.id) touchOpen.current = null;
213
+ setIntent((current) => current === item.id ? pointerOver.current ?? keyFocus.current : current);
214
+ }
215
+ }, confirmDuration);
216
+ }, [confirmDuration]);
217
+ const activate = useCallback(async (item) => {
218
+ if (item.isDisabled || busy === item.id || doneRef.current === item.id) return;
219
+ setIntent(item.id);
220
+ onAction?.(item.id);
221
+ let result;
222
+ try {
223
+ const pending = item.onSelect?.();
224
+ if (pending instanceof Promise) {
225
+ setBusy(item.id);
226
+ result = await pending;
227
+ } else result = pending;
228
+ } catch {
229
+ result = false;
230
+ } finally {
231
+ if (mounted.current) setBusy((current) => current === item.id ? null : current);
232
+ }
233
+ if (!mounted.current || result === false || !item.doneLabel) return;
234
+ confirm(item);
235
+ }, [
236
+ busy,
237
+ confirm,
238
+ onAction
239
+ ]);
240
+ const onItemPointerDown = (item, event) => {
241
+ press.current = {
242
+ id: item.id,
243
+ kind: event.pointerType,
244
+ wasExpanded: expandedId === item.id
245
+ };
246
+ };
247
+ const onItemClick = (item) => {
248
+ const last = press.current;
249
+ press.current = null;
250
+ if (last && last.id === item.id && last.kind === "touch" && !last.wasExpanded) {
251
+ touchOpen.current = item.id;
252
+ setIntent(item.id);
253
+ return;
254
+ }
255
+ if (last?.kind === "touch") touchOpen.current = item.id;
256
+ activate(item);
257
+ };
258
+ const onItemFocus = (item, event) => {
259
+ setFocused(item.id);
260
+ let visible = true;
261
+ try {
262
+ visible = event.currentTarget.matches(":focus-visible");
263
+ } catch {}
264
+ if (!visible) return;
265
+ keyFocus.current = item.id;
266
+ setIntent(item.id);
267
+ };
268
+ const onBlur = (event) => {
269
+ if (root.current?.contains(event.relatedTarget)) return;
270
+ keyFocus.current = null;
271
+ touchOpen.current = null;
272
+ setIntent(pointerOver.current ?? doneRef.current);
273
+ };
274
+ const onPointerMove = (event) => {
275
+ if (event.pointerType !== "mouse") return;
276
+ const at = pointerAt.current;
277
+ if (at && Math.abs(at.x - event.clientX) < 1 && Math.abs(at.y - event.clientY) < 1) return;
278
+ pointerAt.current = {
279
+ x: event.clientX,
280
+ y: event.clientY
281
+ };
282
+ const button = event.target.closest("[data-ebg-item]");
283
+ const id = button?.dataset.id;
284
+ if (!button || !id || id === pointerOver.current) return;
285
+ if (pointerOver.current) {
286
+ const box = button.getBoundingClientRect();
287
+ if (event.clientX < box.left + hysteresis || event.clientX > box.right - hysteresis) return;
288
+ }
289
+ pointerOver.current = id;
290
+ setIntent(id);
291
+ };
292
+ const onPointerLeave = (event) => {
293
+ if (event.pointerType !== "mouse") return;
294
+ pointerAt.current = null;
295
+ pointerOver.current = null;
296
+ setIntent(doneRef.current ?? keyFocus.current);
297
+ };
298
+ const onKeyDown = (event) => {
299
+ const list = Array.from(root.current?.querySelectorAll("[data-ebg-item]") ?? []);
300
+ const index = list.findIndex((button) => button === document.activeElement);
301
+ if (index < 0) return;
302
+ const last = list.length - 1;
303
+ const target = event.key === "ArrowRight" ? index === last ? 0 : index + 1 : event.key === "ArrowLeft" ? index === 0 ? last : index - 1 : event.key === "Home" ? 0 : event.key === "End" ? last : -1;
304
+ if (target < 0) return;
305
+ event.preventDefault();
306
+ list[target].focus();
307
+ };
308
+ const m = metrics[size];
309
+ const vars = {
310
+ "--ebg-h": m.height + "px",
311
+ "--ebg-icon": m.icon + "px",
312
+ "--ebg-start": m.start + "px",
313
+ "--ebg-gap": m.gap + "px",
314
+ "--ebg-end": m.end + "px"
315
+ };
316
+ return /* @__PURE__ */ jsxs("div", {
317
+ ref: root,
318
+ role: "toolbar",
319
+ "aria-label": label,
320
+ "aria-orientation": "horizontal",
321
+ "data-size": size,
322
+ "data-settled": settled ? "" : void 0,
323
+ style: vars,
324
+ onKeyDown,
325
+ onBlur,
326
+ onPointerMove,
327
+ onPointerLeave,
328
+ className: cn("expanding-group", className),
329
+ children: [items.map((item) => /* @__PURE__ */ jsx(Item, {
330
+ item,
331
+ size,
332
+ expanded: expandedId === item.id,
333
+ done: done?.id === item.id,
334
+ busy: busy === item.id,
335
+ tabStop: tabStop === item.id,
336
+ onPointerDown: onItemPointerDown,
337
+ onClick: onItemClick,
338
+ onFocus: onItemFocus
339
+ }, item.id)), /* @__PURE__ */ jsx("span", {
340
+ className: "sr-only",
341
+ role: "status",
342
+ "aria-live": "polite",
343
+ children: announcement
344
+ })]
345
+ });
346
+ }
347
+ //#endregion
348
+ export { ExpandingButtonGroup };
349
+
350
+ //# sourceMappingURL=expanding-button-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expanding-button-group.js","names":[],"sources":["../../src/expanding-button-group/expanding-button-group.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n type CSSProperties,\n type FocusEvent,\n type KeyboardEvent,\n type PointerEvent,\n type ReactNode,\n} from \"react\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { IconSwap } from \"../lib/icon-swap.js\";\nimport { useExitBackstop, useIsomorphicLayoutEffect, useLeavingItems } from \"../lib/motion.js\";\n\nexport type ExpandingButtonGroupSize = \"sm\" | \"md\";\nexport type ExpandingButtonGroupTone = \"neutral\" | \"danger\";\n\nexport interface ExpandingButtonGroupItem {\n /** Stable key for the action. Also the value passed to onAction. */\n id: string;\n /** Visible label once the button expands, and its accessible name at all times. Use a short verb, such as \"Archive\". */\n label: string;\n /** Icon shown while collapsed. A 16px icon fits; it is sized by the group. Mark it `aria-hidden`. */\n icon: ReactNode;\n /** Runs the action. Return false, or reject, to skip the confirmation. A promise keeps the button busy until it settles. */\n onSelect?: () => void | boolean | Promise<void | boolean>;\n /** Past tense word shown in place after the action, such as \"Archived\". The icon becomes a check for confirmDuration. Omit for actions that open something. */\n doneLabel?: string;\n /** `danger` colours the expanded state with the destructive token, for destructive actions such as Delete. */\n tone?: ExpandingButtonGroupTone;\n /** Dimmed and inert. Stays focusable and still reveals its label, so people can learn what it would do. */\n isDisabled?: boolean;\n}\n\nexport interface ExpandingButtonGroupProps {\n items: readonly ExpandingButtonGroupItem[];\n /** Accessible name of the toolbar, such as \"Message actions\". */\n label: string;\n /** @default \"md\" */\n size?: ExpandingButtonGroupSize;\n /**\n * Id of the action whose label shows at rest, usually the primary one. Defaults to the first enabled action: one action is always\n * expanded. Pointing at or focusing another moves the expansion there, and it returns here when the pointer and focus leave.\n */\n defaultExpanded?: string | null;\n /** Called with the item id whenever an action runs, before its own onSelect. */\n onAction?: (id: string) => void;\n /** How long the confirmation stays, in milliseconds. @default 1400 */\n confirmDuration?: number;\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n}\n\n/** Geometry per size. The icon keeps the same left inset collapsed and expanded, so it never moves while the label is revealed. */\nconst metrics = {\n sm: { height: 28, icon: 14, start: 7, gap: 5, end: 11 },\n md: { height: 36, icon: 16, start: 10, gap: 7, end: 14 },\n} as const;\n\n/** Pixels the pointer must travel into a neighbouring action before the expansion moves to it. */\nconst hysteresis = 4;\n\n/** The confirmation tick draws itself from its short stroke. */\nfunction DrawnCheck() {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M4 12.5l5 5L20 6.5\"\n pathLength={1}\n className=\"[stroke-dasharray:1] motion-safe:animate-check-draw-quick\"\n />\n </svg>\n );\n}\n\nfunction LeavingWord({\n id,\n onDone,\n children,\n}: {\n id: number;\n onDone: (id: number) => void;\n children: ReactNode;\n}) {\n const remove = useCallback(() => onDone(id), [onDone, id]);\n useExitBackstop(true, remove);\n return (\n <span\n aria-hidden=\"true\"\n onAnimationEnd={(event) => {\n if (event.target === event.currentTarget) remove();\n }}\n className=\"col-start-1 row-start-1 whitespace-nowrap motion-safe:animate-word-out motion-reduce:animate-fade-out\"\n >\n {children}\n </span>\n );\n}\n\ninterface ItemProps {\n item: ExpandingButtonGroupItem;\n size: ExpandingButtonGroupSize;\n expanded: boolean;\n done: boolean;\n busy: boolean;\n tabStop: boolean;\n onPointerDown: (item: ExpandingButtonGroupItem, event: PointerEvent<HTMLButtonElement>) => void;\n onClick: (item: ExpandingButtonGroupItem) => void;\n onFocus: (item: ExpandingButtonGroupItem, event: FocusEvent<HTMLButtonElement>) => void;\n}\n\nfunction Item({\n item,\n size,\n expanded,\n done,\n busy,\n tabStop,\n onPointerDown,\n onClick,\n onFocus,\n}: ItemProps) {\n const m = metrics[size];\n const labelRef = useRef<HTMLSpanElement>(null);\n const doneRef = useRef<HTMLSpanElement>(null);\n const wordRef = useRef<HTMLSpanElement>(null);\n const [text, setText] = useState(0);\n\n // Hidden copies of both words share the label's grid cell, so the slot is always as wide as the longer one. The confirmation\n // swap then never changes the width, and the server render already has the right width before anything is measured.\n // Changes under half a pixel are ignored, so a re-measure never makes the row wobble.\n useIsomorphicLayoutEffect(() => {\n const measure = () => {\n const next = Math.max(\n labelRef.current?.getBoundingClientRect().width ?? 0,\n doneRef.current?.getBoundingClientRect().width ?? 0,\n );\n setText((current) => (Math.abs(current - next) < 0.5 ? current : next));\n };\n measure();\n if (typeof ResizeObserver === \"undefined\") return;\n // A frame later, so the state it sets cannot report a ResizeObserver loop.\n let frame = 0;\n const observer = new ResizeObserver(() => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(measure);\n });\n if (labelRef.current) observer.observe(labelRef.current);\n if (doneRef.current) observer.observe(doneRef.current);\n return () => {\n cancelAnimationFrame(frame);\n observer.disconnect();\n };\n }, [item.label, item.doneLabel, size]);\n\n const showDone = done && !!item.doneLabel;\n const measured = text > 0;\n // Width rides the morph spring, so neighbours slide and the group's own width follows without a jump.\n const target = expanded && measured ? m.start + m.icon + m.gap + text + m.end : m.height;\n const word = showDone ? item.doneLabel! : item.label;\n const { leaving, changed, remove } = useLeavingItems(word, word, () => wordRef.current);\n\n return (\n <button\n type=\"button\"\n style={{ width: target }}\n data-ebg-item=\"\"\n data-id={item.id}\n data-tone={item.tone ?? \"neutral\"}\n data-state={showDone ? \"done\" : \"idle\"}\n data-expanded={expanded || undefined}\n data-unmeasured={measured ? undefined : \"\"}\n aria-label={item.label}\n aria-disabled={item.isDisabled || undefined}\n aria-busy={busy || undefined}\n tabIndex={tabStop ? 0 : -1}\n onPointerDown={(event) => onPointerDown(item, event)}\n onClick={() => onClick(item)}\n onFocus={(event) => onFocus(item, event)}\n className=\"expanding-group-item focus-visible:outline-solid focus-visible:outline-(length:--focus-ring-width) focus-visible:outline-offset-(--focus-ring-offset) focus-visible:outline-(--color-ring)\"\n >\n <span className=\"expanding-group-icon\" aria-hidden=\"true\">\n <IconSwap iconKey={showDone ? \"done\" : \"icon\"} tight fill className=\"size-full\">\n {showDone ? <DrawnCheck /> : item.icon}\n </IconSwap>\n </span>\n {/* Outgoing and incoming words share one cell, so a confirmation crossfades in place while the width springs between them. */}\n <span className=\"expanding-group-label\" aria-hidden=\"true\">\n {leaving.map((entry) => (\n <LeavingWord key={entry.id} id={entry.id} onDone={remove}>\n {entry.value}\n </LeavingWord>\n ))}\n <span\n key={word}\n ref={wordRef}\n className={cn(\n \"col-start-1 row-start-1 whitespace-nowrap\" +\n (changed ? \" motion-safe:animate-word-in motion-reduce:animate-fade-in\" : \"\"),\n )}\n >\n {word}\n </span>\n {/* Invisible copies of both words hold the slot at the longer one; they are also what gets measured for the width target. */}\n <span\n ref={labelRef}\n className=\"pointer-events-none invisible col-start-1 row-start-1 whitespace-nowrap\"\n >\n {item.label}\n </span>\n {item.doneLabel ? (\n <span\n ref={doneRef}\n className=\"pointer-events-none invisible col-start-1 row-start-1 whitespace-nowrap\"\n >\n {item.doneLabel}\n </span>\n ) : null}\n </span>\n </button>\n );\n}\n\n/**\n * A compact pill of icon buttons for actions. One action always shows its label;\n * the one you point at or focus takes over the label while its neighbours slide\n * aside, and an action can confirm in place: the icon draws a check and the label\n * becomes a past tense word. On touch, the first tap reveals the label and a\n * second tap runs the action.\n *\n * Arrow keys move focus, Home and End jump to the ends. A disabled action stays\n * focusable and still reveals its label, so people can learn what it would do.\n *\n * @example\n * <ExpandingButtonGroup label=\"Message actions\" items={[{ id: \"archive\", label: \"Archive\", doneLabel: \"Archived\", icon: <ArchiveIcon aria-hidden /> }]} />\n */\nexport function ExpandingButtonGroup({\n items,\n label,\n size = \"md\",\n defaultExpanded = null,\n onAction,\n confirmDuration = 1400,\n className,\n}: ExpandingButtonGroupProps) {\n const root = useRef<HTMLDivElement>(null);\n const [intent, setIntent] = useState<string | null>(null);\n const [done, setDone] = useState<{ id: string; seq: number } | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n const [announcement, setAnnouncement] = useState(\"\");\n const [focused, setFocused] = useState<string | null>(null);\n // The width only transitions once the group has been painted and measured, so the first widths land at once.\n const [settled, setSettled] = useState(false);\n\n // Refs mirror what the pointer and keyboard are doing right now, so leave and blur handlers can fall back correctly.\n const pointerOver = useRef<string | null>(null);\n const pointerAt = useRef<{ x: number; y: number } | null>(null);\n const keyFocus = useRef<string | null>(null);\n const touchOpen = useRef<string | null>(null);\n const press = useRef<{ id: string; kind: string; wasExpanded: boolean } | null>(null);\n const doneRef = useRef<string | null>(null);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const mounted = useRef(true);\n const seq = useRef(0);\n\n useEffect(() => {\n mounted.current = true;\n const frames = requestAnimationFrame(() => requestAnimationFrame(() => setSettled(true)));\n return () => {\n mounted.current = false;\n cancelAnimationFrame(frames);\n if (timer.current) clearTimeout(timer.current);\n };\n }, []);\n\n const has = (id: string | null) => !!id && items.some((item) => item.id === id);\n // One action is always expanded: the resting one is defaultExpanded, else the first enabled action.\n const firstEnabled = items.find((item) => !item.isDisabled)?.id ?? items[0]?.id ?? null;\n const restId = has(defaultExpanded) ? defaultExpanded : firstEnabled;\n const expandedId = has(intent) ? intent : restId;\n const tabStop = has(focused) ? focused : restId;\n\n // A tap outside closes a label opened by a first tap.\n useEffect(() => {\n if (!intent || touchOpen.current !== intent) return;\n const onDown = (event: globalThis.PointerEvent) => {\n if (root.current?.contains(event.target as Node)) return;\n touchOpen.current = null;\n setIntent(doneRef.current ?? keyFocus.current);\n };\n document.addEventListener(\"pointerdown\", onDown, true);\n return () => document.removeEventListener(\"pointerdown\", onDown, true);\n }, [intent]);\n\n const confirm = useCallback(\n (item: ExpandingButtonGroupItem) => {\n if (timer.current) clearTimeout(timer.current);\n seq.current += 1;\n doneRef.current = item.id;\n setDone({ id: item.id, seq: seq.current });\n // A zero width space alternates so the same word is announced again on a repeat action.\n setAnnouncement((item.doneLabel ?? \"\") + (seq.current % 2 ? \"\" : \"​\"));\n timer.current = setTimeout(() => {\n doneRef.current = null;\n setDone(null);\n // Collapse unless the pointer or the keyboard is still on it.\n if (pointerOver.current !== item.id && keyFocus.current !== item.id) {\n if (touchOpen.current === item.id) touchOpen.current = null;\n setIntent((current) =>\n current === item.id ? (pointerOver.current ?? keyFocus.current) : current,\n );\n }\n }, confirmDuration);\n },\n [confirmDuration],\n );\n\n const activate = useCallback(\n async (item: ExpandingButtonGroupItem) => {\n if (item.isDisabled || busy === item.id || doneRef.current === item.id) return;\n setIntent(item.id);\n onAction?.(item.id);\n let result: void | boolean;\n try {\n const pending = item.onSelect?.();\n if (pending instanceof Promise) {\n setBusy(item.id);\n result = await pending;\n } else result = pending;\n } catch {\n result = false;\n } finally {\n if (mounted.current) setBusy((current) => (current === item.id ? null : current));\n }\n if (!mounted.current || result === false || !item.doneLabel) return;\n confirm(item);\n },\n [busy, confirm, onAction],\n );\n\n const onItemPointerDown = (\n item: ExpandingButtonGroupItem,\n event: PointerEvent<HTMLButtonElement>,\n ) => {\n press.current = { id: item.id, kind: event.pointerType, wasExpanded: expandedId === item.id };\n };\n\n const onItemClick = (item: ExpandingButtonGroupItem) => {\n const last = press.current;\n press.current = null;\n // Touch has no hover: the first tap opens the label, the second runs it. An item already showing its label runs at once.\n if (last && last.id === item.id && last.kind === \"touch\" && !last.wasExpanded) {\n touchOpen.current = item.id;\n setIntent(item.id);\n return;\n }\n if (last?.kind === \"touch\") touchOpen.current = item.id;\n void activate(item);\n };\n\n const onItemFocus = (item: ExpandingButtonGroupItem, event: FocusEvent<HTMLButtonElement>) => {\n setFocused(item.id);\n // Only keyboard focus expands; a mouse click or a tap already has its own path, and would otherwise leave the label open.\n let visible = true;\n try {\n visible = event.currentTarget.matches(\":focus-visible\");\n } catch {\n /* older engines expand on any focus */\n }\n if (!visible) return;\n keyFocus.current = item.id;\n setIntent(item.id);\n };\n\n const onBlur = (event: FocusEvent<HTMLDivElement>) => {\n if (root.current?.contains(event.relatedTarget)) return;\n keyFocus.current = null;\n touchOpen.current = null;\n setIntent(pointerOver.current ?? doneRef.current);\n };\n\n // Hover follows real pointer movement only. Expanding moves the buttons, and a button that slides under a resting pointer\n // must not take over, or two neighbours could trade places back and forth.\n const onPointerMove = (event: PointerEvent<HTMLDivElement>) => {\n if (event.pointerType !== \"mouse\") return;\n const at = pointerAt.current;\n if (at && Math.abs(at.x - event.clientX) < 1 && Math.abs(at.y - event.clientY) < 1) return;\n pointerAt.current = { x: event.clientX, y: event.clientY };\n const button = (event.target as HTMLElement).closest<HTMLElement>(\"[data-ebg-item]\");\n const id = button?.dataset.id;\n if (!button || !id || id === pointerOver.current) return;\n // Hysteresis: moving from one action to the next needs the pointer a few pixels inside the new one, so resting on a\n // boundary never flips between them.\n if (pointerOver.current) {\n const box = button.getBoundingClientRect();\n if (event.clientX < box.left + hysteresis || event.clientX > box.right - hysteresis) return;\n }\n pointerOver.current = id;\n setIntent(id);\n };\n\n const onPointerLeave = (event: PointerEvent<HTMLDivElement>) => {\n if (event.pointerType !== \"mouse\") return;\n pointerAt.current = null;\n pointerOver.current = null;\n setIntent(doneRef.current ?? keyFocus.current);\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const list = Array.from(\n root.current?.querySelectorAll<HTMLButtonElement>(\"[data-ebg-item]\") ?? [],\n );\n const index = list.findIndex((button) => button === document.activeElement);\n if (index < 0) return;\n const last = list.length - 1;\n const target =\n event.key === \"ArrowRight\"\n ? index === last\n ? 0\n : index + 1\n : event.key === \"ArrowLeft\"\n ? index === 0\n ? last\n : index - 1\n : event.key === \"Home\"\n ? 0\n : event.key === \"End\"\n ? last\n : -1;\n if (target < 0) return;\n event.preventDefault();\n list[target]!.focus();\n };\n\n const m = metrics[size];\n const vars = {\n \"--ebg-h\": m.height + \"px\",\n \"--ebg-icon\": m.icon + \"px\",\n \"--ebg-start\": m.start + \"px\",\n \"--ebg-gap\": m.gap + \"px\",\n \"--ebg-end\": m.end + \"px\",\n } as CSSProperties;\n\n return (\n <div\n ref={root}\n role=\"toolbar\"\n aria-label={label}\n aria-orientation=\"horizontal\"\n data-size={size}\n data-settled={settled ? \"\" : undefined}\n style={vars}\n onKeyDown={onKeyDown}\n onBlur={onBlur}\n onPointerMove={onPointerMove}\n onPointerLeave={onPointerLeave}\n className={cn(\"expanding-group\", className)}\n >\n {items.map((item) => (\n <Item\n key={item.id}\n item={item}\n size={size}\n expanded={expandedId === item.id}\n done={done?.id === item.id}\n busy={busy === item.id}\n tabStop={tabStop === item.id}\n onPointerDown={onItemPointerDown}\n onClick={onItemClick}\n onFocus={onItemFocus}\n />\n ))}\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\">\n {announcement}\n </span>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { ExpandingButtonGroup, ExpandingButtonGroupItem, ExpandingButtonGroupProps, ExpandingButtonGroupSize, ExpandingButtonGroupTone } from "./expanding-button-group.js";
2
+ export { ExpandingButtonGroup, type ExpandingButtonGroupItem, type ExpandingButtonGroupProps, type ExpandingButtonGroupSize, type ExpandingButtonGroupTone };
@@ -0,0 +1,2 @@
1
+ import { ExpandingButtonGroup } from "./expanding-button-group.js";
2
+ export { ExpandingButtonGroup };
@@ -0,0 +1,71 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/file-drop-zone/file-drop-zone.d.ts
3
+ /**
4
+ * FileDropZone: a dashed area a file can be dropped on, with a "Choose file"
5
+ * button that opens the system's file dialog.
6
+ *
7
+ * Built on React Aria's `DropZone` and `FileTrigger`. The browser's own
8
+ * `<input type="file">` ("Choose Files / No file chosen") is never shown: its
9
+ * look differs on every browser and it cannot be styled. FileTrigger keeps a
10
+ * real file input, visually hidden and out of the Tab order, and opens it when
11
+ * the button is pressed, so the keyboard path is Tab to the button, then Enter
12
+ * or Space.
13
+ *
14
+ * The zone states what it takes before a file is chosen: `hint` is where the
15
+ * accepted types and the size limit go.
16
+ *
17
+ * Every string in the cva blocks below is a STATIC literal. Tailwind scans
18
+ * source text, so a class assembled at runtime is invisible to it and would
19
+ * simply never be emitted.
20
+ */
21
+ export declare const fileDropZoneVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
22
+ export declare const fileDropZonePromptVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
23
+ export declare const fileDropZoneHintVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
24
+ /**
25
+ * A place to drop or choose files.
26
+ *
27
+ * @example
28
+ * <FileDropZone
29
+ * label="Contract"
30
+ * prompt="Drop a contract here"
31
+ * hint="PDF only, up to 20 MB."
32
+ * acceptedFileTypes={["application/pdf"]}
33
+ * onFiles={(files) => upload(files[0])}
34
+ * />
35
+ */
36
+ export interface FileDropZoneProps {
37
+ /** What the file is. The drop zone's accessible name. */
38
+ label: string;
39
+ /** The zone's main line: what to drop here, or the chosen file's name. */
40
+ prompt: ReactNode;
41
+ /**
42
+ * What the prompt says while a file is over the zone. When it is given the
43
+ * prompt swaps to it (the new text rises in, the old lifts away) and back again.
44
+ */
45
+ dropPrompt?: ReactNode;
46
+ /** The types and size accepted, and anything else to know before choosing. */
47
+ hint?: ReactNode;
48
+ /**
49
+ * MIME types or extensions the file dialog offers, as for a native
50
+ * `accept`. A drop is not filtered: what was dropped is handed over and the
51
+ * consumer decides what it can read.
52
+ */
53
+ acceptedFileTypes?: string[];
54
+ /** Take several files at once. Otherwise only the first is handed over. */
55
+ allowsMultiple?: boolean;
56
+ /** Called with the chosen or dropped files. */
57
+ onFiles: (files: File[]) => void;
58
+ /**
59
+ * The button's text.
60
+ *
61
+ * @default "Choose file", or "Choose files" with `allowsMultiple`
62
+ */
63
+ buttonLabel?: string;
64
+ /** Take no file: the button is disabled and a drop is refused. */
65
+ isDisabled?: boolean;
66
+ /** Extra classes for the zone. Merged last, so they win conflicts with ours. */
67
+ className?: string;
68
+ }
69
+ export declare const FileDropZone: import("react").ForwardRefExoticComponent<FileDropZoneProps & import("react").RefAttributes<HTMLDivElement>>;
70
+ //#endregion
71
+ //# sourceMappingURL=file-drop-zone.d.ts.map
@@ -0,0 +1,116 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { mergeRefs } from "../lib/merge-refs.js";
4
+ import { Button as Button$1 } from "../button/button.js";
5
+ import { SwapText } from "../lib/swap-text.js";
6
+ import { cva } from "class-variance-authority";
7
+ import { forwardRef, useMemo, useRef } from "react";
8
+ import { DropZone, FileTrigger } from "react-aria-components";
9
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
+ //#region src/file-drop-zone/file-drop-zone.tsx
11
+ /**
12
+ * FileDropZone: a dashed area a file can be dropped on, with a "Choose file"
13
+ * button that opens the system's file dialog.
14
+ *
15
+ * Built on React Aria's `DropZone` and `FileTrigger`. The browser's own
16
+ * `<input type="file">` ("Choose Files / No file chosen") is never shown: its
17
+ * look differs on every browser and it cannot be styled. FileTrigger keeps a
18
+ * real file input, visually hidden and out of the Tab order, and opens it when
19
+ * the button is pressed, so the keyboard path is Tab to the button, then Enter
20
+ * or Space.
21
+ *
22
+ * The zone states what it takes before a file is chosen: `hint` is where the
23
+ * accepted types and the size limit go.
24
+ *
25
+ * Every string in the cva blocks below is a STATIC literal. Tailwind scans
26
+ * source text, so a class assembled at runtime is invisible to it and would
27
+ * simply never be emitted.
28
+ */
29
+ const fileDropZoneVariants = cva([
30
+ "flex flex-col items-center gap-2 px-4 py-8 text-center",
31
+ "rounded-panel border-(length:--border-width) border-dashed border-border",
32
+ "box-border font-sans text-foreground",
33
+ "outline-none",
34
+ "drop-zone-motion",
35
+ "data-[hovered]:bg-muted",
36
+ "data-[drop-target]:border-primary data-[drop-target]:bg-muted",
37
+ "data-[focus-visible]:outline-solid",
38
+ "data-[focus-visible]:outline-(length:--focus-ring-width)",
39
+ "data-[focus-visible]:outline-offset-(--focus-ring-offset)",
40
+ "data-[focus-visible]:outline-(--color-ring)",
41
+ "data-[disabled]:cursor-not-allowed"
42
+ ]);
43
+ const fileDropZonePromptVariants = cva("m-0 text-sm leading-(--leading-normal)");
44
+ const fileDropZoneHintVariants = cva("m-0 text-xs leading-(--leading-normal) text-muted-foreground");
45
+ async function filesOf(event) {
46
+ const items = event.items.filter((item) => item.kind === "file");
47
+ return Promise.all(items.map((item) => item.getFile()));
48
+ }
49
+ const FileDropZone = forwardRef(function FileDropZone({ label, prompt, dropPrompt, hint, acceptedFileTypes, allowsMultiple = false, onFiles, buttonLabel, isDisabled = false, className }, ref) {
50
+ const hand = (files) => {
51
+ if (isDisabled || files.length === 0) return;
52
+ onFiles(allowsMultiple ? files : files.slice(0, 1));
53
+ };
54
+ const zone = useRef(null);
55
+ const refs = useMemo(() => mergeRefs(ref, zone), [ref]);
56
+ const lean = (x, y) => {
57
+ const el = zone.current;
58
+ if (!el) return;
59
+ el.style.setProperty("--drop-x", `${x / Math.max(1, el.offsetWidth) * 100}%`);
60
+ el.style.setProperty("--drop-y", `${y / Math.max(1, el.offsetHeight) * 100}%`);
61
+ };
62
+ return /* @__PURE__ */ jsx(DropZone, {
63
+ ref: refs,
64
+ "aria-label": label,
65
+ "data-slot": "file-drop-zone",
66
+ isDisabled,
67
+ className: cn(fileDropZoneVariants(), className),
68
+ onDropEnter: (event) => lean(event.x, event.y),
69
+ onDropMove: (event) => lean(event.x, event.y),
70
+ onDrop: (event) => {
71
+ filesOf(event).then(hand);
72
+ },
73
+ children: ({ isDropTarget }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
74
+ /* @__PURE__ */ jsx("span", {
75
+ "aria-hidden": "true",
76
+ "data-slot": "file-drop-zone-wash",
77
+ className: "drop-wash"
78
+ }),
79
+ /* @__PURE__ */ jsx("span", {
80
+ "aria-hidden": "true",
81
+ "data-slot": "file-drop-zone-glow",
82
+ className: "drop-glow"
83
+ }),
84
+ /* @__PURE__ */ jsx("p", {
85
+ "data-slot": "file-drop-zone-prompt",
86
+ className: cn(fileDropZonePromptVariants(), "relative"),
87
+ children: dropPrompt == null ? prompt : /* @__PURE__ */ jsx(SwapText, {
88
+ swapKey: isDropTarget ? "drop" : "prompt",
89
+ className: "block",
90
+ children: isDropTarget ? dropPrompt : prompt
91
+ })
92
+ }),
93
+ /* @__PURE__ */ jsx(FileTrigger, {
94
+ acceptedFileTypes,
95
+ allowsMultiple,
96
+ onSelect: (list) => hand(Array.from(list ?? [])),
97
+ children: /* @__PURE__ */ jsx(Button$1, {
98
+ variant: "outlineNeutral",
99
+ size: "sm",
100
+ isDisabled,
101
+ className: "relative",
102
+ children: buttonLabel ?? (allowsMultiple ? "Choose files" : "Choose file")
103
+ })
104
+ }),
105
+ hint == null ? null : /* @__PURE__ */ jsx("p", {
106
+ "data-slot": "file-drop-zone-hint",
107
+ className: cn(fileDropZoneHintVariants(), "relative"),
108
+ children: hint
109
+ })
110
+ ] })
111
+ });
112
+ });
113
+ //#endregion
114
+ export { FileDropZone, fileDropZoneHintVariants, fileDropZonePromptVariants, fileDropZoneVariants };
115
+
116
+ //# sourceMappingURL=file-drop-zone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-drop-zone.js","names":["AriaDropZone","AriaFileTrigger","Button"],"sources":["../../src/file-drop-zone/file-drop-zone.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport { forwardRef, useMemo, useRef, type ReactNode } from \"react\";\nimport {\n DropZone as AriaDropZone,\n FileTrigger as AriaFileTrigger,\n type DropZoneProps as AriaDropZoneProps,\n type FileDropItem,\n} from \"react-aria-components\";\n\nimport { Button } from \"../button/button.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { mergeRefs } from \"../lib/merge-refs.js\";\nimport { SwapText } from \"../lib/swap-text.js\";\n\n/**\n * FileDropZone: a dashed area a file can be dropped on, with a \"Choose file\"\n * button that opens the system's file dialog.\n *\n * Built on React Aria's `DropZone` and `FileTrigger`. The browser's own\n * `<input type=\"file\">` (\"Choose Files / No file chosen\") is never shown: its\n * look differs on every browser and it cannot be styled. FileTrigger keeps a\n * real file input, visually hidden and out of the Tab order, and opens it when\n * the button is pressed, so the keyboard path is Tab to the button, then Enter\n * or Space.\n *\n * The zone states what it takes before a file is chosen: `hint` is where the\n * accepted types and the size limit go.\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 */\nexport const fileDropZoneVariants = cva([\n \"flex flex-col items-center gap-2 px-4 py-8 text-center\",\n \"rounded-panel border-(length:--border-width) border-dashed border-border\",\n // The reset in @seekalfred/styles is opt-in, so a consumer may load none.\n \"box-border font-sans text-foreground\",\n \"outline-none\",\n // Fill and edge ease, a file over it breathes and light follows the pointer (see drop-zone-motion).\n \"drop-zone-motion\",\n \"data-[hovered]:bg-muted\",\n \"data-[drop-target]:border-primary data-[drop-target]:bg-muted\",\n \"data-[focus-visible]:outline-solid\",\n \"data-[focus-visible]:outline-(length:--focus-ring-width)\",\n \"data-[focus-visible]:outline-offset-(--focus-ring-offset)\",\n \"data-[focus-visible]:outline-(--color-ring)\",\n // Disabled dims only the button (its own disabled look). Dimming the whole\n // zone took the prompt and hint below the 4.5:1 contrast floor.\n \"data-[disabled]:cursor-not-allowed\",\n]);\n\nexport const fileDropZonePromptVariants = cva(\"m-0 text-sm leading-(--leading-normal)\");\n\nexport const fileDropZoneHintVariants = cva(\n \"m-0 text-xs leading-(--leading-normal) text-muted-foreground\",\n);\n\n/**\n * A place to drop or choose files.\n *\n * @example\n * <FileDropZone\n * label=\"Contract\"\n * prompt=\"Drop a contract here\"\n * hint=\"PDF only, up to 20 MB.\"\n * acceptedFileTypes={[\"application/pdf\"]}\n * onFiles={(files) => upload(files[0])}\n * />\n */\nexport interface FileDropZoneProps {\n /** What the file is. The drop zone's accessible name. */\n label: string;\n /** The zone's main line: what to drop here, or the chosen file's name. */\n prompt: ReactNode;\n /**\n * What the prompt says while a file is over the zone. When it is given the\n * prompt swaps to it (the new text rises in, the old lifts away) and back again.\n */\n dropPrompt?: ReactNode;\n /** The types and size accepted, and anything else to know before choosing. */\n hint?: ReactNode;\n /**\n * MIME types or extensions the file dialog offers, as for a native\n * `accept`. A drop is not filtered: what was dropped is handed over and the\n * consumer decides what it can read.\n */\n acceptedFileTypes?: string[];\n /** Take several files at once. Otherwise only the first is handed over. */\n allowsMultiple?: boolean;\n /** Called with the chosen or dropped files. */\n onFiles: (files: File[]) => void;\n /**\n * The button's text.\n *\n * @default \"Choose file\", or \"Choose files\" with `allowsMultiple`\n */\n buttonLabel?: string;\n /** Take no file: the button is disabled and a drop is refused. */\n isDisabled?: boolean;\n /** Extra classes for the zone. Merged last, so they win conflicts with ours. */\n className?: string;\n}\n\ntype DropEvent = Parameters<NonNullable<AriaDropZoneProps[\"onDrop\"]>>[0];\n\nasync function filesOf(event: DropEvent): Promise<File[]> {\n const items = event.items.filter((item): item is FileDropItem => item.kind === \"file\");\n return Promise.all(items.map((item) => item.getFile()));\n}\n\nexport const FileDropZone = forwardRef<HTMLDivElement, FileDropZoneProps>(function FileDropZone(\n {\n label,\n prompt,\n dropPrompt,\n hint,\n acceptedFileTypes,\n allowsMultiple = false,\n onFiles,\n buttonLabel,\n isDisabled = false,\n className,\n },\n ref,\n) {\n const hand = (files: File[]) => {\n if (isDisabled || files.length === 0) return;\n onFiles(allowsMultiple ? files : files.slice(0, 1));\n };\n const zone = useRef<HTMLDivElement | null>(null);\n const refs = useMemo(() => mergeRefs(ref, zone), [ref]);\n // Where the file is over the zone, as percentages, for the light that follows it.\n const lean = (x: number, y: number) => {\n const el = zone.current;\n if (!el) return;\n el.style.setProperty(\"--drop-x\", `${(x / Math.max(1, el.offsetWidth)) * 100}%`);\n el.style.setProperty(\"--drop-y\", `${(y / Math.max(1, el.offsetHeight)) * 100}%`);\n };\n return (\n <AriaDropZone\n ref={refs}\n aria-label={label}\n data-slot=\"file-drop-zone\"\n isDisabled={isDisabled}\n className={cn(fileDropZoneVariants(), className)}\n onDropEnter={(event) => lean(event.x, event.y)}\n onDropMove={(event) => lean(event.x, event.y)}\n onDrop={(event) => {\n void filesOf(event).then(hand);\n }}\n >\n {({ isDropTarget }) => (\n <>\n {/* The wash and the edge light sit under the content and follow the file. */}\n <span aria-hidden=\"true\" data-slot=\"file-drop-zone-wash\" className=\"drop-wash\" />\n <span aria-hidden=\"true\" data-slot=\"file-drop-zone-glow\" className=\"drop-glow\" />\n <p data-slot=\"file-drop-zone-prompt\" className={cn(fileDropZonePromptVariants(), \"relative\")}>\n {dropPrompt == null ? (\n prompt\n ) : (\n <SwapText swapKey={isDropTarget ? \"drop\" : \"prompt\"} className=\"block\">\n {isDropTarget ? dropPrompt : prompt}\n </SwapText>\n )}\n </p>\n <AriaFileTrigger\n acceptedFileTypes={acceptedFileTypes}\n allowsMultiple={allowsMultiple}\n onSelect={(list) => hand(Array.from(list ?? []))}\n >\n <Button variant=\"outlineNeutral\" size=\"sm\" isDisabled={isDisabled} className=\"relative\">\n {buttonLabel ?? (allowsMultiple ? \"Choose files\" : \"Choose file\")}\n </Button>\n </AriaFileTrigger>\n {hint == null ? null : (\n <p\n data-slot=\"file-drop-zone-hint\"\n className={cn(fileDropZoneHintVariants(), \"relative\")}\n >\n {hint}\n </p>\n )}\n </>\n )}\n </AriaDropZone>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,MAAa,uBAAuB,IAAI;CACtC;CACA;CAEA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;AACF,CAAC;AAED,MAAa,6BAA6B,IAAI,wCAAwC;AAEtF,MAAa,2BAA2B,IACtC,8DACF;AAkDA,eAAe,QAAQ,OAAmC;CACxD,MAAM,QAAQ,MAAM,MAAM,QAAQ,SAA+B,KAAK,SAAS,MAAM;CACrF,OAAO,QAAQ,IAAI,MAAM,KAAK,SAAS,KAAK,QAAQ,CAAC,CAAC;AACxD;AAEA,MAAa,eAAe,WAA8C,SAAS,aACjF,EACE,OACA,QACA,YACA,MACA,mBACA,iBAAiB,OACjB,SACA,aACA,aAAa,OACb,aAEF,KACA;CACA,MAAM,QAAQ,UAAkB;EAC9B,IAAI,cAAc,MAAM,WAAW,GAAG;EACtC,QAAQ,iBAAiB,QAAQ,MAAM,MAAM,GAAG,CAAC,CAAC;CACpD;CACA,MAAM,OAAO,OAA8B,IAAI;CAC/C,MAAM,OAAO,cAAc,UAAU,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC;CAEtD,MAAM,QAAQ,GAAW,MAAc;EACrC,MAAM,KAAK,KAAK;EAChB,IAAI,CAAC,IAAI;EACT,GAAG,MAAM,YAAY,YAAY,GAAI,IAAI,KAAK,IAAI,GAAG,GAAG,WAAW,IAAK,IAAI,EAAE;EAC9E,GAAG,MAAM,YAAY,YAAY,GAAI,IAAI,KAAK,IAAI,GAAG,GAAG,YAAY,IAAK,IAAI,EAAE;CACjF;CACA,OACE,oBAACA,UAAD;EACE,KAAK;EACL,cAAY;EACZ,aAAU;EACE;EACZ,WAAW,GAAG,qBAAqB,GAAG,SAAS;EAC/C,cAAc,UAAU,KAAK,MAAM,GAAG,MAAM,CAAC;EAC7C,aAAa,UAAU,KAAK,MAAM,GAAG,MAAM,CAAC;EAC5C,SAAS,UAAU;GACjB,QAAa,KAAK,CAAC,CAAC,KAAK,IAAI;EAC/B;EAEE,WAAA,EAAE,mBACF,qBAAA,YAAA,EAAA,UAAA;GAEE,oBAAC,QAAD;IAAM,eAAY;IAAO,aAAU;IAAsB,WAAU;GAAa,CAAA;GAChF,oBAAC,QAAD;IAAM,eAAY;IAAO,aAAU;IAAsB,WAAU;GAAa,CAAA;GAChF,oBAAC,KAAD;IAAG,aAAU;IAAwB,WAAW,GAAG,2BAA2B,GAAG,UAAU;IACxF,UAAA,cAAc,OACb,SAEA,oBAAC,UAAD;KAAU,SAAS,eAAe,SAAS;KAAU,WAAU;KAC5D,UAAA,eAAe,aAAa;IACrB,CAAA;GAEX,CAAA;GACH,oBAACC,aAAD;IACqB;IACH;IAChB,WAAW,SAAS,KAAK,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC;IAE/C,UAAA,oBAACC,UAAD;KAAQ,SAAQ;KAAiB,MAAK;KAAiB;KAAY,WAAU;KAC1E,UAAA,gBAAgB,iBAAiB,iBAAiB;IAC7C,CAAA;GACO,CAAA;GAChB,QAAQ,OAAO,OACd,oBAAC,KAAD;IACE,aAAU;IACV,WAAW,GAAG,yBAAyB,GAAG,UAAU;IAEnD,UAAA;GACA,CAAA;EAEL,EAAA,CAAA;CAEQ,CAAA;AAElB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { FileDropZone, FileDropZoneProps, fileDropZoneHintVariants, fileDropZonePromptVariants, fileDropZoneVariants } from "./file-drop-zone.js";
2
+ export { FileDropZone, type FileDropZoneProps, fileDropZoneHintVariants, fileDropZonePromptVariants, fileDropZoneVariants };
@@ -0,0 +1,2 @@
1
+ import { FileDropZone, fileDropZoneHintVariants, fileDropZonePromptVariants, fileDropZoneVariants } from "./file-drop-zone.js";
2
+ export { FileDropZone, fileDropZoneHintVariants, fileDropZonePromptVariants, fileDropZoneVariants };