@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
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
+ import { useExitBackstop } from "../lib/motion.js";
3
4
  import { cva } from "class-variance-authority";
4
- import { forwardRef } from "react";
5
+ import { forwardRef, useCallback, useState } from "react";
5
6
  import { Button, Text, UNSTABLE_Toast, UNSTABLE_ToastContent, UNSTABLE_ToastQueue, UNSTABLE_ToastRegion } from "react-aria-components";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
7
8
  //#region src/toast/toast.tsx
@@ -43,23 +44,43 @@ const toastRegionVariants = cva([
43
44
  ]);
44
45
  const toastVariants = cva([
45
46
  "flex items-start gap-3 box-border w-full",
46
- "rounded-md border-(length:--border-width) p-(--density-bar-pad-x)",
47
- "font-sans shadow-surface",
48
- "motion-safe:transition-opacity motion-safe:duration-(--duration-fast) motion-safe:ease-standard",
49
- "data-[animation=exiting]:opacity-0"
47
+ "rounded-panel border-(length:--border-width) border-border bg-surface text-foreground",
48
+ "py-3.5 ps-4 pe-3.5 font-sans shadow-floating",
49
+ "motion-safe:animate-toast-in motion-reduce:animate-fade-in",
50
+ "motion-safe:data-[closing]:animate-toast-out motion-reduce:data-[closing]:animate-fade-out"
50
51
  ], {
51
52
  variants: { tone: {
52
- neutral: "bg-background border-separator text-foreground",
53
- success: "bg-success-subtle border-success-strong text-success-foreground",
54
- warning: "bg-warning-subtle border-warning-strong text-warning-foreground",
55
- danger: "bg-destructive-subtle border-destructive-strong text-destructive-subtle-foreground",
56
- info: "bg-info-subtle border-info-strong text-info-foreground"
53
+ neutral: "",
54
+ success: "",
55
+ warning: "",
56
+ danger: "",
57
+ info: ""
57
58
  } },
58
59
  defaultVariants: { tone: "neutral" }
59
60
  });
