@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,858 +0,0 @@
1
- import { useEffect, useEffectEvent, useId, useRef, useState } from "react";
2
- import type { ComponentPropsWithRef, FormEvent, ReactNode } from "react";
3
- import { KeyRound } from "lucide-react";
4
-
5
- import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
6
- import { cn } from "../lib/cn";
7
- import { AlertBanner } from "../components/alert-banner";
8
- import { hasContent } from "../lib/presence";
9
- import { CurrentPasswordInput } from "../components/danger-confirm";
10
- import { OneTimeCodeInput } from "../components/one-time-code-input";
11
- import { TextLink } from "../components/text-link";
12
- import { Button } from "../components/button";
13
- import { Input } from "../components/input";
14
- import { accessAction } from "../landing/access";
15
- import type { AccessChoice } from "../landing/access";
16
- import { useLandingLabels } from "../landing/landing-labels";
17
- import { authErrorCode, isRateLimited, retryAfterSeconds } from "./auth-errors";
18
- import type { KitErrorCode } from "./auth-errors";
19
- import { taggedEmail } from "./email-tag";
20
- import { newPasswordProblem } from "./form-rules";
21
- import { NewPasswordFields } from "./new-password-fields";
22
- import { DEFAULT_SIGN_IN_LABELS } from "./sign-in-form-labels";
23
-
24
- /* ── The answers (§5.1) ──────────────────────────────────────────────────── */
25
-
26
- /**
27
- * What a sign-in call answers, in the kit's words — docs/auth-harmonization.md §5.1,
28
- * keksdose's three shapes. The app maps its own HTTP answer to one of these and resolves
29
- * with it; a refusal REJECTS (with whatever its client throws — {@link authErrorCode}
30
- * reads the code out of it).
31
- *
32
- * | the server answers (keksdose) | resolve with |
33
- * |---|---|
34
- * | `TokenResponse` `{access_token, refresh_token, token_type, user}` | `{ kind: "signed-in" }`, after the app has stored the session |
35
- * | `{requires_2fa: true, challenge_token}` | `{ kind: "2fa", challengeToken: challenge_token }` |
36
- * | `{requires_password_change: true, challenge_token, encrypted}` | `{ kind: "password-change", challengeToken: challenge_token, extra: { encrypted } }` |
37
- * | `401 {code: "invalid_credentials"}` | reject — let the client's error through |
38
- *
39
- * ```ts
40
- * async function toAnswer(res: TokenResponse | TwoFactorChallenge | PasswordChangeChallenge): Promise<SignInAnswer> {
41
- * if ("requires_2fa" in res) return { kind: "2fa", challengeToken: res.challenge_token };
42
- * if ("requires_password_change" in res)
43
- * return { kind: "password-change", challengeToken: res.challenge_token, extra: { encrypted: res.encrypted } };
44
- * await onLoginSuccess(res); // store tokens, load /auth/me, switch language
45
- * return { kind: "signed-in" };
46
- * }
47
- * <SignInForm onSubmit={async (v) => toAnswer(await authApi.login(v))} … />
48
- * ```
49
- *
50
- * The same mapping serves `/auth/login/2fa`, `/auth/login/set-password` and the passkey
51
- * finish, which answer the same union.
52
- */
53
- export type SignInAnswer =
54
- | { kind: "signed-in" }
55
- | { kind: "2fa"; challengeToken: string }
56
- | {
57
- kind: "password-change";
58
- challengeToken: string;
59
- /** The challenge's app fields, passed through untouched — keksdose's `encrypted`,
60
- * which its note on this step reads (`passwordChangeContent`). */
61
- extra?: Readonly<Record<string, unknown>>;
62
- };
63
-
64
- /** The step on screen: the credentials, the second factor, or a new password. */
65
- export type SignInStep = "credentials" | "2fa" | "password-change";
66
-
67
- /** What the person did when a call failed — {@link SignInFormProps.describeError}'s
68
- * second argument. */
69
- export type SignInAction = "password" | "passkey" | "code" | "set-password";
70
-
71
- export interface SignInCredentials {
72
- /** Trimmed. Lower-casing is the server's (§3.1). */
73
- email: string;
74
- /** As typed, never trimmed. */
75
- password: string;
76
- }
77
-
78
- export interface SignInCodeValues {
79
- challengeToken: string;
80
- /** Digits only — {@link OneTimeCodeInput} drops the spaces of "123 456". A backup code
81
- * (`kind: "recovery"`) is trimmed and otherwise as typed: its dashes and case are the
82
- * server's to normalise, as kastlan's `_normalise_backup_code` does. */
83
- code: string;
84
- /**
85
- * 0.30.0: `"recovery"` when the person typed one of their backup codes instead
86
- * (`recoveryCode`); absent for the authenticator's code, as before. kastlan's
87
- * `/auth/login/2fa` takes either in the same `code` and tells them apart itself; an
88
- * app whose server takes a backup code elsewhere routes on this.
89
- */
90
- kind?: "recovery";
91
- }
92
-
93
- export interface SignInNewPasswordValues {
94
- challengeToken: string;
95
- password: string;
96
- }
97
-
98
- /* ── Labels ──────────────────────────────────────────────────────────────── */
99
-
100
- /**
101
- * Every string `SignInForm` renders — the `signIn` namespace of `<UiKitProvider
102
- * labels>`, overridable per instance through `labels`. keksdose's words where it has
103
- * them (`auth.*` in its catalogue).
104
- */
105
- export interface SignInLabels {
106
- email: string;
107
- password: string;
108
- /** The submit button. */
109
- submit: string;
110
- /** The passkey button (`onPasskey`). */
111
- passkey: string;
112
- /** The link to `forgotHref`. */
113
- forgotPassword: string;
114
- /** Before the link to `registerHref`. */
115
- noAccount: string;
116
- /** The link to `registerHref`. */
117
- register: string;
118
- /** The ONE answer to an unknown address, a wrong password and a deactivated account
119
- * (`invalid_credentials`, §5.2). */
120
- invalidCredentials: string;
121
- /** Any other failed sign-in (the network, a 500). */
122
- failed: string;
123
- /** A failed or refused passkey sign-in. */
124
- passkeyFailed: string;
125
- /**
126
- * The hint under `invalidCredentials` (§2.10), shown when `deactivatedContact` is
127
- * given. A TEMPLATE: `{contact}` is replaced by the contact — a `mailto:` link for an
128
- * address — so a language puts it where its grammar needs it.
129
- */
130
- deactivatedHint: string;
131
- /** The hint under `invalidCredentials` when `emailTag` is given (§4.5), given the
132
- * typed address with the app's tag: "Signed up with ada+kastlan@example.com?". */
133
- tagHint: (taggedAddress: string) => string;
134
- /** The second-factor step's heading. */
135
- twoFactorTitle: string;
136
- twoFactorIntro: string;
137
- /** The code field's label. */
138
- code: string;
139
- /** The code step's submit button. */
140
- verify: string;
141
- /** The code was refused. */
142
- codeInvalid: string;
143
- /** The set-a-new-password step's heading. */
144
- setPasswordTitle: string;
145
- setPasswordIntro: string;
146
- newPassword: string;
147
- confirmPassword: string;
148
- passwordMismatch: string;
149
- /** The set-a-new-password step's submit button. */
150
- setPasswordSubmit: string;
151
- setPasswordFailed: string;
152
- /** A challenge was refused as `token_invalid` — it expired between the steps; the
153
- * form is back on the credentials. */
154
- expired: string;
155
- /** From the second and third step back to the credentials. */
156
- backToSignIn: string;
157
- /*
158
- * 0.30.0 — OPTIONAL, like `TwoFactorSettingLabels.qrAlt` and for its reason: a new
159
- * required key is a compile error at every call site that annotates this interface
160
- * (CONTRIBUTING's additive-API rule). Each falls back to the provider's `signIn`, then
161
- * English.
162
- */
163
- /** The second-factor step's switch to a backup code (`recoveryCode`). */
164
- useRecoveryCode?: string;
165
- /** The switch back, from the backup-code field to the authenticator's code. */
166
- useAuthenticatorCode?: string;
167
- /** The backup-code field's label. */
168
- recoveryCode?: string;
169
- /** The step's intro while a backup code is asked for, in place of `twoFactorIntro`. */
170
- recoveryIntro?: string;
171
- /** Under the backup-code field, given how many letters and digits a code has. */
172
- recoveryCodeHint?: (length: number) => string;
173
- /** A refused backup code — wrong, or spent already (each one works once). */
174
- recoveryCodeInvalid?: string;
175
- /** Any step's request was throttled — HTTP 429 ({@link isRateLimited}) — given the
176
- * wait its `Retry-After` asks for, in seconds ({@link retryAfterSeconds}), or
177
- * `undefined` (or `0`) without one. */
178
- rateLimited?: (seconds?: number) => string;
179
- /** 0.31.0: the link after `noAccount` for an invitation-only app (`access` of kind
180
- * `request`) — a mail to support, in place of `register`. */
181
- requestAccess?: string;
182
- }
183
-
184
- // Defined in ./sign-in-form-labels, which holds no component code (0.34, KS U8).
185
- export { DEFAULT_SIGN_IN_LABELS };
186
-
187
- /* ── Props ───────────────────────────────────────────────────────────────── */
188
-
189
- export interface SignInFormProps extends Omit<ComponentPropsWithRef<"div">, "onSubmit" | "children"> {
190
- /**
191
- * The credentials step was submitted. Send them, and resolve with the answer
192
- * ({@link SignInAnswer}) or reject with the client's error. The form never sends a
193
- * request itself (§8): keksdose must see the password on its way, to refuse the same
194
- * string as an encryption passphrase later.
195
- *
196
- * On `signed-in` the form's job is over — it stays busy while the app navigates.
197
- */
198
- onSubmit: (credentials: SignInCredentials) => Promise<SignInAnswer>;
199
- /** The second factor was submitted (`/auth/login/2fa`). Resolves with the next answer
200
- * — keksdose may still require a new password after the code. */
201
- onCode: (values: SignInCodeValues) => Promise<SignInAnswer>;
202
- /** The new password was submitted (`/auth/login/set-password`). Resolves with the
203
- * answer, `signed-in` in practice; keksdose's `key_wrap_unchanged` note is the app's
204
- * to show from here. */
205
- onSetPassword: (values: SignInNewPasswordValues) => Promise<SignInAnswer>;
206
- /**
207
- * The passkey button was pressed: run the ceremony (`/auth/passkey/login/begin|finish`)
208
- * and resolve with its answer. It asks for NO email — a passkey is bound to the site,
209
- * and the browser offers every one it holds (keksdose #126). Left out, no button: pass
210
- * it only where `PublicKeyCredential` exists.
211
- */
212
- onPasskey?: () => Promise<SignInAnswer>;
213
- /**
214
- * Passkey autofill (conditional mediation). The email field is
215
- * `autoComplete="username webauthn"`, so a pending `navigator.credentials.get({
216
- * mediation: "conditional" })` lists the site's passkeys in its dropdown. The form
217
- * calls this ONCE on mount; arm the request there and resolve with its answer when the
218
- * person picks a passkey, or with `null` when nothing happens. The signal aborts on
219
- * unmount — cancel the pending request then (keksdose: `armPasskeyAutofill(onDone,
220
- * signal)` + `cancelPasskeyAutofill()`). A rejection is silent: the button stays the
221
- * reliable path.
222
- */
223
- passkeyAutofill?: (signal: AbortSignal) => Promise<SignInAnswer | null | undefined>;
224
- /** "Forgot your password?" goes here — the app's `/forgot-password`. Left out, no
225
- * link. */
226
- forgotHref?: string;
227
- /** "No account yet? Create account" goes here — `/register`. Left out, no line. */
228
- registerHref?: string;
229
- /**
230
- * 0.31.0 (docs/landing-demo-harmonization.md §4.2): how a visitor gets an account —
231
- * the same value the landing's `PublicHeader` and `Hero` take. `{kind: "request",
232
- * email}` turns the line into "No account yet? Request access", a mail to support with
233
- * the subject and body of `accessAction` (every app is invitation-only); `{kind:
234
- * "register", href}` keeps "Create account", to `href`. Wins over `registerHref`; left
235
- * out, `registerHref` works as before.
236
- */
237
- access?: AccessChoice;
238
- /** The email field's start value — the reset page ends on "Sign in" with the address
239
- * filled in (§6.3). */
240
- defaultEmail?: string;
241
- /**
242
- * The app's address tag (`"kastlan"`, §4.5). After `invalid_credentials` the form also
243
- * says "Signed up with you+kastlan@example.com? Use that address." — sign-in stays
244
- * exact, and the server looks nothing up.
245
- */
246
- emailTag?: string;
247
- /**
248
- * Who a deactivated user writes to (§2.10): an address (drawn as a `mailto:` link) or
249
- * the app's own node. Shown after `invalid_credentials` as "Account deactivated? Write
250
- * to …". Left out, no hint.
251
- */
252
- deactivatedContact?: ReactNode;
253
- /** Digits of the second factor. Default 6 (TOTP). */
254
- codeLength?: number;
255
- /**
256
- * 0.30.0: offer a backup code on the second-factor step (kastlan's 0.29 adoption: its
257
- * `/auth/login/2fa` takes one of the eight codes minted at 2FA setup, and the kit's
258
- * step had no way to type one). A "Use a backup code" switch under the code field
259
- * swaps the digits-only {@link OneTimeCodeInput} for a plain text field; the code goes
260
- * to `onCode` with the same challenge and `kind: "recovery"`.
261
- *
262
- * `true` for a 16-character code (kastlan's `ABCD-EFGH-JKLM-NPQR`), or `{ length }`.
263
- * The length counts letters and digits only — the dashes and spaces a printed code is
264
- * grouped with don't count — and "Verify" waits for it. Left out, no switch.
265
- */
266
- recoveryCode?: boolean | { length?: number };
267
- /** App content at the top of the credentials step — a notice, a demo button. */
268
- credentialsContent?: ReactNode;
269
- /**
270
- * App content on the second-factor step, under its intro. 0.30.0: pass a function and
271
- * it gets the challenge token — kastlan kept its own copy of the token for a "lost
272
- * your device?" link, which the step now hands over.
273
- */
274
- twoFactorContent?: ReactNode | ((challengeToken: string) => ReactNode);
275
- /**
276
- * App content on the set-a-new-password step, under its intro — keksdose's
277
- * private-mode note ("Your encrypted data is untouched …"), which depends on the
278
- * challenge: pass a function and it gets the challenge's `extra`.
279
- */
280
- passwordChangeContent?: ReactNode | ((extra: Readonly<Record<string, unknown>> | undefined) => ReactNode);
281
- /**
282
- * The app's own words for a failure, or `undefined` for the kit's: the device being
283
- * offline, a throttle with its wait ("try again in an hour"). Asked first, for every
284
- * failure; what it returns replaces the message, and the `invalid_credentials` hints
285
- * still follow. A bare `429` needs none since 0.30.0: the kit says `rateLimited`.
286
- */
287
- describeError?: (error: unknown, action: SignInAction) => ReactNode | undefined;
288
- /** The step changed — retitle the page (`AuthLayout`'s `title`) if the app wants. */
289
- onStepChange?: (step: SignInStep) => void;
290
- /** The level of the second and third step's heading. Default `h2`, under the page's
291
- * `h1`; one level under `AuthLayout`'s `headingAs` where that is embedded lower. */
292
- headingAs?: "h2" | "h3" | "h4" | "h5" | "h6";
293
- labels?: LabelOverride<SignInLabels>;
294
- }
295
-
296
- /* ── Parts ───────────────────────────────────────────────────────────────── */
297
-
298
- interface Failure {
299
- action: SignInAction;
300
- code: KitErrorCode | undefined;
301
- message: ReactNode;
302
- /** The address the failed credentials carried — the tag hint names its tagged form. */
303
- email?: string;
304
- }
305
-
306
- /** `{contact}` in the template, replaced by the contact (a `mailto:` link for an
307
- * address). Split, not interpolated, so the link is an element. A template that lost
308
- * its placeholder still shows the contact, after it. */
309
- function withContact(template: string, contact: ReactNode): ReactNode[] {
310
- const node =
311
- typeof contact === "string" && contact.includes("@") ? (
312
- <TextLink key="contact" href={`mailto:${contact}`} tone="secondary">
313
- {contact}
314
- </TextLink>
315
- ) : (
316
- <span key="contact">{contact}</span>
317
- );
318
- if (!template.includes("{contact}")) return [template, " ", node];
319
- return template
320
- .split(/(\{contact\})/)
321
- .filter((part) => part !== "")
322
- .map((part) => (part === "{contact}" ? node : part));
323
- }
324
-
325
- const HINT_CLASS = "text-xs text-secondary";
326
-
327
- /** A backup code's letters and digits — kastlan's: 16, printed `ABCD-EFGH-JKLM-NPQR`. */
328
- const RECOVERY_CODE_LENGTH = 16;
329
-
330
- /** How many letters and digits a typed backup code has: the dashes and spaces it is
331
- * printed in groups with don't count, so "abcd-efgh ijkl mnop" is 16 — the count
332
- * kastlan's server normalises the code to before it compares. */
333
- function recoveryCharacters(value: string): number {
334
- return value.replace(/[^\p{L}\p{N}]/gu, "").length;
335
- }
336
- const INTRO_CLASS = "text-sm text-secondary";
337
-
338
- /* ── The form ────────────────────────────────────────────────────────────── */
339
-
340
- /**
341
- * Sign-in for every app (docs/auth-harmonization.md §5, §8): email and password, or a
342
- * passkey; then the second factor when it is on; then a new password when an admin
343
- * required one. keksdose's `LoginPage` and `ForcedPasswordChangeStep`
344
- * (features/auth/login-page.tsx, forced-password-change.tsx), as one component.
345
- *
346
- * **It never sends a request.** Each step hands its input to a callback and renders the
347
- * {@link SignInAnswer} it resolves with; a rejection is shown in the step it came from.
348
- * The challenge token lives in this component's state only, as in keksdose, so a reload
349
- * costs a fresh sign-in — no route, no storage.
350
- *
351
- * **One error for every wrong credential** (§2.10, §5.2): `invalid_credentials` shows one
352
- * sentence, whatever was wrong, plus two hints UNDER it — "Account deactivated? Write to
353
- * …" (`deactivatedContact`) and "Signed up with you+kastlan@…? Use that address."
354
- * (`emailTag`). Any other failure says "Sign-in failed" and no hint: the hints answer a
355
- * refused credential, not a network that is down. `describeError` puts the app's words
356
- * on a failure the kit cannot know (a throttled attempt).
357
- *
358
- * **The steps.**
359
- * - Credentials: the email field is `username webauthn` (passkey autofill, see
360
- * `passkeyAutofill`), the password a `CurrentPasswordInput` (a password manager fills
361
- * it and never offers a new one). The submit is not disabled while the fields are
362
- * empty: a browser that autofills on load withholds the values until the first
363
- * interaction, and a disabled button would swallow that first click. The fields'
364
- * own `required` answers an empty submit instead. "Forgot your password?" sits under
365
- * the buttons, where someone whose password just failed is already looking
366
- * (keksdose #198).
367
- * - Second factor: {@link OneTimeCodeInput}, focused on arrival. "Verify" waits for the
368
- * whole code. A refused code stays here with its error; `token_invalid` (the
369
- * challenge expired) goes back to the credentials and says why. Kurvenschmiede has
370
- * no 2FA yet, and the step is here from the start, so adding it is backend work only
371
- * (§10.5). With `recoveryCode` (0.30.0) a switch under the field takes a backup code
372
- * instead, through the same `onCode` with `kind: "recovery"`.
373
- *
374
- * **A throttled request** (HTTP 429, {@link isRateLimited}) says "Too many attempts. Try
375
- * again in 30 s." on any step (0.30.0) — the wait from its `Retry-After`, else "Wait a
376
- * moment and try again." — after `describeError`, whose words still come first, and
377
- * instead of "wrong password" or "invalid code", which would send the person to try
378
- * another one.
379
- * - New password: new + confirm with the strength meter, the 8-character / 72-byte
380
- * rules and nothing else (§8). It reads as explained, not blocked (keksdose): the
381
- * person did nothing wrong.
382
- *
383
- * The password is dropped from state once the credentials are answered; "Back to sign in"
384
- * returns to an empty password field.
385
- */
386
- export function SignInForm({
387
- onSubmit,
388
- onCode,
389
- onSetPassword,
390
- onPasskey,
391
- passkeyAutofill,
392
- forgotHref,
393
- registerHref,
394
- access,
395
- defaultEmail = "",
396
- emailTag,
397
- deactivatedContact,
398
- codeLength = 6,
399
- recoveryCode,
400
- credentialsContent,
401
- twoFactorContent,
402
- passwordChangeContent,
403
- describeError,
404
- onStepChange,
405
- headingAs: Heading = "h2",
406
- labels: labelsProp,
407
- className,
408
- ...rest
409
- }: SignInFormProps) {
410
- const labels = useKitLabels("signIn", DEFAULT_SIGN_IN_LABELS, labelsProp);
411
- // The mail's subject and body are the landing's words (`landing` namespace), so the
412
- // request reads the same from every page that offers it.
413
- const landing = useLandingLabels();
414
- const accountLink =
415
- access === undefined
416
- ? registerHref === undefined
417
- ? null
418
- : { href: registerHref, label: labels.register }
419
- : access.kind === "register"
420
- ? { href: access.href, label: labels.register }
421
- : {
422
- href: accessAction(access, landing).href,
423
- label: labels.requestAccess ?? DEFAULT_SIGN_IN_LABELS.requestAccess,
424
- };
425
- const [step, setStep] = useState<SignInStep>("credentials");
426
- const [email, setEmail] = useState(defaultEmail);
427
- const [password, setPassword] = useState("");
428
- const [code, setCode] = useState("");
429
- // 0.30.0: the second factor as a backup code instead of the authenticator's digits.
430
- const [useRecovery, setUseRecovery] = useState(false);
431
- const [recovery, setRecovery] = useState("");
432
- const [newPassword, setNewPassword] = useState("");
433
- const [confirm, setConfirm] = useState("");
434
- const [challenge, setChallenge] = useState<{ token: string; extra?: Readonly<Record<string, unknown>> } | null>(null);
435
- // What is running: one call at a time. "done" after `signed-in` — the app has the
436
- // session and is leaving; the buttons stay busy so nothing is sent twice meanwhile.
437
- const [busy, setBusy] = useState<SignInAction | "done" | null>(null);
438
- const [failure, setFailure] = useState<Failure | null>(null);
439
- const headingId = useId();
440
-
441
- const emailRef = useRef<HTMLInputElement>(null);
442
- const passwordRef = useRef<HTMLInputElement>(null);
443
- const codeRef = useRef<HTMLInputElement>(null);
444
- const recoveryRef = useRef<HTMLInputElement>(null);
445
- const newPasswordRef = useRef<HTMLInputElement>(null);
446
-
447
- // A late answer after unmount (the app navigated away) must not set state.
448
- const mounted = useRef(true);
449
- useEffect(() => {
450
- mounted.current = true;
451
- return () => {
452
- mounted.current = false;
453
- };
454
- }, []);
455
-
456
- const goTo = (next: SignInStep) => {
457
- setStep(next);
458
- onStepChange?.(next);
459
- };
460
-
461
- const present = (answer: SignInAnswer) => {
462
- setFailure(null);
463
- if (answer.kind === "signed-in") {
464
- setBusy("done");
465
- return;
466
- }
467
- setBusy(null);
468
- // The password has done its work; it does not stay in state for the next steps.
469
- setPassword("");
470
- setCode("");
471
- setRecovery("");
472
- setUseRecovery(false);
473
- setNewPassword("");
474
- setConfirm("");
475
- if (answer.kind === "2fa") {
476
- setChallenge({ token: answer.challengeToken });
477
- goTo("2fa");
478
- } else if (answer.kind === "password-change") {
479
- setChallenge({ token: answer.challengeToken, extra: answer.extra });
480
- goTo("password-change");
481
- }
482
- };
483
-
484
- const messageFor = (
485
- error: unknown,
486
- action: SignInAction,
487
- code: KitErrorCode | undefined,
488
- recoveryUsed: boolean,
489
- ): ReactNode => {
490
- const own = describeError?.(error, action);
491
- if (hasContent(own)) return own;
492
- // After the app's words, before the kit's generic ones (0.30.0): a throttle is
493
- // neither a wrong password nor a wrong code, and saying so sends the person to try
494
- // another one — which the limiter counts too.
495
- if (isRateLimited(error))
496
- return (labels.rateLimited ?? DEFAULT_SIGN_IN_LABELS.rateLimited)(retryAfterSeconds(error));
497
- if (action === "password") return code === "invalid_credentials" ? labels.invalidCredentials : labels.failed;
498
- if (action === "passkey") return labels.passkeyFailed;
499
- if (action === "code") {
500
- if (code === "token_invalid") return labels.expired;
501
- return recoveryUsed
502
- ? (labels.recoveryCodeInvalid ?? DEFAULT_SIGN_IN_LABELS.recoveryCodeInvalid)
503
- : labels.codeInvalid;
504
- }
505
- return code === "token_invalid" ? labels.expired : labels.setPasswordFailed;
506
- };
507
-
508
- const fail = (error: unknown, action: SignInAction, sentEmail?: string, recoveryUsed = false) => {
509
- setBusy(null);
510
- // Our own abort (a passkey ceremony cancelled by the unmount) is no failure.
511
- if ((error as { name?: unknown } | null)?.name === "AbortError") return;
512
- const code = authErrorCode(error);
513
- const message = messageFor(error, action, code, recoveryUsed);
514
- // The challenge expired between the steps: only a fresh sign-in helps.
515
- if ((action === "code" || action === "set-password") && code === "token_invalid") {
516
- setChallenge(null);
517
- setCode("");
518
- setRecovery("");
519
- setUseRecovery(false);
520
- setNewPassword("");
521
- setConfirm("");
522
- goTo("credentials");
523
- }
524
- setFailure({ action, code, message, email: sentEmail });
525
- };
526
-
527
- const attempt = (
528
- action: SignInAction,
529
- call: () => Promise<SignInAnswer>,
530
- sentEmail?: string,
531
- recoveryUsed = false,
532
- ) => {
533
- if (busy) return;
534
- setBusy(action);
535
- setFailure(null);
536
- let result: Promise<SignInAnswer>;
537
- try {
538
- result = Promise.resolve(call());
539
- } catch (error) {
540
- result = Promise.reject(error);
541
- }
542
- result.then(
543
- (answer) => {
544
- if (mounted.current) present(answer);
545
- },
546
- (error: unknown) => {
547
- if (mounted.current) fail(error, action, sentEmail, recoveryUsed);
548
- },
549
- );
550
- };
551
-
552
- // Passkey autofill: armed once, on mount; the signal aborts on unmount. Its answer
553
- // arrives whenever the person picks a passkey from the email field's dropdown — and
554
- // is dropped if they have meanwhile started a sign-in of their own.
555
- const armAutofill = useEffectEvent((signal: AbortSignal) => passkeyAutofill?.(signal));
556
- const autofillAnswered = useEffectEvent((answer: SignInAnswer) => {
557
- if (busy === null) present(answer);
558
- });
559
- useEffect(() => {
560
- const controller = new AbortController();
561
- let pending: Promise<SignInAnswer | null | undefined>;
562
- try {
563
- pending = Promise.resolve(armAutofill(controller.signal));
564
- } catch (error) {
565
- pending = Promise.reject(error);
566
- }
567
- pending.then(
568
- (answer) => {
569
- if (answer && !controller.signal.aborted && mounted.current) autofillAnswered(answer);
570
- },
571
- () => {
572
- /* silent — unsupported, declined or aborted; the button stays the way in */
573
- },
574
- );
575
- return () => controller.abort();
576
- }, []);
577
-
578
- // Focus follows the step — not on mount (where it would pop a phone's keyboard over
579
- // the page), only once the person moved to another step.
580
- const shownStep = useRef(step);
581
- useEffect(() => {
582
- if (shownStep.current === step) return;
583
- shownStep.current = step;
584
- if (step === "2fa") codeRef.current?.focus();
585
- else if (step === "password-change") newPasswordRef.current?.focus();
586
- else if (emailRef.current?.value) passwordRef.current?.focus();
587
- else emailRef.current?.focus();
588
- }, [step]);
589
- // The backup-code switch swaps one field for the other under the focus that pressed
590
- // it; the field that came in is where the person is going. Only after a switch on
591
- // this step — arriving on it is the effect above.
592
- const shownRecovery = useRef(useRecovery);
593
- useEffect(() => {
594
- if (shownRecovery.current === useRecovery) return;
595
- shownRecovery.current = useRecovery;
596
- if (step !== "2fa") return;
597
- (useRecovery ? recoveryRef : codeRef).current?.focus();
598
- }, [useRecovery, step]);
599
-
600
- const backToCredentials = () => {
601
- if (busy) return;
602
- setChallenge(null);
603
- setFailure(null);
604
- setCode("");
605
- setRecovery("");
606
- setUseRecovery(false);
607
- setNewPassword("");
608
- setConfirm("");
609
- goTo("credentials");
610
- };
611
-
612
- const working = busy !== null;
613
- const rootClass = cn("space-y-3", className);
614
-
615
- /* ── Step 2: the second factor ── */
616
- if (step === "2fa" && challenge) {
617
- const recoveryOn = recoveryCode !== undefined && recoveryCode !== false;
618
- const recoveryLength = (typeof recoveryCode === "object" ? recoveryCode.length : undefined) ?? RECOVERY_CODE_LENGTH;
619
- const asRecovery = recoveryOn && useRecovery;
620
- const recoveryReady = recoveryCharacters(recovery) === recoveryLength;
621
- const ready = asRecovery ? recoveryReady : code.length === codeLength;
622
- const submitCode = (e: FormEvent) => {
623
- e.preventDefault();
624
- if (!ready) return;
625
- if (asRecovery) {
626
- attempt(
627
- "code",
628
- () => onCode({ challengeToken: challenge.token, code: recovery.trim(), kind: "recovery" }),
629
- undefined,
630
- true,
631
- );
632
- return;
633
- }
634
- attempt("code", () => onCode({ challengeToken: challenge.token, code }));
635
- };
636
- const switchCode = () => {
637
- if (working) return;
638
- setFailure(null);
639
- setCode("");
640
- setRecovery("");
641
- setUseRecovery((on) => !on);
642
- };
643
- const codeError = failure?.action === "code" ? failure.message : undefined;
644
- const content = typeof twoFactorContent === "function" ? twoFactorContent(challenge.token) : twoFactorContent;
645
- return (
646
- <div {...rest} data-step="2fa" className={rootClass}>
647
- <form className="space-y-3" aria-labelledby={headingId} onSubmit={submitCode}>
648
- <Heading id={headingId} className="text-base font-semibold text-primary">
649
- {labels.twoFactorTitle}
650
- </Heading>
651
- <p className={INTRO_CLASS}>
652
- {asRecovery ? (labels.recoveryIntro ?? DEFAULT_SIGN_IN_LABELS.recoveryIntro) : labels.twoFactorIntro}
653
- </p>
654
- {content}
655
- {asRecovery ? (
656
- // A plain text field, not the digits-only one: a backup code is letters and
657
- // digits in printed groups. Nothing a phone keyboard would "correct", and no
658
- // autofill — the browser's suggestion for an unknown field is the username.
659
- <Input
660
- ref={recoveryRef}
661
- label={labels.recoveryCode ?? DEFAULT_SIGN_IN_LABELS.recoveryCode}
662
- name="recovery-code"
663
- value={recovery}
664
- onChange={(e) => {
665
- setRecovery(e.target.value);
666
- if (failure) setFailure(null);
667
- }}
668
- autoComplete="off"
669
- autoCapitalize="characters"
670
- autoCorrect="off"
671
- spellCheck={false}
672
- inputClassName="font-mono"
673
- hint={(labels.recoveryCodeHint ?? DEFAULT_SIGN_IN_LABELS.recoveryCodeHint)(recoveryLength)}
674
- readOnly={working}
675
- error={codeError}
676
- required
677
- />
678
- ) : (
679
- <OneTimeCodeInput
680
- ref={codeRef}
681
- label={labels.code}
682
- name="code"
683
- value={code}
684
- length={codeLength}
685
- onChange={(next) => {
686
- setCode(next);
687
- if (failure) setFailure(null);
688
- }}
689
- readOnly={working}
690
- error={codeError}
691
- required
692
- />
693
- )}
694
- {recoveryOn && (
695
- <p className="text-sm">
696
- <Button type="button" variant="link" size="sm" disabled={working} onClick={switchCode}>
697
- {asRecovery
698
- ? (labels.useAuthenticatorCode ?? DEFAULT_SIGN_IN_LABELS.useAuthenticatorCode)
699
- : (labels.useRecoveryCode ?? DEFAULT_SIGN_IN_LABELS.useRecoveryCode)}
700
- </Button>
701
- </p>
702
- )}
703
- <Button type="submit" className="w-full" disabled={!working && !ready} pending={working}>
704
- {labels.verify}
705
- </Button>
706
- </form>
707
- <BackLink label={labels.backToSignIn} onClick={backToCredentials} disabled={working} />
708
- </div>
709
- );
710
- }
711
-
712
- /* ── Step 3: a new password ── */
713
- if (step === "password-change" && challenge) {
714
- const problem = newPasswordProblem(newPassword, confirm);
715
- const submitPassword = (e: FormEvent) => {
716
- e.preventDefault();
717
- if (problem) return;
718
- attempt("set-password", () => onSetPassword({ challengeToken: challenge.token, password: newPassword }));
719
- };
720
- const content =
721
- typeof passwordChangeContent === "function" ? passwordChangeContent(challenge.extra) : passwordChangeContent;
722
- return (
723
- <div {...rest} data-step="password-change" className={rootClass}>
724
- <form className="space-y-3" aria-labelledby={headingId} onSubmit={submitPassword}>
725
- <Heading id={headingId} className="text-base font-semibold text-primary">
726
- {labels.setPasswordTitle}
727
- </Heading>
728
- <p className={INTRO_CLASS}>{labels.setPasswordIntro}</p>
729
- {content}
730
- {/* Which account the new password is for, for the password manager: it files
731
- the new password under this username instead of guessing. */}
732
- {email !== "" && <input type="email" name="username" autoComplete="username" value={email} readOnly hidden />}
733
- <NewPasswordFields
734
- password={newPassword}
735
- confirm={confirm}
736
- onPasswordChange={setNewPassword}
737
- onConfirmChange={setConfirm}
738
- busy={working}
739
- passwordRef={newPasswordRef}
740
- text={{ password: labels.newPassword, confirm: labels.confirmPassword, mismatch: labels.passwordMismatch }}
741
- />
742
- {failure?.action === "set-password" && (
743
- <AlertBanner tone="danger" size="sm" role="alert">
744
- {failure.message}
745
- </AlertBanner>
746
- )}
747
- <Button type="submit" className="w-full" disabled={!working && problem !== null} pending={working}>
748
- {labels.setPasswordSubmit}
749
- </Button>
750
- </form>
751
- <BackLink label={labels.backToSignIn} onClick={backToCredentials} disabled={working} />
752
- </div>
753
- );
754
- }
755
-
756
- /* ── Step 1: the credentials ── */
757
- const submitCredentials = (e: FormEvent) => {
758
- e.preventDefault();
759
- const sent = email.trim();
760
- if (sent === "" || password === "") return;
761
- attempt("password", () => onSubmit({ email: sent, password }), sent);
762
- };
763
-
764
- const refused = failure?.code === "invalid_credentials";
765
- const tagged =
766
- refused && failure?.action === "password" && emailTag && failure.email
767
- ? taggedEmail(failure.email, emailTag)
768
- : null;
769
- const showDeactivated = refused && hasContent(deactivatedContact);
770
-
771
- return (
772
- <div {...rest} data-step="credentials" className={rootClass}>
773
- <form className="space-y-3" onSubmit={submitCredentials}>
774
- {credentialsContent}
775
- <Input
776
- ref={emailRef}
777
- type="email"
778
- name="email"
779
- // "webauthn" lets the browser list passkeys in this field's dropdown, paired
780
- // with the conditional request `passkeyAutofill` arms.
781
- autoComplete="username webauthn"
782
- label={labels.email}
783
- value={email}
784
- onChange={(e) => setEmail(e.target.value)}
785
- readOnly={working}
786
- required
787
- />
788
- <CurrentPasswordInput
789
- ref={passwordRef}
790
- name="password"
791
- label={labels.password}
792
- value={password}
793
- onValueChange={setPassword}
794
- busy={working}
795
- required
796
- />
797
- {failure && (
798
- // One live region for the sentence and its hints: they are one answer.
799
- <div role="alert" className="space-y-1.5">
800
- <AlertBanner tone="danger" size="sm">
801
- {failure.message}
802
- </AlertBanner>
803
- {showDeactivated && <p className={HINT_CLASS}>{withContact(labels.deactivatedHint, deactivatedContact)}</p>}
804
- {tagged && <p className={HINT_CLASS}>{labels.tagHint(tagged)}</p>}
805
- </div>
806
- )}
807
- <Button
808
- type="submit"
809
- className="w-full"
810
- pending={busy === "password" || busy === "done"}
811
- disabled={busy === "passkey"}
812
- >
813
- {labels.submit}
814
- </Button>
815
- {onPasskey && (
816
- <Button
817
- type="button"
818
- variant="secondary"
819
- className="w-full"
820
- pending={busy === "passkey"}
821
- disabled={busy === "password" || busy === "done"}
822
- onClick={() => attempt("passkey", onPasskey)}
823
- >
824
- <KeyRound aria-hidden className="size-4" />
825
- {labels.passkey}
826
- </Button>
827
- )}
828
- </form>
829
- {forgotHref !== undefined && (
830
- <p className="text-center text-sm">
831
- <TextLink href={forgotHref} tone="secondary">
832
- {labels.forgotPassword}
833
- </TextLink>
834
- </p>
835
- )}
836
- {accountLink !== null && (
837
- <p className="text-center text-sm text-secondary">
838
- {labels.noAccount}{" "}
839
- <TextLink href={accountLink.href} tone="primary">
840
- {accountLink.label}
841
- </TextLink>
842
- </p>
843
- )}
844
- </div>
845
- );
846
- }
847
-
848
- /** "Back to sign in" under the second and third step: a button, since it changes the
849
- * step in place rather than going anywhere. */
850
- function BackLink({ label, onClick, disabled }: { label: string; onClick: () => void; disabled: boolean }) {
851
- return (
852
- <p className="text-center text-sm">
853
- <Button type="button" variant="link" tone="muted" size="sm" disabled={disabled} onClick={onClick}>
854
- {label}
855
- </Button>
856
- </p>
857
- );
858
- }