@eifi1/ui-kit 0.31.1 → 0.32.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 (565) hide show
  1. package/README.md +51 -28
  2. package/dist/account/delete-account-setting.d.ts +8 -3
  3. package/dist/admin/admin-action-confirm.d.ts +8 -3
  4. package/dist/admin/admin-action-log.d.ts +1 -1
  5. package/dist/admin/admin-action-log.js +4 -2
  6. package/dist/admin/admin-action-log.js.map +1 -1
  7. package/dist/admin/invitations-panel.d.ts +8 -3
  8. package/dist/admin/invitations-panel.js +29 -26
  9. package/dist/admin/invitations-panel.js.map +1 -1
  10. package/dist/admin/reviewer-scope-editor.d.ts +8 -3
  11. package/dist/admin/role-select.d.ts +10 -5
  12. package/dist/admin/transfer-ownership-dialog.d.ts +8 -3
  13. package/dist/admin/user-roster.d.ts +10 -5
  14. package/dist/admin/user-roster.js +8 -47
  15. package/dist/admin/user-roster.js.map +1 -1
  16. package/dist/auth/auth-errors.d.ts +43 -8
  17. package/dist/auth/auth-errors.js +24 -1
  18. package/dist/auth/auth-errors.js.map +1 -1
  19. package/dist/auth/register-form.d.ts +8 -3
  20. package/dist/billing/billing-banner.d.ts +184 -0
  21. package/dist/billing/billing-banner.js +98 -0
  22. package/dist/billing/billing-banner.js.map +1 -0
  23. package/dist/billing/billing-labels.d.ts +100 -0
  24. package/dist/billing/billing-labels.js +76 -0
  25. package/dist/billing/billing-labels.js.map +1 -0
  26. package/dist/billing/billing-lock.d.ts +158 -0
  27. package/dist/billing/billing-lock.js +17 -0
  28. package/dist/billing/billing-lock.js.map +1 -0
  29. package/dist/billing/billing-standing.d.ts +149 -0
  30. package/dist/billing/billing-standing.js +28 -0
  31. package/dist/billing/billing-standing.js.map +1 -0
  32. package/dist/billing/plan-card.d.ts +248 -0
  33. package/dist/billing/plan-card.js +248 -0
  34. package/dist/billing/plan-card.js.map +1 -0
  35. package/dist/billing/plan-limit-notice.d.ts +156 -0
  36. package/dist/billing/plan-limit-notice.js +76 -0
  37. package/dist/billing/plan-limit-notice.js.map +1 -0
  38. package/dist/billing/plan-limit.d.ts +34 -0
  39. package/dist/billing/plan-limit.js +20 -0
  40. package/dist/billing/plan-limit.js.map +1 -0
  41. package/dist/billing/plan-price.d.ts +61 -0
  42. package/dist/billing/plan-price.js +45 -0
  43. package/dist/billing/plan-price.js.map +1 -0
  44. package/dist/billing/subscription-actions.d.ts +133 -0
  45. package/dist/billing/subscription-actions.js +28 -0
  46. package/dist/billing/subscription-actions.js.map +1 -0
  47. package/dist/billing/subscription-status-chip.d.ts +149 -0
  48. package/dist/billing/subscription-status-chip.js +48 -0
  49. package/dist/billing/subscription-status-chip.js.map +1 -0
  50. package/dist/chart.d.ts +9 -3
  51. package/dist/chart.js.map +1 -1
  52. package/dist/components/account-chips.d.ts +16 -4
  53. package/dist/components/account-chips.js +21 -3
  54. package/dist/components/account-chips.js.map +1 -1
  55. package/dist/components/alert-banner.d.ts +6 -1
  56. package/dist/components/alert-banner.js +5 -4
  57. package/dist/components/alert-banner.js.map +1 -1
  58. package/dist/components/amount-input.d.ts +8 -3
  59. package/dist/components/amount-input.js +5 -5
  60. package/dist/components/amount-input.js.map +1 -1
  61. package/dist/components/appearance-labels.d.ts +38 -0
  62. package/dist/components/appearance-labels.js +19 -0
  63. package/dist/components/appearance-labels.js.map +1 -0
  64. package/dist/components/autocomplete.js +2 -2
  65. package/dist/components/autocomplete.js.map +1 -1
  66. package/dist/components/breadcrumbs.js +3 -2
  67. package/dist/components/breadcrumbs.js.map +1 -1
  68. package/dist/components/bulk-action-bar.d.ts +2 -2
  69. package/dist/components/bulk-action-bar.js +7 -12
  70. package/dist/components/bulk-action-bar.js.map +1 -1
  71. package/dist/components/button-group.d.ts +8 -3
  72. package/dist/components/button-group.js +7 -1
  73. package/dist/components/button-group.js.map +1 -1
  74. package/dist/components/calculator.d.ts +8 -3
  75. package/dist/components/calculator.js +4 -3
  76. package/dist/components/calculator.js.map +1 -1
  77. package/dist/components/calendar-heatmap.js +5 -5
  78. package/dist/components/calendar-heatmap.js.map +1 -1
  79. package/dist/components/chart-height.d.ts +23 -0
  80. package/dist/components/chart-height.js +15 -0
  81. package/dist/components/chart-height.js.map +1 -0
  82. package/dist/components/chart-zoom.js +6 -1
  83. package/dist/components/chart-zoom.js.map +1 -1
  84. package/dist/components/checkbox-group.js +2 -2
  85. package/dist/components/checkbox-group.js.map +1 -1
  86. package/dist/components/checkbox.d.ts +10 -0
  87. package/dist/components/checkbox.js +25 -10
  88. package/dist/components/checkbox.js.map +1 -1
  89. package/dist/components/chip.d.ts +19 -3
  90. package/dist/components/chip.js +54 -23
  91. package/dist/components/chip.js.map +1 -1
  92. package/dist/components/choice-card.d.ts +1 -1
  93. package/dist/components/choice-card.js +9 -8
  94. package/dist/components/choice-card.js.map +1 -1
  95. package/dist/components/column-mapper.js +1 -1
  96. package/dist/components/column-mapper.js.map +1 -1
  97. package/dist/components/combobox-core.js +8 -7
  98. package/dist/components/combobox-core.js.map +1 -1
  99. package/dist/components/combobox.js +8 -8
  100. package/dist/components/combobox.js.map +1 -1
  101. package/dist/components/confirm-dialog.d.ts +8 -3
  102. package/dist/components/copy-button.d.ts +10 -5
  103. package/dist/components/country-select.js +1 -1
  104. package/dist/components/country-select.js.map +1 -1
  105. package/dist/components/currency-select.js +3 -3
  106. package/dist/components/currency-select.js.map +1 -1
  107. package/dist/components/danger-confirm.d.ts +8 -3
  108. package/dist/components/data-table-cells.d.ts +1 -1
  109. package/dist/components/data-table-filter-popover.d.ts +1 -1
  110. package/dist/components/data-table-filter-popover.js +4 -1
  111. package/dist/components/data-table-filter-popover.js.map +1 -1
  112. package/dist/components/data-table-filters.d.ts +1 -1
  113. package/dist/components/data-table-labels.d.ts +1 -1
  114. package/dist/components/data-table-pagination.d.ts +3 -2
  115. package/dist/components/data-table-pagination.js +15 -6
  116. package/dist/components/data-table-pagination.js.map +1 -1
  117. package/dist/components/data-table.d.ts +1 -1
  118. package/dist/components/data-table.js +123 -52
  119. package/dist/components/data-table.js.map +1 -1
  120. package/dist/components/date-picker.d.ts +1 -1
  121. package/dist/components/date-picker.js +18 -6
  122. package/dist/components/date-picker.js.map +1 -1
  123. package/dist/components/description-list.js +2 -2
  124. package/dist/components/description-list.js.map +1 -1
  125. package/dist/components/dialog-frame.js +2 -1
  126. package/dist/components/dialog-frame.js.map +1 -1
  127. package/dist/components/disclosure.js +3 -2
  128. package/dist/components/disclosure.js.map +1 -1
  129. package/dist/components/dropdown.d.ts +1 -1
  130. package/dist/components/dropdown.js +7 -1
  131. package/dist/components/dropdown.js.map +1 -1
  132. package/dist/components/facing-pair.d.ts +19 -6
  133. package/dist/components/facing-pair.js +3 -2
  134. package/dist/components/facing-pair.js.map +1 -1
  135. package/dist/components/field-parts.d.ts +102 -6
  136. package/dist/components/field-parts.js +81 -6
  137. package/dist/components/field-parts.js.map +1 -1
  138. package/dist/components/field-sync.d.ts +4 -1
  139. package/dist/components/field-sync.js +12 -2
  140. package/dist/components/field-sync.js.map +1 -1
  141. package/dist/components/field.js +2 -2
  142. package/dist/components/field.js.map +1 -1
  143. package/dist/components/file-button.d.ts +8 -3
  144. package/dist/components/file-dropzone.d.ts +8 -3
  145. package/dist/components/floating-panel.js +7 -4
  146. package/dist/components/floating-panel.js.map +1 -1
  147. package/dist/components/focus-ring.d.ts +12 -0
  148. package/dist/components/focus-ring.js +8 -0
  149. package/dist/components/focus-ring.js.map +1 -0
  150. package/dist/components/form-actions.d.ts +8 -3
  151. package/dist/components/form-actions.js +33 -19
  152. package/dist/components/form-actions.js.map +1 -1
  153. package/dist/components/full-bleed-dialog.d.ts +11 -1
  154. package/dist/components/full-bleed-dialog.js +3 -1
  155. package/dist/components/full-bleed-dialog.js.map +1 -1
  156. package/dist/components/iban-input.d.ts +8 -3
  157. package/dist/components/image-grid.js +1 -1
  158. package/dist/components/image-grid.js.map +1 -1
  159. package/dist/components/inline-edit-field.js +10 -4
  160. package/dist/components/inline-edit-field.js.map +1 -1
  161. package/dist/components/language-select.d.ts +8 -3
  162. package/dist/components/legal-page.d.ts +26 -5
  163. package/dist/components/legal-page.js +3 -1
  164. package/dist/components/legal-page.js.map +1 -1
  165. package/dist/components/legal.d.ts +8 -3
  166. package/dist/components/legal.js +2 -1
  167. package/dist/components/legal.js.map +1 -1
  168. package/dist/components/lightbox.js +24 -2
  169. package/dist/components/lightbox.js.map +1 -1
  170. package/dist/components/line-items.js +2 -1
  171. package/dist/components/line-items.js.map +1 -1
  172. package/dist/components/list.d.ts +5 -0
  173. package/dist/components/list.js +13 -9
  174. package/dist/components/list.js.map +1 -1
  175. package/dist/components/measured-grid.d.ts +3 -1
  176. package/dist/components/measured-grid.js +38 -20
  177. package/dist/components/measured-grid.js.map +1 -1
  178. package/dist/components/menu-item.js +2 -1
  179. package/dist/components/menu-item.js.map +1 -1
  180. package/dist/components/mini-calendar.js +8 -4
  181. package/dist/components/mini-calendar.js.map +1 -1
  182. package/dist/components/money-field.d.ts +8 -3
  183. package/dist/components/month-picker.js +50 -39
  184. package/dist/components/month-picker.js.map +1 -1
  185. package/dist/components/nav-pills.js +1 -1
  186. package/dist/components/nav-pills.js.map +1 -1
  187. package/dist/components/number-field.d.ts +8 -3
  188. package/dist/components/number-input.d.ts +11 -4
  189. package/dist/components/number-input.js +8 -6
  190. package/dist/components/number-input.js.map +1 -1
  191. package/dist/components/numpad-sheet.d.ts +8 -3
  192. package/dist/components/numpad-sheet.js +2 -1
  193. package/dist/components/numpad-sheet.js.map +1 -1
  194. package/dist/components/one-time-code-input.js +2 -2
  195. package/dist/components/one-time-code-input.js.map +1 -1
  196. package/dist/components/page-contents.js +2 -2
  197. package/dist/components/page-contents.js.map +1 -1
  198. package/dist/components/phone-input.d.ts +8 -3
  199. package/dist/components/phone-input.js +4 -4
  200. package/dist/components/phone-input.js.map +1 -1
  201. package/dist/components/pie-chart.d.ts +8 -2
  202. package/dist/components/pie-chart.js +11 -7
  203. package/dist/components/pie-chart.js.map +1 -1
  204. package/dist/components/popover.d.ts +9 -1
  205. package/dist/components/popover.js +8 -4
  206. package/dist/components/popover.js.map +1 -1
  207. package/dist/components/row-actions.d.ts +100 -0
  208. package/dist/components/row-actions.js +231 -0
  209. package/dist/components/row-actions.js.map +1 -0
  210. package/dist/components/scroll-area.js +1 -1
  211. package/dist/components/scroll-area.js.map +1 -1
  212. package/dist/components/search-field.js +3 -2
  213. package/dist/components/search-field.js.map +1 -1
  214. package/dist/components/series-chart-budget.d.ts +30 -7
  215. package/dist/components/series-chart-budget.js +12 -4
  216. package/dist/components/series-chart-budget.js.map +1 -1
  217. package/dist/components/series-chart-ticks.d.ts +7 -1
  218. package/dist/components/series-chart-ticks.js +6 -0
  219. package/dist/components/series-chart-ticks.js.map +1 -1
  220. package/dist/components/series-chart.d.ts +58 -28
  221. package/dist/components/series-chart.js +42 -32
  222. package/dist/components/series-chart.js.map +1 -1
  223. package/dist/components/settings-fields.d.ts +57 -8
  224. package/dist/components/settings-fields.js +39 -1
  225. package/dist/components/settings-fields.js.map +1 -1
  226. package/dist/components/share-card.d.ts +11 -6
  227. package/dist/components/share-card.js +8 -2
  228. package/dist/components/share-card.js.map +1 -1
  229. package/dist/components/sign-chip.d.ts +4 -0
  230. package/dist/components/sign-chip.js +17 -4
  231. package/dist/components/sign-chip.js.map +1 -1
  232. package/dist/components/signature-pad.d.ts +3 -1
  233. package/dist/components/signature-pad.js +8 -5
  234. package/dist/components/signature-pad.js.map +1 -1
  235. package/dist/components/slider.js +7 -6
  236. package/dist/components/slider.js.map +1 -1
  237. package/dist/components/sparkline.d.ts +5 -1
  238. package/dist/components/sparkline.js +4 -2
  239. package/dist/components/sparkline.js.map +1 -1
  240. package/dist/components/stat-tile.d.ts +17 -1
  241. package/dist/components/stat-tile.js +48 -20
  242. package/dist/components/stat-tile.js.map +1 -1
  243. package/dist/components/status-dot.d.ts +4 -0
  244. package/dist/components/status-dot.js +9 -2
  245. package/dist/components/status-dot.js.map +1 -1
  246. package/dist/components/swipeable-row.js +10 -2
  247. package/dist/components/swipeable-row.js.map +1 -1
  248. package/dist/components/switch.d.ts +21 -7
  249. package/dist/components/switch.js +24 -11
  250. package/dist/components/switch.js.map +1 -1
  251. package/dist/components/table.js +2 -2
  252. package/dist/components/table.js.map +1 -1
  253. package/dist/components/text-link.d.ts +8 -3
  254. package/dist/components/text-link.js +1 -1
  255. package/dist/components/text-link.js.map +1 -1
  256. package/dist/components/text.d.ts +7 -2
  257. package/dist/components/text.js +5 -5
  258. package/dist/components/text.js.map +1 -1
  259. package/dist/components/tile-radio.js +2 -1
  260. package/dist/components/tile-radio.js.map +1 -1
  261. package/dist/components/time-input.d.ts +8 -3
  262. package/dist/components/toast.d.ts +18 -2
  263. package/dist/components/toast.js +8 -5
  264. package/dist/components/toast.js.map +1 -1
  265. package/dist/components/toggle-group.d.ts +25 -3
  266. package/dist/components/toggle-group.js +40 -11
  267. package/dist/components/toggle-group.js.map +1 -1
  268. package/dist/components/toggle-legend.d.ts +10 -1
  269. package/dist/components/toggle-legend.js +21 -7
  270. package/dist/components/toggle-legend.js.map +1 -1
  271. package/dist/components/translation-review-editor.js +1 -1
  272. package/dist/components/translation-review-editor.js.map +1 -1
  273. package/dist/components/translation-review-parts.d.ts +4 -0
  274. package/dist/components/translation-review.d.ts +4 -0
  275. package/dist/components/translation-review.js +3 -3
  276. package/dist/components/translation-review.js.map +1 -1
  277. package/dist/components/tree-view.js +3 -2
  278. package/dist/components/tree-view.js.map +1 -1
  279. package/dist/components/treemap.d.ts +5 -2
  280. package/dist/components/treemap.js +33 -16
  281. package/dist/components/treemap.js.map +1 -1
  282. package/dist/components/ui.d.ts +8 -3
  283. package/dist/components/ui.js +207 -119
  284. package/dist/components/ui.js.map +1 -1
  285. package/dist/components/use-table-state.d.ts +1 -1
  286. package/dist/components/user-avatar.d.ts +5 -1
  287. package/dist/components/user-avatar.js +1 -1
  288. package/dist/components/user-avatar.js.map +1 -1
  289. package/dist/components/wizard-stepper.js +20 -14
  290. package/dist/components/wizard-stepper.js.map +1 -1
  291. package/dist/{data-table-labels-DUELeXpa.d.ts → data-table-labels-kpAAVi6g.d.ts} +26 -2
  292. package/dist/data-table.d.ts +1 -1
  293. package/dist/{delete-account-setting-CpIhzxxZ.d.ts → delete-account-setting-FLyJf-kZ.d.ts} +642 -60
  294. package/dist/demo/demo-banner.js +1 -0
  295. package/dist/demo/demo-banner.js.map +1 -1
  296. package/dist/feedback/feedback-attachment.d.ts +8 -3
  297. package/dist/feedback/feedback-context.d.ts +8 -3
  298. package/dist/feedback/feedback-crash.d.ts +8 -3
  299. package/dist/feedback/feedback-dialog.d.ts +8 -3
  300. package/dist/feedback/feedback-dialog.js +3 -3
  301. package/dist/feedback/feedback-dialog.js.map +1 -1
  302. package/dist/feedback/feedback-inbox.d.ts +8 -3
  303. package/dist/feedback/feedback-inbox.js +2 -2
  304. package/dist/feedback/feedback-inbox.js.map +1 -1
  305. package/dist/feedback/feedback-labels.d.ts +8 -3
  306. package/dist/feedback/feedback-menu.d.ts +9 -4
  307. package/dist/feedback/feedback-record.d.ts +8 -3
  308. package/dist/feedback/feedback-row-detail.d.ts +8 -3
  309. package/dist/feedback/feedback-status-undo.d.ts +8 -3
  310. package/dist/feedback/feedback-submit.d.ts +8 -3
  311. package/dist/feedback/feedback-swipe.d.ts +8 -3
  312. package/dist/feedback/feedback-table.d.ts +8 -3
  313. package/dist/feedback/feedback-thread.d.ts +8 -3
  314. package/dist/feedback/feedback-thread.js +3 -3
  315. package/dist/feedback/feedback-thread.js.map +1 -1
  316. package/dist/feedback.d.ts +8 -3
  317. package/dist/hooks/use-anchored-panel.d.ts +32 -3
  318. package/dist/hooks/use-anchored-panel.js +21 -3
  319. package/dist/hooks/use-anchored-panel.js.map +1 -1
  320. package/dist/hooks/use-breakpoint.d.ts +88 -0
  321. package/dist/hooks/use-breakpoint.js +50 -0
  322. package/dist/hooks/use-breakpoint.js.map +1 -0
  323. package/dist/hooks/use-file-drop.d.ts +8 -3
  324. package/dist/hooks/use-large-text.d.ts +29 -0
  325. package/dist/hooks/use-large-text.js +20 -0
  326. package/dist/hooks/use-large-text.js.map +1 -0
  327. package/dist/hooks/use-windowed-rows.d.ts +52 -8
  328. package/dist/hooks/use-windowed-rows.js +94 -5
  329. package/dist/hooks/use-windowed-rows.js.map +1 -1
  330. package/dist/i18n/defaults.d.ts +8 -3
  331. package/dist/i18n/defaults.js +8 -0
  332. package/dist/i18n/defaults.js.map +1 -1
  333. package/dist/i18n/german.d.ts +8 -3
  334. package/dist/i18n/german.js +94 -3
  335. package/dist/i18n/german.js.map +1 -1
  336. package/dist/i18n/kit-labels.d.ts +8 -3
  337. package/dist/i18n/kit-labels.js.map +1 -1
  338. package/dist/i18n/languages.d.ts +10 -5
  339. package/dist/i18n/locales/de-CH.d.ts +8 -3
  340. package/dist/i18n/locales/en.d.ts +8 -3
  341. package/dist/i18n/locales/es.d.ts +8 -3
  342. package/dist/i18n/locales/es.js +89 -3
  343. package/dist/i18n/locales/es.js.map +1 -1
  344. package/dist/i18n/locales/fr.d.ts +8 -3
  345. package/dist/i18n/locales/fr.js +91 -3
  346. package/dist/i18n/locales/fr.js.map +1 -1
  347. package/dist/i18n/locales/hu.d.ts +8 -3
  348. package/dist/i18n/locales/hu.js +91 -3
  349. package/dist/i18n/locales/hu.js.map +1 -1
  350. package/dist/i18n/locales/it.d.ts +8 -3
  351. package/dist/i18n/locales/it.js +92 -3
  352. package/dist/i18n/locales/it.js.map +1 -1
  353. package/dist/i18n/locales/zh.d.ts +8 -3
  354. package/dist/i18n/locales/zh.js +89 -3
  355. package/dist/i18n/locales/zh.js.map +1 -1
  356. package/dist/i18n/review.d.ts +8 -3
  357. package/dist/i18n/review.js +15 -1
  358. package/dist/i18n/review.js.map +1 -1
  359. package/dist/index.d.ts +27 -11
  360. package/dist/index.js +77 -4
  361. package/dist/index.js.map +1 -1
  362. package/dist/landing/landing-actions.d.ts +8 -3
  363. package/dist/landing/landing-sections.d.ts +8 -3
  364. package/dist/landing/landing-sections.js +7 -3
  365. package/dist/landing/landing-sections.js.map +1 -1
  366. package/dist/landing/public-header.d.ts +9 -4
  367. package/dist/landing/public-header.js +3 -3
  368. package/dist/landing/public-header.js.map +1 -1
  369. package/dist/landing/routing.d.ts +8 -3
  370. package/dist/lib/cn.js +3 -2
  371. package/dist/lib/cn.js.map +1 -1
  372. package/dist/rhf/fields.d.ts +8 -3
  373. package/dist/rhf/fields.js +1 -1
  374. package/dist/rhf/fields.js.map +1 -1
  375. package/dist/rhf/form.d.ts +8 -3
  376. package/dist/rhf/form.js +2 -2
  377. package/dist/rhf/form.js.map +1 -1
  378. package/dist/rhf.d.ts +8 -3
  379. package/dist/search/command-palette.d.ts +1 -1
  380. package/dist/search/command-palette.js +9 -8
  381. package/dist/search/command-palette.js.map +1 -1
  382. package/dist/settings/settings-layout.js +2 -1
  383. package/dist/settings/settings-layout.js.map +1 -1
  384. package/dist/settings/settings-section.d.ts +8 -3
  385. package/dist/settings/use-account-appearance.d.ts +92 -0
  386. package/dist/settings/use-account-appearance.js +63 -0
  387. package/dist/settings/use-account-appearance.js.map +1 -0
  388. package/dist/settings/use-settings-route.d.ts +1 -1
  389. package/dist/settings/use-settings-route.js +2 -3
  390. package/dist/settings/use-settings-route.js.map +1 -1
  391. package/dist/shell/app-shell.d.ts +12 -171
  392. package/dist/shell/app-shell.js +144 -28
  393. package/dist/shell/app-shell.js.map +1 -1
  394. package/dist/shell/auth-layout.js +1 -1
  395. package/dist/shell/auth-layout.js.map +1 -1
  396. package/dist/shell/option-switcher-menu.js +1 -1
  397. package/dist/shell/option-switcher-menu.js.map +1 -1
  398. package/dist/shell/top-bar-brand.d.ts +8 -3
  399. package/dist/shell/top-bar-brand.js +3 -1
  400. package/dist/shell/top-bar-brand.js.map +1 -1
  401. package/dist/shell/topbar-action-menu.d.ts +4 -0
  402. package/dist/shell/topbar-action-menu.js +3 -3
  403. package/dist/shell/topbar-action-menu.js.map +1 -1
  404. package/dist/shell/topbar-controls.js +4 -4
  405. package/dist/shell/topbar-controls.js.map +1 -1
  406. package/dist/shell.d.ts +9 -5
  407. package/dist/theme/contrast-tokens.d.ts +41 -0
  408. package/dist/theme/contrast-tokens.js +59 -0
  409. package/dist/theme/contrast-tokens.js.map +1 -0
  410. package/dist/theme/contrast.d.ts +110 -0
  411. package/dist/theme/contrast.js +128 -0
  412. package/dist/theme/contrast.js.map +1 -0
  413. package/dist/theme/palette-presets.d.ts +12 -1
  414. package/dist/theme/palette-presets.js +9 -4
  415. package/dist/theme/palette-presets.js.map +1 -1
  416. package/dist/theme/palette-store.js.map +1 -1
  417. package/dist/theme/text-size.d.ts +173 -0
  418. package/dist/theme/text-size.js +121 -0
  419. package/dist/theme/text-size.js.map +1 -0
  420. package/dist/wizard/stepper-nav.d.ts +8 -3
  421. package/dist/wizard/wizard-summary.js +1 -1
  422. package/dist/wizard/wizard-summary.js.map +1 -1
  423. package/dist/wizard.d.ts +8 -3
  424. package/package.json +1 -1
  425. package/src/admin/admin-action-log.tsx +6 -1
  426. package/src/admin/invitations-panel.tsx +36 -29
  427. package/src/admin/user-roster.tsx +17 -72
  428. package/src/auth/auth-errors.ts +68 -7
  429. package/src/billing/billing-banner.tsx +205 -0
  430. package/src/billing/billing-labels.ts +240 -0
  431. package/src/billing/billing-lock.ts +75 -0
  432. package/src/billing/billing-standing.ts +72 -0
  433. package/src/billing/plan-card.tsx +458 -0
  434. package/src/billing/plan-limit-notice.tsx +145 -0
  435. package/src/billing/plan-limit.ts +53 -0
  436. package/src/billing/plan-price.ts +101 -0
  437. package/src/billing/subscription-actions.tsx +76 -0
  438. package/src/billing/subscription-status-chip.tsx +95 -0
  439. package/src/chart.ts +2 -0
  440. package/src/components/account-chips.tsx +36 -10
  441. package/src/components/alert-banner.tsx +16 -7
  442. package/src/components/amount-input.tsx +5 -5
  443. package/src/components/appearance-labels.ts +47 -0
  444. package/src/components/autocomplete.tsx +2 -2
  445. package/src/components/breadcrumbs.tsx +3 -3
  446. package/src/components/bulk-action-bar.tsx +11 -14
  447. package/src/components/button-group.tsx +21 -0
  448. package/src/components/calculator.tsx +4 -3
  449. package/src/components/calendar-heatmap.tsx +5 -5
  450. package/src/components/chart-height.ts +30 -0
  451. package/src/components/chart-zoom.tsx +6 -1
  452. package/src/components/checkbox-group.tsx +2 -2
  453. package/src/components/checkbox.tsx +62 -20
  454. package/src/components/chip.tsx +139 -30
  455. package/src/components/choice-card.tsx +16 -11
  456. package/src/components/column-mapper.tsx +1 -1
  457. package/src/components/combobox-core.tsx +8 -7
  458. package/src/components/combobox.tsx +8 -8
  459. package/src/components/country-select.tsx +1 -1
  460. package/src/components/currency-select.tsx +3 -3
  461. package/src/components/data-table-filter-popover.tsx +7 -1
  462. package/src/components/data-table-pagination.tsx +60 -31
  463. package/src/components/data-table.tsx +164 -43
  464. package/src/components/date-picker.tsx +44 -10
  465. package/src/components/description-list.tsx +2 -2
  466. package/src/components/dialog-frame.tsx +2 -1
  467. package/src/components/disclosure.tsx +3 -2
  468. package/src/components/dropdown.tsx +10 -2
  469. package/src/components/facing-pair.ts +12 -5
  470. package/src/components/field-parts.tsx +190 -7
  471. package/src/components/field-sync.tsx +17 -3
  472. package/src/components/field.tsx +2 -2
  473. package/src/components/floating-panel.tsx +7 -4
  474. package/src/components/focus-ring.ts +12 -0
  475. package/src/components/form-actions.tsx +55 -18
  476. package/src/components/full-bleed-dialog.tsx +18 -4
  477. package/src/components/image-grid.tsx +1 -1
  478. package/src/components/inline-edit-field.tsx +26 -4
  479. package/src/components/legal-page.tsx +28 -2
  480. package/src/components/legal.tsx +19 -1
  481. package/src/components/lightbox.tsx +24 -2
  482. package/src/components/line-items.tsx +7 -1
  483. package/src/components/list.tsx +36 -10
  484. package/src/components/measured-grid.tsx +49 -24
  485. package/src/components/menu-item.tsx +2 -2
  486. package/src/components/mini-calendar.tsx +8 -4
  487. package/src/components/month-picker.tsx +15 -6
  488. package/src/components/nav-pills.tsx +1 -1
  489. package/src/components/number-input.tsx +14 -7
  490. package/src/components/numpad-sheet.tsx +2 -2
  491. package/src/components/one-time-code-input.tsx +2 -2
  492. package/src/components/page-contents.tsx +2 -2
  493. package/src/components/phone-input.tsx +9 -4
  494. package/src/components/pie-chart.tsx +19 -9
  495. package/src/components/popover.tsx +22 -5
  496. package/src/components/row-actions.tsx +450 -0
  497. package/src/components/scroll-area.tsx +1 -1
  498. package/src/components/search-field.tsx +4 -2
  499. package/src/components/series-chart-budget.ts +40 -8
  500. package/src/components/series-chart-ticks.ts +10 -0
  501. package/src/components/series-chart.tsx +123 -72
  502. package/src/components/settings-fields.tsx +89 -5
  503. package/src/components/share-card.tsx +31 -2
  504. package/src/components/sign-chip.tsx +28 -4
  505. package/src/components/signature-pad.tsx +13 -7
  506. package/src/components/slider.tsx +22 -9
  507. package/src/components/sparkline.tsx +11 -3
  508. package/src/components/stat-tile.tsx +70 -14
  509. package/src/components/status-dot.tsx +25 -2
  510. package/src/components/swipeable-row.tsx +10 -2
  511. package/src/components/switch.tsx +57 -23
  512. package/src/components/table.tsx +2 -2
  513. package/src/components/text-link.tsx +1 -1
  514. package/src/components/text.tsx +11 -6
  515. package/src/components/tile-radio.tsx +4 -1
  516. package/src/components/toast.tsx +27 -7
  517. package/src/components/toggle-group.tsx +115 -14
  518. package/src/components/toggle-legend.tsx +53 -8
  519. package/src/components/translation-review-editor.tsx +1 -1
  520. package/src/components/translation-review.tsx +11 -5
  521. package/src/components/tree-view.tsx +3 -2
  522. package/src/components/treemap.tsx +27 -10
  523. package/src/components/ui.tsx +353 -153
  524. package/src/components/user-avatar.tsx +1 -1
  525. package/src/components/wizard-stepper.tsx +5 -1
  526. package/src/demo/demo-banner.tsx +5 -0
  527. package/src/feedback/feedback-dialog.tsx +3 -3
  528. package/src/feedback/feedback-inbox.tsx +2 -2
  529. package/src/feedback/feedback-thread.tsx +3 -3
  530. package/src/hooks/use-anchored-panel.ts +67 -5
  531. package/src/hooks/use-breakpoint.ts +132 -0
  532. package/src/hooks/use-large-text.ts +41 -0
  533. package/src/hooks/use-windowed-rows.ts +168 -12
  534. package/src/i18n/defaults.ts +8 -0
  535. package/src/i18n/german.ts +107 -0
  536. package/src/i18n/kit-labels.tsx +12 -0
  537. package/src/i18n/locales/es.ts +98 -0
  538. package/src/i18n/locales/fr.ts +102 -0
  539. package/src/i18n/locales/hu.ts +100 -0
  540. package/src/i18n/locales/it.ts +103 -0
  541. package/src/i18n/locales/zh.ts +94 -0
  542. package/src/i18n/review.ts +14 -0
  543. package/src/index.ts +76 -6
  544. package/src/landing/landing-sections.tsx +7 -3
  545. package/src/landing/public-header.tsx +4 -4
  546. package/src/lib/cn.ts +13 -2
  547. package/src/rhf/fields.tsx +1 -1
  548. package/src/rhf/form.tsx +2 -2
  549. package/src/search/command-palette.tsx +10 -9
  550. package/src/settings/settings-layout.tsx +2 -1
  551. package/src/settings/use-account-appearance.ts +148 -0
  552. package/src/settings/use-settings-route.ts +3 -4
  553. package/src/shell/app-shell.tsx +278 -54
  554. package/src/shell/auth-layout.tsx +1 -1
  555. package/src/shell/option-switcher-menu.tsx +1 -1
  556. package/src/shell/top-bar-brand.tsx +3 -1
  557. package/src/shell/topbar-action-menu.tsx +3 -3
  558. package/src/shell/topbar-controls.tsx +4 -4
  559. package/src/theme/contrast-tokens.ts +112 -0
  560. package/src/theme/contrast.ts +225 -0
  561. package/src/theme/palette-presets.ts +24 -4
  562. package/src/theme/palette-store.ts +6 -1
  563. package/src/theme/text-size.ts +283 -0
  564. package/src/wizard/wizard-summary.tsx +4 -2
  565. package/tokens.css +158 -8