61
+ /** The status icon's circle: the tone's light fill with its AA text colour. */
62
+ const toastIconVariants = cva("mt-px grid size-7.5 shrink-0 place-items-center rounded-circle [&_svg]:size-4", {
63
+ variants: { tone: {
64
+ neutral: "bg-muted text-text-secondary",
65
+ success: "bg-success-subtle text-success-foreground",
66
+ warning: "bg-warning-subtle text-warning-foreground",
67
+ danger: "bg-destructive-subtle text-destructive-subtle-foreground",
68
+ info: "bg-info-subtle text-info-foreground"
69
+ } },
70
+ defaultVariants: { tone: "neutral" }
71
+ });
72
+ const TONE_ICON_PATHS = {
73
+ neutral: "M6 16v-5a6 6 0 1 1 12 0v5l1.5 2h-15zM10 20.5a2 2 0 0 0 4 0",
74
+ success: "M4 12.5l5 5L20 6.5",
75
+ warning: "M12 7v6.5M12 17.25h.01",
76
+ danger: "M7 7l10 10M17 7L7 17",
77
+ info: "M12 11v6M12 7.25h.01"
78
+ };
60
79
  const toastCloseVariants = cva([
61
- "ms-auto shrink-0 rounded-sm cursor-pointer",
62
- "text-current opacity-70 data-[hovered]:opacity-100",
80
+ "-mt-px -me-0.5 ms-auto grid size-8 shrink-0 place-items-center rounded-circle cursor-pointer",
81
+ "border-0 bg-transparent p-0 text-text-secondary",
82
+ "data-[hovered]:bg-muted data-[hovered]:text-foreground",
83
+ "toast-close",
63
84
  "outline-none",
64
85
  "data-[focus-visible]:outline-solid",
65
86
  "data-[focus-visible]:outline-(length:--focus-ring-width)",
@@ -91,42 +112,64 @@ function toast(content, timeout = 5e3) {
91
112
  return toastQueue.add(content, timeout === 0 ? void 0 : { timeout });
92
113
  }
93
114
  /**
94
- * Renders the queue. Mount ONCE, near the root.
95
- *
96
- * React Aria only renders the landmark while something is queued, so this
97
- * costs nothing on a quiet screen.
115
+ * One toast. Pressing its close control plays the exit first, then closes it in the
116
+ * queue; React Aria unmounts a closed toast at once and has no exit of its own, so a
117
+ * toast closed any other way (the timeout, `toastQueue.close`) leaves without one.
98
118
  */
99
- const ToastRegion = forwardRef(function ToastRegion({ label, closeLabel = "Dismiss", className }, ref) {
100
- return /* @__PURE__ */ jsx(UNSTABLE_ToastRegion, {
101
- ref,
102
- queue: toastQueue,
103
- "aria-label": label,
104
- "data-slot": "toast-region",
105
- className: cn(toastRegionVariants(), className),
106
- children: ({ toast: queued }) => /* @__PURE__ */ jsxs(UNSTABLE_Toast, {
107
- toast: queued,
108
- "data-slot": "toast",
109
- "data-tone": queued.content.tone ?? "neutral",
110
- className: toastVariants({ tone: queued.content.tone }),
111
- children: [/* @__PURE__ */ jsxs(UNSTABLE_ToastContent, {
119
+ function ToastItem({ queued, closeLabel }) {
120
+ const [closing, setClosing] = useState(false);
121
+ const tone = queued.content.tone ?? "neutral";
122
+ const finish = useCallback(() => toastQueue.close(queued.key), [queued.key]);
123
+ useExitBackstop(closing, finish);
124
+ return /* @__PURE__ */ jsxs(UNSTABLE_Toast, {
125
+ toast: queued,
126
+ "data-slot": "toast",
127
+ "data-tone": tone,
128
+ "data-closing": closing || void 0,
129
+ onAnimationEnd: (event) => {
130
+ if (closing && event.target === event.currentTarget) finish();
131
+ },
132
+ className: toastVariants({ tone }),
133
+ children: [
134
+ /* @__PURE__ */ jsx("span", {
135
+ "data-slot": "toast-icon",
136
+ "data-tone": tone,
137
+ "aria-hidden": "true",
138
+ className: toastIconVariants({ tone }),
139
+ children: queued.content.icon ?? /* @__PURE__ */ jsx("svg", {
140
+ viewBox: "0 0 24 24",
141
+ fill: "none",
142
+ stroke: "currentColor",
143
+ strokeWidth: "2.25",
144
+ strokeLinecap: "round",
145
+ strokeLinejoin: "round",
146
+ children: /* @__PURE__ */ jsx("path", {
147
+ d: TONE_ICON_PATHS[tone],
148
+ pathLength: 1,
149
+ className: tone === "success" ? "toast-check" : void 0
150
+ })
151
+ })
152
+ }),
153
+ /* @__PURE__ */ jsxs(UNSTABLE_ToastContent, {
112
154
  "data-slot": "toast-content",
113
- className: "flex min-w-0 flex-col gap-1",
155
+ className: "flex min-w-0 flex-1 flex-col gap-0.5 pt-1.25",
114
156
  children: [/* @__PURE__ */ jsx(Text, {
115
157
  slot: "title",
116
158
  "data-slot": "toast-title",
117
- className: "text-sm leading-(--leading-snug) font-medium",
159
+ className: "text-sm leading-(--leading-normal) font-medium text-foreground",
118
160
  children: queued.content.title
119
161
  }), queued.content.description == null ? null : /* @__PURE__ */ jsx(Text, {
120
162
  slot: "description",
121
163
  "data-slot": "toast-description",
122
- className: "text-sm leading-(--leading-normal) opacity-90",
164
+ className: "text-sm leading-(--leading-normal) text-text-secondary",
123
165
  children: queued.content.description
124
166
  })]
125
- }), /* @__PURE__ */ jsx(Button, {
126
- slot: "close",
167
+ }),
168
+ /* @__PURE__ */ jsx(Button, {
127
169
  "aria-label": closeLabel,
128
170
  "data-slot": "toast-close",
129
171
  className: toastCloseVariants(),
172
+ onPress: () => setClosing(true),
130
173
  children: /* @__PURE__ */ jsx("svg", {
131
174
  "aria-hidden": "true",
132
175
  viewBox: "0 0 16 16",
@@ -137,11 +180,30 @@ const ToastRegion = forwardRef(function ToastRegion({ label, closeLabel = "Dismi
137
180
  className: "size-(--icon-sm)",
138
181
  children: /* @__PURE__ */ jsx("path", { d: "m4 4 8 8M12 4l-8 8" })
139
182
  })
140
- })]
183
+ })
184
+ ]
185
+ });
186
+ }
187
+ /**
188
+ * Renders the queue. Mount ONCE, near the root.
189
+ *
190
+ * React Aria only renders the landmark while something is queued, so this
191
+ * costs nothing on a quiet screen.
192
+ */
193
+ const ToastRegion = forwardRef(function ToastRegion({ label, closeLabel = "Dismiss", className }, ref) {
194
+ return /* @__PURE__ */ jsx(UNSTABLE_ToastRegion, {
195
+ ref,
196
+ queue: toastQueue,
197
+ "aria-label": label,
198
+ "data-slot": "toast-region",
199
+ className: cn(toastRegionVariants(), className),
200
+ children: ({ toast: queued }) => /* @__PURE__ */ jsx(ToastItem, {
201
+ queued,
202
+ closeLabel
141
203
  })
142
204
  });
143
205
  });
144
206
  //#endregion
145
- export { ToastRegion, toast, toastCloseVariants, toastQueue, toastRegionVariants, toastVariants };
207
+ export { ToastRegion, toast, toastCloseVariants, toastIconVariants, toastQueue, toastRegionVariants, toastVariants };
146
208
 
147
209
  //# sourceMappingURL=toast.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toast.js","names":["AriaToastQueue","AriaToastRegion","AriaToast","AriaToastContent","AriaText","AriaButton"],"sources":["../../src/toast/toast.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport {\n Button as AriaButton,\n Text as AriaText,\n UNSTABLE_Toast as AriaToast,\n UNSTABLE_ToastContent as AriaToastContent,\n UNSTABLE_ToastQueue as AriaToastQueue,\n UNSTABLE_ToastRegion as AriaToastRegion,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\n\n/**\n * Toast: a transient message, announced without stealing focus.\n *\n * Maturity: **experimental**, and the reason is upstream rather than here.\n * React Aria ships this API as `UNSTABLE_Toast*` in 1.21.1, so a RAC minor\n * bump can rename or reshape it. The alternative was hand-rolling the live\n * region, the queue, the timers and the focus behaviour, which is how every\n * toast implementation acquires its accessibility bugs -- so this takes the\n * upstream one and labels the risk instead of hiding it.\n *\n * THE PRODUCT HAS 30 FILES CALLING `useToast` AND 67 `toast(...)` CALLS, and\n * its implementation is the shadcn reducer with both of its known defects\n * still in place:\n *\n * TOAST_LIMIT = 1 -- a second toast REPLACES the first, so a\n * burst of results shows only the last one.\n * TOAST_REMOVE_DELAY = 1e6 -- sixteen minutes. Nothing auto-dismisses;\n * every toast waits to be closed by hand.\n *\n * Neither is ported. `maxVisibleToasts` defaults to 3 and `timeout` to 5s,\n * which is the WCAG 2.2.1 floor React Aria enforces -- it REFUSES a timeout\n * under 5000ms, because a message that vanishes faster cannot be read by\n * someone using a screen magnifier.\n *\n * The queue is a module singleton on purpose. The product's `toast()` is\n * importable from anywhere and called from API error handlers and effects\n * that have no component to hang a hook off, and a context-based queue would\n * have made those 67 call sites into 67 refactors.\n */\n\n/** Where the region sits. Fixed, above everything, out of the way of content. */\nexport const toastRegionVariants = cva([\n \"fixed z-50 flex flex-col gap-2 box-border\",\n // Logical insets so the stack follows the writing direction.\n \"bottom-(--density-bar-pad-y) end-(--density-bar-pad-x)\",\n \"w-[min(24rem,calc(100vw-2rem))]\",\n \"outline-none\",\n]);\n\nexport const toastVariants = cva(\n [\n \"flex items-start gap-3 box-border w-full\",\n \"rounded-md border-(length:--border-width) p-(--density-bar-pad-x)\",\n \"font-sans shadow-surface\",\n \"motion-safe:transition-opacity motion-safe:duration-(--duration-fast) motion-safe:ease-standard\",\n // Not colour alone: an exiting toast fades AND the region reflows.\n \"data-[animation=exiting]:opacity-0\",\n ],\n {\n variants: {\n /*\n * The same vocabulary as Badge, deliberately. The product's toast had\n * `default` and `destructive` only, so 38 of its 67 calls pass a variant\n * that cannot say \"this worked\" -- and a save confirmation styled\n * identically to a failure is the most common thing a toast gets wrong.\n */\n tone: {\n neutral: \"bg-background border-separator text-foreground\",\n success: \"bg-success-subtle border-success-strong text-success-foreground\",\n warning: \"bg-warning-subtle border-warning-strong text-warning-foreground\",\n danger:\n \"bg-destructive-subtle border-destructive-strong text-destructive-subtle-foreground\",\n info: \"bg-info-subtle border-info-strong text-info-foreground\",\n },\n },\n defaultVariants: { tone: \"neutral\" },\n },\n);\n\nexport const toastCloseVariants = cva([\n \"ms-auto shrink-0 rounded-sm cursor-pointer\",\n \"text-current opacity-70 data-[hovered]:opacity-100\",\n \"outline-none\",\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]);\n\n/** What a toast carries. `title` is required: an unnamed toast announces nothing. */\nexport interface ToastContent extends VariantProps<typeof toastVariants> {\n /** The message. Required -- a toast with only a description announces as loose text. */\n title: ReactNode;\n /** Secondary detail, beneath the title. */\n description?: ReactNode;\n}\n\n/**\n * The queue every `toast()` call feeds.\n *\n * Exported so a consumer can read `visibleToasts` in a test, or dismiss them\n * on a route change -- there is no `clear()` upstream, so that is\n * `[...toastQueue.visibleToasts].forEach((t) => toastQueue.close(t.key))`.\n * Not something to touch in normal use.\n */\nexport const toastQueue = new AriaToastQueue<ToastContent>({\n /*\n * Three, against the product's one. Its TOAST_LIMIT of 1 means a second\n * toast REPLACES the first -- so a page that reports three failed uploads\n * shows one and silently drops the rest.\n */\n maxVisibleToasts: 3,\n});\n\n/**\n * Show a toast.\n *\n * @example\n * toast({ title: \"Report saved\" });\n * toast({ title: \"Upload failed\", description: err.message, tone: \"danger\" });\n *\n * @param timeout - ms before it dismisses itself. React Aria REFUSES anything\n * under 5000 and anything at all while the region is focused, because a\n * message that disappears before it can be read fails WCAG 2.2.1. Pass 0 to\n * require a manual dismiss, which is right for an error a user must act on.\n */\nexport function toast(content: ToastContent, timeout = 5000) {\n return toastQueue.add(content, timeout === 0 ? undefined : { timeout });\n}\n\nexport interface ToastRegionProps {\n /**\n * Names the region for assistive tech.\n *\n * **Required.** React Aria renders the region as a labelled landmark, and\n * an unnamed one is announced as \"region\" with no indication of what just\n * arrived. It is a prop rather than a default string because\n * ARCHITECTURE section 7 rule 9 routes user-visible copy through the\n * consumer until `useMessages()` exists.\n */\n label: string;\n /** Accessible name for each toast's dismiss control. */\n closeLabel?: string;\n /** Extra classes for the region. Merged last. */\n className?: string;\n}\n\n/**\n * Renders the queue. Mount ONCE, near the root.\n *\n * React Aria only renders the landmark while something is queued, so this\n * costs nothing on a quiet screen.\n */\nexport const ToastRegion = forwardRef<HTMLDivElement, ToastRegionProps>(function ToastRegion(\n { label, closeLabel = \"Dismiss\", className },\n ref,\n) {\n return (\n <AriaToastRegion\n ref={ref}\n queue={toastQueue}\n aria-label={label}\n data-slot=\"toast-region\"\n className={cn(toastRegionVariants(), className)}\n >\n {({ toast: queued }) => (\n <AriaToast\n toast={queued}\n data-slot=\"toast\"\n data-tone={queued.content.tone ?? \"neutral\"}\n className={toastVariants({ tone: queued.content.tone })}\n >\n <AriaToastContent data-slot=\"toast-content\" className=\"flex min-w-0 flex-col gap-1\">\n {/*\n slot=\"title\" is what React Aria announces. A plain div here\n renders identically and leaves the toast unnamed.\n */}\n <AriaText\n slot=\"title\"\n data-slot=\"toast-title\"\n className=\"text-sm leading-(--leading-snug) font-medium\"\n >\n {queued.content.title}\n </AriaText>\n {queued.content.description == null ? null : (\n <AriaText\n slot=\"description\"\n data-slot=\"toast-description\"\n className=\"text-sm leading-(--leading-normal) opacity-90\"\n >\n {queued.content.description}\n </AriaText>\n )}\n </AriaToastContent>\n <AriaButton\n slot=\"close\"\n aria-label={closeLabel}\n data-slot=\"toast-close\"\n className={toastCloseVariants()}\n >\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n className=\"size-(--icon-sm)\"\n >\n <path d=\"m4 4 8 8M12 4l-8 8\" />\n </svg>\n </AriaButton>\n </AriaToast>\n )}\n </AriaToastRegion>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,MAAa,sBAAsB,IAAI;CACrC;CAEA;CACA;CACA;AACF,CAAC;AAED,MAAa,gBAAgB,IAC3B;CACE;CACA;CACA;CACA;CAEA;AACF,GACA;CACE,UAAU,EAOR,MAAM;EACJ,SAAS;EACT,SAAS;EACT,SAAS;EACT,QACE;EACF,MAAM;CACR,EACF;CACA,iBAAiB,EAAE,MAAM,UAAU;AACrC,CACF;AAEA,MAAa,qBAAqB,IAAI;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;AAkBD,MAAa,aAAa,IAAIA,oBAA6B,EAMzD,kBAAkB,EACpB,CAAC;;;;;;;;;;;;;AAcD,SAAgB,MAAM,SAAuB,UAAU,KAAM;CAC3D,OAAO,WAAW,IAAI,SAAS,YAAY,IAAI,KAAA,IAAY,EAAE,QAAQ,CAAC;AACxE;;;;;;;AAyBA,MAAa,cAAc,WAA6C,SAAS,YAC/E,EAAE,OAAO,aAAa,WAAW,aACjC,KACA;CACA,OACE,oBAACC,sBAAD;EACO;EACL,OAAO;EACP,cAAY;EACZ,aAAU;EACV,WAAW,GAAG,oBAAoB,GAAG,SAAS;EAE5C,WAAA,EAAE,OAAO,aACT,qBAACC,gBAAD;GACE,OAAO;GACP,aAAU;GACV,aAAW,OAAO,QAAQ,QAAQ;GAClC,WAAW,cAAc,EAAE,MAAM,OAAO,QAAQ,KAAK,CAAC;GAJxD,UAAA,CAME,qBAACC,uBAAD;IAAkB,aAAU;IAAgB,WAAU;IAAtD,UAAA,CAKE,oBAACC,MAAD;KACE,MAAK;KACL,aAAU;KACV,WAAU;KAET,UAAA,OAAO,QAAQ;IACR,CAAA,GACT,OAAO,QAAQ,eAAe,OAAO,OACpC,oBAACA,MAAD;KACE,MAAK;KACL,aAAU;KACV,WAAU;KAET,UAAA,OAAO,QAAQ;IACR,CAAA,CAEI;GAClB,CAAA,GAAA,oBAACC,QAAD;IACE,MAAK;IACL,cAAY;IACZ,aAAU;IACV,WAAW,mBAAmB;IAE9B,UAAA,oBAAC,OAAD;KACE,eAAY;KACZ,SAAQ;KACR,MAAK;KACL,QAAO;KACP,aAAY;KACZ,eAAc;KACd,WAAU;KAEV,UAAA,oBAAC,QAAD,EAAM,GAAE,qBAAsB,CAAA;IAC3B,CAAA;GACK,CAAA,CACH;;CAEE,CAAA;AAErB,CAAC"}
1
+ {"version":3,"file":"toast.js","names":["AriaToastQueue","AriaToast","AriaToastContent","AriaText","AriaButton","AriaToastRegion"],"sources":["../../src/toast/toast.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { forwardRef, useCallback, useState, type ReactNode } from \"react\";\nimport {\n Button as AriaButton,\n Text as AriaText,\n UNSTABLE_Toast as AriaToast,\n UNSTABLE_ToastContent as AriaToastContent,\n UNSTABLE_ToastQueue as AriaToastQueue,\n UNSTABLE_ToastRegion as AriaToastRegion,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { useExitBackstop } from \"../lib/motion.js\";\n\n/**\n * Toast: a transient message, announced without stealing focus.\n *\n * Maturity: **experimental**, and the reason is upstream rather than here.\n * React Aria ships this API as `UNSTABLE_Toast*` in 1.21.1, so a RAC minor\n * bump can rename or reshape it. The alternative was hand-rolling the live\n * region, the queue, the timers and the focus behaviour, which is how every\n * toast implementation acquires its accessibility bugs -- so this takes the\n * upstream one and labels the risk instead of hiding it.\n *\n * THE PRODUCT HAS 30 FILES CALLING `useToast` AND 67 `toast(...)` CALLS, and\n * its implementation is the shadcn reducer with both of its known defects\n * still in place:\n *\n * TOAST_LIMIT = 1 -- a second toast REPLACES the first, so a\n * burst of results shows only the last one.\n * TOAST_REMOVE_DELAY = 1e6 -- sixteen minutes. Nothing auto-dismisses;\n * every toast waits to be closed by hand.\n *\n * Neither is ported. `maxVisibleToasts` defaults to 3 and `timeout` to 5s,\n * which is the WCAG 2.2.1 floor React Aria enforces -- it REFUSES a timeout\n * under 5000ms, because a message that vanishes faster cannot be read by\n * someone using a screen magnifier.\n *\n * The queue is a module singleton on purpose. The product's `toast()` is\n * importable from anywhere and called from API error handlers and effects\n * that have no component to hang a hook off, and a context-based queue would\n * have made those 67 call sites into 67 refactors.\n */\n\n/** Where the region sits. Fixed, above everything, out of the way of content. */\nexport const toastRegionVariants = cva([\n \"fixed z-50 flex flex-col gap-2 box-border\",\n // Logical insets so the stack follows the writing direction.\n \"bottom-(--density-bar-pad-y) end-(--density-bar-pad-x)\",\n \"w-[min(24rem,calc(100vw-2rem))]\",\n \"outline-none\",\n]);\n\nexport const toastVariants = cva(\n [\n \"flex items-start gap-3 box-border w-full\",\n // A white card on every tone: the status lives in the icon, not the fill.\n \"rounded-panel border-(length:--border-width) border-border bg-surface text-foreground\",\n \"py-3.5 ps-4 pe-3.5 font-sans shadow-floating\",\n // Rises in when it mounts. When its own close control is pressed it sinks out\n // first (data-closing) and the queue is told when that ends. Reduced motion:\n // opacity only. Not colour alone: the region reflows too.\n \"motion-safe:animate-toast-in motion-reduce:animate-fade-in\",\n \"motion-safe:data-[closing]:animate-toast-out motion-reduce:data-[closing]:animate-fade-out\",\n ],\n {\n variants: {\n /*\n * The same vocabulary as Badge, deliberately. The product's toast had\n * `default` and `destructive` only, so 38 of its 67 calls pass a variant\n * that cannot say \"this worked\" -- and a save confirmation styled\n * identically to a failure is the most common thing a toast gets wrong.\n *\n * The tone no longer tints the card (every tone is the same white card);\n * it picks the icon. The variant stays so `toastVariants({ tone })` still\n * type-checks for existing callers.\n */\n tone: {\n neutral: \"\",\n success: \"\",\n warning: \"\",\n danger: \"\",\n info: \"\",\n },\n },\n defaultVariants: { tone: \"neutral\" },\n },\n);\n\n/** The status icon's circle: the tone's light fill with its AA text colour. */\nexport const toastIconVariants = cva(\n \"mt-px grid size-7.5 shrink-0 place-items-center rounded-circle [&_svg]:size-4\",\n {\n variants: {\n tone: {\n neutral: \"bg-muted text-text-secondary\",\n success: \"bg-success-subtle text-success-foreground\",\n warning: \"bg-warning-subtle text-warning-foreground\",\n danger: \"bg-destructive-subtle text-destructive-subtle-foreground\",\n info: \"bg-info-subtle text-info-foreground\",\n },\n },\n defaultVariants: { tone: \"neutral\" },\n },\n);\n\n// One 24px glyph per tone. Success draws its tick on arrival (toast-check).\nconst TONE_ICON_PATHS = {\n neutral: \"M6 16v-5a6 6 0 1 1 12 0v5l1.5 2h-15zM10 20.5a2 2 0 0 0 4 0\",\n success: \"M4 12.5l5 5L20 6.5\",\n warning: \"M12 7v6.5M12 17.25h.01\",\n danger: \"M7 7l10 10M17 7L7 17\",\n info: \"M12 11v6M12 7.25h.01\",\n} as const;\n\nexport const toastCloseVariants = cva([\n // A plain icon: no fill, no border at rest. It hovers to the muted wash.\n \"-mt-px -me-0.5 ms-auto grid size-8 shrink-0 place-items-center rounded-circle cursor-pointer\",\n \"border-0 bg-transparent p-0 text-text-secondary\",\n \"data-[hovered]:bg-muted data-[hovered]:text-foreground\",\n // Quick press, spring release (styles.css).\n \"toast-close\",\n \"outline-none\",\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]);\n\n/** What a toast carries. `title` is required: an unnamed toast announces nothing. */\nexport interface ToastContent extends VariantProps<typeof toastVariants> {\n /** The message. Required -- a toast with only a description announces as loose text. */\n title: ReactNode;\n /** Secondary detail, beneath the title. */\n description?: ReactNode;\n /** Replaces the tone's status icon. Pass a 16px glyph; it is hidden from assistive tech. */\n icon?: ReactNode;\n}\n\n/**\n * The queue every `toast()` call feeds.\n *\n * Exported so a consumer can read `visibleToasts` in a test, or dismiss them\n * on a route change -- there is no `clear()` upstream, so that is\n * `[...toastQueue.visibleToasts].forEach((t) => toastQueue.close(t.key))`.\n * Not something to touch in normal use.\n */\nexport const toastQueue = new AriaToastQueue<ToastContent>({\n /*\n * Three, against the product's one. Its TOAST_LIMIT of 1 means a second\n * toast REPLACES the first -- so a page that reports three failed uploads\n * shows one and silently drops the rest.\n */\n maxVisibleToasts: 3,\n});\n\n/**\n * Show a toast.\n *\n * @example\n * toast({ title: \"Report saved\" });\n * toast({ title: \"Upload failed\", description: err.message, tone: \"danger\" });\n *\n * @param timeout - ms before it dismisses itself. React Aria REFUSES anything\n * under 5000 and anything at all while the region is focused, because a\n * message that disappears before it can be read fails WCAG 2.2.1. Pass 0 to\n * require a manual dismiss, which is right for an error a user must act on.\n */\nexport function toast(content: ToastContent, timeout = 5000) {\n return toastQueue.add(content, timeout === 0 ? undefined : { timeout });\n}\n\ntype Queued = (typeof toastQueue.visibleToasts)[number];\n\n/**\n * One toast. Pressing its close control plays the exit first, then closes it in the\n * queue; React Aria unmounts a closed toast at once and has no exit of its own, so a\n * toast closed any other way (the timeout, `toastQueue.close`) leaves without one.\n */\nfunction ToastItem({ queued, closeLabel }: { queued: Queued; closeLabel: string }) {\n const [closing, setClosing] = useState(false);\n const tone = queued.content.tone ?? \"neutral\";\n const finish = useCallback(() => toastQueue.close(queued.key), [queued.key]);\n // If the animation never reports (reduced motion, a hidden tab), close anyway.\n useExitBackstop(closing, finish);\n return (\n <AriaToast\n toast={queued}\n data-slot=\"toast\"\n data-tone={tone}\n data-closing={closing || undefined}\n onAnimationEnd={(event) => {\n if (closing && event.target === event.currentTarget) finish();\n }}\n className={toastVariants({ tone })}\n >\n <span\n data-slot=\"toast-icon\"\n data-tone={tone}\n aria-hidden=\"true\"\n className={toastIconVariants({ tone })}\n >\n {queued.content.icon ?? (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.25\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path\n d={TONE_ICON_PATHS[tone]}\n pathLength={1}\n className={tone === \"success\" ? \"toast-check\" : undefined}\n />\n </svg>\n )}\n </span>\n <AriaToastContent\n data-slot=\"toast-content\"\n className=\"flex min-w-0 flex-1 flex-col gap-0.5 pt-1.25\"\n >\n {/*\n slot=\"title\" is what React Aria announces. A plain div here\n renders identically and leaves the toast unnamed.\n */}\n <AriaText\n slot=\"title\"\n data-slot=\"toast-title\"\n className=\"text-sm leading-(--leading-normal) font-medium text-foreground\"\n >\n {queued.content.title}\n </AriaText>\n {queued.content.description == null ? null : (\n <AriaText\n slot=\"description\"\n data-slot=\"toast-description\"\n className=\"text-sm leading-(--leading-normal) text-text-secondary\"\n >\n {queued.content.description}\n </AriaText>\n )}\n </AriaToastContent>\n <AriaButton\n aria-label={closeLabel}\n data-slot=\"toast-close\"\n className={toastCloseVariants()}\n onPress={() => setClosing(true)}\n >\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n className=\"size-(--icon-sm)\"\n >\n <path d=\"m4 4 8 8M12 4l-8 8\" />\n </svg>\n </AriaButton>\n </AriaToast>\n );\n}\n\nexport interface ToastRegionProps {\n /**\n * Names the region for assistive tech.\n *\n * **Required.** React Aria renders the region as a labelled landmark, and\n * an unnamed one is announced as \"region\" with no indication of what just\n * arrived. It is a prop rather than a default string because\n * ARCHITECTURE section 7 rule 9 routes user-visible copy through the\n * consumer until `useMessages()` exists.\n */\n label: string;\n /** Accessible name for each toast's dismiss control. */\n closeLabel?: string;\n /** Extra classes for the region. Merged last. */\n className?: string;\n}\n\n/**\n * Renders the queue. Mount ONCE, near the root.\n *\n * React Aria only renders the landmark while something is queued, so this\n * costs nothing on a quiet screen.\n */\nexport const ToastRegion = forwardRef<HTMLDivElement, ToastRegionProps>(function ToastRegion(\n { label, closeLabel = \"Dismiss\", className },\n ref,\n) {\n return (\n <AriaToastRegion\n ref={ref}\n queue={toastQueue}\n aria-label={label}\n data-slot=\"toast-region\"\n className={cn(toastRegionVariants(), className)}\n >\n {({ toast: queued }) => <ToastItem queued={queued} closeLabel={closeLabel} />}\n </AriaToastRegion>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,MAAa,sBAAsB,IAAI;CACrC;CAEA;CACA;CACA;AACF,CAAC;AAED,MAAa,gBAAgB,IAC3B;CACE;CAEA;CACA;CAIA;CACA;AACF,GACA;CACE,UAAU,EAWR,MAAM;EACJ,SAAS;EACT,SAAS;EACT,SAAS;EACT,QAAQ;EACR,MAAM;CACR,EACF;CACA,iBAAiB,EAAE,MAAM,UAAU;AACrC,CACF;;AAGA,MAAa,oBAAoB,IAC/B,iFACA;CACE,UAAU,EACR,MAAM;EACJ,SAAS;EACT,SAAS;EACT,SAAS;EACT,QAAQ;EACR,MAAM;CACR,EACF;CACA,iBAAiB,EAAE,MAAM,UAAU;AACrC,CACF;AAGA,MAAM,kBAAkB;CACtB,SAAS;CACT,SAAS;CACT,SAAS;CACT,QAAQ;CACR,MAAM;AACR;AAEA,MAAa,qBAAqB,IAAI;CAEpC;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;AAoBD,MAAa,aAAa,IAAIA,oBAA6B,EAMzD,kBAAkB,EACpB,CAAC;;;;;;;;;;;;;AAcD,SAAgB,MAAM,SAAuB,UAAU,KAAM;CAC3D,OAAO,WAAW,IAAI,SAAS,YAAY,IAAI,KAAA,IAAY,EAAE,QAAQ,CAAC;AACxE;;;;;;AASA,SAAS,UAAU,EAAE,QAAQ,cAAsD;CACjF,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAC5C,MAAM,OAAO,OAAO,QAAQ,QAAQ;CACpC,MAAM,SAAS,kBAAkB,WAAW,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,GAAG,CAAC;CAE3E,gBAAgB,SAAS,MAAM;CAC/B,OACE,qBAACC,gBAAD;EACE,OAAO;EACP,aAAU;EACV,aAAW;EACX,gBAAc,WAAW,KAAA;EACzB,iBAAiB,UAAU;GACzB,IAAI,WAAW,MAAM,WAAW,MAAM,eAAe,OAAO;EAC9D;EACA,WAAW,cAAc,EAAE,KAAK,CAAC;EARnC,UAAA;GAUE,oBAAC,QAAD;IACE,aAAU;IACV,aAAW;IACX,eAAY;IACZ,WAAW,kBAAkB,EAAE,KAAK,CAAC;IAEpC,UAAA,OAAO,QAAQ,QACd,oBAAC,OAAD;KACE,SAAQ;KACR,MAAK;KACL,QAAO;KACP,aAAY;KACZ,eAAc;KACd,gBAAe;KAEf,UAAA,oBAAC,QAAD;MACE,GAAG,gBAAgB;MACnB,YAAY;MACZ,WAAW,SAAS,YAAY,gBAAgB,KAAA;KACjD,CAAA;IACE,CAAA;GAEH,CAAA;GACN,qBAACC,uBAAD;IACE,aAAU;IACV,WAAU;IAFZ,UAAA,CAQE,oBAACC,MAAD;KACE,MAAK;KACL,aAAU;KACV,WAAU;KAET,UAAA,OAAO,QAAQ;IACR,CAAA,GACT,OAAO,QAAQ,eAAe,OAAO,OACpC,oBAACA,MAAD;KACE,MAAK;KACL,aAAU;KACV,WAAU;KAET,UAAA,OAAO,QAAQ;IACR,CAAA,CAEI;;GAClB,oBAACC,QAAD;IACE,cAAY;IACZ,aAAU;IACV,WAAW,mBAAmB;IAC9B,eAAe,WAAW,IAAI;IAE9B,UAAA,oBAAC,OAAD;KACE,eAAY;KACZ,SAAQ;KACR,MAAK;KACL,QAAO;KACP,aAAY;KACZ,eAAc;KACd,WAAU;KAEV,UAAA,oBAAC,QAAD,EAAM,GAAE,qBAAsB,CAAA;IAC3B,CAAA;GACK,CAAA;EACH;;AAEf;;;;;;;AAyBA,MAAa,cAAc,WAA6C,SAAS,YAC/E,EAAE,OAAO,aAAa,WAAW,aACjC,KACA;CACA,OACE,oBAACC,sBAAD;EACO;EACL,OAAO;EACP,cAAY;EACZ,aAAU;EACV,WAAW,GAAG,oBAAoB,GAAG,SAAS;EAE5C,WAAA,EAAE,OAAO,aAAa,oBAAC,WAAD;GAAmB;GAAoB;EAAa,CAAA;CAC7D,CAAA;AAErB,CAAC"}
@@ -39,12 +39,19 @@ interface TooltipProps$1 extends Omit<TooltipProps, "className" | "style" | "chi
39
39
  /** Extra classes. Merged last, so they win conflicts with ours. */
40
40
  className?: string;
41
41
  /**
42
- * Where it opens. The legacy `side` prop: `"top"` 11 times, `"bottom"`
43
- * once, and the default for the other 22.
42
+ * Where it opens: above the trigger by default. The legacy `side` prop
43
+ * (`"top"` 11 times, `"bottom"` once).
44
44
  *
45
45
  * @default "top"
46
46
  */
47
47
  placement?: TooltipProps["placement"];
48
+ /**
49
+ * Draw a small arrow pointing at the trigger. Off by default: the bubble
50
+ * floats clear of the trigger with no arrow.
51
+ *
52
+ * @default false
53
+ */
54
+ showArrow?: boolean;
48
55
  }
49
56
  declare const Tooltip$1: import("react").ForwardRefExoticComponent<TooltipProps$1 & import("react").RefAttributes<HTMLDivElement>>;
50
57
  /**
@@ -64,7 +71,7 @@ export interface TooltipTriggerProps extends TooltipTriggerComponentProps {
64
71
  /** Hover cool-down in ms. @default 0 */
65
72
  closeDelay?: number;
66
73
  }
67
- declare function TooltipTrigger$1({ delay, closeDelay, ...props }: TooltipTriggerProps): import("react").JSX.Element;
74
+ declare function TooltipTrigger$1({ delay, closeDelay, onOpenChange, ...props }: TooltipTriggerProps): import("react").JSX.Element;
68
75
  //#endregion
69
76
  export { Tooltip$1 as Tooltip, TooltipProps$1 as TooltipProps, TooltipTrigger$1 as TooltipTrigger };
70
77
  //# sourceMappingURL=tooltip.d.ts.map
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
+ import { useIsomorphicLayoutEffect } from "../lib/motion.js";
3
4
  import { cva } from "class-variance-authority";
4
- import { forwardRef } from "react";
5
+ import { forwardRef, useEffect, useRef } from "react";
5
6
  import { OverlayArrow, Tooltip, TooltipTrigger } from "react-aria-components";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
7
8
  //#region src/tooltip/tooltip.tsx
@@ -29,12 +30,47 @@ import { jsx, jsxs } from "react/jsx-runtime";
29
30
  * word -- so `delay` defaults to 0 here, and a story pins the default.
30
31
  */
31
32
  const tooltipVariants = cva([
32
- "w-fit rounded-md px-3 py-1.5",
33
- "bg-primary text-primary-foreground",
34
- "box-border font-sans text-xs leading-(--leading-snug) text-balance",
35
- "outline-none"
33
+ "w-fit max-w-60 rounded-control px-4 py-3",
34
+ "bg-foreground text-background shadow-raised",
35
+ "box-border font-sans text-sm leading-(--leading-normal) text-balance",
36
+ "outline-none",
37
+ "tooltip-motion"
36
38
  ]);
37
- const Tooltip$1 = forwardRef(function Tooltip$2({ children, className, placement = "top", ...props }, ref) {
39
+ const WARM_MS = 300;
40
+ let openCount = 0;
41
+ let coolTimer;
42
+ let warm = false;
43
+ let openedWarm = false;
44
+ function noteOpen(open) {
45
+ if (open) {
46
+ openedWarm = warm;
47
+ openCount += 1;
48
+ clearTimeout(coolTimer);
49
+ warm = true;
50
+ return;
51
+ }
52
+ openCount = Math.max(0, openCount - 1);
53
+ if (openCount) return;
54
+ clearTimeout(coolTimer);
55
+ coolTimer = setTimeout(() => {
56
+ warm = false;
57
+ }, WARM_MS);
58
+ }
59
+ /**
60
+ * Mounts with the open tooltip (the Tooltip function itself runs while closed too) and
61
+ * marks it `data-instant` if its trigger opened it inside the warm window, before paint.
62
+ */
63
+ function WarmMark() {
64
+ const ref = useRef(null);
65
+ useIsomorphicLayoutEffect(() => {
66
+ if (openedWarm) ref.current?.parentElement?.setAttribute("data-instant", "");
67
+ }, []);
68
+ return /* @__PURE__ */ jsx("span", {
69
+ ref,
70
+ hidden: true
71
+ });
72
+ }
73
+ const Tooltip$1 = forwardRef(function Tooltip$2({ children, className, placement = "top", showArrow = false, ...props }, ref) {
38
74
  return /* @__PURE__ */ jsxs(Tooltip, {
39
75
  ref,
40
76
  ...props,
@@ -42,23 +78,36 @@ const Tooltip$1 = forwardRef(function Tooltip$2({ children, className, placement
42
78
  offset: 8,
43
79
  "data-slot": "tooltip",
44
80
  className: cn(tooltipVariants(), className),
45
- children: [/* @__PURE__ */ jsx(OverlayArrow, {
46
- "data-slot": "tooltip-arrow",
47
- children: /* @__PURE__ */ jsx("svg", {
48
- width: "10",
49
- height: "5",
50
- viewBox: "0 0 10 5",
51
- className: "fill-primary",
52
- children: /* @__PURE__ */ jsx("path", { d: "M0 5 5 0l5 5z" })
53
- })
54
- }), children]
81
+ children: [
82
+ showArrow ? /* @__PURE__ */ jsx(OverlayArrow, {
83
+ "data-slot": "tooltip-arrow",
84
+ children: /* @__PURE__ */ jsx("svg", {
85
+ width: "10",
86
+ height: "5",
87
+ viewBox: "0 0 10 5",
88
+ className: "fill-foreground",
89
+ children: /* @__PURE__ */ jsx("path", { d: "M0 5 5 0l5 5z" })
90
+ })
91
+ }) : null,
92
+ /* @__PURE__ */ jsx(WarmMark, {}),
93
+ children
94
+ ]
55
95
  });
56
96
  });
57
- function TooltipTrigger$1({ delay = 0, closeDelay = 0, ...props }) {
97
+ function TooltipTrigger$1({ delay = 0, closeDelay = 0, onOpenChange, ...props }) {
98
+ const isOpen = useRef(false);
99
+ useEffect(() => () => {
100
+ if (isOpen.current) noteOpen(false);
101
+ }, []);
58
102
  return /* @__PURE__ */ jsx(TooltipTrigger, {
59
103
  ...props,
60
104
  delay,
61
- closeDelay
105
+ closeDelay,
106
+ onOpenChange: (open) => {
107
+ isOpen.current = open;
108
+ noteOpen(open);
109
+ onOpenChange?.(open);
110
+ }
62
111
  });
63
112
  }
64
113
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.js","names":["Tooltip","AriaTooltip","AriaOverlayArrow","TooltipTrigger","AriaTooltipTrigger"],"sources":["../../src/tooltip/tooltip.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport {\n OverlayArrow as AriaOverlayArrow,\n Tooltip as AriaTooltip,\n TooltipTrigger as AriaTooltipTrigger,\n type TooltipProps as AriaTooltipProps,\n type TooltipTriggerComponentProps as AriaTooltipTriggerProps,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\n\n/**\n * Tooltip, ported from the legacy shadcn/Radix component.\n *\n * Census: ten files import it but only SEVEN render anything -- three\n * import the parts and use none. Across those seven: `Tooltip` 34,\n * `TooltipTrigger` 34, `TooltipContent` 34, `TooltipProvider` 23. `side`\n * is passed 12 times: `\"top\"` 11, `\"bottom\"` once.\n *\n * `TooltipProvider` IS NOT PORTED, and that removes 23 call sites rather\n * than renaming them. The legacy `Tooltip` already wraps itself in a\n * provider, so every explicit `<TooltipProvider>` in app code nested a\n * second one inside the first -- harmless, but it also meant the\n * `skipDelayDuration` grouping the provider exists for never spanned two\n * tooltips. React Aria has no provider at all; that grouping is\n * module-global.\n *\n * THE DELAY IS THE ONE THING THAT WOULD HAVE CHANGED SILENTLY. The legacy\n * provider hardcodes `delayDuration = 0`, so all 34 tooltips appear\n * instantly on hover. React Aria's default is 1500ms. Porting without\n * noticing would have put a 1.5-second warm-up on every tooltip in the\n * app, and neither the type system nor the test suite would have said a\n * word -- so `delay` defaults to 0 here, and a story pins the default.\n */\nexport const tooltipVariants = cva([\n \"w-fit rounded-md px-3 py-1.5\",\n // The legacy palette, kept: primary-foreground on primary is 8.35:1 and\n // is already in the contrast contract. An inverse-surface tooltip is the\n // more common choice, but changing it would be a design decision with no\n // defect behind it.\n \"bg-primary text-primary-foreground\",\n \"box-border font-sans text-xs leading-(--leading-snug) text-balance\",\n \"outline-none\",\n]);\n\n/**\n * A hover and focus hint.\n *\n * @example\n * <TooltipTrigger>\n * <Button aria-label=\"Mute\"><MicOff /></Button>\n * <Tooltip>Mute</Tooltip>\n * </TooltipTrigger>\n */\nexport interface TooltipProps\n extends Omit<AriaTooltipProps, \"className\" | \"style\" | \"children\"> {\n children?: ReactNode;\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n /**\n * Where it opens. The legacy `side` prop: `\"top\"` 11 times, `\"bottom\"`\n * once, and the default for the other 22.\n *\n * @default \"top\"\n */\n placement?: AriaTooltipProps[\"placement\"];\n}\n\nexport const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(function Tooltip(\n { children, className, placement = \"top\", ...props },\n ref,\n) {\n return (\n <AriaTooltip\n // The ref goes on the tooltip itself, not the OverlayArrow child below\n // -- the arrow is a decorative sub-element, not the tooltip's own DOM\n // node.\n ref={ref}\n {...props}\n placement={placement}\n offset={8}\n data-slot=\"tooltip\"\n className={cn(tooltipVariants(), className)}\n >\n {/*\n An SVG arrow, not the legacy rotated square. That used\n `translate-y-[calc(-50%_-_2px)]` and `rounded-[2px]` -- two bracket\n values check:hardcoding rejects -- and a rotated box has to be\n re-placed for every side. React Aria rotates the whole OverlayArrow\n per placement, so one upward triangle serves all four.\n */}\n <AriaOverlayArrow data-slot=\"tooltip-arrow\">\n <svg width=\"10\" height=\"5\" viewBox=\"0 0 10 5\" className=\"fill-primary\">\n <path d=\"M0 5 5 0l5 5z\" />\n </svg>\n </AriaOverlayArrow>\n {children}\n </AriaTooltip>\n );\n});\n\n/**\n * Pairs a trigger with a tooltip.\n *\n * React Aria's `TooltipTrigger`, EXCEPT that `delay` and `closeDelay`\n * default to 0 to match the legacy provider. React Aria ships 1500ms and\n * 500ms; taking those defaults would have changed all 34 call sites\n * without a word.\n *\n * Focus opens it immediately whatever `delay` says -- React Aria passes\n * `immediate` on focus -- which is the behaviour a keyboard user needs.\n */\nexport interface TooltipTriggerProps extends AriaTooltipTriggerProps {\n /** Hover warm-up in ms. @default 0 */\n delay?: number;\n /** Hover cool-down in ms. @default 0 */\n closeDelay?: number;\n}\n\nexport function TooltipTrigger({ delay = 0, closeDelay = 0, ...props }: TooltipTriggerProps) {\n return <AriaTooltipTrigger {...props} delay={delay} closeDelay={closeDelay} />;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAa,kBAAkB,IAAI;CACjC;CAKA;CACA;CACA;AACF,CAAC;AAyBD,MAAaA,YAAU,WAAyC,SAASA,UACvE,EAAE,UAAU,WAAW,YAAY,OAAO,GAAG,SAC7C,KACA;CACA,OACE,qBAACC,SAAD;EAIO;EACL,GAAI;EACO;EACX,QAAQ;EACR,aAAU;EACV,WAAW,GAAG,gBAAgB,GAAG,SAAS;EAT5C,UAAA,CAkBE,oBAACC,cAAD;GAAkB,aAAU;GAC1B,UAAA,oBAAC,OAAD;IAAK,OAAM;IAAK,QAAO;IAAI,SAAQ;IAAW,WAAU;IACtD,UAAA,oBAAC,QAAD,EAAM,GAAE,gBAAiB,CAAA;GACtB,CAAA;EACW,CAAA,GACjB,QACU;;AAEjB,CAAC;AAoBD,SAAgBC,iBAAe,EAAE,QAAQ,GAAG,aAAa,GAAG,GAAG,SAA8B;CAC3F,OAAO,oBAACC,gBAAD;EAAoB,GAAI;EAAc;EAAmB;CAAa,CAAA;AAC/E"}
1
+ {"version":3,"file":"tooltip.js","names":["Tooltip","AriaTooltip","AriaOverlayArrow","TooltipTrigger","AriaTooltipTrigger"],"sources":["../../src/tooltip/tooltip.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport { forwardRef, useEffect, useRef, type ReactNode } from \"react\";\nimport {\n OverlayArrow as AriaOverlayArrow,\n Tooltip as AriaTooltip,\n TooltipTrigger as AriaTooltipTrigger,\n type TooltipProps as AriaTooltipProps,\n type TooltipTriggerComponentProps as AriaTooltipTriggerProps,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { useIsomorphicLayoutEffect } from \"../lib/motion.js\";\n\n/**\n * Tooltip, ported from the legacy shadcn/Radix component.\n *\n * Census: ten files import it but only SEVEN render anything -- three\n * import the parts and use none. Across those seven: `Tooltip` 34,\n * `TooltipTrigger` 34, `TooltipContent` 34, `TooltipProvider` 23. `side`\n * is passed 12 times: `\"top\"` 11, `\"bottom\"` once.\n *\n * `TooltipProvider` IS NOT PORTED, and that removes 23 call sites rather\n * than renaming them. The legacy `Tooltip` already wraps itself in a\n * provider, so every explicit `<TooltipProvider>` in app code nested a\n * second one inside the first -- harmless, but it also meant the\n * `skipDelayDuration` grouping the provider exists for never spanned two\n * tooltips. React Aria has no provider at all; that grouping is\n * module-global.\n *\n * THE DELAY IS THE ONE THING THAT WOULD HAVE CHANGED SILENTLY. The legacy\n * provider hardcodes `delayDuration = 0`, so all 34 tooltips appear\n * instantly on hover. React Aria's default is 1500ms. Porting without\n * noticing would have put a 1.5-second warm-up on every tooltip in the\n * app, and neither the type system nor the test suite would have said a\n * word -- so `delay` defaults to 0 here, and a story pins the default.\n */\nexport const tooltipVariants = cva([\n // Design spec (Oct 2026): a solid ink bubble with a large corner and\n // comfortable padding, capped at 15rem so a long hint wraps onto a second line.\n \"w-fit max-w-60 rounded-control px-4 py-3\",\n // foreground/background, not a fixed black and white: the pair inverts with\n // the theme (light bubble in dark mode) and its ratio is the page-text pair\n // in the contrast contract.\n \"bg-foreground text-background shadow-raised\",\n \"box-border font-sans text-sm leading-(--leading-normal) text-balance\",\n \"outline-none\",\n // Rises from its trigger and fades; only fades in the warm window (styles.css).\n \"tooltip-motion\",\n]);\n\n/*\n * The warm window: while any tooltip is open, and for 300ms after the last one\n * closes, the next opens with no travel. TooltipTrigger writes it; the tooltip\n * that mounts next reads whether it was warm when its trigger opened it.\n */\nconst WARM_MS = 300;\nlet openCount = 0;\nlet coolTimer: ReturnType<typeof setTimeout> | undefined;\nlet warm = false;\nlet openedWarm = false;\n\nfunction noteOpen(open: boolean) {\n if (open) {\n openedWarm = warm;\n openCount += 1;\n clearTimeout(coolTimer);\n warm = true;\n return;\n }\n openCount = Math.max(0, openCount - 1);\n if (openCount) return;\n clearTimeout(coolTimer);\n coolTimer = setTimeout(() => {\n warm = false;\n }, WARM_MS);\n}\n\n/**\n * Mounts with the open tooltip (the Tooltip function itself runs while closed too) and\n * marks it `data-instant` if its trigger opened it inside the warm window, before paint.\n */\nfunction WarmMark() {\n const ref = useRef<HTMLSpanElement>(null);\n useIsomorphicLayoutEffect(() => {\n if (openedWarm) ref.current?.parentElement?.setAttribute(\"data-instant\", \"\");\n }, []);\n return <span ref={ref} hidden />;\n}\n\n/**\n * A hover and focus hint.\n *\n * @example\n * <TooltipTrigger>\n * <Button aria-label=\"Mute\"><MicOff /></Button>\n * <Tooltip>Mute</Tooltip>\n * </TooltipTrigger>\n */\nexport interface TooltipProps\n extends Omit<AriaTooltipProps, \"className\" | \"style\" | \"children\"> {\n children?: ReactNode;\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n /**\n * Where it opens: above the trigger by default. The legacy `side` prop\n * (`\"top\"` 11 times, `\"bottom\"` once).\n *\n * @default \"top\"\n */\n placement?: AriaTooltipProps[\"placement\"];\n /**\n * Draw a small arrow pointing at the trigger. Off by default: the bubble\n * floats clear of the trigger with no arrow.\n *\n * @default false\n */\n showArrow?: boolean;\n}\n\nexport const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(function Tooltip(\n { children, className, placement = \"top\", showArrow = false, ...props },\n ref,\n) {\n return (\n <AriaTooltip\n // The ref goes on the tooltip itself, not the OverlayArrow child below\n // -- the arrow is a decorative sub-element, not the tooltip's own DOM\n // node.\n ref={ref}\n {...props}\n placement={placement}\n offset={8}\n data-slot=\"tooltip\"\n className={cn(tooltipVariants(), className)}\n >\n {/*\n Opt-in. An SVG arrow, not the legacy rotated square. That used\n `translate-y-[calc(-50%_-_2px)]` and `rounded-[2px]` -- two bracket\n values check:hardcoding rejects -- and a rotated box has to be\n re-placed for every side. React Aria rotates the whole OverlayArrow\n per placement, so one upward triangle serves all four.\n */}\n {showArrow ? (\n <AriaOverlayArrow data-slot=\"tooltip-arrow\">\n <svg width=\"10\" height=\"5\" viewBox=\"0 0 10 5\" className=\"fill-foreground\">\n <path d=\"M0 5 5 0l5 5z\" />\n </svg>\n </AriaOverlayArrow>\n ) : null}\n <WarmMark />\n {children}\n </AriaTooltip>\n );\n});\n\n/**\n * Pairs a trigger with a tooltip.\n *\n * React Aria's `TooltipTrigger`, EXCEPT that `delay` and `closeDelay`\n * default to 0 to match the legacy provider. React Aria ships 1500ms and\n * 500ms; taking those defaults would have changed all 34 call sites\n * without a word.\n *\n * Focus opens it immediately whatever `delay` says -- React Aria passes\n * `immediate` on focus -- which is the behaviour a keyboard user needs.\n */\nexport interface TooltipTriggerProps extends AriaTooltipTriggerProps {\n /** Hover warm-up in ms. @default 0 */\n delay?: number;\n /** Hover cool-down in ms. @default 0 */\n closeDelay?: number;\n}\n\nexport function TooltipTrigger({\n delay = 0,\n closeDelay = 0,\n onOpenChange,\n ...props\n}: TooltipTriggerProps) {\n const isOpen = useRef(false);\n // A trigger that unmounts while open never reports closing; count it out.\n useEffect(\n () => () => {\n if (isOpen.current) noteOpen(false);\n },\n [],\n );\n return (\n <AriaTooltipTrigger\n {...props}\n delay={delay}\n closeDelay={closeDelay}\n onOpenChange={(open) => {\n isOpen.current = open;\n noteOpen(open);\n onOpenChange?.(open);\n }}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,MAAa,kBAAkB,IAAI;CAGjC;CAIA;CACA;CACA;CAEA;AACF,CAAC;AAOD,MAAM,UAAU;AAChB,IAAI,YAAY;AAChB,IAAI;AACJ,IAAI,OAAO;AACX,IAAI,aAAa;AAEjB,SAAS,SAAS,MAAe;CAC/B,IAAI,MAAM;EACR,aAAa;EACb,aAAa;EACb,aAAa,SAAS;EACtB,OAAO;EACP;CACF;CACA,YAAY,KAAK,IAAI,GAAG,YAAY,CAAC;CACrC,IAAI,WAAW;CACf,aAAa,SAAS;CACtB,YAAY,iBAAiB;EAC3B,OAAO;CACT,GAAG,OAAO;AACZ;;;;;AAMA,SAAS,WAAW;CAClB,MAAM,MAAM,OAAwB,IAAI;CACxC,gCAAgC;EAC9B,IAAI,YAAY,IAAI,SAAS,eAAe,aAAa,gBAAgB,EAAE;CAC7E,GAAG,CAAC,CAAC;CACL,OAAO,oBAAC,QAAD;EAAW;EAAK,QAAA;CAAQ,CAAA;AACjC;AAgCA,MAAaA,YAAU,WAAyC,SAASA,UACvE,EAAE,UAAU,WAAW,YAAY,OAAO,YAAY,OAAO,GAAG,SAChE,KACA;CACA,OACE,qBAACC,SAAD;EAIO;EACL,GAAI;EACO;EACX,QAAQ;EACR,aAAU;EACV,WAAW,GAAG,gBAAgB,GAAG,SAAS;EAT5C,UAAA;GAkBG,YACC,oBAACC,cAAD;IAAkB,aAAU;IAC1B,UAAA,oBAAC,OAAD;KAAK,OAAM;KAAK,QAAO;KAAI,SAAQ;KAAW,WAAU;KACtD,UAAA,oBAAC,QAAD,EAAM,GAAE,gBAAiB,CAAA;IACtB,CAAA;GACW,CAAA,IAChB;GACJ,oBAAC,UAAD,CAAW,CAAA;GACV;EACU;;AAEjB,CAAC;AAoBD,SAAgBC,iBAAe,EAC7B,QAAQ,GACR,aAAa,GACb,cACA,GAAG,SACmB;CACtB,MAAM,SAAS,OAAO,KAAK;CAE3B,sBACc;EACV,IAAI,OAAO,SAAS,SAAS,KAAK;CACpC,GACA,CAAC,CACH;CACA,OACE,oBAACC,gBAAD;EACE,GAAI;EACG;EACK;EACZ,eAAe,SAAS;GACtB,OAAO,UAAU;GACjB,SAAS,IAAI;GACb,eAAe,IAAI;EACrB;CACD,CAAA;AAEL"}
@@ -0,0 +1,2 @@
1
+ import { Treemap, TreemapNode, TreemapProps } from "./treemap.js";
2
+ export { Treemap, type TreemapNode, type TreemapProps };
@@ -0,0 +1,2 @@
1
+ import { Treemap } from "./treemap.js";
2
+ export { Treemap };
@@ -0,0 +1,53 @@
1
+ //#region src/treemap/treemap.d.ts
2
+ /**
3
+ * Treemap: a hierarchy of parts, such as revenue by region, country and plan,
4
+ * when sizes matter more than exact comparisons. Tiles are laid out by the
5
+ * squarified algorithm (rows along the short side, each closed when another tile
6
+ * would make the worst aspect ratio worse), two levels at a time: the branches
7
+ * of the node in view, each holding its own children under a header.
8
+ *
9
+ * Tiles grow in a quick wave from the largest the first time the chart is seen.
10
+ * Pressing a branch (or Enter) zooms into it: the tile grows to fill the view and
11
+ * its children open inside it; Escape or a breadcrumb zooms back out, the view
12
+ * shrinking into its tile. New data moves every tile from where it is on screen.
13
+ * Hovering or the arrow keys read a tile in a tooltip, and the rest of its branch
14
+ * steps back. An optional second measure (growth, say) shades tiles in steps.
15
+ *
16
+ * Tiles are absolutely placed and sized each frame by one small spring tween, so
17
+ * their text never scales while they grow or shrink.
18
+ */
19
+ export interface TreemapNode {
20
+ /** Stable identity, unique in the tree. A tile that survives a data change morphs to its new size. */
21
+ id: string;
22
+ label: string;
23
+ /** Leaf size. A branch's size is the sum of its children. */
24
+ value?: number;
25
+ /** Optional second measure for shading, such as growth. A branch uses the size weighted mean of its children. */
26
+ color?: number;
27
+ children?: TreemapNode[];
28
+ }
29
+ export interface TreemapProps {
30
+ /** The root. Its label names the whole in the first breadcrumb. */
31
+ data: TreemapNode;
32
+ /** What the whole is, such as "Revenue". Names the chart for assistive technology. */
33
+ label: string;
34
+ formatValue?: (value: number) => string;
35
+ /** Names the shading measure in the tooltip and scale, such as "Growth". Tiles take the hue of their top level branch and grow deeper with the measure. Leave it out to draw every tile at one depth. */
36
+ colorLabel?: string;
37
+ formatColor?: (value: number) => string;
38
+ /** Range of the colour measure. Defaults to the range of the leaves. */
39
+ colorDomain?: [number, number];
40
+ /** Controlled id of the node that fills the view. */
41
+ focus?: string;
42
+ defaultFocus?: string;
43
+ onFocusChange?: (id: string) => void;
44
+ /** Height of the tiles in pixels. @default 420 */
45
+ height?: number;
46
+ /** @default "No data yet" */
47
+ emptyLabel?: string;
48
+ /** Extra classes for the root. Merged last. */
49
+ className?: string;
50
+ }
51
+ export declare const Treemap: import("react").ForwardRefExoticComponent<TreemapProps & import("react").RefAttributes<HTMLElement>>;
52
+ //#endregion
53
+ //# sourceMappingURL=treemap.d.ts.map