@eifi1/ui-kit 0.11.0 → 0.13.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 (397) hide show
  1. package/README.md +59 -34
  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/amount-input.d.ts +40 -4
  12. package/dist/components/amount-input.js +50 -12
  13. package/dist/components/amount-input.js.map +1 -1
  14. package/dist/components/authed-image.d.ts +68 -0
  15. package/dist/components/authed-image.js +117 -0
  16. package/dist/components/authed-image.js.map +1 -0
  17. package/dist/components/breadcrumbs.d.ts +2 -1
  18. package/dist/components/breadcrumbs.js +5 -2
  19. package/dist/components/breadcrumbs.js.map +1 -1
  20. package/dist/components/bulk-action-bar.d.ts +10 -2
  21. package/dist/components/bulk-action-bar.js.map +1 -1
  22. package/dist/components/button-group.d.ts +51 -2
  23. package/dist/components/button-group.js +5 -1
  24. package/dist/components/button-group.js.map +1 -1
  25. package/dist/components/calculator.d.ts +15 -4
  26. package/dist/components/calendar-heatmap.d.ts +41 -3
  27. package/dist/components/calendar-heatmap.js +48 -7
  28. package/dist/components/calendar-heatmap.js.map +1 -1
  29. package/dist/components/chart.js +14 -8
  30. package/dist/components/chart.js.map +1 -1
  31. package/dist/components/chip.d.ts +2 -1
  32. package/dist/components/chip.js +26 -18
  33. package/dist/components/chip.js.map +1 -1
  34. package/dist/components/choice-card.d.ts +35 -3
  35. package/dist/components/choice-card.js +83 -25
  36. package/dist/components/choice-card.js.map +1 -1
  37. package/dist/components/combobox-core.d.ts +3 -1
  38. package/dist/components/combobox-core.js +18 -5
  39. package/dist/components/combobox-core.js.map +1 -1
  40. package/dist/components/combobox.d.ts +2 -2
  41. package/dist/components/combobox.js +31 -9
  42. package/dist/components/combobox.js.map +1 -1
  43. package/dist/components/copy-button.d.ts +51 -70
  44. package/dist/components/copy-button.js +1 -1
  45. package/dist/components/copy-button.js.map +1 -1
  46. package/dist/components/data-table-cells.d.ts +63 -0
  47. package/dist/components/data-table-cells.js +64 -0
  48. package/dist/components/data-table-cells.js.map +1 -0
  49. package/dist/components/data-table-filter-popover.d.ts +1 -1
  50. package/dist/components/data-table-filter-popover.js +8 -1
  51. package/dist/components/data-table-filter-popover.js.map +1 -1
  52. package/dist/components/data-table-filters.d.ts +1 -1
  53. package/dist/components/data-table-filters.js +31 -1
  54. package/dist/components/data-table-filters.js.map +1 -1
  55. package/dist/components/data-table-labels.d.ts +13 -0
  56. package/dist/components/data-table-labels.js +8 -1
  57. package/dist/components/data-table-labels.js.map +1 -1
  58. package/dist/components/data-table.d.ts +1 -1
  59. package/dist/components/data-table.js +125 -27
  60. package/dist/components/data-table.js.map +1 -1
  61. package/dist/components/date-picker.d.ts +3 -1
  62. package/dist/components/date-picker.js +15 -2
  63. package/dist/components/date-picker.js.map +1 -1
  64. package/dist/components/description-list.d.ts +23 -3
  65. package/dist/components/description-list.js +23 -3
  66. package/dist/components/description-list.js.map +1 -1
  67. package/dist/components/dialog-frame.d.ts +1 -0
  68. package/dist/components/entity-combobox.d.ts +1 -1
  69. package/dist/components/entity-combobox.js +40 -20
  70. package/dist/components/entity-combobox.js.map +1 -1
  71. package/dist/components/error-boundary.d.ts +281 -0
  72. package/dist/components/error-boundary.js +302 -0
  73. package/dist/components/error-boundary.js.map +1 -0
  74. package/dist/components/field-sync.js +90 -83
  75. package/dist/components/field-sync.js.map +1 -1
  76. package/dist/components/field.d.ts +30 -4
  77. package/dist/components/field.js +40 -17
  78. package/dist/components/field.js.map +1 -1
  79. package/dist/components/file-button.d.ts +50 -208
  80. package/dist/components/file-dropzone.d.ts +49 -2
  81. package/dist/components/floating-panel.d.ts +13 -4
  82. package/dist/components/floating-panel.js +7 -3
  83. package/dist/components/floating-panel.js.map +1 -1
  84. package/dist/components/form-actions.d.ts +53 -0
  85. package/dist/components/form-actions.js +98 -0
  86. package/dist/components/form-actions.js.map +1 -0
  87. package/dist/components/full-bleed-dialog.js +4 -0
  88. package/dist/components/full-bleed-dialog.js.map +1 -1
  89. package/dist/components/hover-menu.js +64 -56
  90. package/dist/components/hover-menu.js.map +1 -1
  91. package/dist/components/image-grid.d.ts +67 -0
  92. package/dist/components/image-grid.js +112 -0
  93. package/dist/components/image-grid.js.map +1 -0
  94. package/dist/components/lightbox.d.ts +104 -0
  95. package/dist/components/lightbox.js +229 -0
  96. package/dist/components/lightbox.js.map +1 -0
  97. package/dist/components/line-items.d.ts +114 -0
  98. package/dist/components/line-items.js +238 -0
  99. package/dist/components/line-items.js.map +1 -0
  100. package/dist/components/list.d.ts +37 -4
  101. package/dist/components/list.js +35 -14
  102. package/dist/components/list.js.map +1 -1
  103. package/dist/components/loading-state.d.ts +24 -0
  104. package/dist/components/loading-state.js +32 -0
  105. package/dist/components/loading-state.js.map +1 -0
  106. package/dist/components/menu-item.d.ts +2 -1
  107. package/dist/components/menu-item.js +5 -1
  108. package/dist/components/menu-item.js.map +1 -1
  109. package/dist/components/mini-calendar.d.ts +13 -1
  110. package/dist/components/mini-calendar.js +46 -2
  111. package/dist/components/mini-calendar.js.map +1 -1
  112. package/dist/components/modal.d.ts +20 -1
  113. package/dist/components/modal.js +26 -2
  114. package/dist/components/modal.js.map +1 -1
  115. package/dist/components/month-picker.d.ts +21 -1
  116. package/dist/components/month-picker.js +139 -26
  117. package/dist/components/month-picker.js.map +1 -1
  118. package/dist/components/multi-entity-combobox.d.ts +1 -1
  119. package/dist/components/multi-entity-combobox.js +42 -20
  120. package/dist/components/multi-entity-combobox.js.map +1 -1
  121. package/dist/components/nav-pills.d.ts +2 -1
  122. package/dist/components/nav-pills.js +5 -1
  123. package/dist/components/nav-pills.js.map +1 -1
  124. package/dist/components/number-field.d.ts +24 -5
  125. package/dist/components/number-field.js +5 -7
  126. package/dist/components/number-field.js.map +1 -1
  127. package/dist/components/number-input.d.ts +25 -5
  128. package/dist/components/number-input.js +7 -1
  129. package/dist/components/number-input.js.map +1 -1
  130. package/dist/components/numpad-sheet.d.ts +20 -5
  131. package/dist/components/numpad-sheet.js +3 -2
  132. package/dist/components/numpad-sheet.js.map +1 -1
  133. package/dist/components/page-header.d.ts +35 -6
  134. package/dist/components/page-header.js +7 -1
  135. package/dist/components/page-header.js.map +1 -1
  136. package/dist/components/passkeys-setting.d.ts +67 -0
  137. package/dist/components/passkeys-setting.js +214 -0
  138. package/dist/components/passkeys-setting.js.map +1 -0
  139. package/dist/components/picker-sheet.js +5 -1
  140. package/dist/components/picker-sheet.js.map +1 -1
  141. package/dist/components/pie-chart-labels.d.ts +20 -0
  142. package/dist/components/pie-chart-labels.js +12 -0
  143. package/dist/components/pie-chart-labels.js.map +1 -0
  144. package/dist/components/pie-chart.d.ts +101 -0
  145. package/dist/components/pie-chart.js +283 -0
  146. package/dist/components/pie-chart.js.map +1 -0
  147. package/dist/components/popover.js +3 -0
  148. package/dist/components/popover.js.map +1 -1
  149. package/dist/components/progress-bar.d.ts +44 -3
  150. package/dist/components/progress-bar.js +58 -22
  151. package/dist/components/progress-bar.js.map +1 -1
  152. package/dist/components/qr-code.d.ts +34 -0
  153. package/dist/components/qr-code.js +57 -0
  154. package/dist/components/qr-code.js.map +1 -0
  155. package/dist/components/search-field.d.ts +15 -3
  156. package/dist/components/search-field.js +5 -1
  157. package/dist/components/search-field.js.map +1 -1
  158. package/dist/components/settings-fields.d.ts +49 -1
  159. package/dist/components/signed-amount.d.ts +122 -0
  160. package/dist/components/signed-amount.js +152 -0
  161. package/dist/components/signed-amount.js.map +1 -0
  162. package/dist/components/skeleton.d.ts +10 -3
  163. package/dist/components/skeleton.js +12 -2
  164. package/dist/components/skeleton.js.map +1 -1
  165. package/dist/components/stat-tile.d.ts +2 -1
  166. package/dist/components/stat-tile.js +6 -3
  167. package/dist/components/stat-tile.js.map +1 -1
  168. package/dist/components/swipeable-row.js +4 -3
  169. package/dist/components/swipeable-row.js.map +1 -1
  170. package/dist/components/table.d.ts +39 -5
  171. package/dist/components/table.js +45 -11
  172. package/dist/components/table.js.map +1 -1
  173. package/dist/components/text-link.d.ts +238 -0
  174. package/dist/components/text-link.js +144 -0
  175. package/dist/components/text-link.js.map +1 -0
  176. package/dist/components/text.d.ts +26 -2
  177. package/dist/components/text.js +16 -2
  178. package/dist/components/text.js.map +1 -1
  179. package/dist/components/time-input.d.ts +49 -1
  180. package/dist/components/toggle-group.d.ts +35 -0
  181. package/dist/components/toggle-group.js +43 -14
  182. package/dist/components/toggle-group.js.map +1 -1
  183. package/dist/components/toggle-legend.d.ts +53 -3
  184. package/dist/components/toggle-legend.js +54 -1
  185. package/dist/components/toggle-legend.js.map +1 -1
  186. package/dist/components/tooltip.d.ts +51 -1
  187. package/dist/components/tooltip.js +59 -35
  188. package/dist/components/tooltip.js.map +1 -1
  189. package/dist/components/ui.d.ts +51 -779
  190. package/dist/components/ui.js +364 -34
  191. package/dist/components/ui.js.map +1 -1
  192. package/dist/components/use-table-state.d.ts +3 -52
  193. package/dist/components/use-table-state.js +128 -30
  194. package/dist/components/use-table-state.js.map +1 -1
  195. package/dist/{data-table-filters-Dh9uF_S-.d.ts → data-table-Drun8Fk9.d.ts} +305 -61
  196. package/dist/data-table.d.ts +2 -1
  197. package/dist/data-table.js +5 -1
  198. package/dist/data-table.js.map +1 -1
  199. package/dist/feedback/feedback-attachment.js +4 -6
  200. package/dist/feedback/feedback-attachment.js.map +1 -1
  201. package/dist/feedback/feedback-dialog.d.ts +26 -3
  202. package/dist/feedback/feedback-dialog.js +21 -5
  203. package/dist/feedback/feedback-dialog.js.map +1 -1
  204. package/dist/feedback/feedback-inbox.js +86 -75
  205. package/dist/feedback/feedback-inbox.js.map +1 -1
  206. package/dist/feedback/feedback-thread.d.ts +173 -0
  207. package/dist/feedback/feedback-thread.js +264 -0
  208. package/dist/feedback/feedback-thread.js.map +1 -0
  209. package/dist/feedback.d.ts +2 -1
  210. package/dist/feedback.js +1 -0
  211. package/dist/feedback.js.map +1 -1
  212. package/dist/hooks/use-authed-src.d.ts +71 -0
  213. package/dist/hooks/use-authed-src.js +63 -0
  214. package/dist/hooks/use-authed-src.js.map +1 -0
  215. package/dist/hooks/use-file-drop.d.ts +49 -2
  216. package/dist/hooks/use-hotkey.d.ts +59 -0
  217. package/dist/hooks/use-hotkey.js +105 -0
  218. package/dist/hooks/use-hotkey.js.map +1 -0
  219. package/dist/hooks/use-search-param-state.d.ts +83 -0
  220. package/dist/hooks/use-search-param-state.js +94 -0
  221. package/dist/hooks/use-search-param-state.js.map +1 -0
  222. package/dist/i18n/defaults.d.ts +15 -4
  223. package/dist/i18n/defaults.js +31 -1
  224. package/dist/i18n/defaults.js.map +1 -1
  225. package/dist/i18n/kit-labels.d.ts +46 -312
  226. package/dist/i18n/kit-labels.js +20 -5
  227. package/dist/i18n/kit-labels.js.map +1 -1
  228. package/dist/i18n/locales/de-CH-informal.d.ts +15 -4
  229. package/dist/i18n/locales/de-CH.d.ts +15 -4
  230. package/dist/i18n/locales/de-informal.d.ts +15 -4
  231. package/dist/i18n/locales/de.d.ts +15 -4
  232. package/dist/i18n/locales/de.js +164 -3
  233. package/dist/i18n/locales/de.js.map +1 -1
  234. package/dist/i18n/locales/es.d.ts +15 -4
  235. package/dist/i18n/locales/es.js +161 -3
  236. package/dist/i18n/locales/es.js.map +1 -1
  237. package/dist/i18n/locales/fr.d.ts +15 -4
  238. package/dist/i18n/locales/fr.js +161 -3
  239. package/dist/i18n/locales/fr.js.map +1 -1
  240. package/dist/i18n/locales/hu.d.ts +15 -4
  241. package/dist/i18n/locales/hu.js +161 -3
  242. package/dist/i18n/locales/hu.js.map +1 -1
  243. package/dist/i18n/locales/it.d.ts +15 -4
  244. package/dist/i18n/locales/it.js +161 -3
  245. package/dist/i18n/locales/it.js.map +1 -1
  246. package/dist/i18n/locales/zh.d.ts +15 -4
  247. package/dist/i18n/locales/zh.js +161 -3
  248. package/dist/i18n/locales/zh.js.map +1 -1
  249. package/dist/index.d.ts +39 -19
  250. package/dist/index.js +40 -1
  251. package/dist/index.js.map +1 -1
  252. package/dist/kit-labels-Mz8zZHIF.d.ts +1744 -0
  253. package/dist/lib/format.d.ts +162 -0
  254. package/dist/lib/format.js +151 -0
  255. package/dist/lib/format.js.map +1 -0
  256. package/dist/lib/qr-encode.d.ts +44 -0
  257. package/dist/lib/qr-encode.js +338 -0
  258. package/dist/lib/qr-encode.js.map +1 -0
  259. package/dist/rhf/fields.d.ts +283 -0
  260. package/dist/rhf/fields.js +631 -0
  261. package/dist/rhf/fields.js.map +1 -0
  262. package/dist/rhf/form.d.ts +49 -1
  263. package/dist/rhf/line-items.d.ts +31 -0
  264. package/dist/rhf/line-items.js +59 -0
  265. package/dist/rhf/line-items.js.map +1 -0
  266. package/dist/rhf.d.ts +61 -1
  267. package/dist/rhf.js +2 -0
  268. package/dist/rhf.js.map +1 -1
  269. package/dist/search/command-palette.js +20 -14
  270. package/dist/search/command-palette.js.map +1 -1
  271. package/dist/shell/app-shell.d.ts +99 -2
  272. package/dist/shell/app-shell.js +120 -57
  273. package/dist/shell/app-shell.js.map +1 -1
  274. package/dist/shell/auth-layout.d.ts +74 -0
  275. package/dist/shell/auth-layout.js +97 -0
  276. package/dist/shell/auth-layout.js.map +1 -0
  277. package/dist/shell/top-bar-brand.d.ts +81 -0
  278. package/dist/shell/top-bar-brand.js +47 -0
  279. package/dist/shell/top-bar-brand.js.map +1 -0
  280. package/dist/shell/topbar-action-menu.d.ts +21 -4
  281. package/dist/shell/topbar-action-menu.js +18 -2
  282. package/dist/shell/topbar-action-menu.js.map +1 -1
  283. package/dist/shell.d.ts +56 -1
  284. package/dist/shell.js +2 -0
  285. package/dist/shell.js.map +1 -1
  286. package/dist/tour/tour.js +10 -4
  287. package/dist/tour/tour.js.map +1 -1
  288. package/dist/wizard/stepper-nav.d.ts +48 -1
  289. package/dist/wizard/use-wizard.js +4 -2
  290. package/dist/wizard/use-wizard.js.map +1 -1
  291. package/dist/wizard/wizard-context.d.ts +24 -1
  292. package/dist/wizard/wizard-context.js +19 -2
  293. package/dist/wizard/wizard-context.js.map +1 -1
  294. package/dist/wizard/wizard-step.d.ts +30 -5
  295. package/dist/wizard/wizard-step.js +34 -3
  296. package/dist/wizard/wizard-step.js.map +1 -1
  297. package/dist/wizard.d.ts +50 -3
  298. package/package.json +6 -6
  299. package/src/chart.ts +4 -0
  300. package/src/components/account-settings-labels.ts +190 -0
  301. package/src/components/account-settings.tsx +110 -63
  302. package/src/components/amount-input.tsx +109 -10
  303. package/src/components/authed-image.tsx +190 -0
  304. package/src/components/breadcrumbs.tsx +8 -2
  305. package/src/components/bulk-action-bar.tsx +16 -3
  306. package/src/components/button-group.tsx +7 -2
  307. package/src/components/calendar-heatmap.tsx +105 -10
  308. package/src/components/chart.tsx +19 -8
  309. package/src/components/chip.tsx +14 -4
  310. package/src/components/choice-card.tsx +136 -25
  311. package/src/components/combobox-core.tsx +33 -9
  312. package/src/components/combobox.tsx +33 -9
  313. package/src/components/copy-button.tsx +3 -2
  314. package/src/components/data-table-cells.tsx +119 -0
  315. package/src/components/data-table-filter-popover.tsx +13 -5
  316. package/src/components/data-table-filters.ts +77 -0
  317. package/src/components/data-table-labels.ts +23 -0
  318. package/src/components/data-table.tsx +230 -13
  319. package/src/components/date-picker.tsx +19 -3
  320. package/src/components/description-list.tsx +52 -3
  321. package/src/components/entity-combobox.tsx +25 -7
  322. package/src/components/error-boundary.tsx +640 -0
  323. package/src/components/field-sync.tsx +48 -40
  324. package/src/components/field.tsx +56 -5
  325. package/src/components/floating-panel.tsx +20 -7
  326. package/src/components/form-actions.tsx +191 -0
  327. package/src/components/full-bleed-dialog.tsx +4 -0
  328. package/src/components/hover-menu.tsx +26 -17
  329. package/src/components/image-grid.tsx +181 -0
  330. package/src/components/lightbox.tsx +374 -0
  331. package/src/components/line-items.tsx +385 -0
  332. package/src/components/list.tsx +82 -19
  333. package/src/components/loading-state.tsx +47 -0
  334. package/src/components/menu-item.tsx +7 -2
  335. package/src/components/mini-calendar.tsx +72 -3
  336. package/src/components/modal.tsx +65 -3
  337. package/src/components/month-picker.tsx +181 -26
  338. package/src/components/multi-entity-combobox.tsx +27 -7
  339. package/src/components/nav-pills.tsx +8 -1
  340. package/src/components/number-field.tsx +15 -10
  341. package/src/components/number-input.tsx +17 -1
  342. package/src/components/numpad-sheet.tsx +6 -1
  343. package/src/components/page-header.tsx +42 -5
  344. package/src/components/passkeys-setting.tsx +331 -0
  345. package/src/components/picker-sheet.tsx +10 -1
  346. package/src/components/pie-chart-labels.ts +32 -0
  347. package/src/components/pie-chart.tsx +479 -0
  348. package/src/components/popover.tsx +3 -0
  349. package/src/components/progress-bar.tsx +129 -19
  350. package/src/components/qr-code.tsx +83 -0
  351. package/src/components/search-field.tsx +20 -4
  352. package/src/components/signed-amount.tsx +295 -0
  353. package/src/components/skeleton.tsx +21 -3
  354. package/src/components/stat-tile.tsx +11 -3
  355. package/src/components/swipeable-row.tsx +7 -7
  356. package/src/components/table.tsx +102 -13
  357. package/src/components/text-link.tsx +356 -0
  358. package/src/components/text.tsx +46 -2
  359. package/src/components/toggle-group.tsx +93 -20
  360. package/src/components/toggle-legend.tsx +108 -2
  361. package/src/components/tooltip.tsx +79 -8
  362. package/src/components/ui.tsx +707 -49
  363. package/src/components/use-table-state.ts +265 -33
  364. package/src/data-table.ts +10 -0
  365. package/src/feedback/feedback-attachment.tsx +10 -7
  366. package/src/feedback/feedback-dialog.tsx +49 -7
  367. package/src/feedback/feedback-inbox.tsx +7 -0
  368. package/src/feedback/feedback-thread.tsx +510 -0
  369. package/src/feedback.ts +1 -0
  370. package/src/hooks/use-authed-src.ts +161 -0
  371. package/src/hooks/use-hotkey.ts +172 -0
  372. package/src/hooks/use-search-param-state.ts +187 -0
  373. package/src/i18n/defaults.ts +30 -0
  374. package/src/i18n/kit-labels.tsx +118 -8
  375. package/src/i18n/locales/de.ts +161 -0
  376. package/src/i18n/locales/es.ts +158 -0
  377. package/src/i18n/locales/fr.ts +161 -0
  378. package/src/i18n/locales/hu.ts +159 -0
  379. package/src/i18n/locales/it.ts +159 -0
  380. package/src/i18n/locales/zh.ts +158 -0
  381. package/src/index.ts +59 -0
  382. package/src/lib/format.ts +348 -0
  383. package/src/lib/qr-encode.ts +420 -0
  384. package/src/rhf/fields.tsx +1135 -0
  385. package/src/rhf/line-items.tsx +130 -0
  386. package/src/rhf.ts +6 -0
  387. package/src/search/command-palette.tsx +29 -19
  388. package/src/shell/app-shell.tsx +153 -3
  389. package/src/shell/auth-layout.tsx +190 -0
  390. package/src/shell/top-bar-brand.tsx +76 -0
  391. package/src/shell/topbar-action-menu.tsx +32 -4
  392. package/src/shell.ts +2 -0
  393. package/src/tour/tour.tsx +16 -5
  394. package/src/wizard/use-wizard.ts +8 -4
  395. package/src/wizard/wizard-context.tsx +41 -1
  396. package/src/wizard/wizard-step.tsx +75 -6
  397. package/tokens.css +12 -0
