@eifi1/ui-kit 0.10.0 → 0.12.0

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 (382) hide show
  1. package/README.md +66 -37
  2. package/dist/chart.d.ts +3 -1
  3. package/dist/chart.js +2 -0
  4. package/dist/chart.js.map +1 -1
  5. package/dist/components/account-settings-labels.d.ts +105 -0
  6. package/dist/components/account-settings-labels.js +81 -0
  7. package/dist/components/account-settings-labels.js.map +1 -0
  8. package/dist/components/account-settings.d.ts +36 -52
  9. package/dist/components/account-settings.js +44 -8
  10. package/dist/components/account-settings.js.map +1 -1
  11. package/dist/components/alert-banner.d.ts +26 -1
  12. package/dist/components/alert-banner.js +10 -7
  13. package/dist/components/alert-banner.js.map +1 -1
  14. package/dist/components/amount-input.d.ts +26 -4
  15. package/dist/components/amount-input.js +5 -2
  16. package/dist/components/amount-input.js.map +1 -1
  17. package/dist/components/authed-image.d.ts +68 -0
  18. package/dist/components/authed-image.js +117 -0
  19. package/dist/components/authed-image.js.map +1 -0
  20. package/dist/components/breadcrumbs.d.ts +2 -1
  21. package/dist/components/breadcrumbs.js +5 -2
  22. package/dist/components/breadcrumbs.js.map +1 -1
  23. package/dist/components/bulk-action-bar.d.ts +51 -5
  24. package/dist/components/bulk-action-bar.js +88 -41
  25. package/dist/components/bulk-action-bar.js.map +1 -1
  26. package/dist/components/button-group.d.ts +107 -3
  27. package/dist/components/button-group.js +60 -5
  28. package/dist/components/button-group.js.map +1 -1
  29. package/dist/components/calculator.d.ts +17 -4
  30. package/dist/components/calendar-heatmap.d.ts +162 -0
  31. package/dist/components/calendar-heatmap.js +336 -0
  32. package/dist/components/calendar-heatmap.js.map +1 -0
  33. package/dist/components/chip.d.ts +2 -1
  34. package/dist/components/chip.js +6 -3
  35. package/dist/components/chip.js.map +1 -1
  36. package/dist/components/choice-card.d.ts +66 -2
  37. package/dist/components/choice-card.js +108 -1
  38. package/dist/components/choice-card.js.map +1 -1
  39. package/dist/components/combobox-core.js +2 -0
  40. package/dist/components/combobox-core.js.map +1 -1
  41. package/dist/components/combobox.d.ts +2 -2
  42. package/dist/components/combobox.js +31 -9
  43. package/dist/components/combobox.js.map +1 -1
  44. package/dist/components/copy-button.d.ts +52 -70
  45. package/dist/components/copy-button.js +1 -1
  46. package/dist/components/copy-button.js.map +1 -1
  47. package/dist/components/data-table-cells.d.ts +63 -0
  48. package/dist/components/data-table-cells.js +64 -0
  49. package/dist/components/data-table-cells.js.map +1 -0
  50. package/dist/components/data-table-filter-popover.d.ts +1 -1
  51. package/dist/components/data-table-filters.d.ts +1 -1
  52. package/dist/components/data-table-filters.js +31 -1
  53. package/dist/components/data-table-filters.js.map +1 -1
  54. package/dist/components/data-table-labels.d.ts +13 -0
  55. package/dist/components/data-table-labels.js +8 -1
  56. package/dist/components/data-table-labels.js.map +1 -1
  57. package/dist/components/data-table.d.ts +1 -1
  58. package/dist/components/data-table.js +104 -12
  59. package/dist/components/data-table.js.map +1 -1
  60. package/dist/components/date-picker.d.ts +3 -1
  61. package/dist/components/date-picker.js +15 -2
  62. package/dist/components/date-picker.js.map +1 -1
  63. package/dist/components/description-list.d.ts +23 -3
  64. package/dist/components/description-list.js +23 -3
  65. package/dist/components/description-list.js.map +1 -1
  66. package/dist/components/dialog-frame.d.ts +1 -0
  67. package/dist/components/entity-combobox.d.ts +1 -1
  68. package/dist/components/entity-combobox.js +18 -3
  69. package/dist/components/entity-combobox.js.map +1 -1
  70. package/dist/components/error-boundary.d.ts +92 -0
  71. package/dist/components/error-boundary.js +111 -0
  72. package/dist/components/error-boundary.js.map +1 -0
  73. package/dist/components/field.d.ts +69 -0
  74. package/dist/components/field.js +75 -0
  75. package/dist/components/field.js.map +1 -0
  76. package/dist/components/file-button.d.ts +51 -208
  77. package/dist/components/file-dropzone.d.ts +50 -2
  78. package/dist/components/floating-panel.d.ts +156 -4
  79. package/dist/components/floating-panel.js +193 -29
  80. package/dist/components/floating-panel.js.map +1 -1
  81. package/dist/components/form-actions.d.ts +53 -0
  82. package/dist/components/form-actions.js +98 -0
  83. package/dist/components/form-actions.js.map +1 -0
  84. package/dist/components/image-grid.d.ts +67 -0
  85. package/dist/components/image-grid.js +112 -0
  86. package/dist/components/image-grid.js.map +1 -0
  87. package/dist/components/lightbox.d.ts +104 -0
  88. package/dist/components/lightbox.js +229 -0
  89. package/dist/components/lightbox.js.map +1 -0
  90. package/dist/components/line-items.d.ts +114 -0
  91. package/dist/components/line-items.js +238 -0
  92. package/dist/components/line-items.js.map +1 -0
  93. package/dist/components/list.d.ts +37 -3
  94. package/dist/components/list.js +39 -14
  95. package/dist/components/list.js.map +1 -1
  96. package/dist/components/loading-state.d.ts +24 -0
  97. package/dist/components/loading-state.js +32 -0
  98. package/dist/components/loading-state.js.map +1 -0
  99. package/dist/components/menu-item.d.ts +13 -2
  100. package/dist/components/menu-item.js +11 -2
  101. package/dist/components/menu-item.js.map +1 -1
  102. package/dist/components/mini-calendar.d.ts +82 -5
  103. package/dist/components/mini-calendar.js +212 -64
  104. package/dist/components/mini-calendar.js.map +1 -1
  105. package/dist/components/modal.d.ts +20 -1
  106. package/dist/components/modal.js +26 -2
  107. package/dist/components/modal.js.map +1 -1
  108. package/dist/components/month-picker.d.ts +21 -1
  109. package/dist/components/month-picker.js +139 -26
  110. package/dist/components/month-picker.js.map +1 -1
  111. package/dist/components/multi-entity-combobox.d.ts +1 -1
  112. package/dist/components/multi-entity-combobox.js +19 -3
  113. package/dist/components/multi-entity-combobox.js.map +1 -1
  114. package/dist/components/nav-pills.d.ts +67 -0
  115. package/dist/components/nav-pills.js +69 -0
  116. package/dist/components/nav-pills.js.map +1 -0
  117. package/dist/components/number-field.d.ts +26 -5
  118. package/dist/components/number-field.js +5 -7
  119. package/dist/components/number-field.js.map +1 -1
  120. package/dist/components/number-input.d.ts +27 -5
  121. package/dist/components/number-input.js +7 -1
  122. package/dist/components/number-input.js.map +1 -1
  123. package/dist/components/numpad-sheet.d.ts +17 -4
  124. package/dist/components/passkeys-setting.d.ts +67 -0
  125. package/dist/components/passkeys-setting.js +214 -0
  126. package/dist/components/passkeys-setting.js.map +1 -0
  127. package/dist/components/picker-sheet.js +2 -1
  128. package/dist/components/picker-sheet.js.map +1 -1
  129. package/dist/components/pie-chart-labels.d.ts +20 -0
  130. package/dist/components/pie-chart-labels.js +12 -0
  131. package/dist/components/pie-chart-labels.js.map +1 -0
  132. package/dist/components/pie-chart.d.ts +101 -0
  133. package/dist/components/pie-chart.js +283 -0
  134. package/dist/components/pie-chart.js.map +1 -0
  135. package/dist/components/progress-bar.d.ts +73 -3
  136. package/dist/components/progress-bar.js +110 -8
  137. package/dist/components/progress-bar.js.map +1 -1
  138. package/dist/components/qr-code.d.ts +34 -0
  139. package/dist/components/qr-code.js +57 -0
  140. package/dist/components/qr-code.js.map +1 -0
  141. package/dist/components/search-field.d.ts +15 -3
  142. package/dist/components/search-field.js +5 -1
  143. package/dist/components/search-field.js.map +1 -1
  144. package/dist/components/series-chart.d.ts +16 -0
  145. package/dist/components/series-chart.js +4 -1
  146. package/dist/components/series-chart.js.map +1 -1
  147. package/dist/components/settings-fields.d.ts +50 -1
  148. package/dist/components/signed-amount.d.ts +121 -0
  149. package/dist/components/signed-amount.js +152 -0
  150. package/dist/components/signed-amount.js.map +1 -0
  151. package/dist/components/skeleton.d.ts +10 -3
  152. package/dist/components/skeleton.js +12 -2
  153. package/dist/components/skeleton.js.map +1 -1
  154. package/dist/components/stat-tile.d.ts +2 -1
  155. package/dist/components/stat-tile.js +5 -2
  156. package/dist/components/stat-tile.js.map +1 -1
  157. package/dist/components/status-dot.d.ts +6 -2
  158. package/dist/components/status-dot.js +6 -1
  159. package/dist/components/status-dot.js.map +1 -1
  160. package/dist/components/table.d.ts +77 -11
  161. package/dist/components/table.js +85 -17
  162. package/dist/components/table.js.map +1 -1
  163. package/dist/components/text-link.d.ts +176 -0
  164. package/dist/components/text-link.js +109 -0
  165. package/dist/components/text-link.js.map +1 -0
  166. package/dist/components/text.d.ts +8 -1
  167. package/dist/components/text.js +1 -0
  168. package/dist/components/text.js.map +1 -1
  169. package/dist/components/time-input.d.ts +50 -1
  170. package/dist/components/toggle-group.d.ts +28 -0
  171. package/dist/components/toggle-group.js +58 -9
  172. package/dist/components/toggle-group.js.map +1 -1
  173. package/dist/components/toggle-legend.d.ts +36 -3
  174. package/dist/components/toggle-legend.js +49 -0
  175. package/dist/components/toggle-legend.js.map +1 -1
  176. package/dist/components/tooltip.d.ts +11 -3
  177. package/dist/components/tooltip.js +2 -0
  178. package/dist/components/tooltip.js.map +1 -1
  179. package/dist/components/ui.d.ts +52 -729
  180. package/dist/components/ui.js +296 -27
  181. package/dist/components/ui.js.map +1 -1
  182. package/dist/components/use-table-state.d.ts +3 -52
  183. package/dist/components/use-table-state.js +128 -30
  184. package/dist/components/use-table-state.js.map +1 -1
  185. package/dist/components/user-avatar.d.ts +25 -3
  186. package/dist/components/user-avatar.js +32 -3
  187. package/dist/components/user-avatar.js.map +1 -1
  188. package/dist/{data-table-filters-Dh9uF_S-.d.ts → data-table-Drun8Fk9.d.ts} +305 -61
  189. package/dist/data-table.d.ts +2 -1
  190. package/dist/data-table.js +5 -1
  191. package/dist/data-table.js.map +1 -1
  192. package/dist/feedback/feedback-dialog.d.ts +26 -3
  193. package/dist/feedback/feedback-dialog.js +16 -2
  194. package/dist/feedback/feedback-dialog.js.map +1 -1
  195. package/dist/feedback/feedback-thread.d.ts +133 -0
  196. package/dist/feedback/feedback-thread.js +237 -0
  197. package/dist/feedback/feedback-thread.js.map +1 -0
  198. package/dist/feedback.d.ts +2 -1
  199. package/dist/feedback.js +1 -0
  200. package/dist/feedback.js.map +1 -1
  201. package/dist/hooks/use-authed-src.d.ts +71 -0
  202. package/dist/hooks/use-authed-src.js +63 -0
  203. package/dist/hooks/use-authed-src.js.map +1 -0
  204. package/dist/hooks/use-file-drop.d.ts +50 -2
  205. package/dist/hooks/use-hotkey.d.ts +59 -0
  206. package/dist/hooks/use-hotkey.js +105 -0
  207. package/dist/hooks/use-hotkey.js.map +1 -0
  208. package/dist/hooks/use-search-param-state.d.ts +83 -0
  209. package/dist/hooks/use-search-param-state.js +94 -0
  210. package/dist/hooks/use-search-param-state.js.map +1 -0
  211. package/dist/i18n/defaults.d.ts +17 -4
  212. package/dist/i18n/defaults.js +33 -1
  213. package/dist/i18n/defaults.js.map +1 -1
  214. package/dist/i18n/kit-labels.d.ts +47 -310
  215. package/dist/i18n/kit-labels.js +20 -5
  216. package/dist/i18n/kit-labels.js.map +1 -1
  217. package/dist/i18n/locales/de-CH-informal.d.ts +17 -4
  218. package/dist/i18n/locales/de-CH.d.ts +17 -4
  219. package/dist/i18n/locales/de-informal.d.ts +17 -4
  220. package/dist/i18n/locales/de.d.ts +17 -4
  221. package/dist/i18n/locales/de.js +165 -4
  222. package/dist/i18n/locales/de.js.map +1 -1
  223. package/dist/i18n/locales/es.d.ts +17 -4
  224. package/dist/i18n/locales/es.js +162 -4
  225. package/dist/i18n/locales/es.js.map +1 -1
  226. package/dist/i18n/locales/fr.d.ts +17 -4
  227. package/dist/i18n/locales/fr.js +162 -4
  228. package/dist/i18n/locales/fr.js.map +1 -1
  229. package/dist/i18n/locales/hu.d.ts +17 -4
  230. package/dist/i18n/locales/hu.js +162 -4
  231. package/dist/i18n/locales/hu.js.map +1 -1
  232. package/dist/i18n/locales/it.d.ts +17 -4
  233. package/dist/i18n/locales/it.js +162 -4
  234. package/dist/i18n/locales/it.js.map +1 -1
  235. package/dist/i18n/locales/zh.d.ts +17 -4
  236. package/dist/i18n/locales/zh.js +162 -4
  237. package/dist/i18n/locales/zh.js.map +1 -1
  238. package/dist/index.d.ts +45 -21
  239. package/dist/index.js +43 -1
  240. package/dist/index.js.map +1 -1
  241. package/dist/kit-labels-v3biUF1L.d.ts +1645 -0
  242. package/dist/lib/clipping.d.ts +21 -5
  243. package/dist/lib/clipping.js +3 -0
  244. package/dist/lib/clipping.js.map +1 -1
  245. package/dist/lib/dates.d.ts +17 -1
  246. package/dist/lib/dates.js +19 -0
  247. package/dist/lib/dates.js.map +1 -1
  248. package/dist/lib/format.d.ts +144 -0
  249. package/dist/lib/format.js +149 -0
  250. package/dist/lib/format.js.map +1 -0
  251. package/dist/lib/qr-encode.d.ts +44 -0
  252. package/dist/lib/qr-encode.js +338 -0
  253. package/dist/lib/qr-encode.js.map +1 -0
  254. package/dist/rhf/fields.d.ts +241 -0
  255. package/dist/rhf/fields.js +601 -0
  256. package/dist/rhf/fields.js.map +1 -0
  257. package/dist/rhf/form.d.ts +50 -1
  258. package/dist/rhf/line-items.d.ts +31 -0
  259. package/dist/rhf/line-items.js +59 -0
  260. package/dist/rhf/line-items.js.map +1 -0
  261. package/dist/rhf/use-rhf-wizard-step.d.ts +22 -0
  262. package/dist/rhf/use-rhf-wizard-step.js +38 -0
  263. package/dist/rhf/use-rhf-wizard-step.js.map +1 -0
  264. package/dist/rhf.d.ts +63 -1
  265. package/dist/rhf.js +3 -0
  266. package/dist/rhf.js.map +1 -1
  267. package/dist/shell/app-shell.d.ts +99 -2
  268. package/dist/shell/app-shell.js +58 -3
  269. package/dist/shell/app-shell.js.map +1 -1
  270. package/dist/shell/auth-layout.d.ts +74 -0
  271. package/dist/shell/auth-layout.js +97 -0
  272. package/dist/shell/auth-layout.js.map +1 -0
  273. package/dist/shell/top-bar-brand.d.ts +81 -0
  274. package/dist/shell/top-bar-brand.js +47 -0
  275. package/dist/shell/top-bar-brand.js.map +1 -0
  276. package/dist/shell/topbar-action-menu.d.ts +84 -3
  277. package/dist/shell/topbar-action-menu.js +115 -27
  278. package/dist/shell/topbar-action-menu.js.map +1 -1
  279. package/dist/shell.d.ts +58 -2
  280. package/dist/shell.js +2 -0
  281. package/dist/shell.js.map +1 -1
  282. package/dist/wizard/stepper-nav.d.ts +49 -1
  283. package/dist/wizard/wizard-context.d.ts +30 -1
  284. package/dist/wizard/wizard-context.js +23 -2
  285. package/dist/wizard/wizard-context.js.map +1 -1
  286. package/dist/wizard/wizard-step.d.ts +20 -5
  287. package/dist/wizard/wizard-step.js +16 -3
  288. package/dist/wizard/wizard-step.js.map +1 -1
  289. package/dist/wizard.d.ts +51 -3
  290. package/package.json +1 -1
  291. package/src/chart.ts +4 -0
  292. package/src/components/account-settings-labels.ts +190 -0
  293. package/src/components/account-settings.tsx +110 -63
  294. package/src/components/alert-banner.tsx +36 -7
  295. package/src/components/amount-input.tsx +13 -1
  296. package/src/components/authed-image.tsx +190 -0
  297. package/src/components/breadcrumbs.tsx +8 -2
  298. package/src/components/bulk-action-bar.tsx +163 -57
  299. package/src/components/button-group.tsx +129 -4
  300. package/src/components/calendar-heatmap.tsx +599 -0
  301. package/src/components/chip.tsx +8 -4
  302. package/src/components/choice-card.tsx +208 -1
  303. package/src/components/combobox-core.tsx +5 -0
  304. package/src/components/combobox.tsx +31 -9
  305. package/src/components/copy-button.tsx +3 -2
  306. package/src/components/data-table-cells.tsx +119 -0
  307. package/src/components/data-table-filters.ts +77 -0
  308. package/src/components/data-table-labels.ts +23 -0
  309. package/src/components/data-table.tsx +231 -13
  310. package/src/components/date-picker.tsx +19 -3
  311. package/src/components/description-list.tsx +52 -3
  312. package/src/components/entity-combobox.tsx +18 -3
  313. package/src/components/error-boundary.tsx +216 -0
  314. package/src/components/field.tsx +188 -0
  315. package/src/components/floating-panel.tsx +380 -16
  316. package/src/components/form-actions.tsx +191 -0
  317. package/src/components/image-grid.tsx +181 -0
  318. package/src/components/lightbox.tsx +374 -0
  319. package/src/components/line-items.tsx +385 -0
  320. package/src/components/list.tsx +93 -18
  321. package/src/components/loading-state.tsx +47 -0
  322. package/src/components/menu-item.tsx +29 -3
  323. package/src/components/mini-calendar.tsx +317 -57
  324. package/src/components/modal.tsx +61 -3
  325. package/src/components/month-picker.tsx +181 -26
  326. package/src/components/multi-entity-combobox.tsx +19 -3
  327. package/src/components/nav-pills.tsx +152 -0
  328. package/src/components/number-field.tsx +15 -10
  329. package/src/components/number-input.tsx +16 -1
  330. package/src/components/passkeys-setting.tsx +331 -0
  331. package/src/components/picker-sheet.tsx +7 -1
  332. package/src/components/pie-chart-labels.ts +32 -0
  333. package/src/components/pie-chart.tsx +479 -0
  334. package/src/components/progress-bar.tsx +241 -13
  335. package/src/components/qr-code.tsx +83 -0
  336. package/src/components/search-field.tsx +20 -4
  337. package/src/components/series-chart.tsx +21 -0
  338. package/src/components/signed-amount.tsx +286 -0
  339. package/src/components/skeleton.tsx +21 -3
  340. package/src/components/stat-tile.tsx +8 -2
  341. package/src/components/status-dot.tsx +10 -2
  342. package/src/components/table.tsx +186 -23
  343. package/src/components/text-link.tsx +248 -0
  344. package/src/components/text.tsx +9 -1
  345. package/src/components/toggle-group.tsx +106 -13
  346. package/src/components/toggle-legend.tsx +87 -2
  347. package/src/components/tooltip.tsx +17 -3
  348. package/src/components/ui.tsx +572 -44
  349. package/src/components/use-table-state.ts +265 -33
  350. package/src/components/user-avatar.tsx +57 -3
  351. package/src/data-table.ts +10 -0
  352. package/src/feedback/feedback-dialog.tsx +42 -3
  353. package/src/feedback/feedback-thread.tsx +434 -0
  354. package/src/feedback.ts +1 -0
  355. package/src/hooks/use-authed-src.ts +161 -0
  356. package/src/hooks/use-hotkey.ts +172 -0
  357. package/src/hooks/use-search-param-state.ts +187 -0
  358. package/src/i18n/defaults.ts +32 -0
  359. package/src/i18n/kit-labels.tsx +104 -8
  360. package/src/i18n/locales/de.ts +162 -0
  361. package/src/i18n/locales/es.ts +159 -0
  362. package/src/i18n/locales/fr.ts +162 -0
  363. package/src/i18n/locales/hu.ts +160 -0
  364. package/src/i18n/locales/it.ts +160 -0
  365. package/src/i18n/locales/zh.ts +159 -0
  366. package/src/index.ts +64 -0
  367. package/src/lib/clipping.ts +22 -4
  368. package/src/lib/dates.ts +37 -0
  369. package/src/lib/format.ts +325 -0
  370. package/src/lib/qr-encode.ts +420 -0
  371. package/src/rhf/fields.tsx +1054 -0
  372. package/src/rhf/line-items.tsx +130 -0
  373. package/src/rhf/use-rhf-wizard-step.ts +113 -0
  374. package/src/rhf.ts +8 -0
  375. package/src/shell/app-shell.tsx +147 -2
  376. package/src/shell/auth-layout.tsx +190 -0
  377. package/src/shell/top-bar-brand.tsx +76 -0
  378. package/src/shell/topbar-action-menu.tsx +260 -49
  379. package/src/shell.ts +2 -0
  380. package/src/wizard/wizard-context.tsx +50 -1
  381. package/src/wizard/wizard-step.tsx +43 -6
  382. package/tokens.css +12 -0