@@ -4,6 +4,7 @@ import { cn } from "../lib/cn";
4
4
  import { useAnnounce } from "../hooks/use-announce";
5
5
  import { useKitLabels } from "../i18n/kit-labels";
6
6
  import { Input, Spinner } from "./ui";
7
+ import { FOCUS_RING } from "./focus-ring";
7
8
  import { Tooltip } from "./tooltip";
8
9
  import { useCommitReason } from "./write-lock";
9
10
 
@@ -154,6 +155,23 @@ function RenderEditor<T>({ render, ...props }: InlineEditorProps<T> & { render:
154
155
  return render(props);
155
156
  }
156
157
 
158
+ /**
159
+ * The value at Large and Extra large (0.32.1, keksdose's 0.32 report;
160
+ * docs/text-size-harmonization.md §4 "nothing truncates"): the display button, the
161
+ * locked one and the read-only text wrap instead of ending in "…", and break a word too
162
+ * long for the cell, so an IBAN or an e-mail address shows to its last character. The
163
+ * value IS the button's accessible name and the thing being edited: a reader who needs
164
+ * big type cannot recover a cut-off end by squinting. A `large:` class, so a table of
165
+ * these keeps its one-line cells at Normal.
166
+ *
167
+ * `break-words`, not `[overflow-wrap:anywhere]`: these live in table cells (keksdose's
168
+ * budget and invoice lines), and `anywhere` lowers the value's min-content width to one
169
+ * letter, so an auto-sized column could squeeze an amount to a digit per line. With
170
+ * `break-word` a column keeps each word whole; the button is `w-full`, so a word wider
171
+ * than a sized cell still breaks.
172
+ */
173
+ const VALUE_WRAP_AT_LARGE = "large:whitespace-normal large:break-words";
174
+
157
175
  /** `onCommit`'s result, if it is a promise. */
158
176
  function asPromise(result: unknown): Promise<unknown> | null {
159
177
  return result && typeof (result as Promise<unknown>).then === "function" ? (result as Promise<unknown>) : null;
@@ -414,7 +432,7 @@ export function InlineEditField<T = string>(props: InlineEditFieldProps<T>) {
414
432
  let body: ReactNode;
415
433
  if (readOnly) {
416
434
  body = (
417
- <span {...private_} className={cn("block min-w-0 truncate", alignClass)}>
435
+ <span {...private_} className={cn("block min-w-0 truncate", VALUE_WRAP_AT_LARGE, alignClass)}>
418
436
  {content}
419
437
  </span>
420
438
  );
@@ -467,7 +485,7 @@ export function InlineEditField<T = string>(props: InlineEditFieldProps<T>) {
467
485
  {pending && <Spinner label={null} className="size-4 shrink-0" />}
468
486
  </div>
469
487
  {failed && (
470
- <p id={errorId} className="mt-1 text-[11px] leading-tight text-[var(--danger)]">
488
+ <p id={errorId} className="mt-1 text-caption leading-tight text-[var(--danger)]">
471
489
  {failure}
472
490
  </p>
473
491
  )}
@@ -490,7 +508,9 @@ export function InlineEditField<T = string>(props: InlineEditFieldProps<T>) {
490
508
  aria-describedby={reasonId}
491
509
  onClick={(e) => e.preventDefault()}
492
510
  className={cn(
493
- "block w-full min-w-0 cursor-not-allowed truncate rounded-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--brand)]",
511
+ "block w-full min-w-0 cursor-not-allowed truncate rounded-sm focus:outline-none",
512
+ VALUE_WRAP_AT_LARGE,
513
+ FOCUS_RING,
494
514
  alignClass,
495
515
  )}
496
516
  >
@@ -513,7 +533,9 @@ export function InlineEditField<T = string>(props: InlineEditFieldProps<T>) {
513
533
  {...private_}
514
534
  onClick={() => setOpen(true)}
515
535
  className={cn(
516
- "block w-full min-w-0 truncate rounded-sm underline-offset-2 hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--brand)]",
536
+ "block w-full min-w-0 truncate rounded-sm underline-offset-2 hover:underline focus:outline-none",
537
+ VALUE_WRAP_AT_LARGE,
538
+ FOCUS_RING,
517
539
  alignClass,
518
540
  )}
519
541
  >
@@ -9,6 +9,7 @@ import { cn } from "../lib/cn";
9
9
  import { Checkbox } from "./checkbox";
10
10
  import type { CheckboxProps } from "./checkbox";
11
11
  import {
12
+ DEFAULT_LEGAL_LABELS,
12
13
  LEGAL_HREFS,
13
14
  baseLanguage,
14
15
  LegalFooter,
@@ -22,6 +23,7 @@ import {
22
23
  warnLegalOnce,
23
24
  } from "./legal";
24
25
  import type {
26
+ LegalDisclaimerSectionLabels,
25
27
  LegalFramedSectionLabels,
26
28
  LegalLabels,
27
29
  LegalOperator,
@@ -163,6 +165,7 @@ export type LegalKitSectionProps = LegalKitSectionBase &
163
165
  (
164
166
  | {
165
167
  section: "browser";
168
+ variant?: never;
166
169
  /** What this app keeps in the browser, one entry per item — rendered as a `<ul>`
167
170
  * between the kit's two sentences. The app's words, in every language it serves. */
168
171
  entries: readonly string[];
@@ -171,6 +174,7 @@ export type LegalKitSectionProps = LegalKitSectionBase &
171
174
  }
172
175
  | {
173
176
  section: "legal_basis" | "rights";
177
+ variant?: never;
174
178
  entries?: never;
175
179
  /** `legal_basis`: after the kit's paragraph (consent, where an app relies on
176
180
  * it). `rights`: between the list of rights and the supervisory authorities
@@ -179,12 +183,28 @@ export type LegalKitSectionProps = LegalKitSectionBase &
179
183
  children?: ReactNode;
180
184
  }
181
185
  | {
182
- section: Exclude<LegalKitSectionKey, "browser" | "legal_basis" | "rights">;
186
+ section: "disclaimer";
187
+ /**
188
+ * 0.32.0 (docs/billing-harmonization.md §8, legal decision 7): which disclaimer.
189
+ * `non-commercial` (default) is the beta's "private, non-commercial project";
190
+ * `commercial` is for an app that charges, sold through a Merchant of Record —
191
+ * chosen per app, in the release that turns its billing on.
192
+ */
193
+ variant?: LegalDisclaimerVariant;
194
+ entries?: never;
195
+ children?: never;
196
+ }
197
+ | {
198
+ section: Exclude<LegalKitSectionKey, "browser" | "legal_basis" | "rights" | "disclaimer">;
199
+ variant?: never;
183
200
  entries?: never;
184
201
  children?: never;
185
202
  }
186
203
  );
187
204
 
205
+ /** 0.32.0: the imprint disclaimer's two texts — see {@link LegalKitSectionProps}. */
206
+ export type LegalDisclaimerVariant = "non-commercial" | "commercial";
207
+
188
208
  /** The app's paragraph: a plain string as running text (line breaks kept, refs
189
209
  * resolved), anything else as it is. */
190
210
  function appPart(children: ReactNode): ReactNode {
@@ -261,7 +281,13 @@ export function LegalKitSection(props: LegalKitSectionProps) {
261
281
  parts = [lead, app, tail];
262
282
  }
263
283
  } else {
264
- parts = [<LegalText key="body" text={fill(entry.body)} />, app];
284
+ // The imprint's commercial disclaimer (0.32.0): its own body under the same title.
285
+ const commercial =
286
+ props.section === "disclaimer" && props.variant === "commercial"
287
+ ? ((entry as LegalDisclaimerSectionLabels).commercial ??
288
+ DEFAULT_LEGAL_LABELS.sections.impressum.disclaimer.commercial)
289
+ : undefined;
290
+ parts = [<LegalText key="body" text={commercial ?? fill(entry.body)} />, app];
265
291
  }
266
292
 
267
293
  return (
@@ -132,6 +132,21 @@ export interface LegalTextSectionLabels {
132
132
  body: string;
133
133
  }
134
134
 
135
+ /**
136
+ * 0.32.0: the imprint's disclaimer, with the body of its COMMERCIAL variant
137
+ * (docs/billing-harmonization.md §8; legal decision 7). The title is the same in both:
138
+ * liability for content and links is the subject either way.
139
+ */
140
+ export interface LegalDisclaimerSectionLabels extends LegalTextSectionLabels {
141
+ /**
142
+ * The body for `<LegalKitSection section="disclaimer" variant="commercial">`: a paid
143
+ * service sold through a Merchant of Record, which sells in its own name (§2.2), so the
144
+ * "private, non-commercial … closed beta" of `body` would be untrue. OPTIONAL, as every
145
+ * key added to a namespace an app may annotate: left out, the provider's, then English.
146
+ */
147
+ commercial?: string;
148
+ }
149
+
135
150
  /** A kit section whose text names the operator (§4.3 `{name}`, `{email}`, …). */
136
151
  export interface LegalOperatorSectionLabels {
137
152
  title: string;
@@ -197,7 +212,8 @@ export interface LegalLabels {
197
212
  impressum: {
198
213
  operator: LegalOperatorSectionLabels;
199
214
  contact: LegalOperatorSectionLabels;
200
- disclaimer: LegalTextSectionLabels;
215
+ /** `body` is the default, non-commercial text; `commercial` the 0.32 variant. */
216
+ disclaimer: LegalDisclaimerSectionLabels;
201
217
  };
202
218
  privacy: {
203
219
  controller: LegalOperatorSectionLabels;
@@ -260,6 +276,8 @@ export const DEFAULT_LEGAL_LABELS: LegalLabels = {
260
276
  disclaimer: {
261
277
  title: "Liability for content and links",
262
278
  body: "This is a private, non-commercial project offered during a closed beta, without warranty. External sites we link to are the responsibility of their respective operators; we have no control over their content.",
279
+ commercial:
280
+ "This is a commercial service. Paid plans are sold by our reseller, which acts as the Merchant of Record: it sells the subscription in its own name, takes the payment, issues the invoice and handles VAT, and its terms of sale apply to the purchase. We take care that the content of this service is accurate, but cannot guarantee that it is complete or up to date. External sites we link to are the responsibility of their respective operators; we have no control over their content.",
263
281
  },
264
282
  },
265
283
  privacy: {
@@ -6,6 +6,7 @@ import { cn } from "../lib/cn";
6
6
  import { horizontalStep } from "../lib/direction";
7
7
  import { useKitLabels } from "../i18n/kit-labels";
8
8
  import { useAuthedSrc } from "../hooks/use-authed-src";
9
+ import { useBreakpoint } from "../hooks/use-breakpoint";
9
10
  import type { AuthedFetcher } from "../hooks/use-authed-src";
10
11
  import { FullBleedDialog } from "./full-bleed-dialog";
11
12
  import { IconButton, buttonClasses } from "./ui";
@@ -169,6 +170,16 @@ export function Lightbox({
169
170
  const anchorRef = useRef<HTMLSpanElement>(null);
170
171
  const dir = useAnchorDir(anchorRef, open);
171
172
 
173
+ // The toolbar's words (docs/text-size-harmonization.md §4, §10.8). At Large an
174
+ // IconButton shows its label beside the glyph; on a narrow screen the viewer's header —
175
+ // the counter, Zoom, Download and the dialog's close — has no room for two words at
176
+ // 150 % (a 390 px phone is 260 px of Normal type), so below `sm` the toolbar keeps its
177
+ // icons, as the plain download link hides its word there (`max-sm:sr-only`). From `sm`
178
+ // up, at the same breakpoint the CSS uses, the words show. Each name stays the
179
+ // accessible name and the tooltip either way.
180
+ const narrow = useBreakpoint("max-sm");
181
+ const toolbarLabelVisible = narrow ? false : undefined;
182
+
172
183
  const fetched = useAuthedSrc(item?.src, { fetcher, enabled: open });
173
184
  const kind = item ? imageItemKind(item, fetched.type) : "image";
174
185
 
@@ -236,7 +247,12 @@ export function Lightbox({
236
247
  const downloadControl =
237
248
  download && item ? (
238
249
  onDownload ? (
239
- <IconButton size="sm" label={labels.download} onClick={() => onDownload(item, index)}>
250
+ <IconButton
251
+ size="sm"
252
+ label={labels.download}
253
+ labelVisible={toolbarLabelVisible}
254
+ onClick={() => onDownload(item, index)}
255
+ >
240
256
  <Download />
241
257
  </IconButton>
242
258
  ) : downloadHref ? (
@@ -264,7 +280,13 @@ export function Lightbox({
264
280
  </span>
265
281
  <span className="min-w-0 flex-1" />
266
282
  {zoomEnabled && kind === "image" && (
267
- <IconButton size="sm" label={labels.zoom} pressed={zoomed} onClick={toggleZoom}>
283
+ <IconButton
284
+ size="sm"
285
+ label={labels.zoom}
286
+ labelVisible={toolbarLabelVisible}
287
+ pressed={zoomed}
288
+ onClick={toggleZoom}
289
+ >
268
290
  <ZoomIn />
269
291
  </IconButton>
270
292
  )}
@@ -384,6 +384,12 @@ export function LineItems<T>({
384
384
  variant={isConfirming ? "danger" : "ghost"}
385
385
  tone={isConfirming ? undefined : "danger"}
386
386
  label={isConfirming ? labels.confirmRemove(row) : labels.remove(row)}
387
+ // The icon alone at every text size (docs/text-size-harmonization.md §10.8): the
388
+ // row's one control, in a grid column sized for an icon, whose name becomes a
389
+ // sentence while it waits ("Remove row 3? Press again to confirm") — as text at
390
+ // Large it would push the row's fields aside and change width between the two
391
+ // presses. The name stays the accessible name; the red fill says "confirm".
392
+ labelVisible={false}
387
393
  disabled={!canRemove}
388
394
  onClick={() => void removeAt(index)}
389
395
  onBlur={() => {
@@ -588,7 +594,7 @@ export function LineItems<T>({
588
594
  )}
589
595
 
590
596
  {hasError && (
591
- <p className="text-[11px] leading-tight text-[var(--danger)]">
597
+ <p className="text-caption leading-tight text-[var(--danger)]">
592
598
  {error}
593
599
  </p>
594
600
  )}
@@ -3,7 +3,7 @@ import type { ComponentPropsWithoutRef, HTMLAttributes, MouseEvent, ReactElement
3
3
  import { ChevronDown, ExternalLink } from "lucide-react";
4
4
  import type { LucideIcon } from "lucide-react";
5
5
  import { cn } from "../lib/cn";
6
- import { Spinner } from "./ui";
6
+ import { FOCUS_RING, Spinner } from "./ui";
7
7
  import { StatusDot } from "./status-dot";
8
8
  import { Collapse } from "./disclosure";
9
9
  import { toneTextClass } from "./signed-amount";
@@ -114,8 +114,20 @@ const PAD: Record<
114
114
  * colour of the slot's own, so an element's colour (or the row's) stands. */
115
115
  export type ListItemTrailingTone = TextTone | "inherit";
116
116
 
117
- const TARGET_RING =
118
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--brand)]";
117
+ // The kit's focus frame (§5), inset so the row's own border and its neighbours do not
118
+ // clip it.
119
+ const TARGET_RING = cn(FOCUS_RING, "focus-visible:ring-inset");
120
+
121
+ /**
122
+ * §4 "ListItem: title, subtitle and meta wrap instead of truncating" at Large and Extra
123
+ * large (docs/text-size-harmonization.md). `large:` variants over the Normal look, so
124
+ * a list keeps its one-height rows at Normal and costs no render to switch: a one-line
125
+ * `truncate` wraps (and breaks a word too long for the row), a `line-clamp-2` lets go.
126
+ * An ellipsis hides the end of a name, which is the part a reader who needs big type
127
+ * cannot recover by squinting.
128
+ */
129
+ const WRAP_AT_LARGE = "large:whitespace-normal large:[overflow-wrap:anywhere]";
130
+ const UNCLAMP_AT_LARGE = "large:line-clamp-none";
119
131
 
120
132
  interface ListItemBaseProps {
121
133
  /** The row's name: one line, truncated — unless {@link titleLines} says otherwise. */
@@ -410,6 +422,11 @@ interface NotExpandable {
410
422
  * One row of a {@link List}: leading icon or avatar, title and subtitle (both
411
423
  * truncating by default), a trailing slot, and — beside the row, not inside it — its actions.
412
424
  *
425
+ * At Large and Extra large (0.32, docs/text-size-harmonization.md §4) nothing in it
426
+ * truncates: the overline, title, subtitle and meta wrap, a two-line clamp lets go, and
427
+ * a trailing slot drops under the text when the two no longer fit side by side. The
428
+ * rows lose their one height there; that is the trade the reader asked for.
429
+ *
413
430
  * All three apps draw this row by hand, a dozen times: kastlan's units
414
431
  * (building-detail-page.tsx:402), open tickets (group-overview-page.tsx:160), activity
415
432
  * feed (activity-feed.tsx:53), company users (platform-company-detail-page.tsx:140)
@@ -506,9 +523,12 @@ export const ListItem = forwardRef<HTMLElement, ListItemProps>(function ListItem
506
523
  />
507
524
  )}
508
525
  {leading}
509
- <span className="flex min-w-0 flex-1 flex-col">
526
+ {/* With a trailing slot, a basis at Large: below it the trailing chip or figure
527
+ wraps under the text (the target wraps, see `target`) rather than squeezing the
528
+ now-wrapping title into a column one word wide (§4, 240 px effective width). */}
529
+ <span className={cn("flex min-w-0 flex-1 flex-col", trailing != null && "large:basis-40")}>
510
530
  {overline != null && (
511
- <span className="block truncate text-[11px] font-medium leading-snug text-[var(--text-muted)]">
531
+ <span className={cn("block truncate text-caption font-medium leading-snug text-[var(--text-muted)]", WRAP_AT_LARGE)}>
512
532
  {overline}
513
533
  </span>
514
534
  )}
@@ -517,7 +537,11 @@ export const ListItem = forwardRef<HTMLElement, ListItemProps>(function ListItem
517
537
  id={stacked ? titleId : undefined}
518
538
  className={cn(
519
539
  "block text-sm text-[var(--text-primary)]",
520
- titleLines === 1 ? "truncate" : titleLines === 2 ? "line-clamp-2 break-words" : "break-words",
540
+ titleLines === 1
541
+ ? cn("truncate", WRAP_AT_LARGE)
542
+ : titleLines === 2
543
+ ? cn("line-clamp-2 break-words", UNCLAMP_AT_LARGE)
544
+ : "break-words",
521
545
  unread ? "font-semibold" : "font-medium",
522
546
  )}
523
547
  >
@@ -529,7 +553,7 @@ export const ListItem = forwardRef<HTMLElement, ListItemProps>(function ListItem
529
553
  <span
530
554
  className={cn(
531
555
  "block text-xs text-[var(--text-muted)]",
532
- subtitleLines === 2 ? "line-clamp-2" : "truncate",
556
+ subtitleLines === 2 ? cn("line-clamp-2 break-words", UNCLAMP_AT_LARGE) : cn("truncate", WRAP_AT_LARGE),
533
557
  )}
534
558
  >
535
559
  {subtitle}
@@ -538,8 +562,8 @@ export const ListItem = forwardRef<HTMLElement, ListItemProps>(function ListItem
538
562
  {meta != null && (
539
563
  <span
540
564
  className={cn(
541
- "mt-0.5 text-[11px] leading-snug text-[var(--text-muted)]",
542
- metaWrap ? "flex flex-wrap items-center gap-1" : "block truncate",
565
+ "mt-0.5 text-caption leading-snug text-[var(--text-muted)]",
566
+ metaWrap ? "flex flex-wrap items-center gap-1" : cn("block truncate", WRAP_AT_LARGE),
543
567
  )}
544
568
  >
545
569
  {meta}
@@ -550,7 +574,7 @@ export const ListItem = forwardRef<HTMLElement, ListItemProps>(function ListItem
550
574
  {trailing != null && (
551
575
  <span
552
576
  className={cn(
553
- "flex shrink-0 items-center gap-2 text-xs",
577
+ "flex shrink-0 items-center gap-2 text-xs large:ms-auto",
554
578
  trailingTone !== "inherit" && toneTextClass(trailingTone),
555
579
  )}
556
580
  >
@@ -582,6 +606,8 @@ export const ListItem = forwardRef<HTMLElement, ListItemProps>(function ListItem
582
606
 
583
607
  const target = cn(
584
608
  "flex min-w-0 flex-1 text-start",
609
+ // §4 at Large: the trailing slot drops under the text when both no longer fit.
610
+ trailing != null && "large:flex-wrap",
585
611
  align === "start" ? "items-start" : "items-center",
586
612
  pad.target,
587
613
  // When stacked the target is the top of the box, not all of it, so it takes its
@@ -8,9 +8,9 @@ import { horizontalStep } from "../lib/direction";
8
8
  // be either and the line decides. See the three named rules at the top of table-text.
9
9
  import { cellNumber, isCellNumber, parseRows, splitRow } from "../lib/table-text";
10
10
  import { useKitLabels, useKitLocale } from "../i18n/kit-labels";
11
- import { useWindowedRows } from "../hooks/use-windowed-rows";
11
+ import { useWindowedRows, WINDOWED_ROW_INDEX } from "../hooks/use-windowed-rows";
12
12
  import { ToggleGroup } from "./toggle-group";
13
- import { Button, FIELD_INVALID, Textarea } from "./ui";
13
+ import { Button, FIELD_INVALID, FIELD_TOUCH_TEXT, FOCUS_RING, Textarea } from "./ui";
14
14
 
15
15
  /**
16
16
  * A measured table: a fixed set of numeric columns, typed cell by cell or pasted as a
@@ -101,8 +101,10 @@ export type MeasuredGridView = "cells" | "text";
101
101
  * empty cell is a hole in the measurement, and a table with a hole is not one to save. */
102
102
  const BLANK = "";
103
103
 
104
- /** Height of one grid row, in pixels. Fixed, which is what lets the windowing be
105
- * arithmetic rather than measurement. */
104
+ /** Height of one grid row at Normal text size, in px — the windowing's ESTIMATE since
105
+ * 0.32 (docs/text-size-harmonization.md §10.9): `useWindowedRows` multiplies it by the
106
+ * text size's scale (35 px at Large, 42 at Extra large) and then measures the rows it
107
+ * renders, so a row is never cut to a height the type has outgrown. */
106
108
  const DEFAULT_ROW_HEIGHT = 28;
107
109
 
108
110
  const ALL_VIEWS: readonly MeasuredGridView[] = ["cells", "text"];
@@ -218,7 +220,9 @@ export interface MeasuredGridProps
218
220
  /** Which views the toggle offers, the first being where it opens. Default both;
219
221
  * one view hides the toggle. */
220
222
  views?: ReadonlyArray<MeasuredGridView>;
221
- /** Row height in pixels, for the windowing. Fixed on purpose. Default 28. */
223
+ /** A row's height at Normal text size, in px. Default 28. Since 0.32 it is the
224
+ * windowing's estimate and each row's minimum, multiplied by the text size's scale;
225
+ * the rendered rows are measured (docs/text-size-harmonization.md §10.9). */
222
226
  rowHeight?: number;
223
227
  /** BCP 47 tag for the decimal mark of cells written by a paste or the text view,
224
228
  * and for the row numbers; else the `<UiKitProvider locale>`. */
@@ -288,7 +292,7 @@ export function MeasuredGrid({
288
292
  // to the initial containing block (see sr-only-containment.test).
289
293
  <div {...rest} className={cn("relative", className)}>
290
294
  <div className="mb-1 flex flex-wrap items-center justify-between gap-2">
291
- <span id={labelId} className="text-[11px] font-medium text-[var(--text-muted)]">
295
+ <span id={labelId} className="text-caption font-medium text-[var(--text-muted)]">
292
296
  {label}
293
297
  </span>
294
298
  {offered.length > 1 && (
@@ -330,7 +334,7 @@ export function MeasuredGrid({
330
334
  />
331
335
  )}
332
336
  {hint && (
333
- <p id={hintId} className="mt-1 px-1 text-[11px] text-[var(--text-muted)]">
337
+ <p id={hintId} className="mt-1 px-1 text-caption text-[var(--text-muted)]">
334
338
  {hint}
335
339
  </p>
336
340
  )}
@@ -382,7 +386,11 @@ function CellGrid({
382
386
  // first number, and "add a row" is not the first thing to ask of someone who has
383
387
  // just opened an empty table. It is not written back until something is typed.
384
388
  const grid = cells.length ? cells : [blankRow()];
385
- const { first, last, totalHeight } = useWindowedRows(grid.length, rowHeight, scrollRef);
389
+ const { first, last, totalHeight, offsetOf, heightOf, estimate, measureRef } = useWindowedRows(
390
+ grid.length,
391
+ rowHeight,
392
+ scrollRef,
393
+ );
386
394
  const rowNumber = useMemo(() => new Intl.NumberFormat(locale), [locale]);
387
395
 
388
396
  // The remove buttons are the last column of the grid, reachable by the arrows like
@@ -434,9 +442,11 @@ function CellGrid({
434
442
  if (!element) return;
435
443
  const room = element.clientHeight - (headRef.current?.offsetHeight ?? 0);
436
444
  if (room <= 0) return;
437
- const top = row * rowHeight;
445
+ // Measured where the row has been rendered, the scaled estimate where not (§10.9).
446
+ const top = offsetOf(row);
447
+ const height = heightOf(row);
438
448
  if (top < element.scrollTop) element.scrollTop = top;
439
- else if (top + rowHeight > element.scrollTop + room) element.scrollTop = top + rowHeight - room;
449
+ else if (top + height > element.scrollTop + room) element.scrollTop = top + height - room;
440
450
  };
441
451
 
442
452
  const focusCell = (row: number, column: number) => {
@@ -468,7 +478,7 @@ function CellGrid({
468
478
  const element = scrollRef.current;
469
479
  const room = element ? element.clientHeight - (headRef.current?.offsetHeight ?? 0) : 0;
470
480
  // No layout (a hidden pane, jsdom): a fixed ten rather than one row at a time.
471
- return room > 0 ? Math.max(1, Math.floor(room / rowHeight) - 1) : 10;
481
+ return room > 0 ? Math.max(1, Math.floor(room / estimate) - 1) : 10;
472
482
  };
473
483
 
474
484
  /**
@@ -603,7 +613,7 @@ function CellGrid({
603
613
  <div
604
614
  role="columnheader"
605
615
  aria-label={labels.rowNumber}
606
- className="flex items-end justify-end px-1 py-1 text-[10px] text-[var(--text-placeholder)]"
616
+ className="flex items-end justify-end px-1 py-1 text-micro text-[var(--text-placeholder)]"
607
617
  >
608
618
  #
609
619
  </div>
@@ -617,7 +627,7 @@ function CellGrid({
617
627
  {column.label}
618
628
  </span>
619
629
  {column.unit && (
620
- <span className="block truncate text-[10px] text-[var(--text-muted)]">
630
+ <span className="block truncate text-micro text-[var(--text-muted)]">
621
631
  {column.unit}
622
632
  </span>
623
633
  )}
@@ -632,21 +642,25 @@ function CellGrid({
632
642
  </div>
633
643
  {/* Only the rows in the window are mounted — a swept linkage is thousands of
634
644
  them across fifteen inputs — each placed at its own offset, so mounting
635
- one more (the caret's) costs nothing in the arithmetic. */}
645
+ one more (the caret's) costs nothing in the arithmetic. Since 0.32 a row
646
+ is at least the scaled estimate tall and measured as it renders (§10.9):
647
+ `minHeight`, not `height`, so the type at Extra large is never cut. */}
636
648
  <div role="rowgroup" className="relative" style={{ height: totalHeight }}>
637
649
  {mounted.map((index) => {
638
650
  const row = grid[index];
639
651
  return (
640
652
  <div
641
653
  key={index}
654
+ ref={measureRef}
655
+ {...{ [WINDOWED_ROW_INDEX]: index }}
642
656
  role="row"
643
657
  aria-rowindex={index + 2}
644
658
  className="absolute inset-x-0 grid hover:bg-[var(--bg-hover)]"
645
- style={{ top: index * rowHeight, height: rowHeight, gridTemplateColumns: template }}
659
+ style={{ top: offsetOf(index), minHeight: estimate, gridTemplateColumns: template }}
646
660
  >
647
661
  <div
648
662
  role="rowheader"
649
- className="flex items-center justify-end px-1 text-[10px] tabular-nums text-[var(--text-placeholder)]"
663
+ className="flex items-center justify-end px-1 text-micro tabular-nums text-[var(--text-placeholder)]"
650
664
  >
651
665
  {rowNumber.format(index + 1)}
652
666
  </div>
@@ -672,9 +686,16 @@ function CellGrid({
672
686
  aria-invalid={bad || undefined}
673
687
  className={cn(
674
688
  "block size-full bg-transparent px-2 text-end tabular-nums text-[var(--text-primary)] outline-none",
689
+ // A cell is a field: 16 px on touch, or iOS zooms on focus (§10.1).
690
+ FIELD_TOUCH_TEXT,
675
691
  // Arriving selects the text (typing replaces it); editing
676
692
  // in place is the plain surface with a caret in it.
677
- "focus:bg-[var(--brand-bg)] focus:ring-2 focus:ring-inset focus:ring-[var(--brand)]",
693
+ // The kit's focus frame (§5), inset so the next cell's
694
+ // border does not paint over it. A text input is
695
+ // `:focus-visible` however it was focused.
696
+ "focus:bg-[var(--brand-bg)]",
697
+ FOCUS_RING,
698
+ "focus-visible:ring-inset",
678
699
  isCaret && editing && "focus:bg-[var(--bg-surface)]",
679
700
  disabled && "text-[var(--text-muted)]",
680
701
  bad && cn(FIELD_INVALID, "ring-inset"),
@@ -723,7 +744,10 @@ function CellGrid({
723
744
  disabled={!removable}
724
745
  tabIndex={at.row === index && at.column === width ? 0 : -1}
725
746
  aria-label={labels.removeRow(index + 1)}
726
- className="rounded p-1 text-[var(--text-placeholder)] outline-none hover:text-[var(--danger)] focus-visible:ring-2 focus-visible:ring-[var(--brand)] disabled:cursor-default disabled:hover:text-[var(--text-placeholder)]"
747
+ className={cn(
748
+ "rounded p-1 text-[var(--text-placeholder)] outline-none hover:text-[var(--danger)] disabled:cursor-default disabled:hover:text-[var(--text-placeholder)]",
749
+ FOCUS_RING,
750
+ )}
727
751
  onKeyDown={(event) => onCellKeyDown(event, index, width)}
728
752
  onFocus={() => {
729
753
  if (at.row !== index || at.column !== width) setCaret({ row: index, column: width });
@@ -749,7 +773,7 @@ function CellGrid({
749
773
  <div className="flex flex-wrap items-center gap-x-2 gap-y-1 border-t border-[var(--border)] px-2 py-1.5">
750
774
  <Button
751
775
  variant="ghost"
752
- className="px-2 py-1 text-xs"
776
+ size="sm"
753
777
  disabled={disabled}
754
778
  onClick={() => {
755
779
  onCells([...grid.map(pad), blankRow()]);
@@ -760,7 +784,8 @@ function CellGrid({
760
784
  </Button>
761
785
  <Button
762
786
  variant="ghost"
763
- className="px-2 py-1 text-xs text-[var(--text-muted)]"
787
+ size="sm"
788
+ className="text-[var(--text-muted)]"
764
789
  disabled={disabled || !cells.length}
765
790
  onClick={() => {
766
791
  onCells([]);
@@ -770,14 +795,14 @@ function CellGrid({
770
795
  >
771
796
  <Eraser aria-hidden className="size-3.5" /> {labels.clear}
772
797
  </Button>
773
- <span className="text-[11px] tabular-nums text-[var(--text-muted)]">
798
+ <span className="text-caption tabular-nums text-[var(--text-muted)]">
774
799
  {/* bdi: an LTR label ("3 points") in an RTL grid would reorder to "points 3". */}
775
800
  <bdi>{labels.points(filled.length)}</bdi>
776
801
  </span>
777
802
  {problems > 0 && (
778
- <span className="text-[11px] text-[var(--danger)]">{labels.problems(problems)}</span>
803
+ <span className="text-caption text-[var(--danger)]">{labels.problems(problems)}</span>
779
804
  )}
780
- <span className="ms-auto flex items-center gap-1 text-[11px] text-[var(--text-muted)]">
805
+ <span className="ms-auto flex items-center gap-1 text-caption text-[var(--text-muted)]">
781
806
  <ClipboardPaste aria-hidden className="size-3.5" /> {labels.pasteHint}
782
807
  </span>
783
808
  </div>
@@ -843,7 +868,7 @@ function TextView({ columns, cells, onCells, disabled, mark, labels, labelledBy,
843
868
  onChange={(event) => setDraft(event.target.value)}
844
869
  onBlur={commit}
845
870
  />
846
- <p className="mt-1 px-1 text-[11px] text-[var(--text-muted)]">
871
+ <p className="mt-1 px-1 text-caption text-[var(--text-muted)]">
847
872
  {columns.map((column) => column.label).join(" · ")}
848
873
  {" — "}
849
874
  <bdi>{labels.points(lines)}</bdi>
@@ -3,6 +3,7 @@ import type { MouseEvent, ReactElement, ReactNode, Ref } from "react";
3
3
  import { Check } from "lucide-react";
4
4
  import type { LucideIcon } from "lucide-react";
5
5
  import { cn } from "../lib/cn";
6
+ import { FOCUS_RING } from "./focus-ring";
6
7
  import { useKitLink } from "../i18n/kit-labels";
7
8
  import { pickLinkRenderer } from "./text-link";
8
9
 
@@ -17,8 +18,7 @@ const MENU_ITEM_ROW =
17
18
 
18
19
  /** HoverMenu moves focus onto items with the arrow keys; a pointer user never sees the
19
20
  * ring, a keyboard user always does. Inset, because the panel clips its children. */
20
- const MENU_ITEM_FOCUS =
21
- "focus-visible:outline-none focus-visible:bg-[var(--bg-hover)] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--brand)]";
21
+ const MENU_ITEM_FOCUS = `${FOCUS_RING} focus-visible:bg-[var(--bg-hover)] focus-visible:ring-inset`;
22
22
 
23
23
  export type MenuItemTone = "default" | "danger";
24
24
 
@@ -2,6 +2,7 @@ import { useEffect, useId, useMemo, useRef, useState } from "react";
2
2
  import type { ComponentPropsWithoutRef, KeyboardEvent, ReactNode } from "react";
3
3
  import { ChevronLeft, ChevronRight } from "lucide-react";
4
4
  import { cn } from "../lib/cn";
5
+ import { FOCUS_RING, FOCUS_RING_WIDTH } from "./focus-ring";
5
6
  import { horizontalStep } from "../lib/direction";
6
7
  import { useAnnounce } from "../hooks/use-announce";
7
8
  import {
@@ -576,7 +577,7 @@ export function MiniCalendar({
576
577
  "grid grid-cols-7 text-center font-medium",
577
578
  lg
578
579
  ? "gap-px text-xs text-[var(--text-muted)]"
579
- : "text-[10px] uppercase text-[var(--text-placeholder)]",
580
+ : "text-micro uppercase text-[var(--text-placeholder)]",
580
581
  )}
581
582
  >
582
583
  {weekdayLabels.map((w, i) => (
@@ -639,7 +640,8 @@ export function MiniCalendar({
639
640
  onKeyDown={onDayKeyDown}
640
641
  className={cn(
641
642
  "text-xs tabular-nums text-[var(--text-placeholder)] transition-colors",
642
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--brand)]",
643
+ FOCUS_RING,
644
+ "focus-visible:ring-inset",
643
645
  disabled ? "cursor-not-allowed opacity-60" : "hover:bg-[var(--bg-hover)]",
644
646
  lg
645
647
  ? cn("flex w-full min-w-0 items-start bg-[var(--bg-surface-2)] p-1.5", LG_CELL_HEIGHT)
@@ -730,7 +732,8 @@ export function MiniCalendar({
730
732
  ? cn(
731
733
  "flex w-full min-w-0 flex-col items-stretch gap-1 overflow-hidden p-1.5 text-start text-xs transition-colors",
732
734
  LG_CELL_HEIGHT,
733
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--brand)]",
735
+ FOCUS_RING,
736
+ "focus-visible:ring-inset",
734
737
  disabled
735
738
  ? "cursor-not-allowed bg-[var(--bg-surface)] text-[var(--text-placeholder)]"
736
739
  : isSelected
@@ -745,7 +748,8 @@ export function MiniCalendar({
745
748
  // colour flips on the selected days for the reason the numpad's
746
749
  // "Done" key does — a --brand ring on a --brand fill is a ring
747
750
  // that exists only in the DOM.
748
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset",
751
+ FOCUS_RING_WIDTH,
752
+ "focus-visible:outline-none focus-visible:ring-inset",
749
753
  isStart || isEnd
750
754
  ? "focus-visible:ring-[var(--brand-contrast)]"
751
755
  : "focus-visible:ring-[var(--brand)]",