@eifi1/ui-kit 0.31.1 → 0.32.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 (538) 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/invitations-panel.d.ts +8 -3
  5. package/dist/admin/invitations-panel.js +29 -26
  6. package/dist/admin/invitations-panel.js.map +1 -1
  7. package/dist/admin/reviewer-scope-editor.d.ts +8 -3
  8. package/dist/admin/role-select.d.ts +10 -5
  9. package/dist/admin/transfer-ownership-dialog.d.ts +8 -3
  10. package/dist/admin/user-roster.d.ts +10 -5
  11. package/dist/admin/user-roster.js +8 -47
  12. package/dist/admin/user-roster.js.map +1 -1
  13. package/dist/auth/auth-errors.d.ts +43 -8
  14. package/dist/auth/auth-errors.js +24 -1
  15. package/dist/auth/auth-errors.js.map +1 -1
  16. package/dist/auth/register-form.d.ts +8 -3
  17. package/dist/billing/billing-banner.d.ts +184 -0
  18. package/dist/billing/billing-banner.js +98 -0
  19. package/dist/billing/billing-banner.js.map +1 -0
  20. package/dist/billing/billing-labels.d.ts +100 -0
  21. package/dist/billing/billing-labels.js +74 -0
  22. package/dist/billing/billing-labels.js.map +1 -0
  23. package/dist/billing/billing-lock.d.ts +158 -0
  24. package/dist/billing/billing-lock.js +17 -0
  25. package/dist/billing/billing-lock.js.map +1 -0
  26. package/dist/billing/billing-standing.d.ts +149 -0
  27. package/dist/billing/billing-standing.js +28 -0
  28. package/dist/billing/billing-standing.js.map +1 -0
  29. package/dist/billing/plan-card.d.ts +248 -0
  30. package/dist/billing/plan-card.js +248 -0
  31. package/dist/billing/plan-card.js.map +1 -0
  32. package/dist/billing/plan-limit-notice.d.ts +156 -0
  33. package/dist/billing/plan-limit-notice.js +76 -0
  34. package/dist/billing/plan-limit-notice.js.map +1 -0
  35. package/dist/billing/plan-limit.d.ts +34 -0
  36. package/dist/billing/plan-limit.js +20 -0
  37. package/dist/billing/plan-limit.js.map +1 -0
  38. package/dist/billing/plan-price.d.ts +61 -0
  39. package/dist/billing/plan-price.js +45 -0
  40. package/dist/billing/plan-price.js.map +1 -0
  41. package/dist/billing/subscription-actions.d.ts +133 -0
  42. package/dist/billing/subscription-actions.js +28 -0
  43. package/dist/billing/subscription-actions.js.map +1 -0
  44. package/dist/billing/subscription-status-chip.d.ts +149 -0
  45. package/dist/billing/subscription-status-chip.js +48 -0
  46. package/dist/billing/subscription-status-chip.js.map +1 -0
  47. package/dist/chart.d.ts +9 -3
  48. package/dist/components/account-chips.d.ts +16 -4
  49. package/dist/components/account-chips.js +21 -3
  50. package/dist/components/account-chips.js.map +1 -1
  51. package/dist/components/alert-banner.d.ts +6 -1
  52. package/dist/components/alert-banner.js +4 -3
  53. package/dist/components/alert-banner.js.map +1 -1
  54. package/dist/components/amount-input.d.ts +8 -3
  55. package/dist/components/amount-input.js +5 -5
  56. package/dist/components/amount-input.js.map +1 -1
  57. package/dist/components/appearance-labels.d.ts +32 -0
  58. package/dist/components/appearance-labels.js +18 -0
  59. package/dist/components/appearance-labels.js.map +1 -0
  60. package/dist/components/autocomplete.js +2 -2
  61. package/dist/components/autocomplete.js.map +1 -1
  62. package/dist/components/breadcrumbs.js +3 -2
  63. package/dist/components/breadcrumbs.js.map +1 -1
  64. package/dist/components/bulk-action-bar.d.ts +2 -2
  65. package/dist/components/bulk-action-bar.js +7 -12
  66. package/dist/components/bulk-action-bar.js.map +1 -1
  67. package/dist/components/button-group.d.ts +8 -3
  68. package/dist/components/calculator.d.ts +8 -3
  69. package/dist/components/calculator.js +4 -3
  70. package/dist/components/calculator.js.map +1 -1
  71. package/dist/components/calendar-heatmap.js +5 -5
  72. package/dist/components/calendar-heatmap.js.map +1 -1
  73. package/dist/components/chart-height.d.ts +23 -0
  74. package/dist/components/chart-height.js +15 -0
  75. package/dist/components/chart-height.js.map +1 -0
  76. package/dist/components/chart-zoom.js +6 -1
  77. package/dist/components/chart-zoom.js.map +1 -1
  78. package/dist/components/checkbox-group.js +2 -2
  79. package/dist/components/checkbox-group.js.map +1 -1
  80. package/dist/components/checkbox.d.ts +10 -0
  81. package/dist/components/checkbox.js +25 -10
  82. package/dist/components/checkbox.js.map +1 -1
  83. package/dist/components/chip.d.ts +19 -3
  84. package/dist/components/chip.js +47 -21
  85. package/dist/components/chip.js.map +1 -1
  86. package/dist/components/choice-card.d.ts +1 -1
  87. package/dist/components/choice-card.js +8 -7
  88. package/dist/components/choice-card.js.map +1 -1
  89. package/dist/components/column-mapper.js +1 -1
  90. package/dist/components/column-mapper.js.map +1 -1
  91. package/dist/components/combobox-core.js +8 -7
  92. package/dist/components/combobox-core.js.map +1 -1
  93. package/dist/components/combobox.js +8 -8
  94. package/dist/components/combobox.js.map +1 -1
  95. package/dist/components/confirm-dialog.d.ts +8 -3
  96. package/dist/components/copy-button.d.ts +10 -5
  97. package/dist/components/country-select.js +1 -1
  98. package/dist/components/country-select.js.map +1 -1
  99. package/dist/components/currency-select.js +3 -3
  100. package/dist/components/currency-select.js.map +1 -1
  101. package/dist/components/danger-confirm.d.ts +8 -3
  102. package/dist/components/data-table-cells.d.ts +1 -1
  103. package/dist/components/data-table-filter-popover.d.ts +1 -1
  104. package/dist/components/data-table-filter-popover.js +4 -1
  105. package/dist/components/data-table-filter-popover.js.map +1 -1
  106. package/dist/components/data-table-filters.d.ts +1 -1
  107. package/dist/components/data-table-labels.d.ts +1 -1
  108. package/dist/components/data-table-pagination.d.ts +1 -1
  109. package/dist/components/data-table.d.ts +1 -1
  110. package/dist/components/data-table.js +123 -52
  111. package/dist/components/data-table.js.map +1 -1
  112. package/dist/components/date-picker.d.ts +1 -1
  113. package/dist/components/date-picker.js +7 -5
  114. package/dist/components/date-picker.js.map +1 -1
  115. package/dist/components/description-list.js +2 -2
  116. package/dist/components/description-list.js.map +1 -1
  117. package/dist/components/dialog-frame.js +2 -1
  118. package/dist/components/dialog-frame.js.map +1 -1
  119. package/dist/components/disclosure.js +3 -2
  120. package/dist/components/disclosure.js.map +1 -1
  121. package/dist/components/dropdown.d.ts +1 -1
  122. package/dist/components/dropdown.js +7 -1
  123. package/dist/components/dropdown.js.map +1 -1
  124. package/dist/components/facing-pair.d.ts +19 -6
  125. package/dist/components/facing-pair.js +3 -2
  126. package/dist/components/facing-pair.js.map +1 -1
  127. package/dist/components/field-parts.d.ts +102 -6
  128. package/dist/components/field-parts.js +81 -6
  129. package/dist/components/field-parts.js.map +1 -1
  130. package/dist/components/field-sync.d.ts +4 -1
  131. package/dist/components/field-sync.js +12 -2
  132. package/dist/components/field-sync.js.map +1 -1
  133. package/dist/components/field.js +2 -2
  134. package/dist/components/field.js.map +1 -1
  135. package/dist/components/file-button.d.ts +8 -3
  136. package/dist/components/file-dropzone.d.ts +8 -3
  137. package/dist/components/floating-panel.js +7 -4
  138. package/dist/components/floating-panel.js.map +1 -1
  139. package/dist/components/focus-ring.d.ts +12 -0
  140. package/dist/components/focus-ring.js +8 -0
  141. package/dist/components/focus-ring.js.map +1 -0
  142. package/dist/components/form-actions.d.ts +8 -3
  143. package/dist/components/form-actions.js +33 -19
  144. package/dist/components/form-actions.js.map +1 -1
  145. package/dist/components/full-bleed-dialog.d.ts +11 -1
  146. package/dist/components/full-bleed-dialog.js +3 -1
  147. package/dist/components/full-bleed-dialog.js.map +1 -1
  148. package/dist/components/iban-input.d.ts +8 -3
  149. package/dist/components/image-grid.js +1 -1
  150. package/dist/components/image-grid.js.map +1 -1
  151. package/dist/components/inline-edit-field.js +6 -3
  152. package/dist/components/inline-edit-field.js.map +1 -1
  153. package/dist/components/language-select.d.ts +8 -3
  154. package/dist/components/legal-page.d.ts +26 -5
  155. package/dist/components/legal-page.js +3 -1
  156. package/dist/components/legal-page.js.map +1 -1
  157. package/dist/components/legal.d.ts +8 -3
  158. package/dist/components/legal.js +2 -1
  159. package/dist/components/legal.js.map +1 -1
  160. package/dist/components/lightbox.js +24 -2
  161. package/dist/components/lightbox.js.map +1 -1
  162. package/dist/components/line-items.js +2 -1
  163. package/dist/components/line-items.js.map +1 -1
  164. package/dist/components/list.d.ts +5 -0
  165. package/dist/components/list.js +13 -9
  166. package/dist/components/list.js.map +1 -1
  167. package/dist/components/measured-grid.d.ts +3 -1
  168. package/dist/components/measured-grid.js +38 -20
  169. package/dist/components/measured-grid.js.map +1 -1
  170. package/dist/components/menu-item.js +2 -1
  171. package/dist/components/menu-item.js.map +1 -1
  172. package/dist/components/mini-calendar.js +8 -4
  173. package/dist/components/mini-calendar.js.map +1 -1
  174. package/dist/components/money-field.d.ts +8 -3
  175. package/dist/components/month-picker.js +9 -5
  176. package/dist/components/month-picker.js.map +1 -1
  177. package/dist/components/nav-pills.js +1 -1
  178. package/dist/components/nav-pills.js.map +1 -1
  179. package/dist/components/number-field.d.ts +8 -3
  180. package/dist/components/number-input.d.ts +11 -4
  181. package/dist/components/number-input.js +8 -6
  182. package/dist/components/number-input.js.map +1 -1
  183. package/dist/components/numpad-sheet.d.ts +8 -3
  184. package/dist/components/numpad-sheet.js +2 -1
  185. package/dist/components/numpad-sheet.js.map +1 -1
  186. package/dist/components/one-time-code-input.js +2 -2
  187. package/dist/components/one-time-code-input.js.map +1 -1
  188. package/dist/components/page-contents.js +2 -2
  189. package/dist/components/page-contents.js.map +1 -1
  190. package/dist/components/phone-input.d.ts +8 -3
  191. package/dist/components/phone-input.js +2 -2
  192. package/dist/components/phone-input.js.map +1 -1
  193. package/dist/components/pie-chart.d.ts +8 -2
  194. package/dist/components/pie-chart.js +11 -7
  195. package/dist/components/pie-chart.js.map +1 -1
  196. package/dist/components/popover.d.ts +9 -1
  197. package/dist/components/popover.js +8 -4
  198. package/dist/components/popover.js.map +1 -1
  199. package/dist/components/row-actions.d.ts +100 -0
  200. package/dist/components/row-actions.js +165 -0
  201. package/dist/components/row-actions.js.map +1 -0
  202. package/dist/components/scroll-area.js +1 -1
  203. package/dist/components/scroll-area.js.map +1 -1
  204. package/dist/components/search-field.js +3 -2
  205. package/dist/components/search-field.js.map +1 -1
  206. package/dist/components/series-chart-budget.d.ts +30 -7
  207. package/dist/components/series-chart-budget.js +12 -4
  208. package/dist/components/series-chart-budget.js.map +1 -1
  209. package/dist/components/series-chart-ticks.d.ts +7 -1
  210. package/dist/components/series-chart-ticks.js +6 -0
  211. package/dist/components/series-chart-ticks.js.map +1 -1
  212. package/dist/components/series-chart.d.ts +58 -28
  213. package/dist/components/series-chart.js +42 -32
  214. package/dist/components/series-chart.js.map +1 -1
  215. package/dist/components/settings-fields.d.ts +51 -6
  216. package/dist/components/settings-fields.js +37 -0
  217. package/dist/components/settings-fields.js.map +1 -1
  218. package/dist/components/share-card.d.ts +11 -6
  219. package/dist/components/share-card.js +2 -0
  220. package/dist/components/share-card.js.map +1 -1
  221. package/dist/components/sign-chip.d.ts +4 -0
  222. package/dist/components/sign-chip.js +17 -4
  223. package/dist/components/sign-chip.js.map +1 -1
  224. package/dist/components/signature-pad.d.ts +3 -1
  225. package/dist/components/signature-pad.js +8 -5
  226. package/dist/components/signature-pad.js.map +1 -1
  227. package/dist/components/slider.js +7 -6
  228. package/dist/components/slider.js.map +1 -1
  229. package/dist/components/sparkline.d.ts +5 -1
  230. package/dist/components/sparkline.js +4 -2
  231. package/dist/components/sparkline.js.map +1 -1
  232. package/dist/components/stat-tile.d.ts +17 -1
  233. package/dist/components/stat-tile.js +48 -20
  234. package/dist/components/stat-tile.js.map +1 -1
  235. package/dist/components/status-dot.d.ts +4 -0
  236. package/dist/components/swipeable-row.js +2 -1
  237. package/dist/components/swipeable-row.js.map +1 -1
  238. package/dist/components/switch.d.ts +21 -7
  239. package/dist/components/switch.js +24 -11
  240. package/dist/components/switch.js.map +1 -1
  241. package/dist/components/table.js +2 -2
  242. package/dist/components/table.js.map +1 -1
  243. package/dist/components/text-link.d.ts +8 -3
  244. package/dist/components/text-link.js +1 -1
  245. package/dist/components/text-link.js.map +1 -1
  246. package/dist/components/text.d.ts +7 -2
  247. package/dist/components/text.js +5 -5
  248. package/dist/components/text.js.map +1 -1
  249. package/dist/components/tile-radio.js +2 -1
  250. package/dist/components/tile-radio.js.map +1 -1
  251. package/dist/components/time-input.d.ts +8 -3
  252. package/dist/components/toast.d.ts +18 -2
  253. package/dist/components/toast.js +8 -5
  254. package/dist/components/toast.js.map +1 -1
  255. package/dist/components/toggle-group.d.ts +16 -1
  256. package/dist/components/toggle-group.js +40 -11
  257. package/dist/components/toggle-group.js.map +1 -1
  258. package/dist/components/toggle-legend.d.ts +10 -1
  259. package/dist/components/toggle-legend.js +21 -7
  260. package/dist/components/toggle-legend.js.map +1 -1
  261. package/dist/components/translation-review-parts.d.ts +4 -0
  262. package/dist/components/translation-review.d.ts +4 -0
  263. package/dist/components/translation-review.js +3 -3
  264. package/dist/components/translation-review.js.map +1 -1
  265. package/dist/components/tree-view.js +3 -2
  266. package/dist/components/tree-view.js.map +1 -1
  267. package/dist/components/treemap.d.ts +5 -2
  268. package/dist/components/treemap.js +33 -16
  269. package/dist/components/treemap.js.map +1 -1
  270. package/dist/components/ui.d.ts +8 -3
  271. package/dist/components/ui.js +202 -114
  272. package/dist/components/ui.js.map +1 -1
  273. package/dist/components/use-table-state.d.ts +1 -1
  274. package/dist/components/user-avatar.d.ts +5 -1
  275. package/dist/components/user-avatar.js +1 -1
  276. package/dist/components/user-avatar.js.map +1 -1
  277. package/dist/{data-table-labels-DUELeXpa.d.ts → data-table-labels-kpAAVi6g.d.ts} +26 -2
  278. package/dist/data-table.d.ts +1 -1
  279. package/dist/{delete-account-setting-CpIhzxxZ.d.ts → delete-account-setting-BvdQdbv3.d.ts} +605 -58
  280. package/dist/demo/demo-banner.js +1 -0
  281. package/dist/demo/demo-banner.js.map +1 -1
  282. package/dist/feedback/feedback-attachment.d.ts +8 -3
  283. package/dist/feedback/feedback-context.d.ts +8 -3
  284. package/dist/feedback/feedback-crash.d.ts +8 -3
  285. package/dist/feedback/feedback-dialog.d.ts +8 -3
  286. package/dist/feedback/feedback-dialog.js +3 -3
  287. package/dist/feedback/feedback-dialog.js.map +1 -1
  288. package/dist/feedback/feedback-inbox.d.ts +8 -3
  289. package/dist/feedback/feedback-inbox.js +2 -2
  290. package/dist/feedback/feedback-inbox.js.map +1 -1
  291. package/dist/feedback/feedback-labels.d.ts +8 -3
  292. package/dist/feedback/feedback-menu.d.ts +9 -4
  293. package/dist/feedback/feedback-record.d.ts +8 -3
  294. package/dist/feedback/feedback-row-detail.d.ts +8 -3
  295. package/dist/feedback/feedback-status-undo.d.ts +8 -3
  296. package/dist/feedback/feedback-submit.d.ts +8 -3
  297. package/dist/feedback/feedback-swipe.d.ts +8 -3
  298. package/dist/feedback/feedback-table.d.ts +8 -3
  299. package/dist/feedback/feedback-thread.d.ts +8 -3
  300. package/dist/feedback/feedback-thread.js +3 -3
  301. package/dist/feedback/feedback-thread.js.map +1 -1
  302. package/dist/feedback.d.ts +8 -3
  303. package/dist/hooks/use-anchored-panel.d.ts +32 -3
  304. package/dist/hooks/use-anchored-panel.js +21 -3
  305. package/dist/hooks/use-anchored-panel.js.map +1 -1
  306. package/dist/hooks/use-breakpoint.d.ts +77 -0
  307. package/dist/hooks/use-breakpoint.js +50 -0
  308. package/dist/hooks/use-breakpoint.js.map +1 -0
  309. package/dist/hooks/use-file-drop.d.ts +8 -3
  310. package/dist/hooks/use-large-text.d.ts +29 -0
  311. package/dist/hooks/use-large-text.js +20 -0
  312. package/dist/hooks/use-large-text.js.map +1 -0
  313. package/dist/hooks/use-windowed-rows.d.ts +52 -8
  314. package/dist/hooks/use-windowed-rows.js +94 -5
  315. package/dist/hooks/use-windowed-rows.js.map +1 -1
  316. package/dist/i18n/defaults.d.ts +8 -3
  317. package/dist/i18n/defaults.js +8 -0
  318. package/dist/i18n/defaults.js.map +1 -1
  319. package/dist/i18n/german.d.ts +8 -3
  320. package/dist/i18n/german.js +89 -2
  321. package/dist/i18n/german.js.map +1 -1
  322. package/dist/i18n/kit-labels.d.ts +8 -3
  323. package/dist/i18n/kit-labels.js.map +1 -1
  324. package/dist/i18n/languages.d.ts +10 -5
  325. package/dist/i18n/locales/de-CH.d.ts +8 -3
  326. package/dist/i18n/locales/en.d.ts +8 -3
  327. package/dist/i18n/locales/es.d.ts +8 -3
  328. package/dist/i18n/locales/es.js +84 -2
  329. package/dist/i18n/locales/es.js.map +1 -1
  330. package/dist/i18n/locales/fr.d.ts +8 -3
  331. package/dist/i18n/locales/fr.js +86 -2
  332. package/dist/i18n/locales/fr.js.map +1 -1
  333. package/dist/i18n/locales/hu.d.ts +8 -3
  334. package/dist/i18n/locales/hu.js +86 -2
  335. package/dist/i18n/locales/hu.js.map +1 -1
  336. package/dist/i18n/locales/it.d.ts +8 -3
  337. package/dist/i18n/locales/it.js +87 -2
  338. package/dist/i18n/locales/it.js.map +1 -1
  339. package/dist/i18n/locales/zh.d.ts +8 -3
  340. package/dist/i18n/locales/zh.js +84 -2
  341. package/dist/i18n/locales/zh.js.map +1 -1
  342. package/dist/i18n/review.d.ts +8 -3
  343. package/dist/i18n/review.js +15 -1
  344. package/dist/i18n/review.js.map +1 -1
  345. package/dist/index.d.ts +27 -11
  346. package/dist/index.js +75 -4
  347. package/dist/index.js.map +1 -1
  348. package/dist/landing/landing-actions.d.ts +8 -3
  349. package/dist/landing/landing-sections.d.ts +8 -3
  350. package/dist/landing/public-header.d.ts +9 -4
  351. package/dist/landing/public-header.js +3 -3
  352. package/dist/landing/public-header.js.map +1 -1
  353. package/dist/landing/routing.d.ts +8 -3
  354. package/dist/lib/cn.js +3 -2
  355. package/dist/lib/cn.js.map +1 -1
  356. package/dist/rhf/fields.d.ts +8 -3
  357. package/dist/rhf/fields.js +1 -1
  358. package/dist/rhf/fields.js.map +1 -1
  359. package/dist/rhf/form.d.ts +8 -3
  360. package/dist/rhf/form.js +2 -2
  361. package/dist/rhf/form.js.map +1 -1
  362. package/dist/rhf.d.ts +8 -3
  363. package/dist/search/command-palette.d.ts +1 -1
  364. package/dist/search/command-palette.js +9 -8
  365. package/dist/search/command-palette.js.map +1 -1
  366. package/dist/settings/settings-layout.js +2 -1
  367. package/dist/settings/settings-layout.js.map +1 -1
  368. package/dist/settings/settings-section.d.ts +8 -3
  369. package/dist/settings/use-account-appearance.d.ts +92 -0
  370. package/dist/settings/use-account-appearance.js +63 -0
  371. package/dist/settings/use-account-appearance.js.map +1 -0
  372. package/dist/settings/use-settings-route.d.ts +1 -1
  373. package/dist/settings/use-settings-route.js +2 -3
  374. package/dist/settings/use-settings-route.js.map +1 -1
  375. package/dist/shell/app-shell.d.ts +12 -171
  376. package/dist/shell/app-shell.js +144 -28
  377. package/dist/shell/app-shell.js.map +1 -1
  378. package/dist/shell/auth-layout.js +1 -1
  379. package/dist/shell/auth-layout.js.map +1 -1
  380. package/dist/shell/option-switcher-menu.js +1 -1
  381. package/dist/shell/option-switcher-menu.js.map +1 -1
  382. package/dist/shell/top-bar-brand.d.ts +8 -3
  383. package/dist/shell/top-bar-brand.js +3 -1
  384. package/dist/shell/top-bar-brand.js.map +1 -1
  385. package/dist/shell/topbar-action-menu.d.ts +4 -0
  386. package/dist/shell/topbar-action-menu.js +3 -3
  387. package/dist/shell/topbar-action-menu.js.map +1 -1
  388. package/dist/shell/topbar-controls.js +4 -4
  389. package/dist/shell/topbar-controls.js.map +1 -1
  390. package/dist/shell.d.ts +9 -5
  391. package/dist/theme/contrast-tokens.d.ts +41 -0
  392. package/dist/theme/contrast-tokens.js +59 -0
  393. package/dist/theme/contrast-tokens.js.map +1 -0
  394. package/dist/theme/contrast.d.ts +109 -0
  395. package/dist/theme/contrast.js +128 -0
  396. package/dist/theme/contrast.js.map +1 -0
  397. package/dist/theme/palette-presets.d.ts +12 -1
  398. package/dist/theme/palette-presets.js +9 -4
  399. package/dist/theme/palette-presets.js.map +1 -1
  400. package/dist/theme/palette-store.js.map +1 -1
  401. package/dist/theme/text-size.d.ts +157 -0
  402. package/dist/theme/text-size.js +121 -0
  403. package/dist/theme/text-size.js.map +1 -0
  404. package/dist/wizard/stepper-nav.d.ts +8 -3
  405. package/dist/wizard.d.ts +8 -3
  406. package/package.json +1 -1
  407. package/src/admin/invitations-panel.tsx +36 -29
  408. package/src/admin/user-roster.tsx +17 -72
  409. package/src/auth/auth-errors.ts +68 -7
  410. package/src/billing/billing-banner.tsx +205 -0
  411. package/src/billing/billing-labels.ts +224 -0
  412. package/src/billing/billing-lock.ts +75 -0
  413. package/src/billing/billing-standing.ts +72 -0
  414. package/src/billing/plan-card.tsx +458 -0
  415. package/src/billing/plan-limit-notice.tsx +145 -0
  416. package/src/billing/plan-limit.ts +53 -0
  417. package/src/billing/plan-price.ts +101 -0
  418. package/src/billing/subscription-actions.tsx +76 -0
  419. package/src/billing/subscription-status-chip.tsx +95 -0
  420. package/src/components/account-chips.tsx +36 -10
  421. package/src/components/alert-banner.tsx +11 -6
  422. package/src/components/amount-input.tsx +5 -5
  423. package/src/components/appearance-labels.ts +40 -0
  424. package/src/components/autocomplete.tsx +2 -2
  425. package/src/components/breadcrumbs.tsx +3 -3
  426. package/src/components/bulk-action-bar.tsx +11 -14
  427. package/src/components/calculator.tsx +4 -3
  428. package/src/components/calendar-heatmap.tsx +5 -5
  429. package/src/components/chart-height.ts +30 -0
  430. package/src/components/chart-zoom.tsx +6 -1
  431. package/src/components/checkbox-group.tsx +2 -2
  432. package/src/components/checkbox.tsx +62 -20
  433. package/src/components/chip.tsx +105 -24
  434. package/src/components/choice-card.tsx +15 -10
  435. package/src/components/column-mapper.tsx +1 -1
  436. package/src/components/combobox-core.tsx +8 -7
  437. package/src/components/combobox.tsx +8 -8
  438. package/src/components/country-select.tsx +1 -1
  439. package/src/components/currency-select.tsx +3 -3
  440. package/src/components/data-table-filter-popover.tsx +7 -1
  441. package/src/components/data-table.tsx +160 -43
  442. package/src/components/date-picker.tsx +12 -9
  443. package/src/components/description-list.tsx +2 -2
  444. package/src/components/dialog-frame.tsx +2 -1
  445. package/src/components/disclosure.tsx +3 -2
  446. package/src/components/dropdown.tsx +10 -2
  447. package/src/components/facing-pair.ts +12 -5
  448. package/src/components/field-parts.tsx +190 -7
  449. package/src/components/field-sync.tsx +17 -3
  450. package/src/components/field.tsx +2 -2
  451. package/src/components/floating-panel.tsx +7 -4
  452. package/src/components/focus-ring.ts +12 -0
  453. package/src/components/form-actions.tsx +55 -18
  454. package/src/components/full-bleed-dialog.tsx +18 -4
  455. package/src/components/image-grid.tsx +1 -1
  456. package/src/components/inline-edit-field.tsx +6 -3
  457. package/src/components/legal-page.tsx +28 -2
  458. package/src/components/legal.tsx +19 -1
  459. package/src/components/lightbox.tsx +24 -2
  460. package/src/components/line-items.tsx +7 -1
  461. package/src/components/list.tsx +36 -10
  462. package/src/components/measured-grid.tsx +49 -24
  463. package/src/components/menu-item.tsx +2 -2
  464. package/src/components/mini-calendar.tsx +8 -4
  465. package/src/components/month-picker.tsx +9 -5
  466. package/src/components/nav-pills.tsx +1 -1
  467. package/src/components/number-input.tsx +14 -7
  468. package/src/components/numpad-sheet.tsx +2 -2
  469. package/src/components/one-time-code-input.tsx +2 -2
  470. package/src/components/page-contents.tsx +2 -2
  471. package/src/components/phone-input.tsx +2 -2
  472. package/src/components/pie-chart.tsx +19 -9
  473. package/src/components/popover.tsx +22 -5
  474. package/src/components/row-actions.tsx +344 -0
  475. package/src/components/scroll-area.tsx +1 -1
  476. package/src/components/search-field.tsx +4 -2
  477. package/src/components/series-chart-budget.ts +40 -8
  478. package/src/components/series-chart-ticks.ts +10 -0
  479. package/src/components/series-chart.tsx +123 -72
  480. package/src/components/settings-fields.tsx +81 -2
  481. package/src/components/share-card.tsx +10 -0
  482. package/src/components/sign-chip.tsx +28 -4
  483. package/src/components/signature-pad.tsx +13 -7
  484. package/src/components/slider.tsx +22 -9
  485. package/src/components/sparkline.tsx +11 -3
  486. package/src/components/stat-tile.tsx +70 -14
  487. package/src/components/swipeable-row.tsx +2 -1
  488. package/src/components/switch.tsx +57 -23
  489. package/src/components/table.tsx +2 -2
  490. package/src/components/text-link.tsx +1 -1
  491. package/src/components/text.tsx +11 -6
  492. package/src/components/tile-radio.tsx +4 -1
  493. package/src/components/toast.tsx +27 -7
  494. package/src/components/toggle-group.tsx +99 -12
  495. package/src/components/toggle-legend.tsx +53 -8
  496. package/src/components/translation-review.tsx +10 -5
  497. package/src/components/tree-view.tsx +3 -2
  498. package/src/components/treemap.tsx +27 -10
  499. package/src/components/ui.tsx +331 -145
  500. package/src/components/user-avatar.tsx +1 -1
  501. package/src/demo/demo-banner.tsx +5 -0
  502. package/src/feedback/feedback-dialog.tsx +3 -3
  503. package/src/feedback/feedback-inbox.tsx +2 -2
  504. package/src/feedback/feedback-thread.tsx +3 -3
  505. package/src/hooks/use-anchored-panel.ts +67 -5
  506. package/src/hooks/use-breakpoint.ts +121 -0
  507. package/src/hooks/use-large-text.ts +41 -0
  508. package/src/hooks/use-windowed-rows.ts +168 -12
  509. package/src/i18n/defaults.ts +8 -0
  510. package/src/i18n/german.ts +103 -0
  511. package/src/i18n/kit-labels.tsx +12 -0
  512. package/src/i18n/locales/es.ts +94 -0
  513. package/src/i18n/locales/fr.ts +98 -0
  514. package/src/i18n/locales/hu.ts +96 -0
  515. package/src/i18n/locales/it.ts +99 -0
  516. package/src/i18n/locales/zh.ts +90 -0
  517. package/src/i18n/review.ts +14 -0
  518. package/src/index.ts +74 -6
  519. package/src/landing/public-header.tsx +4 -4
  520. package/src/lib/cn.ts +13 -2
  521. package/src/rhf/fields.tsx +1 -1
  522. package/src/rhf/form.tsx +2 -2
  523. package/src/search/command-palette.tsx +10 -9
  524. package/src/settings/settings-layout.tsx +2 -1
  525. package/src/settings/use-account-appearance.ts +148 -0
  526. package/src/settings/use-settings-route.ts +3 -4
  527. package/src/shell/app-shell.tsx +278 -54
  528. package/src/shell/auth-layout.tsx +1 -1
  529. package/src/shell/option-switcher-menu.tsx +1 -1
  530. package/src/shell/top-bar-brand.tsx +3 -1
  531. package/src/shell/topbar-action-menu.tsx +3 -3
  532. package/src/shell/topbar-controls.tsx +4 -4
  533. package/src/theme/contrast-tokens.ts +112 -0
  534. package/src/theme/contrast.ts +224 -0
  535. package/src/theme/palette-presets.ts +24 -4
  536. package/src/theme/palette-store.ts +6 -1
  537. package/src/theme/text-size.ts +267 -0
  538. package/tokens.css +143 -1