@@ -6,7 +6,8 @@ import { cn } from "../lib/cn.js";
6
6
  import { horizontalStep } from "../lib/direction.js";
7
7
  import { useMediaQuery } from "../hooks/use-media-query.js";
8
8
  import { Tooltip } from "./tooltip.js";
9
- import { DEFAULT_COMMON_LABELS, useKitLabels } from "../i18n/kit-labels.js";
9
+ import { DEFAULT_COMMON_LABELS, useKitLabels, useKitLink } from "../i18n/kit-labels.js";
10
+ import { pickLinkRenderer } from "./text-link.js";
10
11
  const BUTTON_BASE = "inline-flex items-center justify-center rounded-md font-medium transition-colors focus:outline-none focus:ring-2 disabled:opacity-50 disabled:cursor-not-allowed";
11
12
  const BUTTON_SIZES = {
12
13
  md: "gap-2 px-3 py-2 text-sm",
@@ -32,6 +33,10 @@ const BUTTON_TONES = {
32
33
  danger: "text-[var(--text-secondary)] hover:text-[var(--danger)] focus:ring-[var(--danger-border)] disabled:hover:text-[var(--text-secondary)]"
33
34
  };
34
35
  const TONED_VARIANTS = /* @__PURE__ */ new Set(["link", "ghost"]);
36
+ const BUTTON_BOXED_DANGER = {
37
+ secondary: "border-[var(--danger-border)] bg-transparent text-[var(--danger)] hover:bg-[var(--danger-bg)] focus:ring-[var(--danger-border)]",
38
+ primary: "border-[var(--danger-border)] bg-[var(--danger-bg)] text-[var(--danger)] hover:border-[var(--danger)] hover:bg-[var(--danger)] hover:text-[var(--danger-contrast)] focus:ring-[var(--danger-border)] disabled:hover:border-[var(--danger-border)] disabled:hover:bg-[var(--danger-bg)] disabled:hover:text-[var(--danger)]"
39
+ };
35
40
  const BUTTON_LINK_PRESSED = "font-medium text-[var(--brand)] hover:text-[var(--brand)] disabled:hover:text-[var(--brand)]";
36
41
  function buttonClasses(variant = "primary", classNameOrOptions) {
37
42
  const { size = "md", className } = typeof classNameOrOptions === "object" ? classNameOrOptions : { className: classNameOrOptions };
@@ -40,49 +45,151 @@ function buttonClasses(variant = "primary", classNameOrOptions) {
40
45
  function hasContent(node) {
41
46
  return node !== void 0 && node !== null && node !== false && node !== "";
42
47
  }
43
- function Button({
48
+ function buttonLook(variant, size, stretch, tone) {
49
+ return cn(
50
+ BUTTON_BASE,
51
+ BUTTON_SIZES[size],
52
+ // In a flex row next to a taller labelled field, `stretch` makes the button
53
+ // fill the field's height so the two line up (self-stretch overrides the row's
54
+ // align-items). No effect outside a flex row / when it's already the tallest.
55
+ stretch && "self-stretch",
56
+ buttonVariantClasses[variant],
57
+ tone !== "default" && TONED_VARIANTS.has(variant) && BUTTON_TONES[tone],
58
+ tone === "danger" && BUTTON_BOXED_DANGER[variant]
59
+ );
60
+ }
61
+ function Button(props) {
62
+ if (props.href !== void 0) return /* @__PURE__ */ jsx(ButtonLink, { ...props });
63
+ return /* @__PURE__ */ jsx(ButtonElement, { ...props });
64
+ }
65
+ function RenderedButtonLink({ render, ...props }) {
66
+ return render(props);
67
+ }
68
+ function ButtonLink({
69
+ href,
70
+ renderLink,
71
+ external,
72
+ disabled,
73
+ variant = "primary",
74
+ size = "md",
75
+ stretch,
76
+ tone = "default",
77
+ className,
78
+ children,
79
+ target,
80
+ rel,
81
+ onClick,
82
+ ...rest
83
+ }) {
84
+ const kitLink = useKitLink();
85
+ const common = useKitLabels("common", DEFAULT_COMMON_LABELS);
86
+ const Link = pickLinkRenderer(renderLink, kitLink, href);
87
+ const newTab = !disabled && (external || target === "_blank");
88
+ const cls = cn(
89
+ buttonLook(variant, size, stretch, tone),
90
+ // `relative` holds the sr-only note (see sr-only-containment.test).
91
+ newTab && "relative",
92
+ // BUTTON_BASE's `disabled:` classes never match an `<a>`; no pointer events also
93
+ // keeps the hover fill from lighting up on something that refuses the click.
94
+ disabled && "pointer-events-none cursor-not-allowed opacity-50",
95
+ className
96
+ );
97
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
98
+ children,
99
+ newTab && " ",
100
+ newTab && /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
101
+ "(",
102
+ common.opensInNewTab,
103
+ ")"
104
+ ] })
105
+ ] });
106
+ if (disabled) {
107
+ return /* @__PURE__ */ jsx("a", { ...rest, role: "link", "aria-disabled": "true", className: cls, children: body });
108
+ }
109
+ if (external || !Link) {
110
+ return /* @__PURE__ */ jsx(
111
+ "a",
112
+ {
113
+ ...rest,
114
+ href,
115
+ target: external ? "_blank" : target,
116
+ rel: external ? rel ?? "noopener noreferrer" : rel,
117
+ onClick,
118
+ className: cls,
119
+ children: body
120
+ }
121
+ );
122
+ }
123
+ return /* @__PURE__ */ jsx(
124
+ RenderedButtonLink,
125
+ {
126
+ render: Link,
127
+ ...rest,
128
+ href,
129
+ target,
130
+ rel,
131
+ onClick,
132
+ className: cls,
133
+ children: body
134
+ }
135
+ );
136
+ }
137
+ function ButtonElement({
44
138
  variant = "primary",
45
139
  size = "md",
46
140
  stretch,
47
141
  tone = "default",
48
142
  pressed,
49
143
  disabledReason,
144
+ pending,
50
145
  className,
51
146
  onClick,
147
+ children,
148
+ href: _href,
149
+ renderLink: _renderLink,
150
+ external: _external,
52
151
  ...rest
53
152
  }) {
54
153
  const reasonId = useId();
55
154
  const locked = hasContent(disabledReason);
155
+ const inert = locked || Boolean(pending);
56
156
  const ownDescribedBy = rest["aria-describedby"];
57
157
  const button = /* @__PURE__ */ jsx(
58
158
  "button",
59
159
  {
60
160
  ...rest,
61
- disabled: locked ? void 0 : rest.disabled,
62
- "aria-disabled": locked || rest["aria-disabled"],
161
+ disabled: inert ? void 0 : rest.disabled,
162
+ "aria-disabled": inert || rest["aria-disabled"],
163
+ "aria-busy": pending || rest["aria-busy"],
63
164
  "aria-describedby": locked ? ownDescribedBy ? `${ownDescribedBy} ${reasonId}` : reasonId : ownDescribedBy,
64
165
  "aria-pressed": pressed ?? rest["aria-pressed"],
65
166
  onClick: (e) => {
66
- if (locked) {
167
+ if (inert) {
67
168
  e.preventDefault();
68
169
  return;
69
170
  }
70
171
  onClick?.(e);
71
172
  },
72
173
  className: cn(
73
- BUTTON_BASE,
74
- BUTTON_SIZES[size],
75
- // In a flex row next to a taller labelled field, `stretch` makes the button
76
- // fill the field's height so the two line up (self-stretch overrides the row's
77
- // align-items). No effect outside a flex row / when it's already the tallest.
78
- stretch && "self-stretch",
79
- buttonVariantClasses[variant],
80
- tone !== "default" && TONED_VARIANTS.has(variant) && BUTTON_TONES[tone],
174
+ buttonLook(variant, size, stretch, tone),
81
175
  pressed && (variant === "link" ? BUTTON_LINK_PRESSED : ICON_BUTTON_PRESSED),
82
176
  // The disabled look for the focusable kind of disabled.
83
177
  locked && "cursor-not-allowed opacity-50",
178
+ // No dimming while pending: the spinner IS the state, and at half opacity it
179
+ // would be the faintest thing on the button. `relative` anchors it.
180
+ pending && "relative cursor-progress",
84
181
  className
85
- )
182
+ ),
183
+ children: pending ? /* @__PURE__ */ jsxs(Fragment, { children: [
184
+ /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center gap-[inherit] opacity-0", children }),
185
+ /* @__PURE__ */ jsx(
186
+ Spinner,
187
+ {
188
+ label: null,
189
+ className: "absolute inset-0 m-auto size-4 border-current/30 border-t-current"
190
+ }
191
+ )
192
+ ] }) : children
86
193
  }
87
194
  );
88
195
  if (!locked) return button;
@@ -99,6 +206,12 @@ function Button({
99
206
  }
100
207
  const ICON_BUTTON_BASE = "inline-flex items-center justify-center rounded-md transition-colors focus:outline-none focus:ring-2 disabled:opacity-50 disabled:cursor-not-allowed";
101
208
  const ICON_BUTTON_SIZES = {
209
+ // 64px with a 28px glyph: a camera's shutter (keksdose invoices/camera-capture.tsx:248,
210
+ // `size-16` by hand) — the one control of a full-screen capture view, thumb-sized.
211
+ "2xl": "size-16 [&_svg]:size-7",
212
+ // 48px with a 24px glyph: the one primary action of a phone screen or sheet, a step
213
+ // past the 44px minimum rather than on it.
214
+ xl: "size-12 [&_svg]:size-6",
102
215
  // The 44px touch target (WCAG 2.5.5's size) with the same 20px glyph — keksdose's
103
216
  // bulk-action bars write `size-11` by hand over an `md` button to get it on phones.
104
217
  lg: "size-11 [&_svg]:size-5",
@@ -107,6 +220,15 @@ const ICON_BUTTON_SIZES = {
107
220
  xs: "size-7 rounded [&_svg]:size-4",
108
221
  "2xs": "size-6 rounded [&_svg]:size-3.5"
109
222
  };
223
+ const ICON_BUTTON_STRETCH_SIZES = {
224
+ "2xl": "w-16 min-h-16 self-stretch [&_svg]:size-7",
225
+ xl: "w-12 min-h-12 self-stretch [&_svg]:size-6",
226
+ lg: "w-11 min-h-11 self-stretch [&_svg]:size-5",
227
+ md: "w-9 min-h-9 self-stretch [&_svg]:size-5",
228
+ sm: "w-8 min-h-8 self-stretch [&_svg]:size-5",
229
+ xs: "w-7 min-h-7 self-stretch rounded [&_svg]:size-4",
230
+ "2xs": "w-6 min-h-6 self-stretch rounded [&_svg]:size-3.5"
231
+ };
110
232
  const ICON_BUTTON_TONES = {
111
233
  danger: {
112
234
  quiet: "text-[var(--text-placeholder)] hover:bg-[var(--danger-bg)] hover:text-[var(--danger)] focus:ring-[var(--danger-border)]",
@@ -119,10 +241,27 @@ const ICON_BUTTON_TONES = {
119
241
  info: {
120
242
  quiet: "text-[var(--text-placeholder)] hover:bg-[var(--info-bg)] hover:text-[var(--info)] focus:ring-[var(--info-border)]",
121
243
  toned: "text-[var(--info)] hover:bg-[var(--info-bg)] focus:ring-[var(--info-border)]"
244
+ },
245
+ success: {
246
+ quiet: "text-[var(--text-placeholder)] hover:bg-[var(--success-bg)] hover:text-[var(--success)] focus:ring-[var(--success-border)]",
247
+ toned: "text-[var(--success)] hover:bg-[var(--success-bg)] focus:ring-[var(--success-border)]"
248
+ },
249
+ // The hover fill and the ring are MIXED from the one colour, since a custom tone
250
+ // brings no `-bg` / `-border` pair of its own. The fallback is the body colour, so a
251
+ // `custom` tone with no colour set is the default look rather than invisible.
252
+ custom: {
253
+ quiet: "text-[var(--text-placeholder)] hover:bg-[color-mix(in_srgb,var(--icon-button-tone,var(--text-primary))_12%,transparent)] hover:text-[var(--icon-button-tone,var(--text-primary))] focus:ring-[color-mix(in_srgb,var(--icon-button-tone,var(--text-primary))_40%,transparent)]",
254
+ toned: "text-[var(--icon-button-tone,var(--text-primary))] hover:bg-[color-mix(in_srgb,var(--icon-button-tone,var(--text-primary))_12%,transparent)] focus:ring-[color-mix(in_srgb,var(--icon-button-tone,var(--text-primary))_40%,transparent)]"
122
255
  }
123
256
  };
124
257
  const ICON_BUTTON_MUTED = "text-[var(--text-placeholder)] hover:bg-[var(--bg-surface-2)] hover:text-[var(--text-primary)]";
125
- const QUIET_BY_DEFAULT = { danger: true, warning: false, info: false };
258
+ const QUIET_BY_DEFAULT = {
259
+ danger: true,
260
+ warning: false,
261
+ info: false,
262
+ success: false,
263
+ custom: false
264
+ };
126
265
  function iconButtonToneClass(tone, quiet) {
127
266
  if (tone === "default") return "";
128
267
  if (tone === "muted") return cn(ICON_BUTTON_MUTED, ICON_BUTTON_QUIET_DISABLED_REST);
@@ -137,36 +276,67 @@ const ICON_BUTTON_DISABLED_REST = {
137
276
  danger: "disabled:hover:bg-[var(--danger)]",
138
277
  brand: "disabled:hover:bg-[var(--brand)]",
139
278
  link: "disabled:hover:bg-transparent disabled:hover:no-underline",
140
- overlay: "disabled:hover:bg-[color-mix(in_srgb,var(--bg-inverse)_60%,transparent)]"
279
+ overlay: "disabled:hover:bg-[color-mix(in_srgb,var(--bg-inverse)_60%,transparent)]",
280
+ shutter: "disabled:hover:bg-[var(--media-scrim)]"
141
281
  };
142
282
  const ICON_BUTTON_QUIET_DISABLED_REST = "disabled:hover:text-[var(--text-placeholder)]";
143
283
  const ICON_BUTTON_PRESSED = "bg-[var(--brand-bg)] text-[var(--brand)] hover:bg-[var(--brand-bg-hover)] hover:text-[var(--brand)] disabled:hover:bg-[var(--brand-bg)] disabled:hover:text-[var(--brand)]";
144
284
  const ICON_BUTTON_OVERLAY = "rounded-full bg-[color-mix(in_srgb,var(--bg-inverse)_60%,transparent)] text-[var(--text-inverse)] backdrop-blur-sm hover:bg-[color-mix(in_srgb,var(--bg-inverse)_75%,transparent)] focus:ring-[var(--text-inverse)]";
285
+ const ICON_BUTTON_SHUTTER = "rounded-full border-4 border-[var(--media-ink)] bg-[var(--media-scrim)] text-[var(--media-ink)] backdrop-blur-sm hover:bg-[var(--media-scrim-hover)] focus:ring-[var(--media-ink)] focus:ring-offset-2 focus:ring-offset-[var(--media-scrim-hover)]";
286
+ const ICON_BUTTON_GLYPH_SIZES = {
287
+ 12: "[&_svg]:size-3",
288
+ 14: "[&_svg]:size-3.5",
289
+ 16: "[&_svg]:size-4",
290
+ 20: "[&_svg]:size-5",
291
+ 24: "[&_svg]:size-6",
292
+ 28: "[&_svg]:size-7"
293
+ };
145
294
  const IconButton = forwardRef(function IconButton2({
146
295
  variant = "ghost",
147
296
  size = "md",
148
- tone = "default",
297
+ tone: toneProp,
149
298
  quiet,
150
299
  pressed,
151
300
  stopPropagation,
301
+ stretch,
302
+ shape = "square",
303
+ toneColor,
152
304
  label,
153
305
  tooltip = true,
154
306
  tooltipSide,
155
307
  tooltipPortal,
308
+ disabledReason,
309
+ glyphSize,
310
+ badge,
311
+ disabledStyle = "dim",
156
312
  className,
313
+ style,
157
314
  onClick,
158
315
  onKeyDown,
159
316
  ...rest
160
317
  }, ref) {
318
+ const tone = toneProp ?? (toneColor !== void 0 ? "custom" : "default");
319
+ const keep = disabledStyle === "keep";
320
+ const reasonId = useId();
321
+ const locked = hasContent(disabledReason);
322
+ const ownDescribedBy = rest["aria-describedby"];
161
323
  const button = /* @__PURE__ */ jsx(
162
324
  "button",
163
325
  {
164
326
  ref,
165
327
  ...rest,
328
+ disabled: locked ? void 0 : rest.disabled,
329
+ "aria-disabled": locked || rest["aria-disabled"],
330
+ "aria-describedby": locked ? ownDescribedBy ? `${ownDescribedBy} ${reasonId}` : reasonId : ownDescribedBy,
166
331
  "aria-label": rest["aria-label"] ?? label,
167
332
  "aria-pressed": pressed ?? rest["aria-pressed"],
333
+ style: toneColor !== void 0 ? { ...style, ["--icon-button-tone"]: toneColor } : style,
168
334
  onClick: (e) => {
169
335
  if (stopPropagation) e.stopPropagation();
336
+ if (locked) {
337
+ e.preventDefault();
338
+ return;
339
+ }
170
340
  onClick?.(e);
171
341
  },
172
342
  onKeyDown: (e) => {
@@ -175,21 +345,57 @@ const IconButton = forwardRef(function IconButton2({
175
345
  },
176
346
  className: cn(
177
347
  ICON_BUTTON_BASE,
178
- ICON_BUTTON_SIZES[size],
348
+ stretch ? ICON_BUTTON_STRETCH_SIZES[size] : ICON_BUTTON_SIZES[size],
349
+ glyphSize !== void 0 && ICON_BUTTON_GLYPH_SIZES[glyphSize],
179
350
  // After the size, so the overlay's `rounded-full` beats the small sizes' `rounded`.
180
- variant === "overlay" ? ICON_BUTTON_OVERLAY : buttonVariantClasses[variant],
351
+ variant === "overlay" ? ICON_BUTTON_OVERLAY : variant === "shutter" ? ICON_BUTTON_SHUTTER : buttonVariantClasses[variant],
352
+ shape === "round" && "rounded-full",
181
353
  ICON_BUTTON_DISABLED_REST[variant],
182
354
  iconButtonToneClass(tone, quiet),
183
355
  pressed && ICON_BUTTON_PRESSED,
356
+ // The disabled look for the focusable kind of disabled, as on Button.
357
+ locked && (keep ? "cursor-default" : "cursor-not-allowed opacity-50"),
358
+ keep && "disabled:cursor-default disabled:opacity-100",
184
359
  className
185
360
  )
186
361
  }
187
362
  );
188
- if (!tooltip || label === void 0 || label === "") return button;
363
+ const control = hasContent(badge) ? /* @__PURE__ */ jsxs("span", { className: cn("relative inline-flex shrink-0", stretch && "self-stretch"), children: [
364
+ button,
365
+ /* @__PURE__ */ jsx(
366
+ "span",
367
+ {
368
+ "aria-hidden": true,
369
+ "data-slot": "icon-button-badge",
370
+ className: "pointer-events-none absolute -end-0.5 -bottom-0.5 inline-flex rounded-full bg-[var(--bg-surface)] [&_svg]:size-3",
371
+ children: badge
372
+ }
373
+ )
374
+ ] }) : button;
375
+ if (locked) {
376
+ return (
377
+ // Button's shape: the button and the hidden reason in a FRAGMENT, so Tooltip does
378
+ // not add its bubble to the description as well.
379
+ /* @__PURE__ */ jsx(
380
+ Tooltip,
381
+ {
382
+ label: disabledReason,
383
+ side: tooltipSide,
384
+ portal: tooltipPortal,
385
+ className: stretch ? "self-stretch" : void 0,
386
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [
387
+ control,
388
+ /* @__PURE__ */ jsx("span", { id: reasonId, hidden: true, children: disabledReason })
389
+ ] })
390
+ }
391
+ )
392
+ );
393
+ }
394
+ if (!tooltip || label === void 0 || label === "") return control;
189
395
  return (
190
396
  // A fragment, so Tooltip leaves the button's description alone: the bubble says
191
397
  // exactly what `aria-label` already does.
192
- /* @__PURE__ */ jsx(Tooltip, { label, side: tooltipSide, portal: tooltipPortal, children: /* @__PURE__ */ jsx(Fragment, { children: button }) })
398
+ /* @__PURE__ */ jsx(Tooltip, { label, side: tooltipSide, portal: tooltipPortal, className: stretch ? "self-stretch" : void 0, children: /* @__PURE__ */ jsx(Fragment, { children: control }) })
193
399
  );
194
400
  });
195
401
  IconButton.displayName = "IconButton";
@@ -560,19 +766,55 @@ const Textarea = forwardRef(function Textarea2({ className, label, id, placehold
560
766
  ) }) });
561
767
  });
562
768
  Textarea.displayName = "Textarea";
563
- function Card({ className, children, flush, variant = "default", ...rest }) {
769
+ const CARD_TONES = {
770
+ warning: {
771
+ border: "border-[var(--warning-border)]",
772
+ fill: "bg-[var(--warning-bg)]",
773
+ title: "[&_[data-slot=card-title]]:text-[var(--warning)]"
774
+ },
775
+ danger: {
776
+ border: "border-[var(--danger-border)]",
777
+ fill: "bg-[var(--danger-bg)]",
778
+ title: "[&_[data-slot=card-title]]:text-[var(--danger)]"
779
+ },
780
+ info: {
781
+ border: "border-[var(--info-border)]",
782
+ fill: "bg-[var(--info-bg)]",
783
+ title: "[&_[data-slot=card-title]]:text-[var(--info)]"
784
+ },
785
+ success: {
786
+ border: "border-[var(--success-border)]",
787
+ fill: "bg-[var(--success-bg)]",
788
+ title: "[&_[data-slot=card-title]]:text-[var(--success)]"
789
+ }
790
+ };
791
+ const CARD_PADDING = {
792
+ none: "p-0",
793
+ sm: "p-3",
794
+ md: "p-4"
795
+ };
796
+ function Card({ className, children, flush, variant = "default", tone, padding, ...rest }) {
797
+ const toned = tone ? CARD_TONES[tone] : void 0;
798
+ const bordered = variant !== "inset";
564
799
  return /* @__PURE__ */ jsx(
565
800
  "div",
566
801
  {
802
+ "data-tone": tone,
567
803
  ...rest,
568
804
  className: cn(
569
- variant === "inset" ? "rounded-md bg-[var(--bg-surface-2)] p-3" : cn(
805
+ variant === "inset" ? "rounded-md bg-[var(--bg-surface-2)] p-3" : variant === "outline" ? (
806
+ // No shadow and no `flush`: it sits on a surface that already has both.
807
+ "rounded-lg border border-[var(--border)] bg-[var(--bg-surface)] p-4"
808
+ ) : cn(
570
809
  // Surface + border are theme tokens so the palette switcher (feedback
571
810
  // #307) can re-skin every card; a caller's own bg-*/border-* override
572
811
  // still wins via tailwind-merge.
573
812
  "bg-[var(--bg-surface)]",
574
813
  flush ? "border-y border-[var(--border)] md:rounded-lg md:border md:shadow-sm" : "rounded-lg border border-[var(--border)] shadow-sm"
575
814
  ),
815
+ toned && (bordered ? toned.border : toned.fill),
816
+ toned?.title,
817
+ padding && CARD_PADDING[padding],
576
818
  className
577
819
  ),
578
820
  children
@@ -637,7 +879,7 @@ function CardFooter({ className, ...props }) {
637
879
  }
638
880
  );
639
881
  }
640
- function Spinner({ className, label, ...rest }) {
882
+ function Spinner({ className, label, showLabel, labelPosition = "end", ...rest }) {
641
883
  const common = useKitLabels("common", DEFAULT_COMMON_LABELS, {
642
884
  loading: label ?? void 0
643
885
  });
@@ -646,6 +888,23 @@ function Spinner({ className, label, ...rest }) {
646
888
  className
647
889
  );
648
890
  if (label === null) return /* @__PURE__ */ jsx("span", { "aria-hidden": true, ...rest, className: ring });
891
+ if (showLabel) {
892
+ return /* @__PURE__ */ jsxs(
893
+ "span",
894
+ {
895
+ role: "status",
896
+ ...rest,
897
+ className: cn(
898
+ "inline-flex items-center text-sm text-[var(--text-secondary)]",
899
+ labelPosition === "below" ? "flex-col gap-2 text-center" : "gap-2"
900
+ ),
901
+ children: [
902
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: ring }),
903
+ /* @__PURE__ */ jsx("span", { children: common.loading })
904
+ ]
905
+ }
906
+ );
907
+ }
649
908
  return /* @__PURE__ */ jsx("span", { role: "status", ...rest, className: ring, children: /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
650
909
  common.loading,
651
910
  " "
@@ -663,6 +922,7 @@ function EmptyState({
663
922
  headingAs,
664
923
  variant = "box",
665
924
  tone,
925
+ size = "md",
666
926
  className,
667
927
  ...rest
668
928
  }) {
@@ -670,17 +930,26 @@ function EmptyState({
670
930
  const toneClass = tone ? EMPTY_STATE_TONE[tone] : void 0;
671
931
  const hasHint = hint != null && hint !== false && hint !== "";
672
932
  if (variant === "inline") {
933
+ const sm = size === "sm";
673
934
  return /* @__PURE__ */ jsxs(
674
935
  "div",
675
936
  {
676
937
  ...rest,
677
938
  className: cn(
678
- "flex flex-wrap items-center justify-center gap-x-2 gap-y-1 py-4 text-center text-sm text-[var(--text-muted)]",
939
+ "flex flex-wrap items-center text-[var(--text-muted)]",
940
+ sm ? "justify-start gap-x-1.5 gap-y-0.5 py-1 text-start text-xs" : "justify-center gap-x-2 gap-y-1 py-4 text-center text-sm",
679
941
  className
680
942
  ),
681
943
  children: [
682
- icon != null && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("flex text-[var(--text-placeholder)] [&_svg]:size-4", toneClass), children: icon }),
683
- /* @__PURE__ */ jsx(Title, { className: cn("text-sm", toneClass), children: title }),
944
+ icon != null && /* @__PURE__ */ jsx(
945
+ "span",
946
+ {
947
+ "aria-hidden": true,
948
+ className: cn("flex text-[var(--text-placeholder)]", sm ? "[&_svg]:size-3.5" : "[&_svg]:size-4", toneClass),
949
+ children: icon
950
+ }
951
+ ),
952
+ /* @__PURE__ */ jsx(Title, { className: cn(sm ? "text-xs" : "text-sm", toneClass), children: title }),
684
953
  hasHint && /* @__PURE__ */ jsx("span", { className: "text-xs", children: hint }),
685
954
  action != null && /* @__PURE__ */ jsx("span", { className: "flex flex-wrap items-center gap-2", children: action })
686
955
  ]