@eifi1/ui-kit 0.54.0 → 0.55.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 (847) hide show
  1. package/README.md +90 -76
  2. package/dist/admin/plan-change.js +2 -2
  3. package/dist/admin/plan-change.js.map +1 -1
  4. package/dist/admin/user-roster.d.ts +6 -0
  5. package/dist/admin/user-roster.js +4 -0
  6. package/dist/admin/user-roster.js.map +1 -1
  7. package/dist/billing/billing-labels.d.ts +26 -0
  8. package/dist/billing/billing-labels.js +9 -0
  9. package/dist/billing/billing-labels.js.map +1 -1
  10. package/dist/billing/subscription-standing.d.ts +61 -0
  11. package/dist/billing/subscription-standing.js +51 -0
  12. package/dist/billing/subscription-standing.js.map +1 -0
  13. package/dist/billing/usage-meter.d.ts +52 -0
  14. package/dist/billing/usage-meter.js +52 -0
  15. package/dist/billing/usage-meter.js.map +1 -0
  16. package/dist/chart.d.ts +1 -0
  17. package/dist/chart.js +4 -0
  18. package/dist/chart.js.map +1 -1
  19. package/dist/components/alert-banner.js +2 -3
  20. package/dist/components/alert-banner.js.map +1 -1
  21. package/dist/components/amount-input.js +3 -15
  22. package/dist/components/amount-input.js.map +1 -1
  23. package/dist/components/autocomplete.js +2 -2
  24. package/dist/components/autocomplete.js.map +1 -1
  25. package/dist/components/bulk-action-bar.js +2 -1
  26. package/dist/components/bulk-action-bar.js.map +1 -1
  27. package/dist/components/button.d.ts +35 -1
  28. package/dist/components/button.js +5 -9
  29. package/dist/components/button.js.map +1 -1
  30. package/dist/components/calendar-heatmap.js +2 -2
  31. package/dist/components/calendar-heatmap.js.map +1 -1
  32. package/dist/components/camera-button.d.ts +89 -0
  33. package/dist/components/camera-button.js +122 -0
  34. package/dist/components/camera-button.js.map +1 -0
  35. package/dist/components/camera-capture.d.ts +66 -0
  36. package/dist/components/camera-capture.js +190 -0
  37. package/dist/components/camera-capture.js.map +1 -0
  38. package/dist/components/camera-labels.d.ts +20 -0
  39. package/dist/components/camera-labels.js +15 -0
  40. package/dist/components/camera-labels.js.map +1 -0
  41. package/dist/components/chart-edge.d.ts +9 -0
  42. package/dist/components/chart-edge.js +14 -3
  43. package/dist/components/chart-edge.js.map +1 -1
  44. package/dist/components/chart-zoom-core.js +34 -29
  45. package/dist/components/chart-zoom-core.js.map +1 -1
  46. package/dist/components/checkbox-group.js +1 -1
  47. package/dist/components/checkbox-group.js.map +1 -1
  48. package/dist/components/combobox-core.js +3 -2
  49. package/dist/components/combobox-core.js.map +1 -1
  50. package/dist/components/combobox.js +2 -2
  51. package/dist/components/combobox.js.map +1 -1
  52. package/dist/components/consent-again-notice-labels.d.ts +25 -0
  53. package/dist/components/consent-again-notice-labels.js +15 -0
  54. package/dist/components/consent-again-notice-labels.js.map +1 -0
  55. package/dist/components/consent-again-notice.d.ts +85 -0
  56. package/dist/components/consent-again-notice.js +94 -0
  57. package/dist/components/consent-again-notice.js.map +1 -0
  58. package/dist/components/country-select.js +2 -7
  59. package/dist/components/country-select.js.map +1 -1
  60. package/dist/components/currency-select.js +2 -2
  61. package/dist/components/currency-select.js.map +1 -1
  62. package/dist/components/danger-confirm.js +2 -2
  63. package/dist/components/danger-confirm.js.map +1 -1
  64. package/dist/components/data-table-column-settings.js +2 -2
  65. package/dist/components/data-table-column-settings.js.map +1 -1
  66. package/dist/components/data-table-fit.js.map +1 -1
  67. package/dist/components/data-table-virtual.js +13 -3
  68. package/dist/components/data-table-virtual.js.map +1 -1
  69. package/dist/components/date-field.js +2 -2
  70. package/dist/components/date-field.js.map +1 -1
  71. package/dist/components/date-picker.js +2 -2
  72. package/dist/components/date-picker.js.map +1 -1
  73. package/dist/components/date-range-picker.js +2 -6
  74. package/dist/components/date-range-picker.js.map +1 -1
  75. package/dist/components/dialog-frame.d.ts +3 -1
  76. package/dist/components/dialog-frame.js.map +1 -1
  77. package/dist/components/dropdown.js +7 -3
  78. package/dist/components/dropdown.js.map +1 -1
  79. package/dist/components/entity-combobox.js +2 -2
  80. package/dist/components/entity-combobox.js.map +1 -1
  81. package/dist/components/field-parts.d.ts +108 -6
  82. package/dist/components/field-parts.js +59 -6
  83. package/dist/components/field-parts.js.map +1 -1
  84. package/dist/components/field-suggestion-labels.d.ts +2 -0
  85. package/dist/components/field-suggestion-labels.js +10 -0
  86. package/dist/components/field-suggestion-labels.js.map +1 -0
  87. package/dist/components/field.js +1 -1
  88. package/dist/components/field.js.map +1 -1
  89. package/dist/components/file-button.d.ts +1 -1
  90. package/dist/components/file-button.js.map +1 -1
  91. package/dist/components/floating-panel.d.ts +7 -6
  92. package/dist/components/floating-panel.js +3 -17
  93. package/dist/components/floating-panel.js.map +1 -1
  94. package/dist/components/form-actions.d.ts +3 -2
  95. package/dist/components/form-actions.js.map +1 -1
  96. package/dist/components/hover-menu.js +3 -2
  97. package/dist/components/hover-menu.js.map +1 -1
  98. package/dist/components/icon-button.d.ts +23 -5
  99. package/dist/components/icon-button.js +6 -8
  100. package/dist/components/icon-button.js.map +1 -1
  101. package/dist/components/inline-confirm.js +2 -1
  102. package/dist/components/inline-confirm.js.map +1 -1
  103. package/dist/components/inline-entity-combobox.js +2 -2
  104. package/dist/components/inline-entity-combobox.js.map +1 -1
  105. package/dist/components/input.js +2 -2
  106. package/dist/components/input.js.map +1 -1
  107. package/dist/components/jump-calendar.js +3 -3
  108. package/dist/components/jump-calendar.js.map +1 -1
  109. package/dist/components/legal.d.ts +13 -1
  110. package/dist/components/legal.js +12 -0
  111. package/dist/components/legal.js.map +1 -1
  112. package/dist/components/legended-series-chart.d.ts +80 -0
  113. package/dist/components/legended-series-chart.js +70 -0
  114. package/dist/components/legended-series-chart.js.map +1 -0
  115. package/dist/components/lightbox.js +2 -1
  116. package/dist/components/lightbox.js.map +1 -1
  117. package/dist/components/mini-calendar.js +13 -5
  118. package/dist/components/mini-calendar.js.map +1 -1
  119. package/dist/components/modal.d.ts +23 -2
  120. package/dist/components/modal.js +24 -6
  121. package/dist/components/modal.js.map +1 -1
  122. package/dist/components/month-picker.d.ts +1 -1
  123. package/dist/components/month-picker.js +6 -6
  124. package/dist/components/month-picker.js.map +1 -1
  125. package/dist/components/multi-entity-combobox.js +2 -2
  126. package/dist/components/multi-entity-combobox.js.map +1 -1
  127. package/dist/components/multi-select.js +2 -6
  128. package/dist/components/multi-select.js.map +1 -1
  129. package/dist/components/number-input.js +2 -2
  130. package/dist/components/number-input.js.map +1 -1
  131. package/dist/components/page-header-layout.d.ts +18 -0
  132. package/dist/components/page-header-layout.js +23 -0
  133. package/dist/components/page-header-layout.js.map +1 -0
  134. package/dist/components/page-header-skeleton.d.ts +41 -0
  135. package/dist/components/page-header-skeleton.js +52 -0
  136. package/dist/components/page-header-skeleton.js.map +1 -0
  137. package/dist/components/page-header.js +4 -17
  138. package/dist/components/page-header.js.map +1 -1
  139. package/dist/components/popover.js +7 -2
  140. package/dist/components/popover.js.map +1 -1
  141. package/dist/components/release-notes-labels.d.ts +16 -0
  142. package/dist/components/release-notes-labels.js +18 -0
  143. package/dist/components/release-notes-labels.js.map +1 -0
  144. package/dist/components/release-notes.d.ts +65 -0
  145. package/dist/components/release-notes.js +65 -0
  146. package/dist/components/release-notes.js.map +1 -0
  147. package/dist/components/select.js +2 -2
  148. package/dist/components/select.js.map +1 -1
  149. package/dist/components/series-chart-labels.d.ts +9 -0
  150. package/dist/components/series-chart-labels.js +3 -1
  151. package/dist/components/series-chart-labels.js.map +1 -1
  152. package/dist/components/series-chart.d.ts +5 -0
  153. package/dist/components/series-chart.js +89 -36
  154. package/dist/components/series-chart.js.map +1 -1
  155. package/dist/components/toggle-group.js +3 -2
  156. package/dist/components/toggle-group.js.map +1 -1
  157. package/dist/components/treemap-layout.js.map +1 -1
  158. package/dist/components/treemap.d.ts +17 -15
  159. package/dist/components/treemap.js +167 -85
  160. package/dist/components/treemap.js.map +1 -1
  161. package/dist/eslint/index.js +1 -1
  162. package/dist/eslint/role-utilities.d.ts +2 -2
  163. package/dist/eslint/role-utilities.js.map +1 -1
  164. package/dist/feedback/feedback-inbox-page.d.ts +260 -0
  165. package/dist/feedback/feedback-inbox-page.js +207 -0
  166. package/dist/feedback/feedback-inbox-page.js.map +1 -0
  167. package/dist/feedback/feedback-vocabulary.js +2 -2
  168. package/dist/feedback/feedback-vocabulary.js.map +1 -1
  169. package/dist/feedback.d.ts +1 -0
  170. package/dist/feedback.js +6 -0
  171. package/dist/feedback.js.map +1 -1
  172. package/dist/hooks/use-debounce.d.ts +32 -5
  173. package/dist/hooks/use-debounce.js +6 -5
  174. package/dist/hooks/use-debounce.js.map +1 -1
  175. package/dist/hooks/use-file-picker.d.ts +3 -1
  176. package/dist/hooks/use-file-picker.js.map +1 -1
  177. package/dist/hooks/use-focus-trap.d.ts +19 -3
  178. package/dist/hooks/use-focus-trap.js +15 -5
  179. package/dist/hooks/use-focus-trap.js.map +1 -1
  180. package/dist/hooks/use-has-camera.d.ts +36 -0
  181. package/dist/hooks/use-has-camera.js +53 -0
  182. package/dist/hooks/use-has-camera.js.map +1 -0
  183. package/dist/hooks/use-hotkey.js +1 -10
  184. package/dist/hooks/use-hotkey.js.map +1 -1
  185. package/dist/hooks/use-overlay-history.d.ts +6 -1
  186. package/dist/hooks/use-overlay-history.js +10 -2
  187. package/dist/hooks/use-overlay-history.js.map +1 -1
  188. package/dist/i18n/defaults.js +11 -1
  189. package/dist/i18n/defaults.js.map +1 -1
  190. package/dist/i18n/german.js +75 -3
  191. package/dist/i18n/german.js.map +1 -1
  192. package/dist/i18n/kit-labels.d.ts +20 -0
  193. package/dist/i18n/kit-labels.js.map +1 -1
  194. package/dist/i18n/locales/en.js +92 -4
  195. package/dist/i18n/locales/en.js.map +3 -3
  196. package/dist/i18n/locales/es.js +71 -3
  197. package/dist/i18n/locales/es.js.map +1 -1
  198. package/dist/i18n/locales/fr.js +72 -2
  199. package/dist/i18n/locales/fr.js.map +1 -1
  200. package/dist/i18n/locales/hu.js +74 -3
  201. package/dist/i18n/locales/hu.js.map +1 -1
  202. package/dist/i18n/locales/it.js +74 -3
  203. package/dist/i18n/locales/it.js.map +1 -1
  204. package/dist/i18n/locales/zh.js +71 -3
  205. package/dist/i18n/locales/zh.js.map +1 -1
  206. package/dist/i18n/review.js +22 -1
  207. package/dist/i18n/review.js.map +1 -1
  208. package/dist/index.d.ts +24 -5
  209. package/dist/index.js +35 -1
  210. package/dist/index.js.map +1 -1
  211. package/dist/landing/landing-labels.d.ts +8 -0
  212. package/dist/landing/landing-labels.js +2 -1
  213. package/dist/landing/landing-labels.js.map +1 -1
  214. package/dist/lib/changelog.d.ts +130 -0
  215. package/dist/lib/changelog.js +137 -0
  216. package/dist/lib/changelog.js.map +1 -0
  217. package/dist/lib/clipboard-minus.js +2 -2
  218. package/dist/lib/clipboard-minus.js.map +1 -1
  219. package/dist/lib/dates.d.ts +29 -3
  220. package/dist/lib/dates.js +41 -12
  221. package/dist/lib/dates.js.map +1 -1
  222. package/dist/lib/editable-content.d.ts +33 -0
  223. package/dist/lib/editable-content.js +15 -0
  224. package/dist/lib/editable-content.js.map +1 -0
  225. package/dist/lib/focus-left.d.ts +47 -1
  226. package/dist/lib/focus-left.js +11 -2
  227. package/dist/lib/focus-left.js.map +1 -1
  228. package/dist/lib/server-wake.d.ts +49 -9
  229. package/dist/lib/server-wake.js +25 -14
  230. package/dist/lib/server-wake.js.map +1 -1
  231. package/dist/lib/session-refresh.d.ts +53 -0
  232. package/dist/lib/session-refresh.js +27 -1
  233. package/dist/lib/session-refresh.js.map +1 -1
  234. package/dist/rhf/fields.js +3 -3
  235. package/dist/rhf/fields.js.map +1 -1
  236. package/dist/shell/app-shell.d.ts +25 -1
  237. package/dist/shell/app-shell.js +3 -1
  238. package/dist/shell/app-shell.js.map +1 -1
  239. package/dist/shell/dev-menu.d.ts +3 -0
  240. package/dist/shell/dev-menu.js +4 -2
  241. package/dist/shell/dev-menu.js.map +1 -1
  242. package/dist/shell/held-changes-banner-labels.d.ts +23 -0
  243. package/dist/shell/held-changes-banner-labels.js +14 -0
  244. package/dist/shell/held-changes-banner-labels.js.map +1 -0
  245. package/dist/shell/held-changes-banner.d.ts +75 -0
  246. package/dist/shell/held-changes-banner.js +106 -0
  247. package/dist/shell/held-changes-banner.js.map +1 -0
  248. package/dist/shell/sync-status-indicator.d.ts +27 -12
  249. package/dist/shell/sync-status-indicator.js +13 -4
  250. package/dist/shell/sync-status-indicator.js.map +1 -1
  251. package/dist/shell/top-bar-parts-labels.d.ts +5 -0
  252. package/dist/shell/top-bar-parts-labels.js +3 -1
  253. package/dist/shell/top-bar-parts-labels.js.map +1 -1
  254. package/dist/shell.d.ts +2 -0
  255. package/dist/shell.js +3 -0
  256. package/dist/shell.js.map +1 -1
  257. package/dist/sync/engine.d.ts +11 -2
  258. package/dist/sync/engine.js +13 -5
  259. package/dist/sync/engine.js.map +1 -1
  260. package/dist/sync/hooks.d.ts +3 -2
  261. package/dist/sync/hooks.js +4 -2
  262. package/dist/sync/hooks.js.map +1 -1
  263. package/dist/testing/css-variables.generated.d.ts +2 -2
  264. package/dist/testing/css-variables.generated.js +1 -1
  265. package/dist/testing/css-variables.generated.js.map +1 -1
  266. package/dist/theme/chart-palette.d.ts +18 -0
  267. package/dist/theme/chart-palette.js +17 -1
  268. package/dist/theme/chart-palette.js.map +1 -1
  269. package/dist/theme/contrast-tokens.d.ts +3 -3
  270. package/dist/theme/contrast-tokens.js.map +1 -1
  271. package/dist/theme/contrast.d.ts +4 -4
  272. package/dist/theme/contrast.js.map +1 -1
  273. package/dist/tour/tour-overlay.js +2 -1
  274. package/dist/tour/tour-overlay.js.map +1 -1
  275. package/package.json +5 -9
  276. package/tokens.css +19 -54
  277. package/src/account/account-parts.ts +0 -47
  278. package/src/account/account-settings-labels.ts +0 -240
  279. package/src/account/account-settings.tsx +0 -698
  280. package/src/account/data-export-setting-labels.ts +0 -20
  281. package/src/account/data-export-setting.tsx +0 -200
  282. package/src/account/delete-account-setting-labels.ts +0 -33
  283. package/src/account/delete-account-setting.tsx +0 -342
  284. package/src/account/email-change-setting-labels.ts +0 -31
  285. package/src/account/email-change-setting.tsx +0 -443
  286. package/src/account/passkeys-setting.tsx +0 -445
  287. package/src/account/sessions-setting-labels.ts +0 -24
  288. package/src/account/sessions-setting.tsx +0 -283
  289. package/src/admin/admin-action-confirm-labels.ts +0 -19
  290. package/src/admin/admin-action-confirm.tsx +0 -509
  291. package/src/admin/admin-action-log-labels.ts +0 -83
  292. package/src/admin/admin-action-log.tsx +0 -464
  293. package/src/admin/admin-area-labels.ts +0 -114
  294. package/src/admin/admin-forbidden.tsx +0 -75
  295. package/src/admin/admin-overview.tsx +0 -258
  296. package/src/admin/admin-parts.ts +0 -68
  297. package/src/admin/admin-sections.tsx +0 -208
  298. package/src/admin/admin-tool-links.tsx +0 -90
  299. package/src/admin/invitations-panel-labels.ts +0 -31
  300. package/src/admin/invitations-panel.tsx +0 -516
  301. package/src/admin/mail-test-card-labels.ts +0 -19
  302. package/src/admin/mail-test-card.tsx +0 -189
  303. package/src/admin/plan-change-labels.ts +0 -5
  304. package/src/admin/plan-change.tsx +0 -474
  305. package/src/admin/reviewer-scope-editor-labels.ts +0 -16
  306. package/src/admin/reviewer-scope-editor.tsx +0 -224
  307. package/src/admin/role-select-labels.ts +0 -16
  308. package/src/admin/role-select.tsx +0 -282
  309. package/src/admin/transfer-ownership-dialog-labels.ts +0 -20
  310. package/src/admin/transfer-ownership-dialog.tsx +0 -162
  311. package/src/admin/user-roster-labels.ts +0 -17
  312. package/src/admin/user-roster.tsx +0 -559
  313. package/src/auth/accept-invitation-labels.ts +0 -21
  314. package/src/auth/accept-invitation.tsx +0 -210
  315. package/src/auth/auth-errors-labels.ts +0 -23
  316. package/src/auth/auth-errors.ts +0 -439
  317. package/src/auth/complete-name-dialog-labels.ts +0 -16
  318. package/src/auth/complete-name-dialog.tsx +0 -253
  319. package/src/auth/email-tag.ts +0 -75
  320. package/src/auth/forgot-password-form-labels.ts +0 -20
  321. package/src/auth/forgot-password-form.tsx +0 -221
  322. package/src/auth/form-rules.ts +0 -40
  323. package/src/auth/new-password-fields.tsx +0 -85
  324. package/src/auth/not-found-page-labels.ts +0 -12
  325. package/src/auth/not-found-page.tsx +0 -95
  326. package/src/auth/register-form-labels.ts +0 -31
  327. package/src/auth/register-form.tsx +0 -456
  328. package/src/auth/reset-password-form-labels.ts +0 -27
  329. package/src/auth/reset-password-form.tsx +0 -341
  330. package/src/auth/sign-in-form-labels.ts +0 -44
  331. package/src/auth/sign-in-form.tsx +0 -858
  332. package/src/auth/status-parts.tsx +0 -132
  333. package/src/auth/verify-email-labels.ts +0 -26
  334. package/src/auth/verify-email.tsx +0 -445
  335. package/src/billing/billing-banner.tsx +0 -258
  336. package/src/billing/billing-labels.ts +0 -381
  337. package/src/billing/billing-lock.ts +0 -108
  338. package/src/billing/billing-overview.ts +0 -157
  339. package/src/billing/billing-standing.ts +0 -80
  340. package/src/billing/cancel-request.ts +0 -97
  341. package/src/billing/cancel-subscription.tsx +0 -98
  342. package/src/billing/checkout-processing.ts +0 -394
  343. package/src/billing/checkout-return.ts +0 -90
  344. package/src/billing/pay-page.ts +0 -330
  345. package/src/billing/plan-card.tsx +0 -562
  346. package/src/billing/plan-change-labels.ts +0 -66
  347. package/src/billing/plan-limit-notice.tsx +0 -148
  348. package/src/billing/plan-limit-toast.tsx +0 -90
  349. package/src/billing/plan-limit.ts +0 -52
  350. package/src/billing/plan-price.ts +0 -98
  351. package/src/billing/plan-switch.tsx +0 -216
  352. package/src/billing/provider-page.ts +0 -84
  353. package/src/billing/subscription-actions.tsx +0 -247
  354. package/src/billing/subscription-status-chip.tsx +0 -95
  355. package/src/chart.ts +0 -103
  356. package/src/components/account-chips-labels.ts +0 -16
  357. package/src/components/account-chips.tsx +0 -474
  358. package/src/components/alert-banner.tsx +0 -670
  359. package/src/components/amount-input.tsx +0 -816
  360. package/src/components/appearance-labels.ts +0 -63
  361. package/src/components/authed-image-labels.ts +0 -11
  362. package/src/components/authed-image.tsx +0 -209
  363. package/src/components/autocomplete.tsx +0 -645
  364. package/src/components/breadcrumbs-labels.ts +0 -10
  365. package/src/components/breadcrumbs.tsx +0 -205
  366. package/src/components/bulk-action-bar-labels.ts +0 -11
  367. package/src/components/bulk-action-bar.tsx +0 -443
  368. package/src/components/button-group.tsx +0 -223
  369. package/src/components/button-look.ts +0 -256
  370. package/src/components/button.tsx +0 -339
  371. package/src/components/calculator.tsx +0 -341
  372. package/src/components/calendar-heatmap-labels.ts +0 -15
  373. package/src/components/calendar-heatmap.tsx +0 -600
  374. package/src/components/card.tsx +0 -377
  375. package/src/components/chart-edge.ts +0 -106
  376. package/src/components/chart-figure.tsx +0 -35
  377. package/src/components/chart-height.ts +0 -30
  378. package/src/components/chart-zoom-core.tsx +0 -627
  379. package/src/components/chart-zoom.tsx +0 -22
  380. package/src/components/chart.tsx +0 -554
  381. package/src/components/checkbox-group.tsx +0 -247
  382. package/src/components/checkbox.tsx +0 -346
  383. package/src/components/chip-input.tsx +0 -370
  384. package/src/components/chip-labels.ts +0 -13
  385. package/src/components/chip.tsx +0 -843
  386. package/src/components/choice-card.tsx +0 -544
  387. package/src/components/column-mapper-labels.ts +0 -38
  388. package/src/components/column-mapper.tsx +0 -655
  389. package/src/components/combobox-core.tsx +0 -1321
  390. package/src/components/combobox-suggestions.tsx +0 -131
  391. package/src/components/combobox.tsx +0 -716
  392. package/src/components/confirm-context.ts +0 -7
  393. package/src/components/confirm-dialog-labels.ts +0 -13
  394. package/src/components/confirm-dialog.tsx +0 -341
  395. package/src/components/copy-button-labels.ts +0 -13
  396. package/src/components/copy-button.tsx +0 -192
  397. package/src/components/country-select-labels.ts +0 -11
  398. package/src/components/country-select.tsx +0 -539
  399. package/src/components/currency-option-list.tsx +0 -188
  400. package/src/components/currency-select.tsx +0 -343
  401. package/src/components/danger-confirm-labels.ts +0 -20
  402. package/src/components/danger-confirm.tsx +0 -987
  403. package/src/components/data-table-cells.tsx +0 -118
  404. package/src/components/data-table-column-settings.tsx +0 -198
  405. package/src/components/data-table-filter-popover.tsx +0 -289
  406. package/src/components/data-table-filters.ts +0 -315
  407. package/src/components/data-table-fit.ts +0 -301
  408. package/src/components/data-table-groups.tsx +0 -288
  409. package/src/components/data-table-head.tsx +0 -280
  410. package/src/components/data-table-labels.ts +0 -198
  411. package/src/components/data-table-leading-row.tsx +0 -58
  412. package/src/components/data-table-mobile.tsx +0 -1117
  413. package/src/components/data-table-pagination.tsx +0 -202
  414. package/src/components/data-table-resize.ts +0 -188
  415. package/src/components/data-table-row-actions.tsx +0 -302
  416. package/src/components/data-table-row.tsx +0 -496
  417. package/src/components/data-table-selection.ts +0 -71
  418. package/src/components/data-table-shared.tsx +0 -287
  419. package/src/components/data-table-sort.ts +0 -163
  420. package/src/components/data-table-virtual.ts +0 -576
  421. package/src/components/data-table.tsx +0 -2598
  422. package/src/components/date-field.tsx +0 -684
  423. package/src/components/date-format-setting.tsx +0 -64
  424. package/src/components/date-picker.tsx +0 -404
  425. package/src/components/date-range-picker.tsx +0 -518
  426. package/src/components/description-list-labels.ts +0 -9
  427. package/src/components/description-list.tsx +0 -386
  428. package/src/components/dialog-frame-labels.ts +0 -7
  429. package/src/components/dialog-frame.tsx +0 -284
  430. package/src/components/disclosure.tsx +0 -476
  431. package/src/components/dropdown.tsx +0 -461
  432. package/src/components/empty-state.tsx +0 -136
  433. package/src/components/entity-combobox.tsx +0 -422
  434. package/src/components/error-boundary-labels.ts +0 -20
  435. package/src/components/error-boundary.tsx +0 -675
  436. package/src/components/facing-pair.ts +0 -93
  437. package/src/components/field-base-labels.ts +0 -20
  438. package/src/components/field-base.tsx +0 -656
  439. package/src/components/field-parts.tsx +0 -825
  440. package/src/components/field-strip.tsx +0 -129
  441. package/src/components/field.tsx +0 -206
  442. package/src/components/file-button.tsx +0 -295
  443. package/src/components/file-dropzone.tsx +0 -559
  444. package/src/components/floating-panel-labels.ts +0 -10
  445. package/src/components/floating-panel.tsx +0 -828
  446. package/src/components/focus-ring.ts +0 -16
  447. package/src/components/form-actions-labels.ts +0 -11
  448. package/src/components/form-actions.tsx +0 -578
  449. package/src/components/full-bleed-dialog.tsx +0 -294
  450. package/src/components/grouped-picker.tsx +0 -184
  451. package/src/components/help-popover.tsx +0 -117
  452. package/src/components/hover-menu.tsx +0 -343
  453. package/src/components/iban-input-labels.ts +0 -14
  454. package/src/components/iban-input.tsx +0 -236
  455. package/src/components/icon-button.tsx +0 -959
  456. package/src/components/icon-picker-labels.ts +0 -13
  457. package/src/components/icon-picker.tsx +0 -232
  458. package/src/components/image-grid-labels.ts +0 -11
  459. package/src/components/image-grid.tsx +0 -202
  460. package/src/components/inline-confirm.tsx +0 -116
  461. package/src/components/inline-edit-field-labels.ts +0 -11
  462. package/src/components/inline-edit-field.tsx +0 -552
  463. package/src/components/inline-entity-combobox.tsx +0 -849
  464. package/src/components/input.tsx +0 -394
  465. package/src/components/jump-calendar.tsx +0 -265
  466. package/src/components/language-select.tsx +0 -93
  467. package/src/components/legal-labels.ts +0 -105
  468. package/src/components/legal-page.tsx +0 -711
  469. package/src/components/legal.tsx +0 -668
  470. package/src/components/lightbox-labels.ts +0 -18
  471. package/src/components/lightbox.tsx +0 -399
  472. package/src/components/line-items-labels.ts +0 -14
  473. package/src/components/line-items.tsx +0 -602
  474. package/src/components/list-labels.ts +0 -12
  475. package/src/components/list.tsx +0 -870
  476. package/src/components/loading-state.tsx +0 -78
  477. package/src/components/measured-grid-labels.ts +0 -25
  478. package/src/components/measured-grid.tsx +0 -837
  479. package/src/components/menu-item.tsx +0 -241
  480. package/src/components/mini-calendar-labels.ts +0 -17
  481. package/src/components/mini-calendar.tsx +0 -792
  482. package/src/components/modal.tsx +0 -534
  483. package/src/components/money-draft.ts +0 -83
  484. package/src/components/money-field.tsx +0 -76
  485. package/src/components/month-grid.tsx +0 -229
  486. package/src/components/month-picker-labels.ts +0 -22
  487. package/src/components/month-picker.tsx +0 -1087
  488. package/src/components/multi-entity-combobox.tsx +0 -369
  489. package/src/components/multi-select.tsx +0 -376
  490. package/src/components/nav-pills.tsx +0 -198
  491. package/src/components/number-field.tsx +0 -327
  492. package/src/components/number-input.tsx +0 -559
  493. package/src/components/numeric-field.ts +0 -169
  494. package/src/components/numpad-sheet.tsx +0 -285
  495. package/src/components/one-time-code-input.tsx +0 -270
  496. package/src/components/page-contents-labels.ts +0 -9
  497. package/src/components/page-contents.tsx +0 -282
  498. package/src/components/page-header-context.ts +0 -8
  499. package/src/components/page-header.tsx +0 -298
  500. package/src/components/password-strength-labels.ts +0 -22
  501. package/src/components/password-strength.tsx +0 -241
  502. package/src/components/phone-input-labels.ts +0 -10
  503. package/src/components/phone-input.tsx +0 -282
  504. package/src/components/picker-sheet.tsx +0 -330
  505. package/src/components/pie-chart-labels.ts +0 -40
  506. package/src/components/pie-chart.tsx +0 -480
  507. package/src/components/popover-labels.ts +0 -14
  508. package/src/components/popover.tsx +0 -268
  509. package/src/components/progress-bar-labels.ts +0 -10
  510. package/src/components/progress-bar.tsx +0 -479
  511. package/src/components/qr-code.tsx +0 -76
  512. package/src/components/reauth-dialog-labels.ts +0 -13
  513. package/src/components/reauth-dialog.tsx +0 -265
  514. package/src/components/row-actions-labels.ts +0 -12
  515. package/src/components/row-actions.tsx +0 -795
  516. package/src/components/scroll-area.tsx +0 -123
  517. package/src/components/search-field.tsx +0 -192
  518. package/src/components/select.tsx +0 -294
  519. package/src/components/separator.tsx +0 -33
  520. package/src/components/series-chart-axes.ts +0 -342
  521. package/src/components/series-chart-budget.ts +0 -150
  522. package/src/components/series-chart-labels.ts +0 -33
  523. package/src/components/series-chart-thin.ts +0 -180
  524. package/src/components/series-chart-ticks.ts +0 -194
  525. package/src/components/series-chart.tsx +0 -1906
  526. package/src/components/server-wake-labels.ts +0 -11
  527. package/src/components/server-wake.tsx +0 -129
  528. package/src/components/settings-fields.tsx +0 -237
  529. package/src/components/share-card-labels.ts +0 -30
  530. package/src/components/share-card.tsx +0 -675
  531. package/src/components/signature-pad-labels.ts +0 -24
  532. package/src/components/signature-pad.tsx +0 -747
  533. package/src/components/signed-amount-labels.ts +0 -10
  534. package/src/components/signed-amount.tsx +0 -336
  535. package/src/components/skeleton.tsx +0 -80
  536. package/src/components/slider.tsx +0 -338
  537. package/src/components/sparkline-labels.ts +0 -14
  538. package/src/components/sparkline.tsx +0 -322
  539. package/src/components/spinner.tsx +0 -81
  540. package/src/components/stat-tile-labels.ts +0 -15
  541. package/src/components/stat-tile.tsx +0 -754
  542. package/src/components/status-dot.tsx +0 -170
  543. package/src/components/swatch-picker-labels.ts +0 -10
  544. package/src/components/swatch-picker.tsx +0 -283
  545. package/src/components/swipeable-row.tsx +0 -386
  546. package/src/components/switch.tsx +0 -273
  547. package/src/components/table-skeleton.tsx +0 -136
  548. package/src/components/table.tsx +0 -647
  549. package/src/components/tabs-labels.ts +0 -13
  550. package/src/components/tabs.tsx +0 -693
  551. package/src/components/text-link.tsx +0 -359
  552. package/src/components/text.tsx +0 -150
  553. package/src/components/textarea.tsx +0 -330
  554. package/src/components/tile-radio.tsx +0 -332
  555. package/src/components/time-input.tsx +0 -121
  556. package/src/components/toast-labels.ts +0 -12
  557. package/src/components/toast.tsx +0 -519
  558. package/src/components/toggle-group.tsx +0 -752
  559. package/src/components/toggle-legend.tsx +0 -394
  560. package/src/components/tooltip.tsx +0 -1149
  561. package/src/components/translation-review-editor.tsx +0 -290
  562. package/src/components/translation-review-labels.ts +0 -181
  563. package/src/components/translation-review-parts.tsx +0 -272
  564. package/src/components/translation-review.tsx +0 -1240
  565. package/src/components/tree-view.tsx +0 -589
  566. package/src/components/treemap-labels.ts +0 -47
  567. package/src/components/treemap-layout.ts +0 -210
  568. package/src/components/treemap.tsx +0 -1184
  569. package/src/components/trigger-aria.ts +0 -44
  570. package/src/components/use-anchor-dir.ts +0 -20
  571. package/src/components/use-mobile-reveal.ts +0 -62
  572. package/src/components/use-table-state.ts +0 -753
  573. package/src/components/user-avatar.tsx +0 -116
  574. package/src/components/wizard-stepper.tsx +0 -42
  575. package/src/components/write-lock-labels.ts +0 -10
  576. package/src/components/write-lock.tsx +0 -253
  577. package/src/currencies.ts +0 -90
  578. package/src/data-table.ts +0 -42
  579. package/src/demo/demo-banner.tsx +0 -153
  580. package/src/demo/demo-countdown.ts +0 -136
  581. package/src/demo/demo-ended.tsx +0 -90
  582. package/src/demo/demo-labels.ts +0 -78
  583. package/src/demo/demo-session.ts +0 -32
  584. package/src/demo/demo-start.tsx +0 -156
  585. package/src/eslint/index.ts +0 -161
  586. package/src/eslint/role-utilities.generated.ts +0 -146
  587. package/src/eslint/role-utilities.ts +0 -233
  588. package/src/feedback/feedback-attachment-download.tsx +0 -77
  589. package/src/feedback/feedback-attachment-labels.ts +0 -37
  590. package/src/feedback/feedback-attachment.tsx +0 -1239
  591. package/src/feedback/feedback-capture.ts +0 -287
  592. package/src/feedback/feedback-comment-thread.tsx +0 -353
  593. package/src/feedback/feedback-context-labels.ts +0 -11
  594. package/src/feedback/feedback-context.tsx +0 -245
  595. package/src/feedback/feedback-crash.ts +0 -547
  596. package/src/feedback/feedback-diagnostics.tsx +0 -41
  597. package/src/feedback/feedback-dialog-labels.ts +0 -29
  598. package/src/feedback/feedback-dialog.tsx +0 -452
  599. package/src/feedback/feedback-entry-file.tsx +0 -150
  600. package/src/feedback/feedback-inbox.tsx +0 -552
  601. package/src/feedback/feedback-labels.ts +0 -144
  602. package/src/feedback/feedback-menu-labels.ts +0 -12
  603. package/src/feedback/feedback-menu.tsx +0 -177
  604. package/src/feedback/feedback-mutation.ts +0 -20
  605. package/src/feedback/feedback-page-link.ts +0 -90
  606. package/src/feedback/feedback-public-labels.ts +0 -81
  607. package/src/feedback/feedback-public-list.tsx +0 -524
  608. package/src/feedback/feedback-public-switch.tsx +0 -102
  609. package/src/feedback/feedback-public-types.ts +0 -101
  610. package/src/feedback/feedback-record.ts +0 -428
  611. package/src/feedback/feedback-replies-context.ts +0 -9
  612. package/src/feedback/feedback-replies.tsx +0 -343
  613. package/src/feedback/feedback-rework-entry-chip.tsx +0 -18
  614. package/src/feedback/feedback-row-detail-labels.ts +0 -31
  615. package/src/feedback/feedback-row-detail.tsx +0 -871
  616. package/src/feedback/feedback-status-undo.ts +0 -109
  617. package/src/feedback/feedback-submit-dialog.tsx +0 -131
  618. package/src/feedback/feedback-submit.tsx +0 -270
  619. package/src/feedback/feedback-swipe.tsx +0 -192
  620. package/src/feedback/feedback-table-labels.ts +0 -27
  621. package/src/feedback/feedback-table.tsx +0 -912
  622. package/src/feedback/feedback-thread-labels.ts +0 -22
  623. package/src/feedback/feedback-thread-parts-labels.ts +0 -41
  624. package/src/feedback/feedback-thread.tsx +0 -905
  625. package/src/feedback/feedback-vocabulary.ts +0 -263
  626. package/src/feedback/feedback-vote-button.tsx +0 -124
  627. package/src/feedback.ts +0 -116
  628. package/src/hooks/use-anchored-panel.ts +0 -396
  629. package/src/hooks/use-anchored-rect.ts +0 -77
  630. package/src/hooks/use-announce.ts +0 -85
  631. package/src/hooks/use-authed-src.ts +0 -167
  632. package/src/hooks/use-body-scroll-lock.ts +0 -119
  633. package/src/hooks/use-breakpoint.ts +0 -133
  634. package/src/hooks/use-close-transition.ts +0 -107
  635. package/src/hooks/use-copy-to-clipboard.ts +0 -122
  636. package/src/hooks/use-debounce.ts +0 -114
  637. package/src/hooks/use-dismiss.ts +0 -371
  638. package/src/hooks/use-document-title.ts +0 -33
  639. package/src/hooks/use-file-drop.ts +0 -121
  640. package/src/hooks/use-file-picker-labels.ts +0 -28
  641. package/src/hooks/use-file-picker.tsx +0 -359
  642. package/src/hooks/use-focus-trap.ts +0 -199
  643. package/src/hooks/use-hotkey.ts +0 -212
  644. package/src/hooks/use-large-text.ts +0 -41
  645. package/src/hooks/use-long-press.ts +0 -140
  646. package/src/hooks/use-media-query.ts +0 -39
  647. package/src/hooks/use-mounted.ts +0 -39
  648. package/src/hooks/use-noindex.ts +0 -37
  649. package/src/hooks/use-overlay-history.ts +0 -714
  650. package/src/hooks/use-row-swipe.ts +0 -207
  651. package/src/hooks/use-search-param-state.ts +0 -434
  652. package/src/hooks/use-windowed-rows.ts +0 -225
  653. package/src/i18n/defaults.ts +0 -267
  654. package/src/i18n/german.ts +0 -2059
  655. package/src/i18n/kit-labels.tsx +0 -1003
  656. package/src/i18n/languages.ts +0 -349
  657. package/src/i18n/locales/de-CH.ts +0 -24
  658. package/src/i18n/locales/en.ts +0 -267
  659. package/src/i18n/locales/es.ts +0 -1999
  660. package/src/i18n/locales/fr.ts +0 -2037
  661. package/src/i18n/locales/hu.ts +0 -2004
  662. package/src/i18n/locales/it.ts +0 -2014
  663. package/src/i18n/locales/zh.ts +0 -1912
  664. package/src/i18n/plurals.ts +0 -86
  665. package/src/i18n/review.ts +0 -475
  666. package/src/i18n/shared-labels.ts +0 -138
  667. package/src/i18n/swiss.ts +0 -29
  668. package/src/index.ts +0 -1191
  669. package/src/landing/access.ts +0 -93
  670. package/src/landing/landing-actions.tsx +0 -97
  671. package/src/landing/landing-labels.ts +0 -59
  672. package/src/landing/landing-sections.tsx +0 -341
  673. package/src/landing/page-seo.ts +0 -261
  674. package/src/landing/public-header.tsx +0 -121
  675. package/src/landing/public-page.tsx +0 -106
  676. package/src/landing/routing.tsx +0 -225
  677. package/src/lib/broadcast.ts +0 -52
  678. package/src/lib/calc.ts +0 -323
  679. package/src/lib/chip-edge-snap.ts +0 -212
  680. package/src/lib/clipboard-minus.ts +0 -107
  681. package/src/lib/clipping.ts +0 -34
  682. package/src/lib/cn.ts +0 -28
  683. package/src/lib/column-mapping.ts +0 -234
  684. package/src/lib/countries.ts +0 -91
  685. package/src/lib/data-attributes.ts +0 -14
  686. package/src/lib/date-format.ts +0 -227
  687. package/src/lib/dates.ts +0 -288
  688. package/src/lib/day-format.ts +0 -96
  689. package/src/lib/decimal-marks.ts +0 -108
  690. package/src/lib/describe-failure.ts +0 -18
  691. package/src/lib/device-settings.ts +0 -147
  692. package/src/lib/direction.ts +0 -74
  693. package/src/lib/document-navigation.ts +0 -17
  694. package/src/lib/document-title.ts +0 -41
  695. package/src/lib/download.ts +0 -172
  696. package/src/lib/float-clearance.ts +0 -70
  697. package/src/lib/floating-stack.ts +0 -70
  698. package/src/lib/focus-left.ts +0 -156
  699. package/src/lib/format.ts +0 -585
  700. package/src/lib/http-status.ts +0 -38
  701. package/src/lib/iban.ts +0 -251
  702. package/src/lib/ime.ts +0 -24
  703. package/src/lib/intl-cache.ts +0 -27
  704. package/src/lib/iso-day.ts +0 -13
  705. package/src/lib/lazy-with-fallback.ts +0 -82
  706. package/src/lib/logger.ts +0 -69
  707. package/src/lib/minus.ts +0 -50
  708. package/src/lib/path-pattern.ts +0 -55
  709. package/src/lib/person-name.ts +0 -155
  710. package/src/lib/phone.ts +0 -208
  711. package/src/lib/plain-text.ts +0 -22
  712. package/src/lib/presence.ts +0 -18
  713. package/src/lib/qr-encode.ts +0 -444
  714. package/src/lib/quiet-focus.ts +0 -32
  715. package/src/lib/reduced-motion.ts +0 -22
  716. package/src/lib/refs.ts +0 -22
  717. package/src/lib/round.ts +0 -43
  718. package/src/lib/safe-storage.ts +0 -119
  719. package/src/lib/server-wake.ts +0 -315
  720. package/src/lib/session-refresh.ts +0 -472
  721. package/src/lib/share-format.ts +0 -18
  722. package/src/lib/status-tone.ts +0 -43
  723. package/src/lib/strip-fade.ts +0 -287
  724. package/src/lib/table-text.ts +0 -554
  725. package/src/lib/text-case.ts +0 -19
  726. package/src/lib/text-match.ts +0 -169
  727. package/src/lib/thenable.ts +0 -19
  728. package/src/lib/translation-review.ts +0 -769
  729. package/src/notifications/device-zone-report.ts +0 -67
  730. package/src/notifications/feedback-notification-types-labels.ts +0 -33
  731. package/src/notifications/feedback-notification-types.ts +0 -71
  732. package/src/notifications/notification-bell.tsx +0 -119
  733. package/src/notifications/notification-inbox.tsx +0 -309
  734. package/src/notifications/notification-parts.tsx +0 -81
  735. package/src/notifications/notification-types-setting.tsx +0 -406
  736. package/src/notifications/notification-types.ts +0 -89
  737. package/src/notifications/notifications-labels.ts +0 -287
  738. package/src/notifications/push-device-setting.tsx +0 -230
  739. package/src/notifications/push-devices-setting.tsx +0 -374
  740. package/src/notifications/push-worker.ts +0 -168
  741. package/src/notifications/quiet-hours-setting.tsx +0 -238
  742. package/src/notifications/unsubscribe-panel.tsx +0 -200
  743. package/src/notifications/use-push-device.ts +0 -448
  744. package/src/offline/local-first.ts +0 -100
  745. package/src/offline/pwa-update-prompt-labels.ts +0 -9
  746. package/src/offline/pwa-update-prompt.tsx +0 -78
  747. package/src/offline/query-persistence.ts +0 -391
  748. package/src/offline/service-worker-updates.ts +0 -81
  749. package/src/offline/shared-computer-labels.ts +0 -8
  750. package/src/offline/shared-computer.tsx +0 -87
  751. package/src/offline/sign-out-pending-dialog-labels.ts +0 -21
  752. package/src/offline/sign-out-pending-dialog.tsx +0 -135
  753. package/src/offline.ts +0 -37
  754. package/src/push-worker.ts +0 -25
  755. package/src/rhf/fields.tsx +0 -2187
  756. package/src/rhf/form-core.tsx +0 -324
  757. package/src/rhf/form.tsx +0 -12
  758. package/src/rhf/line-items.tsx +0 -135
  759. package/src/rhf/use-rhf-wizard-step.ts +0 -104
  760. package/src/rhf.ts +0 -21
  761. package/src/search/command-palette-labels.ts +0 -16
  762. package/src/search/command-palette.tsx +0 -624
  763. package/src/search/global-search-labels.ts +0 -13
  764. package/src/search/global-search.tsx +0 -660
  765. package/src/search/search-index.ts +0 -283
  766. package/src/search/use-command-key.ts +0 -23
  767. package/src/search.ts +0 -14
  768. package/src/settings/device-reset-setting-labels.ts +0 -20
  769. package/src/settings/device-reset-setting.tsx +0 -116
  770. package/src/settings/settings-card-classes.ts +0 -11
  771. package/src/settings/settings-catalogue.ts +0 -150
  772. package/src/settings/settings-context.ts +0 -33
  773. package/src/settings/settings-heading.tsx +0 -67
  774. package/src/settings/settings-labels.ts +0 -87
  775. package/src/settings/settings-layout.tsx +0 -471
  776. package/src/settings/settings-section.tsx +0 -108
  777. package/src/settings/use-account-appearance.ts +0 -148
  778. package/src/settings/use-account-language.ts +0 -146
  779. package/src/settings/use-settings-focus.ts +0 -128
  780. package/src/settings/use-settings-route.ts +0 -258
  781. package/src/shell/account-menu-language.tsx +0 -130
  782. package/src/shell/account-menu-text-size.tsx +0 -80
  783. package/src/shell/admin-menu.tsx +0 -183
  784. package/src/shell/app-shell-labels.ts +0 -11
  785. package/src/shell/app-shell.tsx +0 -1560
  786. package/src/shell/auth-layout.tsx +0 -186
  787. package/src/shell/company-switcher-labels.ts +0 -13
  788. package/src/shell/company-switcher.tsx +0 -136
  789. package/src/shell/dev-menu.tsx +0 -257
  790. package/src/shell/fill-height.tsx +0 -45
  791. package/src/shell/language-code.ts +0 -5
  792. package/src/shell/option-switcher-menu.tsx +0 -84
  793. package/src/shell/sync-status-indicator.tsx +0 -303
  794. package/src/shell/top-bar-actions.tsx +0 -87
  795. package/src/shell/top-bar-brand.tsx +0 -78
  796. package/src/shell/top-bar-parts-labels.ts +0 -148
  797. package/src/shell/top-bar.tsx +0 -40
  798. package/src/shell/topbar-action-menu.tsx +0 -567
  799. package/src/shell/topbar-controls.tsx +0 -269
  800. package/src/shell/tour-menu.tsx +0 -187
  801. package/src/shell.ts +0 -108
  802. package/src/sync/db.ts +0 -129
  803. package/src/sync/engine.ts +0 -1011
  804. package/src/sync/hooks.ts +0 -98
  805. package/src/sync/testing.ts +0 -73
  806. package/src/sync/wire.ts +0 -61
  807. package/src/sync.ts +0 -37
  808. package/src/table-text.ts +0 -8
  809. package/src/testing/css-variables.generated.ts +0 -112
  810. package/src/testing/css-variables.ts +0 -189
  811. package/src/testing/index.ts +0 -29
  812. package/src/testing/react.ts +0 -58
  813. package/src/testing/tour.ts +0 -41
  814. package/src/testing/viewport.ts +0 -357
  815. package/src/theme/chart-palette.ts +0 -232
  816. package/src/theme/color.ts +0 -272
  817. package/src/theme/contrast-tokens.ts +0 -268
  818. package/src/theme/contrast.ts +0 -250
  819. package/src/theme/palette-derive.ts +0 -825
  820. package/src/theme/palette-presets.ts +0 -544
  821. package/src/theme/palette-store.ts +0 -108
  822. package/src/theme/text-size.ts +0 -289
  823. package/src/theme/theme-store.ts +0 -157
  824. package/src/tour/tour-catalogue-labels.ts +0 -75
  825. package/src/tour/tour-catalogue.tsx +0 -335
  826. package/src/tour/tour-dock.ts +0 -134
  827. package/src/tour/tour-engine.ts +0 -37
  828. package/src/tour/tour-gates.ts +0 -218
  829. package/src/tour/tour-guide-button.tsx +0 -64
  830. package/src/tour/tour-guide-labels.ts +0 -15
  831. package/src/tour/tour-info.ts +0 -144
  832. package/src/tour/tour-labels.ts +0 -23
  833. package/src/tour/tour-overlay.tsx +0 -1170
  834. package/src/tour/tour.tsx +0 -750
  835. package/src/tour/use-tour-progress.ts +0 -671
  836. package/src/tour/use-tour-url-sync.ts +0 -266
  837. package/src/tour.ts +0 -21
  838. package/src/vite-env.d.ts +0 -23
  839. package/src/wizard/stepper-nav.tsx +0 -360
  840. package/src/wizard/types.ts +0 -275
  841. package/src/wizard/use-wizard.ts +0 -560
  842. package/src/wizard/validation.ts +0 -39
  843. package/src/wizard/wizard-context.tsx +0 -74
  844. package/src/wizard/wizard-labels.ts +0 -29
  845. package/src/wizard/wizard-step.tsx +0 -76
  846. package/src/wizard/wizard-summary.tsx +0 -84
  847. package/src/wizard.ts +0 -15