@@ -61,7 +61,7 @@ import {
61
61
  } from "./chart-zoom";
62
62
  import { STEP_DASH, strokeDash, type LegendEntry } from "./toggle-legend";
63
63
  import { DEFAULT_SERIES_CHART_LABELS, type SeriesChartLabels } from "./series-chart-labels";
64
- import { categoryTicks, integerTicks, niceTicks, timeTicksWithUnit, type TimeTickUnit } from "./series-chart-ticks";
64
+ import { categoryTicks, integerTicks, niceTicks, tickTarget, timeTicksWithUnit, type TimeTickUnit } from "./series-chart-ticks";
65
65
  // The tick module stays internal; the one type of it a public prop names is re-exported.
66
66
  export type { TimeTickUnit } from "./series-chart-ticks";
67
67
  import { autoAxisBudget, axisUnit, budgetedAxes, type SeriesChartAxisBudget } from "./series-chart-budget";
@@ -74,7 +74,9 @@ import {
74
74
  useKitLocale,
75
75
  type ChartTooltipPlacement,
76
76
  } from "../i18n/kit-labels";
77
- import { useMediaQuery } from "../hooks/use-media-query";
77
+ import { useBreakpoint } from "../hooks/use-breakpoint";
78
+ import { useTextSize } from "../theme/text-size";
79
+ import { chartHeightProps, type ChartHeight } from "./chart-height";
78
80
  import { cn } from "../lib/cn";