@@ -21,6 +21,13 @@ export interface SkeletonProps extends Omit<ComponentPropsWithoutRef<"div">, "ch
21
21
  shape?: SkeletonShape;
22
22
  /** For `line`: this many lines, the last one shorter — a paragraph's outline. */
23
23
  lines?: number;
24
+ /**
25
+ * Say what is loading, once: wraps the placeholder in a `role="status"` region with
26
+ * this as its (visually hidden) text — kastlan's activity feed (activity-feed:52)
27
+ * built exactly that by hand around `<Skeleton lines={5} />`. The placeholder itself
28
+ * stays hidden. Left out, nothing is announced, as before.
29
+ */
30
+ label?: string;
24
31
  }
25
32
 
26
33
  const SHAPE: Record<SkeletonShape, string> = {
@@ -37,10 +44,21 @@ const SHAPE: Record<SkeletonShape, string> = {
37
44
  *
38
45
  * ALWAYS `aria-hidden`. A placeholder is not content, and a reader that met twelve
39
46
  * unnamed grey boxes would have learned nothing. Say "loading" once, where it
40
- * belongs: `aria-busy` on the region being filled, or a `Spinner` / sr-only line
41
- * beside the skeletons.
47
+ * belongs: `aria-busy` on the region being filled, a `Spinner` / sr-only line
48
+ * beside the skeletons, or this component's own `label`.
42
49
  */
43
- export function Skeleton({ shape = "line", lines, className, ...rest }: SkeletonProps) {
50
+ export function Skeleton({ label, ...props }: SkeletonProps) {
51
+ if (!label) return <SkeletonFill {...props} />;
52
+ return (
53
+ // `relative`: the containing block for the sr-only text (sr-only-containment.test).
54
+ <div role="status" className="relative" data-skeleton-status="">
55
+ <span className="sr-only">{label}</span>
56
+ <SkeletonFill {...props} />
57
+ </div>
58
+ );
59
+ }
60
+
61
+ function SkeletonFill({ shape = "line", lines, className, ...rest }: Omit<SkeletonProps, "label">) {
44
62
  if (shape === "line" && lines !== undefined && lines > 1) {
45
63
  return (
46
64
  <div {...rest} aria-hidden className={cn("flex flex-col gap-2", className)} data-skeleton="lines">
@@ -2,7 +2,8 @@ import { isValidElement, useId, useLayoutEffect, useState } from "react";
2
2
  import type { ComponentPropsWithoutRef, CSSProperties, ReactElement, ReactNode } from "react";
3
3
  import { ArrowDown, ArrowUp, Minus } from "lucide-react";
4
4
  import { cn } from "../lib/cn";
5
- import { useKitLabels, useKitLocale } from "../i18n/kit-labels";
5
+ import { useKitLabels, useKitLink, useKitLocale } from "../i18n/kit-labels";
6
+ import { pickLinkRenderer, RenderedKitLink } from "./text-link";
6
7
  import { Card, FieldHint } from "./ui";
7
8
  import { Sparkline } from "./sparkline";
8
9
  import { Tooltip } from "./tooltip";
@@ -219,7 +220,8 @@ export interface StatTileProps
219
220
  /** Makes the tile a link. See {@link renderLink} for a router. */
220
221
  href?: string;
221
222
  /** Renders the link for `href` — pass your router's `<Link>` here, since a plain
222
- * `<a>` reloads a single-page app. Default: `<a>`. */
223
+ * `<a>` reloads a single-page app. Default: the `<UiKitProvider linkComponent>`
224
+ * (for an in-app `href`), then `<a>`. */
223
225
  renderLink?: (props: StatTileLinkProps) => ReactElement;
224
226
  /** Makes the tile a button (ignored when `href` is given). */
225
227
  onClick?: () => void;
@@ -297,6 +299,7 @@ export function StatTile({
297
299
  ...rest
298
300
  }: StatTileProps) {
299
301
  const text = useKitLabels("statTile", DEFAULT_STAT_TILE_LABELS, labels);
302
+ const kitLink = useKitLink();
300
303
  const [labelEl, setLabelEl] = useState<HTMLElement | null>(null);
301
304
  const labelCut = useIsTruncated(truncateLabel ? labelEl : null);
302
305
  const kitLocale = useKitLocale(locale);
@@ -334,8 +337,11 @@ export function StatTile({
334
337
  "aria-describedby": describedBy,
335
338
  children: label,
336
339
  };
340
+ const kit = pickLinkRenderer<StatTileLinkProps>(undefined, kitLink, href);
337
341
  labelNode = renderLink ? (
338
342
  renderLink(linkProps)
343
+ ) : kit ? (
344
+ <RenderedKitLink render={kit} props={linkProps} />
339
345
  ) : (
340
346
  <a href={href} className={stretched} aria-describedby={describedBy}>
341
347
  {label}
@@ -373,7 +379,9 @@ export function StatTile({
373
379
  <div className="relative mt-1 flex flex-wrap items-center gap-x-1.5 text-xs tabular-nums">
374
380
  <span id={deltaId} data-private={priv} className={cn("inline-flex items-center gap-0.5 font-medium", deltaTone)}>
375
381
  <Icon className="size-3 shrink-0" aria-hidden />
376
- <span aria-hidden>{dir === "flat" ? null : amount}</span>
382
+ {/* The figure at zero too, like Delta (kastlan 48): "0 %" says the change was
383
+ measured; a bare dash reads like a missing value. */}
384
+ <span aria-hidden>{amount}</span>
377
385
  <span className="sr-only">{spoken}</span>
378
386
  </span>
379
387
  {d.label != null && <span className="text-[var(--text-muted)]">{d.label}</span>}
@@ -164,13 +164,13 @@ export function SwipeableRow({
164
164
  // painted the RIGHT action's colour into the gap. With no left action at all that
165
165
  // colour was the only thing the gesture ever showed.
166
166
  //
167
- // Written during render rather than in an effect: an effect would repaint a frame
168
- // later (visibly, at 150ms) and `setState` in an effect body is an eslint error in
169
- // the consuming app. The value is derived from this render's own dx, so a
170
- // concurrent re-render recomputes it identically.
171
- const lastSide = useRef<"left" | "right">("right");
172
- if (dx !== 0) lastSide.current = dx < 0 ? "left" : "right";
173
- const draggingLeft = dx !== 0 ? dx < 0 : lastSide.current === "left";
167
+ // Adjusted during render rather than in an effect: an effect would repaint a frame
168
+ // later (visibly, at 150ms). State set while rendering re-renders this component
169
+ // before anything is committed, so the released frame already has the right side.
170
+ const [lastSide, setLastSide] = useState<"left" | "right">("right");
171
+ const side = dx === 0 ? null : dx < 0 ? "left" : "right";
172
+ if (side && side !== lastSide) setLastSide(side);
173
+ const draggingLeft = side ? side === "left" : lastSide === "left";
174
174
  const shown = draggingLeft
175
175
  ? leftActions[Math.max(0, swipe.armedLeftIndex)]
176
176
  : rightActions[Math.max(0, swipe.armedRightIndex)];
@@ -29,10 +29,21 @@ export type TableHeaderCellSize = "xs" | "sm";
29
29
  /** The header cell's weight. Default `medium`. */
30
30
  export type TableHeaderCellWeight = "normal" | "medium" | "semibold";
31
31
 
32
+ /**
33
+ * What a {@link TableRow} is in a statement-style table (0.12.0): an ordinary `row`, a
34
+ * `group` heading ("Current assets", a tinted full-width label row), a `subtotal` under
35
+ * a group, or the `total` of the whole table. kastlan's balance sheet, income statement
36
+ * and journal entry each spelled these as `className="font-medium"`, `"font-bold
37
+ * border-t-2"` and `bg-muted/50` on the cell — three pages, three sets of classes for
38
+ * the same four kinds of line.
39
+ */
40
+ export type TableRowVariant = "row" | "group" | "subtotal" | "total";
41
+
32
42
  interface TableContextValue {
33
43
  density: TableDensity;
34
44
  zebra: boolean;
35
45
  hover: boolean;
46
+ rowDividers: boolean;
36
47
  captionId: string;
37
48
  registerCaption: () => () => void;
38
49
  }
@@ -41,12 +52,44 @@ const TableContext = createContext<TableContextValue>({
41
52
  density: "comfortable",
42
53
  zebra: false,
43
54
  hover: false,
55
+ rowDividers: true,
44
56
  captionId: "",
45
57
  registerCaption: () => () => {},
46
58
  });
47
59
 
48
- /** Which section a row sits in — zebra and hover apply to body rows only. */
49
- const SectionContext = createContext<"head" | "body" | "foot">("body");
60
+ type TableSection = "head" | "body" | "foot";
61
+
62
+ /** Which section a row sits in — zebra and hover apply to body rows only. `undefined`
63
+ * outside the kit's section parts: a raw `<thead>` / `<tbody>`, which
64
+ * {@link useSection} then reads off the DOM. */
65
+ const SectionContext = createContext<TableSection | undefined>(undefined);
66
+
67
+ const SECTION_OF_TAG: Record<string, TableSection> = { THEAD: "head", TBODY: "body", TFOOT: "foot" };
68
+
69
+ /**
70
+ * The section a row or cell sits in: the kit part's context where there is one, else the
71
+ * nearest `<thead>` / `<tbody>` / `<tfoot>` in the DOM.
72
+ *
73
+ * keksdose's VAT summary writes a raw `<thead>` round kit cells in places, and a
74
+ * `TableHeaderCell` there took itself for a BODY cell — `scope="row"`, body type — with
75
+ * nothing on the page to say why. React cannot see an ancestor's tag, so the fallback
76
+ * reads it after mount; a layout effect, so the corrected cell is what gets painted.
77
+ */
78
+ function useSection<E extends HTMLElement>(): [TableSection, ((el: E | null) => void) | undefined] {
79
+ const fromContext = useContext(SectionContext);
80
+ const [node, setNode] = useState<E | null>(null);
81
+ const [detected, setDetected] = useState<TableSection | undefined>(undefined);
82
+ useLayoutEffect(() => {
83
+ if (fromContext !== undefined || !node) return;
84
+ const section = node.closest("thead, tbody, tfoot");
85
+ const found = section ? SECTION_OF_TAG[section.tagName] : undefined;
86
+ // eslint-disable-next-line react-hooks/set-state-in-effect -- read off the DOM, which only exists after mount
87
+ if (found !== detected) setDetected(found);
88
+ }, [fromContext, node, detected]);
89
+ // No ref at all under a kit section: holding the node would cost every row and cell
90
+ // a second render on mount for an answer the context already gave.
91
+ return [fromContext ?? detected ?? "body", fromContext === undefined ? setNode : undefined];
92
+ }
50
93
 
51
94
  /** A {@link TableRow}'s `valign`, which its cells take unless they set their own. It
52
95
  * cannot be left to CSS inheritance: every cell states its own default alignment,
@@ -102,6 +145,22 @@ export interface TableProps extends ComponentPropsWithoutRef<"table"> {
102
145
  wrapperClassName?: string;
103
146
  /** See {@link TableLayout}. Unset leaves the browser's `auto` and adds no class. */
104
147
  layout?: TableLayout;
148
+ /**
149
+ * A rounded border round the whole table (0.12.0) — for a table standing on the page
150
+ * or in a dialog rather than inside a card. kastlan wraps six of them in
151
+ * `<div className="rounded-md border">` by hand (payment allocation, the new-budget
152
+ * lines, the meter readings, the deposit transactions, the unit values editor, the
153
+ * maintenance detail), and a hand-made frame outside the scroll wrapper does not clip
154
+ * the rows' tint to its corners.
155
+ */
156
+ framed?: boolean;
157
+ /**
158
+ * The rule between body rows. Default true. `false` for a small table whose rows are
159
+ * spaced by their own content — keksdose's VAT summary, a block of three quiet
160
+ * columns inside a card — which otherwise had to drop to raw `<tr>`s to lose it. One
161
+ * row can still say otherwise with {@link TableRowProps.bordered}.
162
+ */
163
+ rowDividers?: boolean;
105
164
  }
106
165
 
107
166
  /**
@@ -127,6 +186,8 @@ export function Table({
127
186
  hover = false,
128
187
  wrapperClassName,
129
188
  layout,
189
+ framed = false,
190
+ rowDividers = true,
130
191
  className,
131
192
  "aria-label": ariaLabel,
132
193
  ...rest
@@ -141,13 +202,14 @@ export function Table({
141
202
  density,
142
203
  zebra,
143
204
  hover,
205
+ rowDividers,
144
206
  captionId,
145
207
  registerCaption: () => {
146
208
  setCaptions((n) => n + 1);
147
209
  return () => setCaptions((n) => n - 1);
148
210
  },
149
211
  }),
150
- [density, zebra, hover, captionId],
212
+ [density, zebra, hover, rowDividers, captionId],
151
213
  );
152
214
 
153
215
  const regionName = captions > 0 ? { "aria-labelledby": captionId } : ariaLabel ? { "aria-label": ariaLabel } : null;
@@ -163,9 +225,13 @@ export function Table({
163
225
  tabIndex={overflowing ? 0 : undefined}
164
226
  data-overflowing={overflowing || undefined}
165
227
  data-clips=""
228
+ data-framed={framed || undefined}
166
229
  className={cn(
167
230
  // `relative`: the containing block for an `sr-only` caption.
168
231
  "relative w-full overflow-x-auto",
232
+ // On the scroll wrapper itself, so its clipping keeps the rows inside the
233
+ // rounded corners.
234
+ framed && "rounded-md border border-[var(--border)]",
169
235
  THIN_SCROLLBAR_CLASS,
170
236
  "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[var(--brand)]",
171
237
  wrapperClassName,
@@ -187,12 +253,16 @@ export function Table({
187
253
  );
188
254
  }
189
255
 
190
- export type TableHeadProps = ComponentPropsWithoutRef<"thead">;
256
+ export interface TableHeadProps extends ComponentPropsWithoutRef<"thead"> {
257
+ /** The rule under the head. Default true; `false` for a quiet header over a small
258
+ * table (keksdose's VAT summary wrote `className="border-b-0"` to lose it). */
259
+ bordered?: boolean;
260
+ }
191
261
 
192
- export function TableHead({ className, ...rest }: TableHeadProps) {
262
+ export function TableHead({ bordered = true, className, ...rest }: TableHeadProps) {
193
263
  return (
194
264
  <SectionContext.Provider value="head">
195
- <thead {...rest} className={cn("border-b border-[var(--border)]", className)} />
265
+ <thead {...rest} className={cn(bordered && "border-b border-[var(--border)]", className)} />
196
266
  </SectionContext.Provider>
197
267
  );
198
268
  }
@@ -290,24 +360,42 @@ export function TableFoot({ className, ...rest }: TableFootProps) {
290
360
  );
291
361
  }
292
362
 
363
+ const ROW_VARIANT: Record<TableRowVariant, string | false> = {
364
+ row: false,
365
+ group: "bg-[var(--bg-surface-2)] font-semibold",
366
+ subtotal: "font-medium",
367
+ // A 2px rule over the 1px divider the row above draws on its bottom: collapsed
368
+ // borders meet on one line, the wider wins, and the heavier rule is what says "sum".
369
+ total: "border-t-2 border-t-[var(--border-strong)] font-semibold",
370
+ };
371
+
293
372
  /** The deprecated HTML `valign` attribute is replaced by a class-backed one. */
294
373
  export interface TableRowProps extends ComponentPropsWithoutRef<"tr"> {
295
374
  /** Vertical alignment for every cell of the row that does not set its own. See
296
375
  * {@link TableVAlign}. Left out, each cell keeps its default. */
297
376
  valign?: TableVAlign;
377
+ /** See {@link TableRowVariant}. Default `row`. Zebra and hover tint ordinary rows
378
+ * only: a group heading or a total is not one more record. */
379
+ variant?: TableRowVariant;
380
+ /** The rule under this body row. Default: the table's `rowDividers`. */
381
+ bordered?: boolean;
298
382
  }
299
383
 
300
- export function TableRow({ valign, className, ...rest }: TableRowProps) {
301
- const { zebra, hover } = useContext(TableContext);
302
- const section = useContext(SectionContext);
384
+ export function TableRow({ valign, variant = "row", bordered, className, ...rest }: TableRowProps) {
385
+ const { zebra, hover, rowDividers } = useContext(TableContext);
386
+ const [section, ref] = useSection<HTMLTableRowElement>();
303
387
  const body = section === "body";
388
+ const record = body && variant === "row";
304
389
  const row = (
305
390
  <tr
391
+ ref={ref}
306
392
  {...rest}
393
+ data-variant={variant === "row" ? undefined : variant}
307
394
  className={cn(
308
- body && "border-b border-[var(--border)]",
309
- body && zebra && "even:bg-[var(--bg-surface-2)]",
310
- body && hover && "transition-colors hover:bg-[var(--bg-hover)]",
395
+ body && (bordered ?? rowDividers) && "border-b border-[var(--border)]",
396
+ record && zebra && "even:bg-[var(--bg-surface-2)]",
397
+ record && hover && "transition-colors hover:bg-[var(--bg-hover)]",
398
+ ROW_VARIANT[variant],
311
399
  // On the row as well, for a raw `<td>` of the caller's, which inherits it.
312
400
  valign && VALIGN[valign],
313
401
  className,
@@ -356,12 +444,13 @@ export function TableHeaderCell({
356
444
  ...rest
357
445
  }: TableHeaderCellProps) {
358
446
  const { density } = useContext(TableContext);
359
- const section = useContext(SectionContext);
447
+ const [section, ref] = useSection<HTMLTableCellElement>();
360
448
  const rowVAlign = useContext(RowVAlignContext);
361
449
  const head = section === "head";
362
450
  const textSize = size ?? (head ? "xs" : undefined);
363
451
  return (
364
452
  <th
453
+ ref={ref}
365
454
  {...rest}
366
455
  scope={scope ?? (section === "head" ? "col" : "row")}
367
456
  className={cn(