@@ -1,825 +0,0 @@
1
- import type { ThemeMode } from "./theme-store";
2
- import type { TokenSet } from "./palette-presets";
3
- import type { HeatStops } from "./chart-palette";
4
- import {
5
- contrast,
6
- deltaE,
7
- toHex,
8
- hexToOklch,
9
- oklchToHex,
10
- parseHex,
11
- rgbToOklch,
12
- simulateCvd,
13
- solveLightness,
14
- } from "./color";
15
- import type { CvdType, Oklch } from "./color";
16
- import type { ContrastLevel } from "./contrast";
17
- import { brandSoft, contrastStep, hoverFill, steppedWellFill, WELL_STEP_MIN } from "./contrast-tokens";
18
-
19
- /**
20
- * Build a whole palette from one brand colour, plus any number of colours pinned by
21
- * hand, with every contrast ratio SOLVED rather than chosen and then hoped for.
22
- *
23
- * The presets this package shipped were assembled by eye and annotated with the ratios
24
- * they were believed to hold — `tokens.css` records "7.0:1 and 4.8:1", and
25
- * `palette-presets.ts` records "2.67:1 … lifted they clear it at 3.30:1". Nothing
26
- * computed any of them, and the audit found four of the nine default light chart hues
27
- * below the 3:1 that WCAG 1.4.11 requires of a graphical object. A comment is not a
28
- * test. Everything here is derived to a target and then measured, and
29
- * {@link auditPalette} returns the measurements so a caller can refuse a palette that
30
- * does not hold up.
31
- *
32
- * WHAT IS DERIVED AND WHAT IS NOT. The UI palette and the CATEGORICAL CHART RAMP solve
33
- * different problems and are deliberately kept apart. A UI colour needs contrast against
34
- * one known surface and carries a fixed meaning; a chart colour needs to stay separable
35
- * from eight unknown siblings, at roughly equal salience, with no implied order.
36
- * Optimising a set for one makes it worse at the other, which is why `deriveTokenSet`
37
- * leaves `chart` alone unless you explicitly ask for {@link deriveChartRamp}.
38
- */
39
-
40
- /* ── Inputs ───────────────────────────────────────────────────────────────── */
41
-
42
- /** A role whose hue may be pinned by the caller instead of chosen by the deriver. */
43
- export type AnchorRole = "brand" | "accent" | "danger" | "warning" | "success" | "info";
44
-
45
- export type PaletteAnchors = { brand: string } & Partial<Record<Exclude<AnchorRole, "brand">, string>>;
46
-
47
- export interface DeriveOptions {
48
- anchors: PaletteAnchors;
49
- mode: ThemeMode;
50
- /**
51
- * How strongly the surfaces carry the brand's hue, 0–1 of the maximum useful tint.
52
- * 0 gives neutral greys; the shipped default is a visible warmth, because a page that
53
- * is very slightly the brand's hue reads as considered where a pure grey reads as
54
- * unstyled. Above ~0.5 the surfaces start competing with the content.
55
- */
56
- surfaceTint?: number;
57
- /** Contrast targets for the three text roles against the WORST surface. */
58
- textContrast?: { primary?: number; secondary?: number; muted?: number };
59
- }
60
-
61
- /* ── Outputs ──────────────────────────────────────────────────────────────── */
62
-
63
- /** The semantic layer, which lives in tokens.css rather than in `TokenSet`. */
64
- export interface SemanticTokens {
65
- danger: string;
66
- dangerHover: string;
67
- dangerContrast: string;
68
- dangerBorder: string;
69
- /** The error line (invalid field, danger banner, destructive focus ring): as loud as
70
- * `dangerBorder` was before 0.15.5, so it keeps 3:1 against the surface. */
71
- dangerBorderStrong: string;
72
- dangerBg: string;
73
- warning: string;
74
- warningBorder: string;
75
- warningBg: string;
76
- info: string;
77
- infoBorder: string;
78
- infoBg: string;
79
- success: string;
80
- successBorder: string;
81
- successBg: string;
82
- /** Present only when a `accent` (secondary brand) anchor was supplied. */
83
- accent?: string;
84
- accentContrast?: string;
85
- accentBg?: string;
86
- }
87
-
88
- export interface ContrastCheck {
89
- /** e.g. "textMuted on bgPage". */
90
- pair: string;
91
- ratio: number;
92
- /** What WCAG asks of this pair. */
93
- required: number;
94
- /** Which rule the requirement comes from, for a reader who wants to argue with it. */
95
- rule: string;
96
- passes: boolean;
97
- }
98
-
99
- export interface ContrastReport {
100
- checks: ContrastCheck[];
101
- failures: ContrastCheck[];
102
- passes: boolean;
103
- }
104
-
105
- export interface DerivedPalette {
106
- tokens: TokenSet;
107
- semantic: SemanticTokens;
108
- /** {@link auditPalette} at both contrast levels: the More-contrast checks carry a
109
- * " (More contrast)" suffix (0.36). */
110
- audit: ContrastReport;
111
- /** Compromises the deriver had to make, in plain words. Never silent. */
112
- warnings: string[];
113
- }
114
-
115
- /* ── The hue homes ────────────────────────────────────────────────────────── */
116
-
117
- /**
118
- * Where each semantic role wants to sit, and how far it may be pushed.
119
- *
120
- * A semantic colour is a convention before it is an aesthetic: danger is red because
121
- * every other interface the user has ever used made it red, and a "danger" button in
122
- * the brand's teal is a worse button however well it matches. So each role has a home
123
- * hue and a narrow licence to move — enough to get out of the brand's way when the
124
- * brand happens to live in the same neighbourhood, not enough to stop meaning what it
125
- * means. If it cannot get far enough, that is a warning, not a silent compromise.
126
- */
127
- const HUE_HOME: Record<Exclude<AnchorRole, "brand" | "accent">, { hue: number; slack: number }> = {
128
- danger: { hue: 27, slack: 14 },
129
- warning: { hue: 75, slack: 16 },
130
- success: { hue: 150, slack: 20 },
131
- info: { hue: 240, slack: 22 },
132
- };
133
-
134
- /** Circular distance between two hue angles, 0–180. */
135
- function hueGap(a: number, b: number): number {
136
- const d = Math.abs(((a - b) % 360) + 360) % 360;
137
- return d > 180 ? 360 - d : d;
138
- }
139
-
140
- /**
141
- * Nudge `home` within `slack` to maximise the distance from every taken hue.
142
- *
143
- * Sampled rather than solved: the objective is a min-of-distances over a handful of
144
- * points on a short arc, which is piecewise-linear with kinks wherever the nearest
145
- * neighbour changes. Gradient methods stall on those kinks; 2° steps over a ±22° arc is
146
- * 23 evaluations of some trigonometry and cannot stall.
147
- */
148
- function placeHue(home: number, slack: number, taken: number[]): number {
149
- let best = home;
150
- let bestGap = Math.min(...taken.map((t) => hueGap(home, t)), 360);
151
- for (let d = -slack; d <= slack; d += 2) {
152
- const h = (home + d + 360) % 360;
153
- const gap = Math.min(...taken.map((t) => hueGap(h, t)), 360);
154
- // Ties go to the hue nearest home: a role should move only as far as it must.
155
- if (gap > bestGap + 1e-9) {
156
- best = h;
157
- bestGap = gap;
158
- }
159
- }
160
- return best;
161
- }
162
-
163
- /* ── Derivation ───────────────────────────────────────────────────────────── */
164
-
165
- const SURFACE_L = {
166
- // Light: the PAGE is slightly darker than the cards on it, so a card reads as raised
167
- // without needing a shadow to say so. Matches the shipped presets' relationship.
168
- //
169
- // The light WELL is the page itself (0.33, docs/colour-roles-harmonization.md §5.3,
170
- // k26). Between the card and the page it sat 1.02–1.05:1 from the card it is inset
171
- // in, which is no well at all; at the page's lightness it stands out from the card
172
- // exactly as far as the card does from the page, and nothing re-solves, because the
173
- // page is already the surface every text role is solved against. Dark keeps its
174
- // well a step lighter than the card (1.11–1.13:1).
175
- light: { page: 0.912, surface: 0.945, surface2: 0.912 },
176
- dark: { page: 0.158, surface: 0.206, surface2: 0.249 },
177
- } as const;
178
-
179
- /**
180
- * What a hairline has to clear against the surface it divides.
181
- *
182
- * WCAG has nothing to say here — a decorative border is not a graphical object that
183
- * conveys information — so this is a house rule, and it is deliberately low. A border
184
- * that clears 3:1 is a RULE, not a hairline: it draws the eye to the box instead of to
185
- * what is in it. 1.5:1 is the point at which the edge is reliably findable without
186
- * becoming part of the composition.
187
- */
188
- const BORDER_CONTRAST = 1.5;
189
-
190
- /** The most tint a surface can carry before it stops reading as a neutral ground. */
191
- const MAX_SURFACE_CHROMA = 0.034;
192
-
193
- /**
194
- * The brand chroma from which the surfaces and the greys carry the brand's hue in full;
195
- * below it they carry it in proportion, down to none for a grey (round 0.34 BUG-8). A
196
- * grey has no hue — OKLCH reports 0, which is pink — and at full tint #808080 painted
197
- * every surface #eddde1.
198
- */
199
- const FULL_HUE_CHROMA = 0.06;
200
-
201
- /** How much of the brand's hue the neutrals may carry: 0 for a grey, 1 from {@link FULL_HUE_CHROMA}. */
202
- function hueWeight(brand: Oklch): number {
203
- return Math.min(1, brand.c / FULL_HUE_CHROMA);
204
- }
205
-
206
- function surfaceSet(hue: number, mode: ThemeMode, tint: number, weight: number) {
207
- const c = MAX_SURFACE_CHROMA * Math.max(0, Math.min(1, tint)) * weight;
208
- const L = SURFACE_L[mode];
209
- const bgPage = oklchToHex({ l: L.page, c, h: hue });
210
- const bgSurface = oklchToHex({ l: L.surface, c, h: hue });
211
- const bgSurface2 = oklchToHex({ l: L.surface2, c, h: hue });
212
- // Solved, not guessed: a fixed lightness that looks right against a pale warm ground
213
- // disappears against a deep cold one, and both are reachable from the same `hue`
214
- // input. The border carries a little more chroma than the surfaces because at these
215
- // lightnesses a perfectly neutral hairline on a tinted ground reads as a wrong grey.
216
- const borderChroma = c * 1.6;
217
- // Solved against the surface the hairline is HARDEST to see on, not against one of
218
- // the three. Solving against `bgSurface` alone left it at 1.36:1 on `bgPage`, so the
219
- // target and the audit disagreed about the same border.
220
- const hardest = [bgPage, bgSurface, bgSurface2].reduce((a, b) =>
221
- contrast(a, mode === "light" ? "#000000" : "#ffffff") < contrast(b, mode === "light" ? "#000000" : "#ffffff")
222
- ? a
223
- : b,
224
- );
225
- const borderL = solveLightness(
226
- BORDER_CONTRAST,
227
- parseHex(hardest)!,
228
- hue,
229
- borderChroma,
230
- mode === "light" ? "darker" : "lighter",
231
- );
232
- return {
233
- bgPage,
234
- bgSurface,
235
- bgSurface2,
236
- border: oklchToHex({ l: borderL, c: borderChroma, h: hue }),
237
- };
238
- }
239
-
240
- /** Solve a colour at this hue that clears `target` against `against`, keeping chroma. */
241
- function solveAgainst(hue: number, chroma: number, target: number, against: string, mode: ThemeMode): string {
242
- const bg = parseHex(against)!;
243
- const l = solveLightness(target, bg, hue, chroma, mode === "light" ? "darker" : "lighter");
244
- return oklchToHex({ l, c: chroma, h: hue });
245
- }
246
-
247
- /** Whichever of near-white / near-black reads better ON `fill`. */
248
- function contrastOn(fill: string): string {
249
- const light = "#ffffff";
250
- const dark = "#12100e";
251
- return contrast(fill, light) >= contrast(fill, dark) ? light : dark;
252
- }
253
-
254
- /** A soft tint of `hue` sitting on the surface — a badge fill, not a button fill. */
255
- function tintOn(hue: number, chroma: number, surface: string, mode: ThemeMode): string {
256
- const s = hexToOklch(surface)!;
257
- // Toward the colour, but only far enough to be seen: these back TEXT of the same hue,
258
- // and a strong tint leaves the text nowhere to go.
259
- const l = mode === "light" ? s.l - 0.055 : s.l + 0.055;
260
- return oklchToHex({ l, c: Math.min(chroma * 0.45, 0.06), h: hue });
261
- }
262
-
263
- export function derivePalette({ anchors, mode, surfaceTint = 0.55, textContrast }: DeriveOptions): DerivedPalette {
264
- const warnings: string[] = [];
265
- const brand = hexToOklch(anchors.brand);
266
- if (!brand) {
267
- throw new Error(
268
- `derivePalette: brand "${anchors.brand}" is not a #rgb or #rrggbb colour. ` +
269
- `Anchors must be hex — a named colour or an rgba() string cannot be converted.`,
270
- );
271
- }
272
-
273
- const targets = { primary: 10, secondary: 7, muted: 4.6, ...textContrast };
274
-
275
- // ── Surfaces, from the brand's hue.
276
- const weight = hueWeight(brand);
277
- const surfaces = surfaceSet(brand.h, mode, surfaceTint, weight);
278
- // Every text role is solved against the WORST of the three, so a token is legible
279
- // wherever it lands. Solving against `bgSurface` alone is the mistake that makes a
280
- // muted label fail on the page background it also sits on.
281
- const worstSurface = [surfaces.bgPage, surfaces.bgSurface, surfaces.bgSurface2].reduce((a, b) =>
282
- contrast(a, mode === "light" ? "#000000" : "#ffffff") < contrast(b, mode === "light" ? "#000000" : "#ffffff")
283
- ? a
284
- : b,
285
- );
286
-
287
- // ── Text. A trace of the brand hue keeps the greys from reading cold on a warm page.
288
- const textChroma = 0.014 * weight;
289
- const textPrimary = solveAgainst(brand.h, textChroma, targets.primary, worstSurface, mode);
290
- const textSecondary = solveAgainst(brand.h, textChroma, targets.secondary, worstSurface, mode);
291
- const textMuted = solveAgainst(brand.h, textChroma, targets.muted, worstSurface, mode);
292
-
293
- // The darkest fill text sits on (the lightest, in dark): the worst surface, or a
294
- // hovered row on the card (`--bg-hover`), which in light is a shade darker than the
295
- // page. The colours that are solved exactly to 4.5:1 — money, the semantic text — are
296
- // solved against this, so they hold on a hovered row too (0.33, §12.10). The text
297
- // roles above keep their margin (4.6:1 and up) and need no second solve.
298
- const hover = hoverFill({ textPrimary, bgSurface: surfaces.bgSurface });
299
- const worstText = [worstSurface, hover].reduce((a, b) =>
300
- contrast(a, mode === "light" ? "#000000" : "#ffffff") < contrast(b, mode === "light" ? "#000000" : "#ffffff")
301
- ? a
302
- : b,
303
- );
304
-
305
- // ── Brand. Keep the hue the caller asked for; move only the lightness, and only as
306
- // far as 3:1 against the worst surface — WCAG 1.4.11, since a brand-filled control is
307
- // a graphical object whose boundary has to be perceivable.
308
- //
309
- // In light the worst surface includes More contrast's well (0.36, colour-roles §13.4):
310
- // 10 % ink into the card, darker than the page. The step is applied, not derived, but
311
- // the brand is not stepped, so both brand solves measure there too and a derived
312
- // palette holds at both levels.
313
- const moreWell = steppedWellFill({ textPrimary, bgSurface: surfaces.bgSurface });
314
- const brandGround = moreWell
315
- ? [worstSurface, moreWell].reduce((a, b) => (contrast(a, "#000000") < contrast(b, "#000000") ? a : b))
316
- : worstSurface;
317
- const brandChroma = Math.max(brand.c, 0.06);
318
- const brandRatio = contrast(anchors.brand, brandGround);
319
- // NORMALISED, never the caller's raw string. `parseHex` accepts "4f46e5" and "#abc",
320
- // and passing either through unchanged put a value in the TokenSet that is not a CSS
321
- // colour — it then fails silently at paint time, three layers from here.
322
- let brandHex =
323
- brandRatio >= 3 ? toHex(parseHex(anchors.brand)!) : solveAgainst(brand.h, brandChroma, 3, brandGround, mode);
324
- if (brandRatio < 3) {
325
- warnings.push(
326
- `brand ${anchors.brand} sits at ${brandRatio.toFixed(2)}:1 against the ${mode} surfaces, ` +
327
- `below the 3:1 WCAG 1.4.11 asks of a control boundary. Lightness was adjusted to ` +
328
- `${brandHex}; hue and chroma are unchanged.`,
329
- );
330
- }
331
- // `--brand-muted` is the brand AS TEXT — a soft brand chip's label, an outline chip, a
332
- // current link — and tokens.css derives it: 62 % brand into the ink. A brand solved
333
- // to 3:1 left it at 4.43–4.51:1 in three dark presets (0.33, §5.5), so it gets the
334
- // text floor here: the brand moves away from the surfaces, a step at a time, until its
335
- // muted form clears 4.5:1 on the worst fill and on its own soft chip, at rest
336
- // (`--brand-bg`) and hovered (`--brand-bg-hover`, the harder of the two: §12.11).
337
- const brandMutedWorst = (hex: string) => {
338
- const soft = brandSoft({ brand: hex, textPrimary, bgSurface: surfaces.bgSurface });
339
- return Math.min(
340
- contrast(soft.brandMuted, worstText),
341
- contrast(soft.brandMuted, soft.brandBg),
342
- contrast(soft.brandMuted, soft.brandBgHover),
343
- // …and on More contrast's light well, where a link button reads it (§13.3).
344
- moreWell ? contrast(soft.brandMuted, moreWell) : Infinity,
345
- );
346
- };
347
- for (let i = 0; i < 40 && brandMutedWorst(brandHex) < 4.5; i++) {
348
- const lch = hexToOklch(brandHex)!;
349
- brandHex = oklchToHex({ ...lch, l: mode === "light" ? lch.l - 0.005 : lch.l + 0.005 });
350
- }
351
- if (brandMutedWorst(brandHex) < 4.5) {
352
- warnings.push(
353
- `the brand as text (--brand-muted) reaches only ${brandMutedWorst(brandHex).toFixed(2)}:1 ` +
354
- `against the ${mode} surfaces (needs 4.5:1).`,
355
- );
356
- }
357
- const brandLch = hexToOklch(brandHex)!;
358
- const brandContrast = contrastOn(brandHex);
359
- const brandHover = oklchToHex({
360
- ...brandLch,
361
- // Hover moves AWAY from the colour of the text on it (0.33, §5.5): darker under
362
- // white, lighter under a dark ink. It used to move away from the page, which in dark
363
- // lightened a fill that carries WHITE text, toward its own label: 4.07:1.
364
- l: brandContrast === "#ffffff" ? brandLch.l - 0.06 : brandLch.l + 0.06,
365
- });
366
- const onBrand = contrast(brandHex, brandContrast);
367
- if (onBrand < 4.5) {
368
- warnings.push(
369
- `text on the brand fill reaches only ${onBrand.toFixed(2)}:1 (needs 4.5:1). ` +
370
- `A mid-lightness, high-chroma brand cannot carry legible text at any ink; ` +
371
- `use it as an accent and keep primary buttons on a darker or lighter variant.`,
372
- );
373
- }
374
-
375
- // ── Semantic roles. Anchors are honoured exactly; the rest are placed away from the
376
- // brand and from each other, within each role's licence to move.
377
- const taken: number[] = [brandLch.h];
378
- const accentLch = anchors.accent ? hexToOklch(anchors.accent) : null;
379
- if (anchors.accent && !accentLch) {
380
- warnings.push(`accent "${anchors.accent}" is not a hex colour and was ignored.`);
381
- }
382
- if (accentLch) taken.push(accentLch.h);
383
-
384
- const semanticHue = {} as Record<Exclude<AnchorRole, "brand" | "accent">, number>;
385
- const semanticChroma = {} as Record<Exclude<AnchorRole, "brand" | "accent">, number>;
386
- for (const role of ["danger", "warning", "success", "info"] as const) {
387
- const pinned = anchors[role] ? hexToOklch(anchors[role]!) : null;
388
- if (anchors[role] && !pinned) {
389
- warnings.push(`${role} "${anchors[role]}" is not a hex colour and was ignored.`);
390
- }
391
- const home = HUE_HOME[role];
392
- const hue = pinned ? pinned.h : placeHue(home.hue, home.slack, taken);
393
- if (!pinned) {
394
- const gap = Math.min(...taken.map((t) => hueGap(hue, t)));
395
- if (gap < 20) {
396
- warnings.push(
397
- `${role} could only reach ${gap.toFixed(0)}° from the nearest pinned hue, which is ` +
398
- `too close to tell apart at a glance. Pin ${role} explicitly, or move the brand.`,
399
- );
400
- }
401
- }
402
- semanticHue[role] = hue;
403
- semanticChroma[role] = pinned ? Math.max(pinned.c, 0.08) : 0.13;
404
- taken.push(hue);
405
- }
406
-
407
- /**
408
- * A semantic colour has two jobs and therefore two backgrounds: plain text on the
409
- * page, and the label inside its own tinted badge. The badge is the harder of the
410
- * two — it is a step toward the colour — so solving only against the surface produced
411
- * a badge at 4.1:1 while the loose text passed, which is the failure mode that is
412
- * hardest to notice because nine tenths of the uses look fine.
413
- */
414
- const sem = (role: Exclude<AnchorRole, "brand" | "accent">) => {
415
- const hue = semanticHue[role];
416
- const chroma = semanticChroma[role];
417
- const bg = tintOn(hue, chroma, surfaces.bgSurface, mode);
418
- const onSurface = solveLightness(4.5, parseHex(worstText)!, hue, chroma, mode === "light" ? "darker" : "lighter");
419
- const onTint = solveLightness(4.5, parseHex(bg)!, hue, chroma, mode === "light" ? "darker" : "lighter");
420
- const l = mode === "light" ? Math.min(onSurface, onTint) : Math.max(onSurface, onTint);
421
- return oklchToHex({ l, c: chroma, h: hue });
422
- };
423
-
424
- const danger = sem("danger");
425
- const dangerLch = hexToOklch(danger)!;
426
- const semantic: SemanticTokens = {
427
- danger,
428
- dangerHover: oklchToHex({
429
- ...dangerLch,
430
- l: mode === "light" ? dangerLch.l - 0.06 : dangerLch.l + 0.06,
431
- }),
432
- dangerContrast: contrastOn(danger),
433
- // The tone border follows its siblings' lightness in dark mode (warning 0.44, info
434
- // and success 0.45) — a soft frame; the strong line keeps the old, louder recipe.
435
- dangerBorder: oklchToHex({
436
- l: mode === "light" ? dangerLch.l + 0.22 : 0.45,
437
- c: semanticChroma.danger,
438
- h: semanticHue.danger,
439
- }),
440
- dangerBorderStrong: oklchToHex({
441
- l: mode === "light" ? dangerLch.l + 0.22 : dangerLch.l - 0.22,
442
- c: semanticChroma.danger,
443
- h: semanticHue.danger,
444
- }),
445
- dangerBg: tintOn(semanticHue.danger, semanticChroma.danger, surfaces.bgSurface, mode),
446
- warning: sem("warning"),
447
- warningBorder: oklchToHex({
448
- l: mode === "light" ? 0.82 : 0.44,
449
- c: semanticChroma.warning,
450
- h: semanticHue.warning,
451
- }),
452
- warningBg: tintOn(semanticHue.warning, semanticChroma.warning, surfaces.bgSurface, mode),
453
- info: sem("info"),
454
- infoBorder: oklchToHex({
455
- l: mode === "light" ? 0.8 : 0.45,
456
- c: semanticChroma.info,
457
- h: semanticHue.info,
458
- }),
459
- infoBg: tintOn(semanticHue.info, semanticChroma.info, surfaces.bgSurface, mode),
460
- success: sem("success"),
461
- successBorder: oklchToHex({
462
- l: mode === "light" ? 0.81 : 0.45,
463
- c: semanticChroma.success,
464
- h: semanticHue.success,
465
- }),
466
- successBg: tintOn(semanticHue.success, semanticChroma.success, surfaces.bgSurface, mode),
467
- };
468
-
469
- if (accentLch) {
470
- const accent = solveAgainst(accentLch.h, Math.max(accentLch.c, 0.06), 3, worstSurface, mode);
471
- semantic.accent = accent;
472
- semantic.accentContrast = contrastOn(accent);
473
- semantic.accentBg = tintOn(accentLch.h, Math.max(accentLch.c, 0.06), surfaces.bgSurface, mode);
474
- }
475
-
476
- // ── Money. A THIRD system again: these are data colours with fixed meanings, and the
477
- // one rule that outranks everything is that income and expense must never be the
478
- // red/green pair — which is why the shipped presets use teal/amber/violet. Derived
479
- // here at fixed hues rather than from the brand, for the same reason `--danger` is:
480
- // a consumer who rebrands does not thereby change what "money out" looks like.
481
- const money = (hue: number, target: number) => solveAgainst(hue, 0.12, target, worstText, mode);
482
- const moneyIncome = money(175, 4.5);
483
- const moneyExpense = money(70, 4.5);
484
- const moneyNet = money(300, 4.5);
485
- // "No money has moved": a quiet grey at a fixed lightness, but printed as TEXT (the
486
- // numpad's sign, a future row's figure), so it gets the text floor too (0.33). The
487
- // fixed lightness left it at 4.24:1 on four light pages.
488
- const neutralChroma = 0.012 * weight;
489
- const neutralFloor = solveLightness(
490
- 4.5,
491
- parseHex(worstText)!,
492
- brand.h,
493
- neutralChroma,
494
- mode === "light" ? "darker" : "lighter",
495
- );
496
- const moneyNeutral = oklchToHex({
497
- l: mode === "light" ? Math.min(0.52, neutralFloor) : Math.max(0.72, neutralFloor),
498
- c: neutralChroma,
499
- h: brand.h,
500
- });
501
-
502
- const tokens: TokenSet = {
503
- ...surfaces,
504
- textPrimary,
505
- textSecondary,
506
- textMuted,
507
- brand: brandHex,
508
- brandHover,
509
- brandContrast,
510
- moneyIncome,
511
- moneyExpense,
512
- moneyNet,
513
- moneyNeutral,
514
- // Left alone. See the note at the top of this file about why the categorical ramp is
515
- // not derived from the brand unless the caller asks.
516
- //
517
- // ⚠️ EMPTY, not absent: a caller who hands this straight to `applyTokenSet` keeps
518
- // whatever `--chart-1…9` were already on the element. That is deliberate — the ramp
519
- // is a separate decision and clearing it would leave charts unpainted — but it means
520
- // a derived palette applied over another preset is a MIX until you also supply a
521
- // ramp. `deriveChartRamp` is how you supply one.
522
- chart: [],
523
- heat: deriveHeat(moneyIncome, moneyExpense, surfaces, mode),
524
- };
525
-
526
- // Audited at both contrast levels (0.36, colour-roles §13.5): More contrast steps the
527
- // text, the border and, in light, the well and money of this set. The derived semantic
528
- // colours are audited at Standard only: they are solved for the standard grounds, and
529
- // only tokens.css's shipped literals step for the darker well.
530
- const standard = auditPalette(tokens, semantic);
531
- const more = auditPalette(tokens, undefined, { level: "more" });
532
- const checks = [...standard.checks, ...more.checks];
533
- const failures = checks.filter((c) => !c.passes);
534
- return { tokens, semantic, audit: { checks, failures, passes: failures.length === 0 }, warnings };
535
- }
536
-
537
- /**
538
- * Heatmap stops, reusing the money pair.
539
- *
540
- * `under` is the good direction and `over` the bad one, at the SAME hues as
541
- * `moneyIncome`/`moneyExpense` — so a heatmap cell and the figure printed beside it
542
- * agree about which way is which, rather than each inventing its own convention.
543
- */
544
- function deriveHeat(income: string, expense: string, surfaces: { bgSurface2: string }, mode: ThemeMode): HeatStops {
545
- const exp = hexToOklch(expense)!;
546
- return {
547
- neutral: surfaces.bgSurface2,
548
- under: income,
549
- over: expense,
550
- seqLow: oklchToHex({ l: mode === "light" ? 0.93 : 0.26, c: 0.05, h: exp.h }),
551
- seqHigh: expense,
552
- empty: mode === "light" ? "rgba(120,110,95,0.14)" : "rgba(160,170,190,0.10)",
553
- };
554
- }
555
-
556
- /* ── Audit ────────────────────────────────────────────────────────────────── */
557
-
558
- /**
559
- * Measure every pair that has a requirement, and say which ones fail.
560
- *
561
- * This is the part the shipped presets were missing. `derivePalette` runs it on the way
562
- * out, and the preset test runs it over everything the package ships, so a palette that
563
- * does not hold up cannot be merged with a comment claiming that it does.
564
- *
565
- * **`level: "more"`** (0.36, docs/colour-roles-harmonization.md §13.5) measures the set as
566
- * More contrast paints it: the stepped secondary, muted and border, and in a light set the
567
- * stepped well (as `bgSurface2`) and money — the same pairs, named with a " (More
568
- * contrast)" suffix. Two things change with the level: the border is a field's boundary
569
- * there, held to WCAG 1.4.11's 3:1 rather than the hairline's 1.1, and a light set's well
570
- * must stand {@link WELL_STEP_MIN}:1 from the card. Pass `semantic` with tokens.css's More
571
- * literals for a light set (the status colours step there); the status text is then
572
- * measured on the stepped well too.
573
- */
574
- export function auditPalette(
575
- set: TokenSet,
576
- semantic?: SemanticTokens,
577
- options: { level?: ContrastLevel } = {},
578
- ): ContrastReport {
579
- const more = options.level === "more";
580
- const step = more ? contrastStep(set) : null;
581
- // The set as it paints at this level: what `applyTokenSet` writes for it.
582
- const t: TokenSet = step
583
- ? {
584
- ...set,
585
- textSecondary: step.textSecondary,
586
- textMuted: step.textMuted,
587
- border: step.border,
588
- ...(step.well && {
589
- bgSurface2: step.well.bgSurface2,
590
- moneyIncome: step.well.moneyIncome,
591
- moneyExpense: step.well.moneyExpense,
592
- moneyNet: step.well.moneyNet,
593
- moneyNeutral: step.well.moneyNeutral,
594
- }),
595
- }
596
- : set;
597
- const suffix = more ? " (More contrast)" : "";
598
- const checks: ContrastCheck[] = [];
599
- const surfaces: Array<[string, string]> = [
600
- ["bgPage", t.bgPage],
601
- ["bgSurface", t.bgSurface],
602
- ["bgSurface2", t.bgSurface2],
603
- ];
604
- // A hovered row on the card (`--bg-hover`) carries the same text as the card, and in
605
- // light it is the darkest fill that text sits on (0.33, §12.10). Text is measured on
606
- // it; the brand fill and the hairline, which are not text, are not.
607
- const hover = hoverFill(t);
608
- const textGrounds: Array<[string, string]> = [...surfaces, ["bgHover", hover]];
609
- // `--brand-muted`, `--brand-bg` and `--brand-bg-hover`, mixed as tokens.css mixes them.
610
- const { brandMuted, brandBg, brandBgHover } = brandSoft(t);
611
-
612
- // The 0.05 of slack is for a pair with a color-mix on one side, and only for that: the
613
- // browser mixes in float and paints the result, where this mixes and rounds to hex, so
614
- // the two can differ by a hair. Hex against hex is what the page paints, measured
615
- // exactly — the slack used to cover those too, and passed the Contrast preset's dark
616
- // brand fill at 2.998:1 (round 0.34 BUG-8).
617
- const MIXED = /\b(bgHover|brandMuted|brandBg|brandBgHover)\b/;
618
- const add = (pair: string, fg: string, bg: string, required: number, rule: string) => {
619
- const ratio = contrast(fg, bg);
620
- const slack = MIXED.test(pair) ? 0.05 : 0;
621
- checks.push({ pair: pair + suffix, ratio, required, rule, passes: ratio >= required - slack });
622
- };
623
-
624
- for (const [name, bg] of surfaces) {
625
- add(`brand on ${name}`, t.brand, bg, 3, "WCAG 1.4.11 graphical object");
626
- if (more) add(`border on ${name}`, t.border, bg, 3, "WCAG 1.4.11 — under More contrast a border bounds a field");
627
- else add(`border on ${name}`, t.border, bg, 1.1, "house rule: a hairline must be findable");
628
- }
629
- // The stepped light well, a hex `applyTokenSet` writes (§13.3, decision 2).
630
- if (step?.well) {
631
- add(
632
- "bgSurface2 on bgSurface",
633
- t.bgSurface2,
634
- t.bgSurface,
635
- WELL_STEP_MIN,
636
- "house rule: the well stands two hover steps from the card",
637
- );
638
- }
639
- for (const [name, bg] of textGrounds) {
640
- add(`textPrimary on ${name}`, t.textPrimary, bg, 7, "WCAG 1.4.6 AAA body text");
641
- add(`textSecondary on ${name}`, t.textSecondary, bg, 4.5, "WCAG 1.4.3 AA body text");
642
- add(`textMuted on ${name}`, t.textMuted, bg, 4.5, "WCAG 1.4.3 AA body text");
643
- add(`brandMuted on ${name}`, brandMuted, bg, 4.5, "WCAG 1.4.3 — the brand as text");
644
- for (const [key, hex] of [
645
- ["moneyIncome", t.moneyIncome],
646
- ["moneyExpense", t.moneyExpense],
647
- ["moneyNet", t.moneyNet],
648
- // Not a figure's colour but still printed as one (the numpad's sign, a future
649
- // row's amount) — measured since 0.33, when it was found at 4.24:1.
650
- ["moneyNeutral", t.moneyNeutral],
651
- ] as const) {
652
- add(`${key} on ${name}`, hex, bg, 4.5, "WCAG 1.4.3 — these are rendered as TEXT");
653
- }
654
- }
655
-
656
- add("brandContrast on brand", t.brandContrast, t.brand, 4.5, "WCAG 1.4.3 AA body text");
657
- // A hovered brand button carries the same label (0.33): the derived dark presets
658
- // lightened the hover toward their white label and left it at 4.07:1.
659
- add("brandContrast on brandHover", t.brandContrast, t.brandHover, 4.5, "WCAG 1.4.3 AA body text");
660
- add("brandMuted on brandBg", brandMuted, brandBg, 4.5, "WCAG 1.4.3 — a soft brand chip's label");
661
- // The same label on the chip hovered (§12.11): a current link, a selected day. At 70 %
662
- // brand the muted text read 4.08–4.42:1 here (Default and Moss light; Ink, Moss, Plum
663
- // and Contrast dark).
664
- add("brandMuted on brandBgHover", brandMuted, brandBgHover, 4.5, "WCAG 1.4.3 — a hovered soft brand chip's label");
665
-
666
- if (semantic) {
667
- for (const [name, fg] of [
668
- ["danger", semantic.danger],
669
- ["warning", semantic.warning],
670
- ["info", semantic.info],
671
- ["success", semantic.success],
672
- ] as const) {
673
- add(`${name} on bgSurface`, fg, t.bgSurface, 4.5, "WCAG 1.4.3 — rendered as text");
674
- add(`${name} on bgHover`, fg, hover, 4.5, "WCAG 1.4.3 — rendered as text, on a hovered row");
675
- // The darker light well the More literals were solved for (§13.3).
676
- if (step?.well) add(`${name} on bgSurface2`, fg, t.bgSurface2, 4.5, "WCAG 1.4.3 — rendered as text, on the well");
677
- }
678
- add("danger on dangerBg", semantic.danger, semantic.dangerBg, 4.5, "WCAG 1.4.3 — badge text");
679
- add("warning on warningBg", semantic.warning, semantic.warningBg, 4.5, "WCAG 1.4.3 — badge text");
680
- add("info on infoBg", semantic.info, semantic.infoBg, 4.5, "WCAG 1.4.3 — badge text");
681
- add("success on successBg", semantic.success, semantic.successBg, 4.5, "WCAG 1.4.3 — badge text");
682
- add("dangerContrast on danger", semantic.dangerContrast, semantic.danger, 4.5, "WCAG 1.4.3 AA body text");
683
- }
684
-
685
- const failures = checks.filter((c) => !c.passes);
686
- return { checks, failures, passes: failures.length === 0 };
687
- }
688
-
689
- /* ── Categorical chart ramp ───────────────────────────────────────────────── */
690
-
691
- export interface ChartRampReport {
692
- colors: string[];
693
- /** Series pairs that are too close under normal vision or any simulated CVD. */
694
- collisions: Array<{ a: number; b: number; under: "normal" | CvdType; distance: number }>;
695
- /** Series that do not clear 3:1 against a surface they may be drawn on. */
696
- lowContrast: Array<{ index: number; surface: string; ratio: number }>;
697
- /** The worst pairwise separation, across normal vision and all three dichromacies. */
698
- minSeparation: number;
699
- /** The worst contrast any series reaches against any surface it was measured on. */
700
- minContrast: number;
701
- passes: boolean;
702
- }
703
-
704
- /**
705
- * The floor for pairwise separation in OKLab, across normal vision and each dichromacy.
706
- *
707
- * CALIBRATED, not chosen. Paul Tol's "Muted" set — which this package ships and which is
708
- * a well-regarded CVD-safe palette — bottoms out at 0.059 in its light variant and 0.032
709
- * in the lightened dark one. A threshold above 0.059 would fail a palette that is known
710
- * to work, which is worse than having no check at all: an audit that cries wolf gets
711
- * switched off. 0.05 sits just under the known-good case.
712
- */
713
- const MIN_SEPARATION = 0.05;
714
-
715
- /**
716
- * **The categorical trade-off, measured.** At a SINGLE lightness, the most series that
717
- * can satisfy both the 3:1 fill contrast of WCAG 1.4.11 and {@link MIN_SEPARATION} under
718
- * dichromacy is FOUR. Searched exhaustively over starting hue and lightness:
719
- *
720
- * n=4 best separation 0.065 — both satisfiable
721
- * n=5 best separation 0.041 — not satisfiable
722
- * n=9 best separation 0.015 — not satisfiable
723
- *
724
- * The reason is structural: dichromacy collapses the red-green axis, so hue alone stops
725
- * distinguishing colours once you need more than a handful, and the remaining channel is
726
- * LIGHTNESS — the very thing a uniform-contrast ramp holds constant. Paul Tol's set
727
- * varies lightness deliberately and pays for it in contrast; that is not an oversight in
728
- * their palette, it is the only currency left.
729
- *
730
- * So above four series this deriver varies lightness too, and reports what it gave up
731
- * rather than pretending both constraints were met.
732
- *
733
- * NOTE ON WHAT THIS BOUND IS. It describes the PROBLEM, not a guarantee about
734
- * {@link deriveChartRamp}. That function fixes lightness and starts the hue wheel at the
735
- * brand's own hue rather than searching for the best start, so it reaches the bound only
736
- * where the brand happens to sit well: sweeping 72 brand hues against the default light
737
- * surfaces, 7 of 72 produced a passing 4-series ramp (12 of 72 on dark), and none passed
738
- * at 5 or 9. Read the report it returns; do not assume a pass.
739
- */
740
- const SINGLE_LIGHTNESS_MAX_SERIES = 4;
741
-
742
- /**
743
- * A categorical ramp of `count` hues, evenly spaced and equal in perceived lightness,
744
- * then MEASURED for separability — including under each dichromacy.
745
- *
746
- * Offered but not used by default, and the distinction matters. Evenly spaced hues at
747
- * one lightness are a reasonable generic answer; Paul Tol's "Muted" set, which this
748
- * package ships, is a better specific one, because it was optimised against real
749
- * confusion lines rather than derived from a formula. So this exists for a consumer who
750
- * wants their charts to follow their brand and is willing to read the report — not as
751
- * a silent upgrade to the default.
752
- */
753
- export function deriveChartRamp(brandHex: string, mode: ThemeMode, surfaces: string[], count = 9): ChartRampReport {
754
- const brand = hexToOklch(brandHex) ?? { l: 0.6, c: 0.12, h: 264 };
755
- const base = mode === "light" ? 0.58 : 0.74;
756
- const c = Math.max(0.09, Math.min(brand.c, 0.15));
757
- // Up to four series, one lightness: a scale that varies lightness implies rank, and a
758
- // categorical one must not. Beyond four, lightness is the only channel left that
759
- // survives dichromacy — see SINGLE_LIGHTNESS_MAX_SERIES — so it alternates in a
760
- // three-step cycle, which keeps ADJACENT series (the ones a legend puts side by side)
761
- // at different lightnesses as well as different hues.
762
- const vary = count > SINGLE_LIGHTNESS_MAX_SERIES;
763
- const offsets = [0, mode === "light" ? -0.1 : 0.1, mode === "light" ? 0.08 : -0.08];
764
- const colors = Array.from({ length: count }, (_, i) =>
765
- oklchToHex({
766
- l: vary ? base + offsets[i % offsets.length] : base,
767
- c,
768
- h: (brand.h + (360 / count) * i) % 360,
769
- }),
770
- );
771
-
772
- return measureRamp(colors, surfaces);
773
- }
774
-
775
- /** Audit a ramp somebody else chose — the shipped Paul Tol set, say. */
776
- export function auditChartRamp(colors: string[], surfaces: string[]): ChartRampReport {
777
- return measureRamp(colors, surfaces);
778
- }
779
-
780
- function measureRamp(colors: string[], surfaces: string[]): ChartRampReport {
781
- const collisions: ChartRampReport["collisions"] = [];
782
- const rgbs = colors.map((hex) => parseHex(hex)).filter((v): v is NonNullable<typeof v> => !!v);
783
- let minSeparation = Infinity;
784
- for (let i = 0; i < rgbs.length; i++) {
785
- for (let j = i + 1; j < rgbs.length; j++) {
786
- const normal = deltaE(rgbs[i], rgbs[j]);
787
- minSeparation = Math.min(minSeparation, normal);
788
- if (normal < MIN_SEPARATION) {
789
- collisions.push({ a: i, b: j, under: "normal", distance: normal });
790
- }
791
- for (const type of ["protanopia", "deuteranopia", "tritanopia"] as const) {
792
- const d = deltaE(simulateCvd(rgbs[i], type), simulateCvd(rgbs[j], type));
793
- minSeparation = Math.min(minSeparation, d);
794
- if (d < MIN_SEPARATION) collisions.push({ a: i, b: j, under: type, distance: d });
795
- }
796
- }
797
- }
798
-
799
- const lowContrast: ChartRampReport["lowContrast"] = [];
800
- let minContrast = Infinity;
801
- colors.forEach((hex, index) => {
802
- for (const surface of surfaces) {
803
- const ratio = contrast(hex, surface);
804
- minContrast = Math.min(minContrast, ratio);
805
- // WCAG 1.4.11: a graphical object carrying meaning needs 3:1 against what is
806
- // adjacent to it. A bar the same value as the card behind it has no boundary.
807
- if (ratio < 3) lowContrast.push({ index, surface, ratio });
808
- }
809
- });
810
-
811
- return {
812
- colors,
813
- collisions,
814
- lowContrast,
815
- minSeparation: Number.isFinite(minSeparation) ? minSeparation : 0,
816
- minContrast: Number.isFinite(minContrast) ? minContrast : 0,
817
- passes: collisions.length === 0 && lowContrast.length === 0,
818
- };
819
- }
820
-
821
- /** Convenience: the OKLCH of a hex, for a caller inspecting an anchor. */
822
- export function describe(hex: string): Oklch | null {
823
- const rgb = parseHex(hex);
824
- return rgb ? rgbToOklch(rgb) : null;
825
- }