79
81
 
80
82
  export interface SeriesChartSeries {
@@ -343,7 +345,7 @@ export interface SeriesChartX {
343
345
  * instead of being centred across it; the anchor is physical, like the plot (see
344
346
  * `ChartContainer`), so it is the same in RTL. The band under the axis grows to the
345
347
  * rotated height of the longest label on show, estimated from its length (at most
346
- * 120 px, past which a label is clipped). Default 0.
348
+ * 120 px × the text size's scale, past which a label is clipped). Default 0.
347
349
  */
348
350
  tickAngle?: number;
349
351
  /**
@@ -365,10 +367,6 @@ export interface SeriesChartX {
365
367
  /** Where the tooltip goes — see {@link SeriesChartTooltip.placement}. */
366
368
  export type SeriesChartTooltipPlacement = ChartTooltipPlacement;
367
369
 
368
- /** Below Tailwind's `sm` — where `"auto"` takes the tooltip off the plot. Narrower than
369
- * the kit's `PHONE_QUERY` (767 px) on purpose: a tablet's plot is wide enough that the
370
- * box beside the finger leaves the data in view; a phone's is not. */
371
- const TOOLTIP_READOUT_QUERY = "(max-width: 639px)";
372
370
 
373
371
  /**
374
372
  * The placement a chart actually uses: its own, else the provider's, else `"cursor"`;
@@ -537,13 +535,22 @@ export interface SeriesChartProps {
537
535
  /** A value in the tooltip, where a number stands on its own and needs its unit.
538
536
  * Default: `Intl.NumberFormat` in the kit's locale. */
539
537
  valueFormat?: (value: number) => string;
540
- /** Tailwind height class, or a height in pixels. Default `h-72`. The empty state
541
- * takes it too, so a chart losing its last line does not relayout the page under it.
542
- * A number is for a height the caller holds as a number — keksdose's report charts
543
- * take `height = 260` as a prop and wrap the chart in a `SizedSeriesChart` div
544
- * (reports/charts/networth-line.tsx) only to turn it into a style, since a class
545
- * cannot be built from a number Tailwind never saw. */
546
- height?: string | number;
538
+ /**
539
+ * The chart's height: a CSS length, a Tailwind height class, or px. Default `h-72`
540
+ * (18rem). The empty state takes it too, so a chart losing its last line does not
541
+ * relayout the page under it.
542
+ *
543
+ * - **A CSS length** (0.32) — `"20rem"`, `"min(20rem, 60dvh)"` — set inline. The form
544
+ * for a height that should grow with the text size and still stop at the screen
545
+ * (docs/text-size-harmonization.md §10.10): `min(30rem, 60dvh)` is 480 px at Normal
546
+ * on a desktop and never more than 60 % of a phone at Extra large, where a scaled
547
+ * 480 px would be 720.
548
+ * - **A Tailwind class** — `"h-72"`, `"h-64 md:h-80"` — as before.
549
+ * - **A number** is px, set inline, and does NOT follow the text size: kept for a
550
+ * height the caller holds as a number (keksdose's report charts take
551
+ * `height = 260` as a prop). Prefer `"16.25rem"`, or a `min()` with a viewport cap.
552
+ */
553
+ height?: ChartHeight;
547
554
  /** Bridge holes left by sources sampled on different grids. See {@link mergeSeries}. */
548
555
  connectNulls?: boolean;
549
556
  /** Shown, centred at the chart's height, instead of an empty chart. Default: the
@@ -587,17 +594,23 @@ export interface SeriesChartProps {
587
594
  maxVisibleAxes?: SeriesChartAxisBudget;
588
595
  /**
589
596
  * `"auto"` (the default): a chart so narrow that its axes' bands would leave the plot
590
- * under 160 px (`MIN_PLOT_WIDTH`) draws ONE axis a side — lenkbank's four-axis curve
591
- * plot on a phone, whose plot was 10 px wide. Measured on the chart's own box
592
- * (`ResizeObserver`), and applied on top of `maxVisibleAxes`.
597
+ * under 160 px (`MIN_PLOT_WIDTH`, × the text size's scale) draws ONE axis a side —
598
+ * lenkbank's four-axis curve plot on a phone, whose plot was 10 px wide. And a chart
599
+ * with an axis on EACH side that one a side still leaves too narrow (0.32: at 150 % a
600
+ * 390 px phone's plot kept about 80 px between its two bands) drops the right-hand,
601
+ * secondary axis too. Measured on the chart's own box (`ResizeObserver`), and applied
602
+ * on top of `maxVisibleAxes`. Either way the series on an axis it hid say the axis'
603
+ * unit in the tooltip and the readout ("Rack load (N)"), and in a legend built by
604
+ * {@link seriesLegendEntries} with `onAxisBudget`'s ids.
593
605
  *
594
- * On by default because it cannot touch a layout that works: it needs a side with two
595
- * or more axes AND a plot that would otherwise be under 160 px — a four-axis chart
596
- * below about 440 px, a two-left-axis one below about 300. A chart with at most one
597
- * axis a side (every facing pair, every single-axis chart) is never budgeted, at any
598
- * width. `"off"` keeps every declared axis whatever the width: for a stack of
599
- * multi-axis charts that must keep identical bands, or a caller budgeting itself.
600
- * Without layout (jsdom, SSR) nothing is measured and nothing is hidden.
606
+ * On by default because it cannot touch a layout that works: it needs a plot that
607
+ * would otherwise be under 160 px — a four-axis chart below about 440 px at Normal, a
608
+ * two-left-axis one below about 300, a one-a-side one below about 290 — and the
609
+ * left-hand axis always stays. A chart with one axis (each chart of a facing pair,
610
+ * every single-axis chart) is never budgeted, at any width. `"off"` keeps every
611
+ * declared axis whatever the width: for a stack of multi-axis charts that must keep
612
+ * identical bands, or a caller budgeting itself. Without layout (jsdom, SSR) nothing is
613
+ * measured and nothing is hidden.
601
614
  */
602
615
  axisBudget?: "auto" | "off";
603
616
  /**
@@ -621,38 +634,48 @@ export interface SeriesChartProps {
621
634
  minBarLength?: number;
622
635
  }
623
636
 
624
- /** How much of an axis band the rotated title takes, in px. Reserved rather than
625
- * shared with the ticks: a title merely offset inside the band prints on top of a
626
- * five-figure tick, and which gives way depends on the data. */
637
+ /** How much of an axis band the rotated title takes, in px at Normal — × the text size's
638
+ * scale on the chart (§3.2), since the title is text. Reserved rather than shared with
639
+ * the ticks: a title merely offset inside the band prints on top of a five-figure tick,
640
+ * and which gives way depends on the data. */
627
641
  export const AXIS_TITLE_STRIP = 16;
628
642
 
629
643
  /** Where inside its strip the rotated title sits. */
630
644
  const AXIS_TITLE_OFFSET = 10;
631
645
 
632
- /** The tallest band tilted x ticks reserve, in px. A category name longer than this at
633
- * its angle is clipped rather than squeezing the plot down to a strip. */
646
+ /** The tallest band tilted x ticks reserve, in px at Normal (× the scale). A category
647
+ * name longer than this at its angle is clipped rather than squeezing the plot down to
648
+ * a strip. */
634
649
  const MAX_TILTED_TICK_BAND = 120;
635
650
 
636
- /** What one character of a tick label is taken to be, in px, for the tilted band — the
637
- * shell's `text-xs`. An estimate: the SVG is not laid out yet when the band is decided. */
651
+ /** What one character of a tick label is taken to be, in px at Normal, for the tilted
652
+ * band — the shell's `text-xs`. An estimate: the SVG is not laid out yet when the band
653
+ * is decided. Both grow with the text size, as `text-xs` does (§3.2). */
638
654
  const TICK_CHAR_WIDTH = 7;
639
655
  const TICK_LINE_HEIGHT = 12;
640
- /** recharts' gap between the axis line and a bottom tick's text. */
656
+ /** recharts' gap between the axis line and a bottom tick's text — px, at every size:
657
+ * recharts draws it, not the type. */
641
658
  const TICK_GAP = 8;
659
+ /** recharts' own band under level x ticks. */
660
+ const LEVEL_TICK_BAND = 30;
661
+ /** The least room recharts' x ticks keep between labels, in px at Normal. */
662
+ const MIN_TICK_GAP = 32;
642
663
 
643
664
  /**
644
- * The height the x axis reserves for ticks tilted by `angle` degrees: the rotated box of
645
- * the longest label, from its length. `undefined` for level ticks — recharts' own 30 px.
665
+ * The height the x axis reserves for its ticks at a text `scale`: tilted by `angle`
666
+ * degrees, the rotated box of the longest label, from its length; level, recharts' own
667
+ * 30 px grown with the labels. `undefined` for level ticks at Normal, where recharts'
668
+ * default is exactly that.
646
669
  */
647
- function tiltedTickBand(labels: readonly string[], angle: number): number | undefined {
648
- if (!angle) return undefined;
670
+ function tiltedTickBand(labels: readonly string[], angle: number, scale = 1): number | undefined {
671
+ if (!angle) return scale === 1 ? undefined : Math.ceil(LEVEL_TICK_BAND * scale);
649
672
  const rad = (Math.abs(angle) * Math.PI) / 180;
650
- const longest = Math.max(0, ...labels.map((label) => label.length)) * TICK_CHAR_WIDTH;
651
- const band = Math.sin(rad) * longest + Math.cos(rad) * TICK_LINE_HEIGHT + TICK_GAP;
652
- return Math.min(MAX_TILTED_TICK_BAND, Math.max(30, Math.ceil(band)));
673
+ const longest = Math.max(0, ...labels.map((label) => label.length)) * TICK_CHAR_WIDTH * scale;
674
+ const band = Math.sin(rad) * longest + Math.cos(rad) * TICK_LINE_HEIGHT * scale + TICK_GAP;
675
+ return Math.min(Math.round(MAX_TILTED_TICK_BAND * scale), Math.max(Math.ceil(LEVEL_TICK_BAND * scale), Math.ceil(band)));
653
676
  }
654
677
 
655
- /** The width the ticks of a y axis get when a caller does not say. */
678
+ /** The width the ticks of a y axis get when a caller does not say, in px at Normal. */
656
679
  export const AXIS_TICK_WIDTH = 48;
657
680
 
658
681
  /**
@@ -686,10 +709,19 @@ export function padBand(low: number, high: number): [number, number] | undefined
686
709
  return [low - pad, high + pad];
687
710
  }
688
711
 
689
- /** The whole band a y axis occupies: its ticks, and its title when it draws one. For
690
- * lining a heading up over a PLOT rather than over its column. */
691
- export function axisBandWidth(tickWidth: number | undefined, titled: boolean): number {
692
- return (tickWidth ?? AXIS_TICK_WIDTH) + (titled ? AXIS_TITLE_STRIP : 0);
712
+ /**
713
+ * The whole band a y axis occupies: its ticks, and its title when it draws one. For
714
+ * lining a heading up over a PLOT rather than over its column.
715
+ *
716
+ * `scale` is the text size's (`useTextSize().scale`, §3.2, §10.10): the chart draws every
717
+ * band — the default 48 px and a caller's own `width` alike (keksdose's
718
+ * `MONEY_AXIS_WIDTH`) — this many times wider, because the ticks in it are `text-xs`
719
+ * and grow with the text. A heading lined up over the plot has to pass the same scale.
720
+ * One factor for both sides of a facing pair, so the mirrored bands stay equal.
721
+ */
722
+ export function axisBandWidth(tickWidth: number | undefined, titled: boolean, scale = 1): number {
723
+ const band = (tickWidth ?? AXIS_TICK_WIDTH) + (titled ? AXIS_TITLE_STRIP : 0);
724
+ return scale === 1 ? band : Math.round(band * scale);
693
725
  }
694
726
 
695
727
  /**
@@ -1016,10 +1048,13 @@ function focusedBarShape(index: number) {
1016
1048
  };
1017
1049
  }
1018
1050
 
1019
- /** A marker label's size and weight — the one place both the text and its width
1020
- * estimate read them from. */
1051
+ /** A marker label's size in px at Normal — the one place both the text and its width
1052
+ * estimate read it from. × the text size's scale where it is drawn (§10.10). */
1021
1053
  const MARKER_LABEL_SIZE = 11;
1022
1054
 
1055
+ /** A reference line's label, in px at Normal, × the scale likewise. */
1056
+ const REFERENCE_LABEL_SIZE = 10;
1057
+
1023
1058
  /**
1024
1059
  * A marker's label, centred over its point but clamped inside the plot. recharts'
1025
1060
  * `position: "top"` centres on the point no matter where it is, so a marker near the
@@ -1037,16 +1072,17 @@ function MarkerLabel({
1037
1072
  const plot = usePlotArea();
1038
1073
  const ref = useRef<SVGTextElement>(null);
1039
1074
  const [measured, setMeasured] = useState<number>();
1075
+ const fontSize = MARKER_LABEL_SIZE * useTextSize().scale;
1040
1076
  const text = value == null ? "" : String(value);
1041
1077
  useLayoutEffect(() => {
1042
1078
  const el = ref.current;
1043
1079
  if (!el || typeof el.getComputedTextLength !== "function") return;
1044
1080
  const w = el.getComputedTextLength();
1045
1081
  if (w > 0 && w !== measured) setMeasured(w);
1046
- }, [text, measured]);
1082
+ }, [text, measured, fontSize]);
1047
1083
  if (!viewBox || viewBox.x == null || viewBox.y == null || text === "") return null;
1048
1084
  const cx = viewBox.x + (viewBox.width ?? 0) / 2;
1049
- const half = (measured ?? text.length * MARKER_LABEL_SIZE * 0.6) / 2;
1085
+ const half = (measured ?? text.length * fontSize * 0.6) / 2;
1050
1086
  // The start clamp applied last: a label wider than the plot keeps its start on screen.
1051
1087
  const x = plot ? Math.max(plot.x + half, Math.min(cx, plot.x + plot.width - half)) : cx;
1052
1088
  return (
@@ -1055,7 +1091,7 @@ function MarkerLabel({
1055
1091
  x={x}
1056
1092
  y={viewBox.y - 5}
1057
1093
  textAnchor="middle"
1058
- fontSize={MARKER_LABEL_SIZE}
1094
+ fontSize={fontSize}
1059
1095
  fontWeight={600}
1060
1096
  fill="var(--text-primary)"
1061
1097
  className="recharts-label"
@@ -1216,12 +1252,22 @@ function SeriesPlot({
1216
1252
  const labels = useKitLabels("seriesChart", DEFAULT_SERIES_CHART_LABELS, labelsProp);
1217
1253
  const locale = useKitLocale(localeProp);
1218
1254
  const number = useDefaultFormat(localeProp);
1255
+ // The text size (docs/text-size-harmonization.md §3.2, §4, §10.10): the axis bands, the
1256
+ // tick spacing and the labels drawn in px grow with it — the tick text is `text-xs` and
1257
+ // grows by itself — and the axes aim at three ticks instead of five from Large up.
1258
+ // Strokes, dashes and the grid stay px.
1259
+ const { scale } = useTextSize();
1260
+ const ticksAim = tickTarget(scale);
1261
+ const grow = (px: number) => (scale === 1 ? px : Math.round(px * scale));
1219
1262
  // The keyboard stops' roving tab stop, and the one that has focus (see `PointKeys`).
1220
1263
  // Up here, above the empty state's early return, like every hook.
1221
1264
  const [keyStop, setKeyStop] = useState(0);
1222
1265
  const [keyFocus, setKeyFocus] = useState<number | undefined>(undefined);
1223
1266
  // Where the tooltip goes, and — off the plot — the row it is portalled into.
1224
- const phone = useMediaQuery(TOOLTIP_READOUT_QUERY, false);
1267
+ // Below `sm` (`max-sm:`, at the text size in force) — where `"auto"` takes the tooltip
1268
+ // off the plot. Narrower than the phone layout on purpose: a tablet's plot is wide
1269
+ // enough that the box beside the finger leaves the data in view; a phone's is not.
1270
+ const phone = useBreakpoint("max-sm", false);
1225
1271
  const placement = resolveTooltipPlacement(tooltip?.placement, useKitChartTooltipPlacement(), phone);
1226
1272
  const [readout, setReadout] = useState<HTMLDivElement | null>(null);
1227
1273
 
@@ -1248,8 +1294,11 @@ function SeriesPlot({
1248
1294
  ? []
1249
1295
  : budgetedAxes(
1250
1296
  afterCap,
1251
- autoAxisBudget(afterCap, width, (axis) =>
1252
- axisBandWidth(axis.width, Boolean(axis.title)),
1297
+ autoAxisBudget(
1298
+ afterCap,
1299
+ width,
1300
+ (axis) => axisBandWidth(axis.width, Boolean(axis.title), scale),
1301
+ scale,
1253
1302
  ),
1254
1303
  );
1255
1304
  const budgeted = [...capped, ...auto];
@@ -1263,10 +1312,9 @@ function SeriesPlot({
1263
1312
  onAxisBudget?.(budgetKey ? budgetKey.split("\n") : []);
1264
1313
  }, [budgetKey, onAxisBudget]);
1265
1314
 
1266
- // A number is pixels, set inline; a string is a class. Either way the one value
1267
- // sizes both the chart and its empty state.
1268
- const heightClass = typeof height === "string" ? height : undefined;
1269
- const heightStyle = typeof height === "number" ? { height } : undefined;
1315
+ // A number or a CSS length is set inline; any other string is a class. Either way the
1316
+ // one value sizes both the chart and its empty state.
1317
+ const { className: heightClass, style: heightStyle } = chartHeightProps(height);
1270
1318
 
1271
1319
  // The empty state takes the chart's own height and is centred in it: a chart that
1272
1320
  // shrank to its "nothing to draw" sentence moved everything under it up the page
@@ -1321,11 +1369,12 @@ function SeriesPlot({
1321
1369
  // overhang of the first/last x tick where no y axis covers it.
1322
1370
  const margin = {
1323
1371
  // Room for a marker's label over a point at the top of the band.
1324
- top: markers?.some((marker) => marker.label) ? 22 : 8,
1325
- right: onRight ? 0 : 10,
1326
- left: onLeft ? 0 : 10,
1372
+ top: markers?.some((marker) => marker.label) ? grow(22) : 8,
1373
+ // The first and last x tick's overhang: text, so it grows with it.
1374
+ right: onRight ? 0 : grow(10),
1375
+ left: onLeft ? 0 : grow(10),
1327
1376
  // Under the ticks, not under the whole axis: whatever comes next owns the gap.
1328
- bottom: x.title ? 18 : 2,
1377
+ bottom: x.title ? grow(18) : 2,
1329
1378
  };
1330
1379
 
1331
1380
  const refs = references ?? [];
@@ -1353,7 +1402,7 @@ function SeriesPlot({
1353
1402
  ) ?? [Infinity, -Infinity]),
1354
1403
  ));
1355
1404
 
1356
- const timeUnit = model.kind === "time" ? timeTicksWithUnit(fittedX) : undefined;
1405
+ const timeUnit = model.kind === "time" ? timeTicksWithUnit(fittedX, ticksAim) : undefined;
1357
1406
  // Whole-number ticks on a number line whose rows are all whole numbers — see
1358
1407
  // `SeriesChartX.integerTicks`.
1359
1408
  const integerX =
@@ -1370,8 +1419,8 @@ function SeriesPlot({
1370
1419
  : model.kind === "time"
1371
1420
  ? timeUnit?.ticks
1372
1421
  : integerX
1373
- ? (integerTicks(fittedX) ?? niceTicks(fittedX))
1374
- : niceTicks(fittedX));
1422
+ ? (integerTicks(fittedX, ticksAim) ?? niceTicks(fittedX, ticksAim))
1423
+ : niceTicks(fittedX, ticksAim));
1375
1424
 
1376
1425
  // Ticks and the tooltip heading, back in the caller's terms.
1377
1426
  const timeFormat = new Intl.DateTimeFormat(locale, TIME_TICK_FORMAT[timeUnit?.unit ?? "day"]);
@@ -1404,7 +1453,7 @@ function SeriesPlot({
1404
1453
  const xLabel = (position: number) => label(position, tickAt(position));
1405
1454
 
1406
1455
  const tickAngle = x.ticks === false ? 0 : (x.tickAngle ?? 0);
1407
- const tickBand = tiltedTickBand((xTicks ?? []).map((tick) => xFormat(tick)), tickAngle);
1456
+ const tickBand = tiltedTickBand((xTicks ?? []).map((tick) => xFormat(tick)), tickAngle, scale);
1408
1457
 
1409
1458
  const source: ZoomFitSource = {
1410
1459
  rows: plotted,
@@ -1597,7 +1646,7 @@ function SeriesPlot({
1597
1646
  allowDataOverflow={zoom?.xDomain !== undefined || model.kind === "category"}
1598
1647
  tickLine={false}
1599
1648
  axisLine={false}
1600
- minTickGap={32}
1649
+ minTickGap={grow(MIN_TICK_GAP)}
1601
1650
  // Where the ticks crowd, drop every Nth rather than recharts' default
1602
1651
  // `preserveEnd`, which drops whichever single tick collides: a phone's whole-week
1603
1652
  // axis came out 2 4 6 8 _ 12, a doubled gap that reads as a missing week. Every
@@ -1616,8 +1665,8 @@ function SeriesPlot({
1616
1665
  <Label
1617
1666
  value={x.title}
1618
1667
  position="insideBottom"
1619
- offset={-12}
1620
- className="fill-[var(--text-muted)] text-[11px]"
1668
+ offset={-grow(12)}
1669
+ className="fill-[var(--text-muted)] text-caption"
1621
1670
  />
1622
1671
  )}
1623
1672
  </XAxis>
@@ -1634,7 +1683,9 @@ function SeriesPlot({
1634
1683
  domain={domain}
1635
1684
  ticks={
1636
1685
  resolveTicks(axis.tickValues, domain, finite) ??
1637
- (wholeOnly(axis) ? (integerTicks(domain) ?? niceTicks(domain)) : niceTicks(domain))
1686
+ (wholeOnly(axis)
1687
+ ? (integerTicks(domain, ticksAim) ?? niceTicks(domain, ticksAim))
1688
+ : niceTicks(domain, ticksAim))
1638
1689
  }
1639
1690
  allowDataOverflow={zoomed}
1640
1691
  orientation={axis.orientation ?? "left"}
@@ -1642,7 +1693,7 @@ function SeriesPlot({
1642
1693
  // what the budget does on every resize across its threshold — kept its old
1643
1694
  // width in recharts' stacking of that side, and pushed the axes still drawn
1644
1695
  // off the chart's edge. A zero width leaves nothing stale to count.
1645
- width={axis.hide ? 0 : axisBandWidth(axis.width, Boolean(axis.title))}
1696
+ width={axis.hide ? 0 : axisBandWidth(axis.width, Boolean(axis.title), scale)}
1646
1697
  tickLine={false}
1647
1698
  axisLine={false}
1648
1699
  tickFormatter={axis.format ?? number}
@@ -1659,8 +1710,8 @@ function SeriesPlot({
1659
1710
  // Inline, so a sole series' colour beats the class's neutral fill —
1660
1711
  // and absent for a shared axis, so the class draws it.
1661
1712
  style={{ textAnchor: "middle", fill: soleSeriesColor(axis, series) }}
1662
- offset={AXIS_TITLE_OFFSET}
1663
- className="fill-[var(--text-muted)] text-[11px]"
1713
+ offset={grow(AXIS_TITLE_OFFSET)}
1714
+ className="fill-[var(--text-muted)] text-caption"
1664
1715
  />
1665
1716
  )}
1666
1717
  </YAxis>
@@ -1817,7 +1868,7 @@ function SeriesPlot({
1817
1868
  ? {
1818
1869
  value: ref.label,
1819
1870
  position: "insideTopLeft",
1820
- fontSize: 10,
1871
+ fontSize: REFERENCE_LABEL_SIZE * scale,
1821
1872
  fill: color,
1822
1873
  }
1823
1874
  : undefined
@@ -4,11 +4,19 @@ import type { SelectProps } from "./ui";
4
4
  import { ToggleGroup } from "./toggle-group";
5
5
  import type { ToggleGroupBaseProps } from "./toggle-group";
6
6
  import type { ThemePreference } from "../theme/theme-store";
7
+ import { TEXT_SIZES } from "../theme/text-size";
8
+ import type { TextSize } from "../theme/text-size";
9
+ import { CONTRAST_MODES } from "../theme/contrast";
10
+ import type { ContrastMode } from "../theme/contrast";
11
+ import { useAppearanceLabels } from "./appearance-labels";
12
+ import type { AppearanceLabels } from "./appearance-labels";
7
13
 
8
14
  /**
9
15
  * App-agnostic settings-field components (feedback #333): the language + theme
10
- * controls that every app's settings page needs, so they live in @hb/ui and the
11
- * app just supplies the current value, a change handler and translated labels.
16
+ * controls that every app's settings page needs — and, since 0.32, the text size and
17
+ * the contrast (docs/text-size-harmonization.md §6), whose words are the kit's own
18
+ * `appearance` namespace — so they live in @hb/ui and the app just supplies the
19
+ * current value, a change handler and translated labels.
12
20
  * The app owns WHERE these render (its own settings page) and any app-specific
13
21
  * fields around them.
14
22
  */
@@ -115,3 +123,74 @@ export function LanguageSetting({ value, onChange, label, options, id, ...rest }
115
123
  </Select>
116
124
  );
117
125
  }
126
+
127
+ /**
128
+ * What {@link TextSizeSetting} and {@link ContrastSetting} take: a {@link ToggleGroup}'s
129
+ * props — `labelPlacement`, `disabledReason`, `commit`, `size`, `overflow` — minus the
130
+ * options and the value, which they own, as {@link ThemeSettingToggleProps} does.
131
+ */
132
+ type AppearanceToggleProps<T extends string> = Omit<ToggleGroupBaseProps<T>, "options" | "label" | "ariaLabel"> & {
133
+ value: T;
134
+ onChange: (value: T) => void;
135
+ /**
136
+ * The field's visible label. Leave it out inside a row already titled with the
137
+ * setting's name: the group is then named by `aria-label` / `aria-labelledby` if
138
+ * given, else by the kit's own word ("Text size", "Contrast").
139
+ */
140
+ label?: ReactNode;
141
+ /** The `appearance` namespace, for this instance. */
142
+ labels?: Partial<AppearanceLabels>;
143
+ };
144
+
145
+ export type TextSizeSettingProps = AppearanceToggleProps<TextSize>;
146
+
147
+ /**
148
+ * The text size (0.32, docs/text-size-harmonization.md §6): Normal, Large, Extra large as
149
+ * one segmented control, in the core `appearance` group after the theme. Bind it to the
150
+ * size IN FORCE — `useAccountAppearance().textSize` — and hand a pick to its
151
+ * `pickTextSize`, which stores the device's choice and, signed in, the account's.
152
+ *
153
+ * The options wrap rather than truncate (`overflow="wrap"`): at Extra large on a 360 px
154
+ * phone the group has 240 px, and "Extra large" cut to "Extra l…" would be the one
155
+ * setting that cannot read its own value.
156
+ */
157
+ export function TextSizeSetting({ value, onChange, label, labels: labelsProp, overflow = "wrap", ...rest }: TextSizeSettingProps) {
158
+ const labels = useAppearanceLabels(labelsProp);
159
+ const named = label !== undefined && label !== null && label !== false;
160
+ return (
161
+ <ToggleGroup<TextSize>
162
+ {...rest}
163
+ aria-label={named || rest["aria-labelledby"] ? rest["aria-label"] : (rest["aria-label"] ?? labels.textSize)}
164
+ label={label}
165
+ overflow={overflow}
166
+ value={value}
167
+ onChange={onChange}
168
+ options={TEXT_SIZES.map((size) => ({ value: size, label: labels.textSizes[size] }))}
169
+ />
170
+ );
171
+ }
172
+
173
+ export type ContrastSettingProps = AppearanceToggleProps<ContrastMode>;
174
+
175
+ /**
176
+ * More contrast (0.32, §5, §6): System, Standard, More as one segmented control, beside
177
+ * the text size. Bind it to the stored MODE, "system" included — never to whether more
178
+ * contrast is on at the moment, or a device that asks for more contrast would show
179
+ * "More" and could not say "follow the device" (the theme's lesson, §8 of the settings
180
+ * contract). `useAccountAppearance().contrast` is that mode.
181
+ */
182
+ export function ContrastSetting({ value, onChange, label, labels: labelsProp, overflow = "wrap", ...rest }: ContrastSettingProps) {
183
+ const labels = useAppearanceLabels(labelsProp);
184
+ const named = label !== undefined && label !== null && label !== false;
185
+ return (
186
+ <ToggleGroup<ContrastMode>
187
+ {...rest}
188
+ aria-label={named || rest["aria-labelledby"] ? rest["aria-label"] : (rest["aria-label"] ?? labels.contrast)}
189
+ label={label}
190
+ overflow={overflow}
191
+ value={value}
192
+ onChange={onChange}
193
+ options={CONTRAST_MODES.map((mode) => ({ value: mode, label: labels.contrastModes[mode] }))}
194
+ />
195
+ );
196
+ }
@@ -478,6 +478,12 @@ export function SharePanel({
478
478
  size="xs"
479
479
  commit
480
480
  label={labels.remove}
481
+ // The icon alone at every text size (§10.8): the row's one
482
+ // control beside its role toggle, where "Remove access" as
483
+ // text at Large would not fit a 240 px row. It carries a
484
+ // spinner and the write lock, which a "⋯" menu entry
485
+ // cannot, and its confirmation names the action in words.
486
+ labelVisible={false}
481
487
  pending={busy === key}
482
488
  disabled={busy !== null}
483
489
  onClick={async () => {
@@ -531,6 +537,10 @@ export function SharePanel({
531
537
  size="xs"
532
538
  commit
533
539
  label={labels.revokePending}
540
+ // As the grantee's remove above: one action beside the
541
+ // copy icon (which is an icon at every size), and the
542
+ // confirmation says it in words.
543
+ labelVisible={false}
534
544
  pending={busy === key}
535
545
  disabled={busy !== null}
536
546
  onClick={async () => {
@@ -3,6 +3,7 @@ import { Chip } from "./chip";
3
3
  import { Tooltip } from "./tooltip";
4
4
  import { cn } from "../lib/cn";
5
5
  import { useKitLabels } from "../i18n/kit-labels";
6
+ import { useLargeText } from "../hooks/use-large-text";
6
7
 
7
8
  // ── Labels ────────────────────────────────────────────────────────────────────
8
9
 
@@ -17,12 +18,17 @@ export interface SignChipLabels {
17
18
  * turns it into — `current` and `next` are the two words above. The other option is
18
19
  * nowhere on screen to be read, so the name has to say both. */
19
20
  direction: (current: string, next: string) => string;
21
+ /** 0.32: what a press does, in words under the chip at Large and Extra large —
22
+ * `next` is the other direction's word ("Switch to Inflow"). The tooltip's half of
23
+ * `direction`, shown, since a fact may not live only in a tooltip there (§4). */
24
+ switchTo: (next: string) => string;
20
25
  }
21
26
 
22
27
  export const DEFAULT_SIGN_CHIP_LABELS: SignChipLabels = {
23
28
  outflow: "Outflow",
24
29
  inflow: "Inflow",
25
30
  direction: (current, next) => `Direction: ${current} — switch to ${next}`,
31
+ switchTo: (next) => `Switch to ${next}`,
26
32
  };
27
33
 
28
34
  export interface SignChipProps {
@@ -79,8 +85,10 @@ export function SignChip({ negative, onNegativeChange, disabled, labels: labelsP
79
85
  const current = negative ? labels.outflow : labels.inflow;
80
86
  const next = negative ? labels.inflow : labels.outflow;
81
87
  const name = labels.direction(current, next);
82
- return (
83
- <Tooltip label={name} lazy>
88
+ // §4: at Large the chip's word is joined by what a press does, as a line under it —
89
+ // and the bubble that said only that goes.
90
+ const large = useLargeText();
91
+ const chip = (
84
92
  <Chip
85
93
  size="lg"
86
94
  tone={negative ? "expense" : "income"}
@@ -91,13 +99,29 @@ export function SignChip({ negative, onNegativeChange, disabled, labels: labelsP
91
99
  // `gap-1.5 px-3`: the chip's narrower body, because on a 375px screen every
92
100
  // pixel of it is taken from the figure beside it (#430). `md:py-2.5` with the
93
101
  // hairline border is the 42px a labelled field measures (#431).
94
- className={cn("shrink-0 gap-1.5 whitespace-nowrap px-3 font-medium md:min-h-0 md:py-2.5", className)}
102
+ className={cn("shrink-0 gap-1.5 whitespace-nowrap px-3 font-medium md:min-h-0 md:py-2.5", !large && className)}
95
103
  >
96
104
  {current}
97
105
  {/* The swap arrows after the word, in the label's own row: decoration (the
98
106
  name already says what a press does), set a little apart from the word. */}
99
107
  <ArrowUpDown className="ms-1.5 inline size-3.5 align-[-0.2em] opacity-60" aria-hidden />
100
108
  </Chip>
101
- </Tooltip>
109
+ );
110
+ if (!large) {
111
+ return (
112
+ <Tooltip label={name} lazy>
113
+ {chip}
114
+ </Tooltip>
115
+ );
116
+ }
117
+ return (
118
+ // The caller's placement (`self-end`…) moves to the pair, which is now the row's item.
119
+ <span data-slot="sign-chip" className={cn("inline-flex shrink-0 flex-col items-start gap-0.5", className)}>
120
+ {chip}
121
+ {/* Hidden from the accessibility tree: the chip's name already says it. */}
122
+ <span aria-hidden className="text-xs text-[var(--text-muted)]">
123
+ {labels.switchTo(next)}
124
+ </span>
125
+ </span>
102
126
  );
103
127
  }
@@ -4,6 +4,7 @@ import { Eraser, Keyboard, PenLine, Undo2 } from "lucide-react";
4
4
  import { cn } from "../lib/cn";
5
5
  import { useAnnounce } from "../hooks/use-announce";
6
6
  import { useKitLabels } from "../i18n/kit-labels";
7
+ import { useTextSize } from "../theme/text-size";
7
8
  import { Button, FIELD_INVALID, Input } from "./ui";
8
9
 
9
10
  /**
@@ -144,7 +145,9 @@ export interface SignaturePadProps extends Omit<ComponentPropsWithoutRef<"div">,
144
145
  exportInk?: string;
145
146
  /** Fill behind the exported PNG. Default transparent. */
146
147
  exportBackground?: string;
147
- /** Base stroke width in CSS pixels. Default 2.5. */
148
+ /** Base stroke width in CSS pixels at Normal text size. Default 2.5. It grows with the
149
+ * text size (× 1.25 / × 1.5, docs/text-size-harmonization.md §10.11), as the pad's
150
+ * rem height does, so a signature keeps its weight on a larger pad. */
148
151
  lineWidth?: number;
149
152
  /** Classes for the canvas — its height, chiefly (default `h-40`). */
150
153
  canvasClassName?: string;
@@ -291,10 +294,13 @@ export const SignaturePad = forwardRef<SignaturePadHandle, SignaturePadProps>(fu
291
294
 
292
295
  // Everything the paint and export paths read that can change between renders, so
293
296
  // the observers below subscribe once instead of on every keystroke.
294
- const opts = useRef({ lineWidth, exportInk, exportBackground });
297
+ // The stroke follows the text size like everything in rem around it (§10.11).
298
+ const { scale: textScale } = useTextSize();
299
+ const strokeWidth = lineWidth * textScale;
300
+ const opts = useRef({ lineWidth: strokeWidth, exportInk, exportBackground });
295
301
  useEffect(() => {
296
- opts.current = { lineWidth, exportInk, exportBackground };
297
- }, [lineWidth, exportInk, exportBackground]);
302
+ opts.current = { lineWidth: strokeWidth, exportInk, exportBackground };
303
+ }, [strokeWidth, exportInk, exportBackground]);
298
304
 
299
305
  const sceneEmpty = () => {
300
306
  const s = scene.current;
@@ -356,10 +362,10 @@ export const SignaturePad = forwardRef<SignaturePadHandle, SignaturePadProps>(fu
356
362
  resize();
357
363
  }, [resize]);
358
364
 
359
- // A changed base width redraws what is already there.
365
+ // A changed base width — or text size — redraws what is already there.
360
366
  useEffect(() => {
361
367
  repaint();
362
- }, [lineWidth, repaint]);
368
+ }, [strokeWidth, repaint]);
363
369
 
364
370
  useEffect(() => {
365
371
  const canvas = canvasRef.current;
@@ -627,7 +633,7 @@ export const SignaturePad = forwardRef<SignaturePadHandle, SignaturePadProps>(fu
627
633
  </div>
628
634
 
629
635
  {hasError && (
630
- <p id={errorId} className="mt-1 text-[11px] leading-tight text-[var(--danger)]">
636
+ <p id={errorId} className="mt-1 text-caption leading-tight text-[var(--danger)]">
631
637
  {error}
632
638
  </p>
633
639
  )}