@eifi1/ui-kit 0.51.6 → 0.52.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 (805) hide show
  1. package/README.md +146 -26
  2. package/dist/account/account-parts.d.ts +10 -8
  3. package/dist/account/account-parts.js +1 -18
  4. package/dist/account/account-parts.js.map +1 -1
  5. package/dist/account/data-export-setting-labels.js +1 -1
  6. package/dist/account/data-export-setting-labels.js.map +1 -1
  7. package/dist/account/delete-account-setting-labels.js +1 -1
  8. package/dist/account/delete-account-setting-labels.js.map +1 -1
  9. package/dist/account/email-change-setting-labels.js +1 -1
  10. package/dist/account/email-change-setting-labels.js.map +1 -1
  11. package/dist/account/passkeys-setting.d.ts +9 -2
  12. package/dist/account/passkeys-setting.js +41 -29
  13. package/dist/account/passkeys-setting.js.map +1 -1
  14. package/dist/account/sessions-setting.d.ts +3 -2
  15. package/dist/account/sessions-setting.js +10 -8
  16. package/dist/account/sessions-setting.js.map +1 -1
  17. package/dist/admin/admin-action-confirm.js +3 -7
  18. package/dist/admin/admin-action-confirm.js.map +1 -1
  19. package/dist/admin/admin-parts.d.ts +6 -3
  20. package/dist/admin/admin-parts.js +6 -21
  21. package/dist/admin/admin-parts.js.map +1 -1
  22. package/dist/admin/mail-test-card-labels.js +1 -1
  23. package/dist/admin/mail-test-card-labels.js.map +1 -1
  24. package/dist/admin/plan-change-labels.d.ts +2 -2
  25. package/dist/admin/plan-change-labels.js +1 -17
  26. package/dist/admin/plan-change-labels.js.map +1 -1
  27. package/dist/admin/plan-change.d.ts +3 -42
  28. package/dist/admin/plan-change.js +1 -1
  29. package/dist/admin/plan-change.js.map +1 -1
  30. package/dist/admin/reviewer-scope-editor.js +3 -3
  31. package/dist/admin/reviewer-scope-editor.js.map +1 -1
  32. package/dist/auth/auth-errors-labels.d.ts +11 -0
  33. package/dist/auth/auth-errors-labels.js +13 -0
  34. package/dist/auth/auth-errors-labels.js.map +1 -0
  35. package/dist/auth/auth-errors.d.ts +7 -23
  36. package/dist/auth/auth-errors.js +2 -15
  37. package/dist/auth/auth-errors.js.map +1 -1
  38. package/dist/auth/complete-name-dialog.d.ts +3 -2
  39. package/dist/auth/complete-name-dialog.js +3 -5
  40. package/dist/auth/complete-name-dialog.js.map +1 -1
  41. package/dist/auth/forgot-password-form-labels.js +1 -1
  42. package/dist/auth/forgot-password-form-labels.js.map +1 -1
  43. package/dist/auth/forgot-password-form.js +7 -2
  44. package/dist/auth/forgot-password-form.js.map +1 -1
  45. package/dist/auth/register-form-labels.js +1 -1
  46. package/dist/auth/register-form-labels.js.map +1 -1
  47. package/dist/auth/reset-password-form-labels.js +1 -1
  48. package/dist/auth/reset-password-form-labels.js.map +1 -1
  49. package/dist/auth/reset-password-form.js +5 -1
  50. package/dist/auth/reset-password-form.js.map +1 -1
  51. package/dist/auth/sign-in-form-labels.js +1 -1
  52. package/dist/auth/sign-in-form-labels.js.map +1 -1
  53. package/dist/auth/status-parts.d.ts +0 -3
  54. package/dist/auth/status-parts.js +0 -4
  55. package/dist/auth/status-parts.js.map +1 -1
  56. package/dist/auth/verify-email-labels.js +1 -1
  57. package/dist/auth/verify-email-labels.js.map +1 -1
  58. package/dist/auth/verify-email.js +7 -2
  59. package/dist/auth/verify-email.js.map +1 -1
  60. package/dist/billing/cancel-request.d.ts +11 -2
  61. package/dist/billing/cancel-request.js +15 -3
  62. package/dist/billing/cancel-request.js.map +1 -1
  63. package/dist/billing/cancel-subscription.d.ts +22 -10
  64. package/dist/billing/cancel-subscription.js +8 -11
  65. package/dist/billing/cancel-subscription.js.map +1 -1
  66. package/dist/billing/dialog-close.d.ts +29 -0
  67. package/dist/billing/dialog-close.js +8 -0
  68. package/dist/billing/dialog-close.js.map +1 -0
  69. package/dist/billing/plan-card.d.ts +14 -4
  70. package/dist/billing/plan-card.js +15 -8
  71. package/dist/billing/plan-card.js.map +1 -1
  72. package/dist/billing/plan-change-labels.d.ts +42 -0
  73. package/dist/billing/plan-change-labels.js +22 -0
  74. package/dist/billing/plan-change-labels.js.map +1 -0
  75. package/dist/billing/plan-switch.d.ts +21 -9
  76. package/dist/billing/plan-switch.js +10 -8
  77. package/dist/billing/plan-switch.js.map +1 -1
  78. package/dist/chart.d.ts +12 -0
  79. package/dist/chart.js +16 -1
  80. package/dist/chart.js.map +1 -1
  81. package/dist/components/account-chips.d.ts +5 -5
  82. package/dist/components/account-chips.js +11 -13
  83. package/dist/components/account-chips.js.map +1 -1
  84. package/dist/components/alert-banner.d.ts +16 -5
  85. package/dist/components/alert-banner.js +46 -1
  86. package/dist/components/alert-banner.js.map +1 -1
  87. package/dist/components/amount-input.d.ts +22 -4
  88. package/dist/components/amount-input.js +3 -3
  89. package/dist/components/amount-input.js.map +1 -1
  90. package/dist/components/autocomplete.js +57 -65
  91. package/dist/components/autocomplete.js.map +1 -1
  92. package/dist/components/bulk-action-bar.d.ts +12 -2
  93. package/dist/components/bulk-action-bar.js +65 -21
  94. package/dist/components/bulk-action-bar.js.map +1 -1
  95. package/dist/components/button-look.d.ts +5 -5
  96. package/dist/components/button-look.js.map +1 -1
  97. package/dist/components/button.d.ts +2 -2
  98. package/dist/components/button.js.map +1 -1
  99. package/dist/components/calculator.d.ts +21 -2
  100. package/dist/components/calculator.js +53 -14
  101. package/dist/components/calculator.js.map +1 -1
  102. package/dist/components/chart-edge.d.ts +16 -0
  103. package/dist/components/chart-edge.js +14 -1
  104. package/dist/components/chart-edge.js.map +1 -1
  105. package/dist/components/chart-figure.d.ts +13 -0
  106. package/dist/components/chart-figure.js +15 -0
  107. package/dist/components/chart-figure.js.map +1 -0
  108. package/dist/components/chart-zoom-core.js +1 -4
  109. package/dist/components/chart-zoom-core.js.map +1 -1
  110. package/dist/components/chart.d.ts +8 -1
  111. package/dist/components/chart.js +19 -10
  112. package/dist/components/chart.js.map +1 -1
  113. package/dist/components/combobox-core.d.ts +119 -7
  114. package/dist/components/combobox-core.js +151 -46
  115. package/dist/components/combobox-core.js.map +1 -1
  116. package/dist/components/combobox.d.ts +1 -1
  117. package/dist/components/combobox.js +142 -131
  118. package/dist/components/combobox.js.map +1 -1
  119. package/dist/components/copy-button.d.ts +6 -5
  120. package/dist/components/copy-button.js +5 -3
  121. package/dist/components/copy-button.js.map +1 -1
  122. package/dist/components/country-select.js +2 -2
  123. package/dist/components/country-select.js.map +1 -1
  124. package/dist/components/data-table-column-settings.d.ts +1 -1
  125. package/dist/components/data-table-column-settings.js +33 -7
  126. package/dist/components/data-table-column-settings.js.map +1 -1
  127. package/dist/components/data-table-filters.d.ts +4 -2
  128. package/dist/components/data-table-filters.js +2 -2
  129. package/dist/components/data-table-filters.js.map +1 -1
  130. package/dist/components/data-table-fit.d.ts +6 -4
  131. package/dist/components/data-table-fit.js +4 -1
  132. package/dist/components/data-table-fit.js.map +1 -1
  133. package/dist/components/data-table-groups.d.ts +1 -1
  134. package/dist/components/data-table-groups.js.map +1 -1
  135. package/dist/components/data-table-head.d.ts +1 -1
  136. package/dist/components/data-table-head.js +15 -12
  137. package/dist/components/data-table-head.js.map +1 -1
  138. package/dist/components/data-table-mobile.d.ts +36 -7
  139. package/dist/components/data-table-mobile.js +63 -31
  140. package/dist/components/data-table-mobile.js.map +1 -1
  141. package/dist/components/data-table-pagination.js +11 -6
  142. package/dist/components/data-table-pagination.js.map +1 -1
  143. package/dist/components/data-table-resize.d.ts +1 -1
  144. package/dist/components/data-table-resize.js.map +1 -1
  145. package/dist/components/data-table-row-actions.d.ts +2 -2
  146. package/dist/components/data-table-row-actions.js.map +1 -1
  147. package/dist/components/data-table-row.d.ts +6 -2
  148. package/dist/components/data-table-row.js +17 -10
  149. package/dist/components/data-table-row.js.map +1 -1
  150. package/dist/components/data-table-selection.d.ts +1 -1
  151. package/dist/components/data-table-selection.js.map +1 -1
  152. package/dist/components/data-table-shared.d.ts +10 -2
  153. package/dist/components/data-table-shared.js +18 -0
  154. package/dist/components/data-table-shared.js.map +1 -1
  155. package/dist/components/data-table-sort.d.ts +21 -2
  156. package/dist/components/data-table-sort.js +24 -0
  157. package/dist/components/data-table-sort.js.map +1 -1
  158. package/dist/components/data-table-virtual.d.ts +1 -1
  159. package/dist/components/data-table-virtual.js +18 -6
  160. package/dist/components/data-table-virtual.js.map +1 -1
  161. package/dist/components/data-table.d.ts +25 -8
  162. package/dist/components/data-table.js +154 -25
  163. package/dist/components/data-table.js.map +1 -1
  164. package/dist/components/date-field.d.ts +24 -2
  165. package/dist/components/date-field.js +33 -8
  166. package/dist/components/date-field.js.map +1 -1
  167. package/dist/components/date-picker.d.ts +15 -2
  168. package/dist/components/date-picker.js +55 -26
  169. package/dist/components/date-picker.js.map +1 -1
  170. package/dist/components/date-range-picker.d.ts +47 -20
  171. package/dist/components/date-range-picker.js +23 -7
  172. package/dist/components/date-range-picker.js.map +1 -1
  173. package/dist/components/dialog-frame.d.ts +2 -1
  174. package/dist/components/dialog-frame.js.map +1 -1
  175. package/dist/components/entity-combobox.js +4 -2
  176. package/dist/components/entity-combobox.js.map +1 -1
  177. package/dist/components/error-boundary.js +37 -30
  178. package/dist/components/error-boundary.js.map +1 -1
  179. package/dist/components/{ui-labels.d.ts → field-base-labels.d.ts} +0 -2
  180. package/dist/components/{ui-labels.js → field-base-labels.js} +2 -9
  181. package/dist/components/field-base-labels.js.map +1 -0
  182. package/dist/components/field-base.d.ts +4 -3
  183. package/dist/components/field-base.js +3 -3
  184. package/dist/components/field-base.js.map +1 -1
  185. package/dist/components/field-sync-labels.d.ts +1 -0
  186. package/dist/components/field-sync-labels.js.map +1 -1
  187. package/dist/components/field-sync.d.ts +23 -1
  188. package/dist/components/field-sync.js.map +1 -1
  189. package/dist/components/form-actions.js +11 -5
  190. package/dist/components/form-actions.js.map +1 -1
  191. package/dist/components/hover-menu.d.ts +3 -0
  192. package/dist/components/hover-menu.js +5 -3
  193. package/dist/components/hover-menu.js.map +1 -1
  194. package/dist/components/icon-button.js +14 -9
  195. package/dist/components/icon-button.js.map +1 -1
  196. package/dist/components/inline-confirm.d.ts +43 -0
  197. package/dist/components/inline-confirm.js +67 -0
  198. package/dist/components/inline-confirm.js.map +1 -0
  199. package/dist/components/inline-entity-combobox.d.ts +4 -3
  200. package/dist/components/inline-entity-combobox.js +150 -141
  201. package/dist/components/inline-entity-combobox.js.map +1 -1
  202. package/dist/components/input.js +1 -1
  203. package/dist/components/input.js.map +1 -1
  204. package/dist/components/jump-calendar.js +28 -112
  205. package/dist/components/jump-calendar.js.map +1 -1
  206. package/dist/components/legal-page.d.ts +3 -1
  207. package/dist/components/legal-page.js +3 -2
  208. package/dist/components/legal-page.js.map +1 -1
  209. package/dist/components/legal.d.ts +4 -2
  210. package/dist/components/legal.js.map +1 -1
  211. package/dist/components/lightbox.d.ts +2 -2
  212. package/dist/components/lightbox.js +17 -6
  213. package/dist/components/lightbox.js.map +1 -1
  214. package/dist/components/list.d.ts +6 -2
  215. package/dist/components/list.js +4 -3
  216. package/dist/components/list.js.map +1 -1
  217. package/dist/components/measured-grid.d.ts +1 -1
  218. package/dist/components/measured-grid.js +2 -1
  219. package/dist/components/measured-grid.js.map +1 -1
  220. package/dist/components/mini-calendar.js +3 -5
  221. package/dist/components/mini-calendar.js.map +1 -1
  222. package/dist/components/modal.d.ts +24 -0
  223. package/dist/components/modal.js +12 -4
  224. package/dist/components/modal.js.map +1 -1
  225. package/dist/components/money-draft.js +7 -5
  226. package/dist/components/money-draft.js.map +1 -1
  227. package/dist/components/money-field.d.ts +2 -2
  228. package/dist/components/money-field.js.map +1 -1
  229. package/dist/components/month-grid.d.ts +55 -0
  230. package/dist/components/month-grid.js +148 -0
  231. package/dist/components/month-grid.js.map +1 -0
  232. package/dist/components/month-picker.d.ts +36 -4
  233. package/dist/components/month-picker.js +123 -146
  234. package/dist/components/month-picker.js.map +1 -1
  235. package/dist/components/multi-entity-combobox.js +2 -1
  236. package/dist/components/multi-entity-combobox.js.map +1 -1
  237. package/dist/components/multi-select.d.ts +2 -2
  238. package/dist/components/multi-select.js +11 -6
  239. package/dist/components/multi-select.js.map +1 -1
  240. package/dist/components/number-field.d.ts +6 -4
  241. package/dist/components/number-field.js +3 -2
  242. package/dist/components/number-field.js.map +1 -1
  243. package/dist/components/number-input.d.ts +4 -1
  244. package/dist/components/number-input.js +3 -2
  245. package/dist/components/number-input.js.map +1 -1
  246. package/dist/components/numpad-sheet.js.map +1 -1
  247. package/dist/components/picker-sheet.js +2 -1
  248. package/dist/components/picker-sheet.js.map +1 -1
  249. package/dist/components/pie-chart-labels.d.ts +7 -0
  250. package/dist/components/pie-chart-labels.js +1 -0
  251. package/dist/components/pie-chart-labels.js.map +1 -1
  252. package/dist/components/pie-chart.d.ts +5 -3
  253. package/dist/components/pie-chart.js +7 -22
  254. package/dist/components/pie-chart.js.map +1 -1
  255. package/dist/components/popover.d.ts +3 -0
  256. package/dist/components/popover.js +7 -1
  257. package/dist/components/popover.js.map +1 -1
  258. package/dist/components/reauth-dialog.d.ts +4 -5
  259. package/dist/components/reauth-dialog.js +1 -4
  260. package/dist/components/reauth-dialog.js.map +1 -1
  261. package/dist/components/row-actions.js +2 -1
  262. package/dist/components/row-actions.js.map +1 -1
  263. package/dist/components/section-nav.d.ts +7 -0
  264. package/dist/components/section-nav.js.map +1 -1
  265. package/dist/components/series-chart-axes.d.ts +10 -3
  266. package/dist/components/series-chart-axes.js +1 -0
  267. package/dist/components/series-chart-axes.js.map +1 -1
  268. package/dist/components/series-chart-labels.d.ts +7 -4
  269. package/dist/components/series-chart-labels.js.map +1 -1
  270. package/dist/components/series-chart.d.ts +31 -7
  271. package/dist/components/series-chart.js +72 -29
  272. package/dist/components/series-chart.js.map +1 -1
  273. package/dist/components/share-card.js +3 -3
  274. package/dist/components/share-card.js.map +1 -1
  275. package/dist/components/sign-chip-labels.d.ts +1 -0
  276. package/dist/components/sign-chip-labels.js.map +1 -1
  277. package/dist/components/sign-chip.d.ts +10 -1
  278. package/dist/components/sign-chip.js.map +1 -1
  279. package/dist/components/tabs-labels.d.ts +2 -0
  280. package/dist/components/tabs-labels.js +11 -0
  281. package/dist/components/tabs-labels.js.map +1 -0
  282. package/dist/components/tabs.d.ts +1 -1
  283. package/dist/components/tabs.js +13 -11
  284. package/dist/components/tabs.js.map +1 -1
  285. package/dist/components/toggle-legend.d.ts +2 -2
  286. package/dist/components/toggle-legend.js +6 -6
  287. package/dist/components/toggle-legend.js.map +1 -1
  288. package/dist/components/translation-review-editor.d.ts +4 -2
  289. package/dist/components/translation-review-editor.js +2 -3
  290. package/dist/components/translation-review-editor.js.map +1 -1
  291. package/dist/components/translation-review.d.ts +2 -1
  292. package/dist/components/translation-review.js +2 -2
  293. package/dist/components/translation-review.js.map +1 -1
  294. package/dist/components/treemap-labels.d.ts +26 -0
  295. package/dist/components/treemap-labels.js +10 -0
  296. package/dist/components/treemap-labels.js.map +1 -0
  297. package/dist/components/treemap-layout.d.ts +62 -0
  298. package/dist/components/treemap-layout.js +126 -0
  299. package/dist/components/treemap-layout.js.map +1 -0
  300. package/dist/components/treemap.d.ts +140 -17
  301. package/dist/components/treemap.js +324 -97
  302. package/dist/components/treemap.js.map +1 -1
  303. package/dist/components/use-table-state.d.ts +5 -5
  304. package/dist/components/use-table-state.js +4 -1
  305. package/dist/components/use-table-state.js.map +1 -1
  306. package/dist/data-table.d.ts +6 -2
  307. package/dist/data-table.js +7 -2
  308. package/dist/data-table.js.map +1 -1
  309. package/dist/eslint/index.js +1 -1
  310. package/dist/eslint/role-utilities.d.ts +36 -7
  311. package/dist/eslint/role-utilities.js +42 -9
  312. package/dist/eslint/role-utilities.js.map +1 -1
  313. package/dist/feedback/feedback-dialog.d.ts +25 -16
  314. package/dist/feedback/feedback-dialog.js +6 -2
  315. package/dist/feedback/feedback-dialog.js.map +1 -1
  316. package/dist/feedback/feedback-mutation.d.ts +30 -0
  317. package/dist/feedback/feedback-mutation.js +16 -0
  318. package/dist/feedback/feedback-mutation.js.map +1 -0
  319. package/dist/feedback/feedback-page-link.d.ts +53 -0
  320. package/dist/feedback/feedback-page-link.js +37 -0
  321. package/dist/feedback/feedback-page-link.js.map +1 -0
  322. package/dist/feedback/feedback-public-list.d.ts +12 -3
  323. package/dist/feedback/feedback-public-list.js +2 -1
  324. package/dist/feedback/feedback-public-list.js.map +1 -1
  325. package/dist/feedback/feedback-replies.d.ts +3 -1
  326. package/dist/feedback/feedback-replies.js +5 -4
  327. package/dist/feedback/feedback-replies.js.map +1 -1
  328. package/dist/feedback/feedback-row-detail-labels.js +5 -0
  329. package/dist/feedback/feedback-row-detail-labels.js.map +1 -1
  330. package/dist/feedback/feedback-row-detail.d.ts +64 -28
  331. package/dist/feedback/feedback-row-detail.js +30 -28
  332. package/dist/feedback/feedback-row-detail.js.map +1 -1
  333. package/dist/feedback/feedback-status-undo.d.ts +30 -11
  334. package/dist/feedback/feedback-status-undo.js +10 -15
  335. package/dist/feedback/feedback-status-undo.js.map +1 -1
  336. package/dist/feedback/feedback-submit-dialog.d.ts +1 -1
  337. package/dist/feedback/feedback-submit-dialog.js +1 -1
  338. package/dist/feedback/feedback-submit-dialog.js.map +1 -1
  339. package/dist/feedback/feedback-submit.js +9 -3
  340. package/dist/feedback/feedback-submit.js.map +1 -1
  341. package/dist/feedback/feedback-swipe.d.ts +1 -1
  342. package/dist/feedback/feedback-swipe.js.map +1 -1
  343. package/dist/feedback/feedback-table.d.ts +21 -9
  344. package/dist/feedback/feedback-table.js +45 -25
  345. package/dist/feedback/feedback-table.js.map +1 -1
  346. package/dist/feedback/feedback-thread-labels.d.ts +2 -2
  347. package/dist/feedback/feedback-thread-labels.js.map +1 -1
  348. package/dist/feedback/feedback-thread.d.ts +24 -23
  349. package/dist/feedback/feedback-thread.js +2 -1
  350. package/dist/feedback/feedback-thread.js.map +1 -1
  351. package/dist/feedback.d.ts +34 -0
  352. package/dist/feedback.js +42 -0
  353. package/dist/feedback.js.map +1 -1
  354. package/dist/hooks/use-dismiss.js.map +1 -1
  355. package/dist/hooks/use-focus-trap.d.ts +35 -0
  356. package/dist/hooks/use-focus-trap.js +6 -4
  357. package/dist/hooks/use-focus-trap.js.map +1 -1
  358. package/dist/hooks/use-hotkey.d.ts +5 -2
  359. package/dist/hooks/use-hotkey.js +5 -4
  360. package/dist/hooks/use-hotkey.js.map +1 -1
  361. package/dist/hooks/use-long-press.d.ts +7 -4
  362. package/dist/hooks/use-long-press.js +3 -0
  363. package/dist/hooks/use-long-press.js.map +1 -1
  364. package/dist/hooks/use-media-query.js +12 -4
  365. package/dist/hooks/use-media-query.js.map +1 -1
  366. package/dist/hooks/use-mounted.d.ts +22 -0
  367. package/dist/hooks/use-mounted.js +24 -0
  368. package/dist/hooks/use-mounted.js.map +1 -0
  369. package/dist/hooks/use-overlay-history.d.ts +7 -1
  370. package/dist/hooks/use-overlay-history.js +35 -5
  371. package/dist/hooks/use-overlay-history.js.map +1 -1
  372. package/dist/i18n/defaults.js +4 -5
  373. package/dist/i18n/defaults.js.map +1 -1
  374. package/dist/i18n/german.js +7 -1
  375. package/dist/i18n/german.js.map +1 -1
  376. package/dist/i18n/kit-labels.d.ts +9 -2
  377. package/dist/i18n/kit-labels.js.map +1 -1
  378. package/dist/i18n/locales/en.js +20 -41
  379. package/dist/i18n/locales/en.js.map +3 -3
  380. package/dist/i18n/locales/es.js +7 -1
  381. package/dist/i18n/locales/es.js.map +1 -1
  382. package/dist/i18n/locales/fr.js +20 -10
  383. package/dist/i18n/locales/fr.js.map +1 -1
  384. package/dist/i18n/locales/hu.js +9 -1
  385. package/dist/i18n/locales/hu.js.map +1 -1
  386. package/dist/i18n/locales/it.js +7 -1
  387. package/dist/i18n/locales/it.js.map +1 -1
  388. package/dist/i18n/locales/zh.js +8 -1
  389. package/dist/i18n/locales/zh.js.map +1 -1
  390. package/dist/i18n/review.js +5 -0
  391. package/dist/i18n/review.js.map +1 -1
  392. package/dist/index.d.ts +64 -17
  393. package/dist/index.js +77 -12
  394. package/dist/index.js.map +1 -1
  395. package/dist/landing/routing.d.ts +3 -1
  396. package/dist/landing/routing.js +4 -7
  397. package/dist/landing/routing.js.map +1 -1
  398. package/dist/lib/broadcast.d.ts +17 -0
  399. package/dist/lib/broadcast.js +30 -0
  400. package/dist/lib/broadcast.js.map +1 -0
  401. package/dist/lib/calc.d.ts +7 -1
  402. package/dist/lib/calc.js +3 -1
  403. package/dist/lib/calc.js.map +1 -1
  404. package/dist/lib/clipboard-minus.d.ts +2 -2
  405. package/dist/lib/clipboard-minus.js +1 -1
  406. package/dist/lib/clipboard-minus.js.map +1 -1
  407. package/dist/lib/date-format.d.ts +37 -2
  408. package/dist/lib/date-format.js +34 -8
  409. package/dist/lib/date-format.js.map +1 -1
  410. package/dist/lib/day-format.d.ts +46 -0
  411. package/dist/lib/day-format.js +46 -0
  412. package/dist/lib/day-format.js.map +1 -0
  413. package/dist/lib/decimal-marks.d.ts +7 -1
  414. package/dist/lib/decimal-marks.js +5 -2
  415. package/dist/lib/decimal-marks.js.map +1 -1
  416. package/dist/lib/describe-failure.d.ts +14 -0
  417. package/dist/lib/describe-failure.js +9 -0
  418. package/dist/lib/describe-failure.js.map +1 -0
  419. package/dist/lib/direction.d.ts +16 -0
  420. package/dist/lib/direction.js +9 -1
  421. package/dist/lib/direction.js.map +1 -1
  422. package/dist/lib/focus-left.d.ts +63 -0
  423. package/dist/lib/focus-left.js +67 -0
  424. package/dist/lib/focus-left.js.map +1 -0
  425. package/dist/lib/format.d.ts +5 -3
  426. package/dist/lib/format.js +16 -13
  427. package/dist/lib/format.js.map +1 -1
  428. package/dist/lib/http-status.d.ts +24 -0
  429. package/dist/lib/http-status.js +14 -0
  430. package/dist/lib/http-status.js.map +1 -0
  431. package/dist/lib/intl-cache.d.ts +14 -0
  432. package/dist/lib/intl-cache.js +15 -0
  433. package/dist/lib/intl-cache.js.map +1 -0
  434. package/dist/lib/isin.d.ts +10 -0
  435. package/dist/lib/isin.js.map +1 -1
  436. package/dist/lib/iso-day.d.ts +11 -0
  437. package/dist/lib/iso-day.js +8 -0
  438. package/dist/lib/iso-day.js.map +1 -0
  439. package/dist/lib/lazy-with-fallback.d.ts +31 -0
  440. package/dist/lib/lazy-with-fallback.js +40 -0
  441. package/dist/lib/lazy-with-fallback.js.map +1 -0
  442. package/dist/lib/path-pattern.d.ts +34 -0
  443. package/dist/lib/path-pattern.js +24 -0
  444. package/dist/lib/path-pattern.js.map +1 -0
  445. package/dist/lib/reduced-motion.d.ts +2 -1
  446. package/dist/lib/reduced-motion.js.map +1 -1
  447. package/dist/lib/round.d.ts +2 -1
  448. package/dist/lib/round.js +2 -1
  449. package/dist/lib/round.js.map +1 -1
  450. package/dist/lib/safe-storage.d.ts +24 -5
  451. package/dist/lib/safe-storage.js +27 -2
  452. package/dist/lib/safe-storage.js.map +1 -1
  453. package/dist/lib/session-refresh.js +1 -1
  454. package/dist/lib/session-refresh.js.map +1 -1
  455. package/dist/lib/share-format.d.ts +13 -0
  456. package/dist/lib/share-format.js +10 -0
  457. package/dist/lib/share-format.js.map +1 -0
  458. package/dist/lib/text-case.d.ts +17 -0
  459. package/dist/lib/text-case.js +8 -0
  460. package/dist/lib/text-case.js.map +1 -0
  461. package/dist/lib/text-match.d.ts +38 -0
  462. package/dist/lib/text-match.js +24 -2
  463. package/dist/lib/text-match.js.map +1 -1
  464. package/dist/lib/thenable.d.ts +13 -0
  465. package/dist/lib/thenable.js +8 -0
  466. package/dist/lib/thenable.js.map +1 -0
  467. package/dist/lib/translation-review.d.ts +7 -2
  468. package/dist/lib/translation-review.js +4 -4
  469. package/dist/lib/translation-review.js.map +1 -1
  470. package/dist/notifications/device-zone-report.js +1 -1
  471. package/dist/notifications/device-zone-report.js.map +1 -1
  472. package/dist/notifications/notification-bell.d.ts +2 -1
  473. package/dist/notifications/notification-bell.js +3 -3
  474. package/dist/notifications/notification-bell.js.map +1 -1
  475. package/dist/notifications/notification-inbox.d.ts +10 -6
  476. package/dist/notifications/notification-inbox.js +26 -48
  477. package/dist/notifications/notification-inbox.js.map +1 -1
  478. package/dist/notifications/notification-parts.d.ts +3 -2
  479. package/dist/notifications/notification-parts.js +1 -3
  480. package/dist/notifications/notification-parts.js.map +1 -1
  481. package/dist/notifications/notification-types-setting.js +1 -1
  482. package/dist/notifications/notification-types-setting.js.map +1 -1
  483. package/dist/notifications/notifications-labels.d.ts +6 -0
  484. package/dist/notifications/notifications-labels.js +1 -0
  485. package/dist/notifications/notifications-labels.js.map +1 -1
  486. package/dist/notifications/push-device-setting.js +1 -1
  487. package/dist/notifications/push-device-setting.js.map +1 -1
  488. package/dist/notifications/push-devices-setting.d.ts +2 -1
  489. package/dist/notifications/push-devices-setting.js +27 -49
  490. package/dist/notifications/push-devices-setting.js.map +1 -1
  491. package/dist/notifications/quiet-hours-setting.d.ts +10 -3
  492. package/dist/notifications/quiet-hours-setting.js +65 -26
  493. package/dist/notifications/quiet-hours-setting.js.map +1 -1
  494. package/dist/notifications/unsubscribe-panel.js +4 -7
  495. package/dist/notifications/unsubscribe-panel.js.map +1 -1
  496. package/dist/notifications/use-push-device.d.ts +39 -1
  497. package/dist/notifications/use-push-device.js +28 -7
  498. package/dist/notifications/use-push-device.js.map +1 -1
  499. package/dist/offline/query-persistence.d.ts +3 -1
  500. package/dist/offline/query-persistence.js +19 -2
  501. package/dist/offline/query-persistence.js.map +1 -1
  502. package/dist/rhf/fields.d.ts +11 -4
  503. package/dist/rhf/fields.js.map +1 -1
  504. package/dist/search/command-palette.js +1 -1
  505. package/dist/search/command-palette.js.map +1 -1
  506. package/dist/search/global-search.js +19 -9
  507. package/dist/search/global-search.js.map +1 -1
  508. package/dist/search/use-command-key.d.ts +12 -1
  509. package/dist/search/use-command-key.js +3 -12
  510. package/dist/search/use-command-key.js.map +1 -1
  511. package/dist/search.d.ts +7 -0
  512. package/dist/search.js +10 -0
  513. package/dist/search.js.map +1 -1
  514. package/dist/settings/use-settings-focus.js +1 -0
  515. package/dist/settings/use-settings-focus.js.map +1 -1
  516. package/dist/shell/account-menu-language.d.ts +21 -5
  517. package/dist/shell/account-menu-language.js +3 -1
  518. package/dist/shell/account-menu-language.js.map +1 -1
  519. package/dist/shell/account-menu-text-size.d.ts +26 -9
  520. package/dist/shell/account-menu-text-size.js +3 -2
  521. package/dist/shell/account-menu-text-size.js.map +1 -1
  522. package/dist/shell/dev-menu.js +5 -18
  523. package/dist/shell/dev-menu.js.map +1 -1
  524. package/dist/shell/role-switcher.d.ts +7 -0
  525. package/dist/shell/role-switcher.js.map +1 -1
  526. package/dist/shell/top-bar-actions.d.ts +1 -1
  527. package/dist/shell/top-bar-actions.js.map +1 -1
  528. package/dist/shell/top-bar-parts-labels.d.ts +0 -2
  529. package/dist/shell/top-bar-parts-labels.js +0 -1
  530. package/dist/shell/top-bar-parts-labels.js.map +1 -1
  531. package/dist/shell.d.ts +27 -8
  532. package/dist/shell.js +28 -7
  533. package/dist/shell.js.map +1 -1
  534. package/dist/sync/engine.d.ts +30 -4
  535. package/dist/sync/engine.js +172 -52
  536. package/dist/sync/engine.js.map +1 -1
  537. package/dist/sync.d.ts +6 -2
  538. package/dist/sync.js +6 -1
  539. package/dist/sync.js.map +1 -1
  540. package/dist/testing/css-variables.js +3 -8
  541. package/dist/testing/css-variables.js.map +1 -1
  542. package/dist/theme/contrast.d.ts +2 -1
  543. package/dist/theme/contrast.js +3 -8
  544. package/dist/theme/contrast.js.map +1 -1
  545. package/dist/theme/palette-store.js +6 -6
  546. package/dist/theme/palette-store.js.map +1 -1
  547. package/dist/theme/text-size.js +3 -8
  548. package/dist/theme/text-size.js.map +1 -1
  549. package/dist/theme/theme-store.js +3 -6
  550. package/dist/theme/theme-store.js.map +1 -1
  551. package/dist/tour/tour-catalogue.d.ts +7 -4
  552. package/dist/tour/tour-catalogue.js +12 -10
  553. package/dist/tour/tour-catalogue.js.map +1 -1
  554. package/dist/tour/tour-dock.d.ts +0 -2
  555. package/dist/tour/tour-dock.js +0 -2
  556. package/dist/tour/tour-dock.js.map +1 -1
  557. package/dist/tour/tour-gates.d.ts +4 -0
  558. package/dist/tour/tour-gates.js +14 -0
  559. package/dist/tour/tour-gates.js.map +1 -1
  560. package/dist/tour/tour-overlay.d.ts +27 -0
  561. package/dist/tour/tour-overlay.js +741 -0
  562. package/dist/tour/tour-overlay.js.map +1 -0
  563. package/dist/tour/tour.d.ts +16 -4
  564. package/dist/tour/tour.js +62 -778
  565. package/dist/tour/tour.js.map +1 -1
  566. package/dist/tour/use-tour-progress.js +1 -1
  567. package/dist/tour/use-tour-progress.js.map +1 -1
  568. package/dist/tour/use-tour-url-sync.js +2 -2
  569. package/dist/tour/use-tour-url-sync.js.map +1 -1
  570. package/dist/wizard/stepper-nav.d.ts +5 -1
  571. package/dist/wizard/stepper-nav.js.map +1 -1
  572. package/dist/wizard/types.d.ts +6 -2
  573. package/dist/wizard/types.js.map +1 -1
  574. package/dist/wizard/use-wizard.d.ts +3 -1
  575. package/dist/wizard/use-wizard.js.map +1 -1
  576. package/dist/wizard/validation.d.ts +3 -1
  577. package/dist/wizard/validation.js.map +1 -1
  578. package/package.json +12 -8
  579. package/src/account/account-parts.ts +5 -25
  580. package/src/account/data-export-setting-labels.ts +1 -1
  581. package/src/account/delete-account-setting-labels.ts +1 -1
  582. package/src/account/email-change-setting-labels.ts +1 -1
  583. package/src/account/passkeys-setting.tsx +60 -38
  584. package/src/account/sessions-setting.tsx +18 -12
  585. package/src/admin/admin-action-confirm.tsx +5 -10
  586. package/src/admin/admin-parts.ts +11 -25
  587. package/src/admin/mail-test-card-labels.ts +1 -1
  588. package/src/admin/plan-change-labels.ts +5 -23
  589. package/src/admin/plan-change.tsx +7 -44
  590. package/src/admin/reviewer-scope-editor.tsx +3 -3
  591. package/src/auth/auth-errors-labels.ts +23 -0
  592. package/src/auth/auth-errors.ts +11 -38
  593. package/src/auth/complete-name-dialog.tsx +9 -8
  594. package/src/auth/forgot-password-form-labels.ts +1 -1
  595. package/src/auth/forgot-password-form.tsx +11 -6
  596. package/src/auth/register-form-labels.ts +1 -1
  597. package/src/auth/reset-password-form-labels.ts +1 -1
  598. package/src/auth/reset-password-form.tsx +8 -4
  599. package/src/auth/sign-in-form-labels.ts +1 -1
  600. package/src/auth/status-parts.tsx +0 -6
  601. package/src/auth/verify-email-labels.ts +1 -1
  602. package/src/auth/verify-email.tsx +11 -6
  603. package/src/billing/cancel-request.ts +28 -6
  604. package/src/billing/cancel-subscription.tsx +29 -22
  605. package/src/billing/dialog-close.ts +34 -0
  606. package/src/billing/plan-card.tsx +36 -11
  607. package/src/billing/plan-change-labels.ts +66 -0
  608. package/src/billing/plan-switch.tsx +31 -20
  609. package/src/chart.ts +21 -3
  610. package/src/components/account-chips.tsx +20 -23
  611. package/src/components/alert-banner.tsx +82 -5
  612. package/src/components/amount-input.tsx +32 -14
  613. package/src/components/autocomplete.tsx +64 -70
  614. package/src/components/bulk-action-bar.tsx +70 -2
  615. package/src/components/button-look.ts +5 -5
  616. package/src/components/button.tsx +2 -2
  617. package/src/components/calculator.tsx +98 -17
  618. package/src/components/chart-edge.ts +34 -1
  619. package/src/components/chart-figure.tsx +35 -0
  620. package/src/components/chart-zoom-core.tsx +6 -5
  621. package/src/components/chart.tsx +26 -5
  622. package/src/components/combobox-core.tsx +303 -69
  623. package/src/components/combobox.tsx +184 -155
  624. package/src/components/copy-button.tsx +34 -23
  625. package/src/components/country-select.tsx +16 -11
  626. package/src/components/data-table-column-settings.tsx +52 -10
  627. package/src/components/data-table-filters.ts +6 -4
  628. package/src/components/data-table-fit.ts +19 -5
  629. package/src/components/data-table-groups.tsx +1 -1
  630. package/src/components/data-table-head.tsx +32 -22
  631. package/src/components/data-table-mobile.tsx +110 -27
  632. package/src/components/data-table-pagination.tsx +21 -6
  633. package/src/components/data-table-resize.ts +1 -1
  634. package/src/components/data-table-row-actions.tsx +3 -3
  635. package/src/components/data-table-row.tsx +25 -14
  636. package/src/components/data-table-selection.ts +1 -1
  637. package/src/components/data-table-shared.tsx +33 -1
  638. package/src/components/data-table-sort.ts +57 -2
  639. package/src/components/data-table-virtual.ts +32 -8
  640. package/src/components/data-table.tsx +267 -41
  641. package/src/components/date-field.tsx +65 -8
  642. package/src/components/date-picker.tsx +125 -48
  643. package/src/components/date-range-picker.tsx +82 -31
  644. package/src/components/dialog-frame.tsx +2 -1
  645. package/src/components/entity-combobox.tsx +4 -1
  646. package/src/components/error-boundary.tsx +53 -39
  647. package/src/components/field-base-labels.ts +20 -0
  648. package/src/components/field-base.tsx +13 -7
  649. package/src/components/field-sync-labels.ts +1 -0
  650. package/src/components/field-sync.tsx +23 -1
  651. package/src/components/form-actions.tsx +20 -5
  652. package/src/components/hover-menu.tsx +18 -8
  653. package/src/components/icon-button.tsx +14 -9
  654. package/src/components/inline-confirm.tsx +116 -0
  655. package/src/components/inline-entity-combobox.tsx +198 -152
  656. package/src/components/input.tsx +1 -1
  657. package/src/components/jump-calendar.tsx +30 -146
  658. package/src/components/legal-page.tsx +10 -7
  659. package/src/components/legal.tsx +4 -2
  660. package/src/components/lightbox.tsx +21 -8
  661. package/src/components/list.tsx +14 -5
  662. package/src/components/measured-grid.tsx +8 -4
  663. package/src/components/mini-calendar.tsx +6 -5
  664. package/src/components/modal.tsx +45 -4
  665. package/src/components/money-draft.ts +16 -5
  666. package/src/components/money-field.tsx +2 -2
  667. package/src/components/month-grid.tsx +229 -0
  668. package/src/components/month-picker.tsx +192 -200
  669. package/src/components/multi-entity-combobox.tsx +1 -0
  670. package/src/components/multi-select.tsx +21 -9
  671. package/src/components/number-field.tsx +14 -7
  672. package/src/components/number-input.tsx +9 -3
  673. package/src/components/numpad-sheet.tsx +4 -3
  674. package/src/components/picker-sheet.tsx +12 -9
  675. package/src/components/pie-chart-labels.ts +8 -0
  676. package/src/components/pie-chart.tsx +22 -28
  677. package/src/components/popover.tsx +18 -1
  678. package/src/components/reauth-dialog.tsx +6 -10
  679. package/src/components/row-actions.tsx +2 -1
  680. package/src/components/section-nav.tsx +7 -0
  681. package/src/components/series-chart-axes.ts +11 -3
  682. package/src/components/series-chart-labels.ts +7 -4
  683. package/src/components/series-chart.tsx +178 -69
  684. package/src/components/share-card.tsx +6 -6
  685. package/src/components/sign-chip-labels.ts +1 -0
  686. package/src/components/sign-chip.tsx +10 -1
  687. package/src/components/tabs-labels.ts +13 -0
  688. package/src/components/tabs.tsx +35 -19
  689. package/src/components/toggle-legend.tsx +16 -11
  690. package/src/components/translation-review-editor.tsx +6 -5
  691. package/src/components/translation-review.tsx +4 -3
  692. package/src/components/treemap-labels.ts +39 -0
  693. package/src/components/treemap-layout.ts +210 -0
  694. package/src/components/treemap.tsx +722 -133
  695. package/src/components/use-table-state.ts +12 -9
  696. package/src/data-table.ts +9 -2
  697. package/src/eslint/role-utilities.ts +97 -19
  698. package/src/feedback/feedback-dialog.tsx +30 -19
  699. package/src/feedback/feedback-mutation.ts +41 -0
  700. package/src/feedback/feedback-page-link.ts +90 -0
  701. package/src/feedback/feedback-public-list.tsx +17 -5
  702. package/src/feedback/feedback-replies.tsx +13 -6
  703. package/src/feedback/feedback-row-detail-labels.ts +5 -0
  704. package/src/feedback/feedback-row-detail.tsx +103 -67
  705. package/src/feedback/feedback-status-undo.ts +41 -27
  706. package/src/feedback/feedback-submit-dialog.tsx +2 -2
  707. package/src/feedback/feedback-submit.tsx +21 -7
  708. package/src/feedback/feedback-swipe.tsx +1 -1
  709. package/src/feedback/feedback-table.tsx +86 -38
  710. package/src/feedback/feedback-thread-labels.ts +2 -2
  711. package/src/feedback/feedback-thread.tsx +27 -25
  712. package/src/feedback.ts +42 -0
  713. package/src/hooks/use-dismiss.ts +3 -2
  714. package/src/hooks/use-focus-trap.ts +8 -24
  715. package/src/hooks/use-hotkey.ts +24 -7
  716. package/src/hooks/use-long-press.ts +16 -2
  717. package/src/hooks/use-media-query.ts +20 -4
  718. package/src/hooks/use-mounted.ts +39 -0
  719. package/src/hooks/use-overlay-history.ts +70 -5
  720. package/src/i18n/defaults.ts +4 -5
  721. package/src/i18n/german.ts +8 -2
  722. package/src/i18n/kit-labels.tsx +9 -2
  723. package/src/i18n/locales/es.ts +8 -2
  724. package/src/i18n/locales/fr.ts +21 -13
  725. package/src/i18n/locales/hu.ts +10 -2
  726. package/src/i18n/locales/it.ts +8 -2
  727. package/src/i18n/locales/zh.ts +9 -2
  728. package/src/i18n/review.ts +5 -0
  729. package/src/index.ts +103 -13
  730. package/src/landing/routing.tsx +14 -10
  731. package/src/lib/broadcast.ts +52 -0
  732. package/src/lib/calc.ts +13 -2
  733. package/src/lib/clipboard-minus.ts +14 -4
  734. package/src/lib/date-format.ts +89 -13
  735. package/src/lib/day-format.ts +96 -0
  736. package/src/lib/decimal-marks.ts +12 -3
  737. package/src/lib/describe-failure.ts +18 -0
  738. package/src/lib/direction.ts +39 -0
  739. package/src/lib/focus-left.ts +156 -0
  740. package/src/lib/format.ts +34 -19
  741. package/src/lib/http-status.ts +38 -0
  742. package/src/lib/intl-cache.ts +25 -0
  743. package/src/lib/isin.ts +10 -0
  744. package/src/lib/iso-day.ts +13 -0
  745. package/src/lib/lazy-with-fallback.ts +82 -0
  746. package/src/lib/path-pattern.ts +55 -0
  747. package/src/lib/reduced-motion.ts +2 -1
  748. package/src/lib/round.ts +7 -2
  749. package/src/lib/safe-storage.ts +48 -6
  750. package/src/lib/session-refresh.ts +1 -1
  751. package/src/lib/share-format.ts +18 -0
  752. package/src/lib/text-case.ts +19 -0
  753. package/src/lib/text-match.ts +69 -2
  754. package/src/lib/thenable.ts +19 -0
  755. package/src/lib/translation-review.ts +13 -5
  756. package/src/notifications/device-zone-report.ts +1 -1
  757. package/src/notifications/notification-bell.tsx +7 -4
  758. package/src/notifications/notification-inbox.tsx +40 -58
  759. package/src/notifications/notification-parts.tsx +3 -4
  760. package/src/notifications/notification-types-setting.tsx +1 -1
  761. package/src/notifications/notifications-labels.ts +7 -0
  762. package/src/notifications/push-device-setting.tsx +1 -1
  763. package/src/notifications/push-devices-setting.tsx +30 -55
  764. package/src/notifications/quiet-hours-setting.tsx +93 -31
  765. package/src/notifications/unsubscribe-panel.tsx +4 -7
  766. package/src/notifications/use-push-device.ts +76 -10
  767. package/src/offline/query-persistence.ts +35 -3
  768. package/src/rhf/fields.tsx +11 -4
  769. package/src/search/command-palette.tsx +2 -4
  770. package/src/search/global-search.tsx +36 -15
  771. package/src/search/use-command-key.ts +13 -12
  772. package/src/search.ts +9 -0
  773. package/src/settings/use-settings-focus.ts +3 -0
  774. package/src/shell/account-menu-language.tsx +27 -5
  775. package/src/shell/account-menu-text-size.tsx +32 -10
  776. package/src/shell/dev-menu.tsx +7 -21
  777. package/src/shell/role-switcher.tsx +7 -0
  778. package/src/shell/top-bar-actions.tsx +1 -1
  779. package/src/shell/top-bar-parts-labels.ts +0 -3
  780. package/src/shell.ts +40 -9
  781. package/src/sync/engine.ts +339 -61
  782. package/src/sync.ts +8 -1
  783. package/src/testing/css-variables.ts +8 -9
  784. package/src/theme/contrast.ts +8 -9
  785. package/src/theme/palette-store.ts +9 -9
  786. package/src/theme/text-size.ts +6 -8
  787. package/src/theme/theme-store.ts +7 -9
  788. package/src/tour/tour-catalogue.tsx +26 -15
  789. package/src/tour/tour-dock.ts +0 -2
  790. package/src/tour/tour-gates.ts +23 -0
  791. package/src/tour/tour-overlay.tsx +1170 -0
  792. package/src/tour/tour.tsx +116 -1193
  793. package/src/tour/use-tour-progress.ts +1 -1
  794. package/src/tour/use-tour-url-sync.ts +7 -3
  795. package/src/wizard/stepper-nav.tsx +3 -1
  796. package/src/wizard/types.ts +11 -2
  797. package/src/wizard/use-wizard.ts +2 -1
  798. package/src/wizard/validation.ts +8 -2
  799. package/tokens.css +2 -1
  800. package/dist/components/ui-labels.js.map +0 -1
  801. package/dist/shell/dev-switchers.d.ts +0 -6
  802. package/dist/shell/dev-switchers.js +0 -12
  803. package/dist/shell/dev-switchers.js.map +0 -1
  804. package/src/components/ui-labels.ts +0 -24
  805. package/src/shell/dev-switchers.tsx +0 -18
@@ -0,0 +1,96 @@
1
+ import { useCallback } from "react";
2
+ import { useKitDateFormatter, useKitLocale, useKitTimeZone } from "../i18n/kit-labels";
3
+ import { toLocalIso } from "./dates";
4
+ import { clockTime } from "./date-format";
5
+ import { EMPTY_FORMATTED_VALUE, formatDate, toDate, type DateInput, type FormatDateStyle } from "./format";
6
+ import { dateFormatter } from "./intl-cache";
7
+ import { isBareIsoDay } from "./iso-day";
8
+
9
+ /**
10
+ * How a kit component prints a day — ONE ladder (refactor audit 2026-10-30, DUP-2):
11
+ *
12
+ * 1. the component's own prop (`formatDate`, `renderDate`), when the app gave one and it
13
+ * answers;
14
+ * 2. else the `<UiKitProvider formatDate>` (keksdose K12: the app's date-format
15
+ * preference), asked for the calendar day with `source: "dateMark"`;
16
+ * 3. else the kit's `formatDate` in the provider's locale AND `timeZone` (0.46).
17
+ *
18
+ * 0.46's rule — "a label that identifies a day follows the preference" — held only where
19
+ * a component wrote that ladder itself: four copies (admin's `useDayText`, AccountStateChip,
20
+ * DateMark, the feedback table), while about twelve components took their own prop or
21
+ * nothing and went straight to `lib/format`. keksdose set the provider's `formatDate` and
22
+ * still passed it into six components by hand; and the 10 that imported the raw
23
+ * `formatDate` ignored the provider's `timeZone`.
24
+ *
25
+ * @internal Not part of the barrel: the components' props are the public way in.
26
+ */
27
+
28
+ /** What a {@link DayFormatter} call may ask for. */
29
+ export interface DayTextOptions {
30
+ /**
31
+ * Name the day of the week — what the provider's formatter is told (its `weekday`).
32
+ * keksdose's rule: a date in a COLUMN carries it, a date in a SENTENCE does not
33
+ * (dev#546). Default `false`. The kit's own rendering follows `style`, not this.
34
+ */
35
+ weekday?: boolean;
36
+ /** Add the clock time, in the language (date-format rule 3): a timestamp. Default false. */
37
+ time?: boolean;
38
+ /** The kit's own rendering (step 3). Default `"medium"`, `"dateTime"` with `time`. */
39
+ style?: FormatDateStyle | Intl.DateTimeFormatOptions;
40
+ /** `false`: skip the provider (step 2) — a component's explicit style wins over it,
41
+ * as `DateMark`'s `dateStyle` does. Default `true`. */
42
+ preference?: boolean;
43
+ /** Printed for no value. Default "—". */
44
+ empty?: string;
45
+ }
46
+
47
+ /** A component's day printer: a value in, its text out. */
48
+ export type DayFormatter<V extends DateInput = DateInput> = (value: V, options?: DayTextOptions) => string;
49
+
50
+ /** The calendar day `date` falls on in `timeZone`, as "YYYY-MM-DD" — so the day the
51
+ * provider is asked for is the day the kit's own rendering would print. */
52
+ function isoDayIn(date: Date, timeZone: string | undefined): string {
53
+ if (!timeZone) return toLocalIso(date);
54
+ try {
55
+ // `en-CA` writes YYYY-MM-DD with Latin digits.
56
+ const parts = dateFormatter("en-CA", { timeZone, year: "numeric", month: "2-digit", day: "2-digit" }).formatToParts(
57
+ date,
58
+ );
59
+ const part = (type: Intl.DateTimeFormatPartTypes) => parts.find((p) => p.type === type)?.value ?? "";
60
+ return `${part("year")}-${part("month")}-${part("day")}`;
61
+ } catch {
62
+ return toLocalIso(date);
63
+ }
64
+ }
65
+
66
+ /**
67
+ * The component's day printer, bound to its `prop`, the provider's `formatDate`, locale
68
+ * and `timeZone`. `prop` is called with the value as the component passed it, and wins
69
+ * whenever it answers non-empty. A value that does not parse is printed as it came
70
+ * (a bug upstream is better seen than hidden behind a dash).
71
+ */
72
+ export function useDayFormatter<V extends DateInput = DateInput>(
73
+ prop?: ((value: V) => string) | null,
74
+ localeProp?: string,
75
+ ): DayFormatter<V> {
76
+ const locale = useKitLocale(localeProp);
77
+ const timeZone = useKitTimeZone();
78
+ const fromProvider = useKitDateFormatter();
79
+ return useCallback<DayFormatter<V>>(
80
+ (value, options = {}) => {
81
+ const own = prop?.(value);
82
+ if (own) return own;
83
+ if (value === null || value === undefined || value === "") return options.empty ?? EMPTY_FORMATTED_VALUE;
84
+ const date = toDate(value);
85
+ if (!date) return String(value);
86
+ const bareDay = isBareIsoDay(value);
87
+ if (fromProvider && options.preference !== false) {
88
+ const iso = bareDay ? value : isoDayIn(date, timeZone);
89
+ const day = fromProvider(iso, { unit: "day", source: "dateMark", locale, weekday: options.weekday ?? false });
90
+ if (day) return options.time && !bareDay ? `${day}, ${clockTime(date, locale, timeZone)}` : day;
91
+ }
92
+ return formatDate(value, options.style ?? (options.time ? "dateTime" : "medium"), { locale, timeZone });
93
+ },
94
+ [prop, fromProvider, locale, timeZone],
95
+ );
96
+ }
@@ -37,7 +37,13 @@ export function decimalMark(locale: string | undefined): "," | "." {
37
37
  * field's settle then made that 1.23, final. This decides per operand, from the
38
38
  * typist's own text, before that fold:
39
39
  *
40
- * - both marks present: the one that is not the locale's is grouping, and goes;
40
+ * - both marks present: the LAST one is the decimal mark, whichever the locale's is, and
41
+ * the other is grouping and goes. The order says the convention the figure was written
42
+ * in — "1.234,56" German, "1,234.56" English — and a figure pasted from another app or
43
+ * locale keeps it. Taking the non-locale mark as grouping wherever it stood read
44
+ * "1.234,56" in a "." locale (en, de-CH) as 1.23456, which a money field then settled
45
+ * to 1.23 (refactor audit 2026-10-30, INP-3). Typed in the locale's own convention, its
46
+ * mark comes last and nothing changes;
41
47
  * - in a "," locale, only "." present: grouping when it cannot be a decimal as a
42
48
  * German reader writes it — twice ("1.234.567"), or in thousands shape ("1.234",
43
49
  * "12.500") — otherwise a decimal ("1.5", typed by a dot-decimal habit). A first
@@ -53,10 +59,13 @@ export function decimalMark(locale: string | undefined): "," | "." {
53
59
  export function normalizeTypedMarks(raw: string, mark: "," | "."): string {
54
60
  const other = mark === "," ? "." : ",";
55
61
  return raw.replace(/[0-9.,]+/g, (operand) => {
56
- const hasMark = operand.includes(mark);
57
62
  const count = operand.split(other).length - 1;
58
63
  if (count === 0) return operand;
59
- const grouping = hasMark ? true : count > 1 || (mark === "," && /^[1-9]\d{0,2}(\.\d{3})+$/.test(operand));
64
+ if (operand.includes(mark)) {
65
+ const grouping = operand.lastIndexOf(mark) > operand.lastIndexOf(other) ? other : mark;
66
+ return operand.split(grouping).join("");
67
+ }
68
+ const grouping = count > 1 || (mark === "," && /^[1-9]\d{0,2}(\.\d{3})+$/.test(operand));
60
69
  return grouping ? operand.split(other).join("") : operand;
61
70
  });
62
71
  }
@@ -0,0 +1,18 @@
1
+ import type { ReactNode } from "react";
2
+ import { hasContent } from "./presence";
3
+
4
+ /**
5
+ * The failure ladder, once: the app's words for a failure when it has any, else the
6
+ * kit's `fallback`.
7
+ *
8
+ * "Any" is {@link hasContent}, so an app's `describeError` answering `""` (nothing to say
9
+ * about this one) gets the kit's sentence. Written as `own ?? fallback` in the auth forms,
10
+ * where `""` printed an empty alert, and both ways within one file in the reviewer scope
11
+ * editor; it lived in the notification cards' parts only (refactor audit 2026-10-30,
12
+ * DUP-14).
13
+ *
14
+ * @internal Package-private — not re-exported from the barrel.
15
+ */
16
+ export function describeFailure(own: ReactNode | undefined, fallback: ReactNode): ReactNode {
17
+ return hasContent(own) ? own : fallback;
18
+ }
@@ -33,3 +33,42 @@ export function horizontalStep(key: string, el: Element | null | undefined): 1 |
33
33
  const forward = (key === "ArrowRight") !== isRtl(el);
34
34
  return forward ? 1 : -1;
35
35
  }
36
+
37
+ /**
38
+ * Where a key moves the focus in a list with ONE tab stop (a roving tabindex): the index
39
+ * to focus from `at` among `count` items, or `undefined` for a key that moves nothing.
40
+ * ←/→ along `dir` — → is next in `ltr` and previous in `rtl` — ↓/↑ as next and previous,
41
+ * Home and End to the ends. With `wrap`, past the last is the first and before the first
42
+ * the last (a ring: PieChart's slices); without, the ends hold (a plane: Treemap's tiles).
43
+ *
44
+ * The charts each mapped the keys themselves, and differently at the ends (0.52 code
45
+ * review of treemap.tsx, finding 9); the end rule is now a word at the call.
46
+ *
47
+ * `dir` and not an element to read it off (0.52 code review, deep, charts, findings 1 and
48
+ * 14): a list in the page's flow takes the page's (`dirOf(el)`), but a plot is laid out
49
+ * left to right in any page (see `ChartContainer`) and passes `"ltr"` — read off the
50
+ * element, Treemap's → walked an RTL page's tiles backwards, against the picture.
51
+ */
52
+ export function rovingTarget(
53
+ key: string,
54
+ dir: Direction,
55
+ at: number,
56
+ count: number,
57
+ wrap: boolean,
58
+ ): number | undefined {
59
+ const physical = key === "ArrowRight" ? 1 : key === "ArrowLeft" ? -1 : 0;
60
+ const step = dir === "rtl" ? -physical : physical;
61
+ const to = step
62
+ ? at + step
63
+ : key === "ArrowDown"
64
+ ? at + 1
65
+ : key === "ArrowUp"
66
+ ? at - 1
67
+ : key === "Home"
68
+ ? 0
69
+ : key === "End"
70
+ ? count - 1
71
+ : undefined;
72
+ if (to === undefined || count <= 0) return undefined;
73
+ return wrap ? ((to % count) + count) % count : Math.max(0, Math.min(count - 1, to));
74
+ }
@@ -0,0 +1,156 @@
1
+ // "The focused node left" (refactor audit 2026-10-30, Wave 1: DSP-4, DSP-15). When the
2
+ // element holding the keyboard's focus is removed — a table row deleted, filtered out or
3
+ // approved; a bulk bar gone with its Clear; a banner its × took away — the browser puts
4
+ // focus on <body> and says nothing: no blur in Chromium, none in jsdom. A keyboard or
5
+ // screen-reader user then starts again from the top of the page. The overlays give focus
6
+ // back to their opener (use-focus-trap); these helpers are for the controls that leave
7
+ // the page while the focus is IN them, and decide where it goes instead.
8
+
9
+ /**
10
+ * Candidate tab stops, in DOM order — narrowed by {@link isTabStop} to the ones a Tab
11
+ * really reaches. The kit's one copy of the rule (0.52 code review, lib/focus-left.ts):
12
+ * this file and use-focus-trap each had it, with an exported `firstTabStop` apiece that
13
+ * disagreed about the element itself, and a combobox panel's toolbar had a third
14
+ * selector. The trap, the focus a removed node drops (below), the tour's field ring and
15
+ * the toolbar all read it here, so "the next stop" is the same stop everywhere.
16
+ *
17
+ * The selector is the one `Modal` used. On its own it was not enough (round 0.34
18
+ * BUG-4): only the bare `[tabindex]` clause excluded `-1`, so a `button`, an `input` or
19
+ * a link taken out of the tab order still counted. A panel that ends in a roving grid —
20
+ * the calendar's days, the month grid, the picker sheet's rows, every one of them `-1`
21
+ * but the active cell — then had a "last" stop no Tab ever reaches: Tab from the real
22
+ * last stop was not wrapped and walked out of the open panel, and Shift+Tab from the
23
+ * first landed on a cell that is not a stop at all.
24
+ */
25
+ // `input[type=hidden]` is no stop: a Tab never lands on it and focus() on it does nothing,
26
+ // but its tabIndex reads 0, so a trap could take a form's hidden field for its first or last
27
+ // stop and Shift+Tab left the dialog (0.52 code review).
28
+ const TAB_STOP =
29
+ 'a[href],button:not([disabled]),textarea:not([disabled]),input:not([disabled]):not([type="hidden"]),select:not([disabled]),[tabindex]:not([tabindex="-1"])';
30
+
31
+ /**
32
+ * A stop the browser's own Tab would land on: in the tab order (`tabIndex` ≥ 0) and not
33
+ * inside something `hidden` or `inert`. Removes only elements a native Tab never
34
+ * reaches, so no correct order changes. `visibility: hidden` and closed `<details>` are
35
+ * still not walked — they need layout, which this rule has never read.
36
+ */
37
+ function isTabStop(el: HTMLElement): boolean {
38
+ return el.tabIndex >= 0 && !el.closest("[hidden],[inert]");
39
+ }
40
+
41
+ export interface TabStopOptions {
42
+ /** Whether `el` itself counts, first, when it is a stop. Default true: the tour's
43
+ * target may BE the field (refactor audit 2026-10-30, DUP-9). False for "a control
44
+ * inside it" — a row, a drawer, a trap's container, a toolbar. */
45
+ includeSelf?: boolean;
46
+ }
47
+
48
+ /** The tab stops in `el`, in DOM order — `el` itself first when it is one, unless
49
+ * `includeSelf: false`. */
50
+ export function tabStops(el: Element, { includeSelf = true }: TabStopOptions = {}): HTMLElement[] {
51
+ const inside = Array.from(el.querySelectorAll<HTMLElement>(TAB_STOP)).filter(isTabStop);
52
+ const own = includeSelf && el instanceof HTMLElement && el.matches(TAB_STOP) && isTabStop(el);
53
+ return own ? [el, ...inside] : inside;
54
+ }
55
+
56
+ /** The first of {@link tabStops} — the control a person types into or presses — or null. */
57
+ export function firstTabStop(el: Element, options?: TabStopOptions): HTMLElement | null {
58
+ return tabStops(el, options)[0] ?? null;
59
+ }
60
+
61
+ /**
62
+ * Whether the focus has fallen out of the page: onto `<body>`, onto nothing, or onto a
63
+ * node no longer in the document. False on the server, where nothing has focus to lose.
64
+ * A recovery asks this first: focus that went somewhere real (a dialog, the next field,
65
+ * an app's own `focus()`) is the user's or the app's, and is left where it is.
66
+ */
67
+ export function focusIsLost(): boolean {
68
+ if (typeof document === "undefined") return false;
69
+ const el = document.activeElement;
70
+ return !el || el === document.body || !el.isConnected;
71
+ }
72
+
73
+ /**
74
+ * Calls `then` when a `blur`/`focusout` was the user's own move to nothing — a click on
75
+ * the page's background, or a click Safari answers by focusing nothing (it focuses no
76
+ * button or link on a click, and blurs what had the focus) — after which a note of where
77
+ * the focus was is stale (0.52 code review: DataTable's row, BulkActionBar's and
78
+ * AlertBanner's notes outlived it, and a removal much later pulled the focus, and the
79
+ * scroll, back to them).
80
+ *
81
+ * No element took the focus, the document holds none, and the node that lost it could
82
+ * still hold it. Not when it was removed, hidden, made inert or disabled: that is the page
83
+ * taking the focus away — the very case those notes are kept for. Not a window losing the
84
+ * focus either, which leaves the node the document's active element. Decided a microtask
85
+ * later, once the event's own work is done: a browser that blurs a node it is removing
86
+ * (or hiding) may do it while the node is still in place, and only after it is gone is
87
+ * that told apart from a click.
88
+ */
89
+ export function whenFocusLeftForNothing(
90
+ e: { target: EventTarget | null; relatedTarget: EventTarget | null },
91
+ then: () => void,
92
+ ): void {
93
+ const el = e.target;
94
+ if (e.relatedTarget !== null || !(el instanceof Element)) return;
95
+ queueMicrotask(() => {
96
+ if (!el.isConnected || el.matches(":disabled") || el.closest("[hidden],[inert]")) return;
97
+ // `display: none`, where the browser can say (jsdom cannot).
98
+ if (typeof el.checkVisibility === "function" && !el.checkVisibility()) return;
99
+ if (focusIsLost()) then();
100
+ });
101
+ }
102
+
103
+ /**
104
+ * The tab stops around `frame`, outside it, nearest first on each side — where focus
105
+ * goes once `frame` is gone. Read BEFORE it goes: a removed node has no place in the
106
+ * document to measure from. `limit` per side keeps a long page's stops out of memory.
107
+ *
108
+ * Walked outwards from the frame, `limit` stops each way (0.52 code review,
109
+ * lib/focus-left.ts): read from every stop in the page, a banner under a 2000-row table
110
+ * read all 2000 to keep the nearest five before it.
111
+ */
112
+ export function tabStopsAround(frame: Element, limit = 5): { after: HTMLElement[]; before: HTMLElement[] } {
113
+ const doc = frame.ownerDocument;
114
+ const walker = doc.createTreeWalker(doc.documentElement, NodeFilter.SHOW_ELEMENT);
115
+ const isStop = (node: Node): node is HTMLElement =>
116
+ node instanceof HTMLElement && node.matches(TAB_STOP) && isTabStop(node);
117
+ // After: from the first element past the frame's own subtree, in document order.
118
+ const after: HTMLElement[] = [];
119
+ walker.currentNode = frame;
120
+ let node: Node | null = walker.nextSibling();
121
+ while (!node && walker.parentNode()) node = walker.nextSibling();
122
+ for (; node && after.length < limit; node = walker.nextNode()) if (isStop(node)) after.push(node);
123
+ // Before: back from the frame, nearest first (its ancestors among them, as before).
124
+ const before: HTMLElement[] = [];
125
+ walker.currentNode = frame;
126
+ for (node = walker.previousNode(); node && before.length < limit; node = walker.previousNode())
127
+ if (isStop(node)) before.push(node);
128
+ return { after, before };
129
+ }
130
+
131
+ /**
132
+ * Focus the first of `candidates` that is still in the page and takes the focus; true
133
+ * when one did. Each is tried and checked, since `focus()` on a node that cannot hold it
134
+ * (detached, `display: none`, disabled since) fails without a word.
135
+ */
136
+ export function focusFirst(candidates: Iterable<Element | null | undefined>): boolean {
137
+ for (const el of candidates) {
138
+ if (!(el instanceof HTMLElement) || !el.isConnected) continue;
139
+ el.focus();
140
+ if (document.activeElement === el) return true;
141
+ }
142
+ return false;
143
+ }
144
+
145
+ /**
146
+ * Focus a container that is not a tab stop of its own — a table, a list — as the place
147
+ * the user is in, without making it one: `tabindex="-1"` for as long as it holds the
148
+ * focus, unless it already carries a `tabindex` of its own.
149
+ */
150
+ export function focusContainer(el: HTMLElement): void {
151
+ if (!el.hasAttribute("tabindex")) {
152
+ el.setAttribute("tabindex", "-1");
153
+ el.addEventListener("blur", () => el.removeAttribute("tabindex"), { once: true });
154
+ }
155
+ el.focus();
156
+ }
package/src/lib/format.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { useMemo } from "react";
2
2
  import { useKitLocale, useKitTimeZone } from "../i18n/kit-labels";
3
3
  import { parseIsoDate } from "./dates";
4
+ import { dateFormatter } from "./intl-cache";
5
+ import { isBareIsoDay } from "./iso-day";
4
6
  import { formatWithMinus, type MinusStyle } from "./minus";
5
7
  import { roundHalfAway } from "./round";
6
8
 
@@ -278,9 +280,6 @@ export interface FormatDateOptions extends BaseOptions {
278
280
  timeZone?: string;
279
281
  }
280
282
 
281
- /** A bare ISO calendar day, `"YYYY-MM-DD"`. */
282
- const BARE_ISO_DAY = /^\d{4}-\d{2}-\d{2}$/;
283
-
284
283
  /** What {@link formatDate} and {@link formatRelativeTime} accept. */
285
284
  export type DateInput = string | number | Date | null | undefined;
286
285
 
@@ -292,22 +291,11 @@ export type DateInput = string | number | Date | null | undefined;
292
291
  */
293
292
  export function toDate(value: DateInput): Date | null {
294
293
  if (value === null || value === undefined || value === "") return null;
295
- if (typeof value === "string" && BARE_ISO_DAY.test(value)) return parseIsoDate(value);
294
+ if (isBareIsoDay(value)) return parseIsoDate(value);
296
295
  const d = value instanceof Date ? value : new Date(value);
297
296
  return Number.isNaN(d.getTime()) ? null : d;
298
297
  }
299
298
 
300
- const dateFormatters = new Map<string, Intl.DateTimeFormat>();
301
- function dateFormatter(locale: string | undefined, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {
302
- const key = `${locale ?? ""}|${JSON.stringify(options)}`;
303
- let f = dateFormatters.get(key);
304
- if (!f) {
305
- f = new Intl.DateTimeFormat(locale, options);
306
- dateFormatters.set(key, f);
307
- }
308
- return f;
309
- }
310
-
311
299
  /**
312
300
  * A date or timestamp in `locale`. Takes an ISO date ("2026-07-08", read on the local
313
301
  * calendar), an ISO timestamp ("2026-07-08T14:05:00Z"), epoch milliseconds or a Date.
@@ -327,7 +315,7 @@ export function formatDate(
327
315
  // A bare "YYYY-MM-DD" is a calendar day, which has no zone: it is the day it names
328
316
  // wherever it is read, so a `timeZone` (in `options` or the style) never moves it — the
329
317
  // device's local midnight shown in a zone west of it was the day before (round 0.45, N9).
330
- if (typeof value === "string" && BARE_ISO_DAY.test(value)) {
318
+ if (isBareIsoDay(value)) {
331
319
  const day = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
332
320
  return dateFormatter(options.locale, { ...base, timeZone: "UTC" }).format(day);
333
321
  }
@@ -335,8 +323,8 @@ export function formatDate(
335
323
  }
336
324
 
337
325
  export interface FormatRelativeTimeOptions extends BaseOptions {
338
- /** The zone of the date printed past `absoluteAfterDays` (0.46). Left out: the
339
- * device's. */
326
+ /** The zone of the date printed past `absoluteAfterDays` (0.46), and (0.51.7) the zone
327
+ * whose calendar days "yesterday" and "2 days ago" count. Left out: the device's. */
340
328
  timeZone?: string;
341
329
  /** The moment it is measured from. Default: now. */
342
330
  now?: DateInput;
@@ -370,6 +358,20 @@ const RELATIVE_STEPS: Array<[number, Intl.RelativeTimeFormatUnit, number]> = [
370
358
  [Infinity, "year", 365.25 * DAY],
371
359
  ];
372
360
 
361
+ /**
362
+ * `d`'s calendar day in `timeZone` (left out: the device's), as a whole number of days:
363
+ * that day's UTC midnight over a day's length. Two of them subtract to whole calendar
364
+ * days — a 23- or 25-hour DST day still counts one.
365
+ */
366
+ function dayNumber(d: Date, timeZone: string | undefined): number {
367
+ if (!timeZone) return Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()) / DAY;
368
+ // `en-US`: Gregorian, Latin digits — the parts are read back as numbers.
369
+ const fields: Intl.DateTimeFormatOptions = { timeZone, year: "numeric", month: "numeric", day: "numeric" };
370
+ const parts = dateFormatter("en-US", fields).formatToParts(d);
371
+ const part = (type: Intl.DateTimeFormatPartTypes) => Number(parts.find((p) => p.type === type)?.value);
372
+ return Date.UTC(part("year"), part("month") - 1, part("day")) / DAY;
373
+ }
374
+
373
375
  const relativeFormatters = new Map<string, Intl.RelativeTimeFormat>();
374
376
  function relativeFormatter(
375
377
  locale: string | undefined,
@@ -389,7 +391,9 @@ function relativeFormatter(
389
391
  * How long ago (or until) `value` is, in `locale`'s words, through
390
392
  * `Intl.RelativeTimeFormat`: "3 hours ago", "vor 3 Stunden", "il y a 3 heures",
391
393
  * "in 2 days", and under 45 seconds "now". The unit is picked by size — seconds,
392
- * minutes, hours, days, weeks, months, years — and the count is rounded.
394
+ * minutes, hours, days, weeks, months, years — and the count is rounded; days are
395
+ * CALENDAR days (0.51.7), in `timeZone` when given: "yesterday" is the day before today,
396
+ * however few hours ago that was.
393
397
  */
394
398
  export function formatRelativeTime(value: DateInput, options: FormatRelativeTimeOptions = {}): string {
395
399
  const d = toDate(value);
@@ -402,6 +406,17 @@ export function formatRelativeTime(value: DateInput, options: FormatRelativeTime
402
406
  }
403
407
  const rtf = relativeFormatter(options.locale, options.numeric ?? "auto", options.style ?? "long");
404
408
  const [, unit, size] = RELATIVE_STEPS.find(([limit]) => abs < limit)!;
409
+ if (unit === "day") {
410
+ // By the calendar, not in 24-hour units (refactor audit 2026-10-30, DSP-7): rounded
411
+ // elapsed time made 00:10 seen at 23:50 "yesterday" and 01:00 yesterday seen at 23:30
412
+ // "2 days ago", beside an exact date (DateMark's second line, the feedback thread's
413
+ // tooltip) that said otherwise. Counted in `timeZone`, the zone that date is printed
414
+ // in; a bare "YYYY-MM-DD" is the day it names wherever it is read, as in formatDate.
415
+ // Still the same day (22 hours and more since just after midnight): in hours.
416
+ const bareDay = isBareIsoDay(value);
417
+ const days = dayNumber(d, bareDay ? undefined : options.timeZone) - dayNumber(now, options.timeZone);
418
+ return days === 0 ? rtf.format(Math.round(diff / HOUR), "hour") : rtf.format(days, "day");
419
+ }
405
420
  // Under 45 seconds is "now" rather than "12 seconds ago": a feed that ticks through
406
421
  // the seconds is noise, and nothing reads a timestamp to the second.
407
422
  const count = unit === "second" ? 0 : Math.round(diff / size);
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The HTTP status of a thrown error, as one probe (DUP-11, refactor audit 2026-10: the
3
+ * session refresh carried its own copy).
4
+ *
5
+ * It lived in `auth/auth-errors.ts` until 0.52, which made `lib/session-refresh` and
6
+ * `/sync`'s engine import the auth folder — and put auth's English error words in the
7
+ * `/sync` entry's closure — for a three-line reader of `status` (refactor audit
8
+ * 2026-10-30, MOD-6). `auth-errors.ts` re-exports it, so nothing that imported it there
9
+ * moved.
10
+ *
11
+ * @internal Package-private — not re-exported from the barrel.
12
+ */
13
+
14
+ type Bag = Record<string, unknown>;
15
+
16
+ const isBag = (value: unknown): value is Bag => typeof value === "object" && value !== null;
17
+
18
+ /** An HTTP status as a number, or undefined. */
19
+ function statusOf(value: unknown): number | undefined {
20
+ return typeof value === "number" && Number.isInteger(value) ? value : undefined;
21
+ }
22
+
23
+ /**
24
+ * The HTTP status a thrown error carries, wherever the apps' HTTP clients put it —
25
+ * without depending on any of them:
26
+ *
27
+ * 1. `err.response.status` — axios (all three apps' clients);
28
+ * 2. `err.status` — ofetch's `FetchError`, the generated OpenAPI clients' `ApiError`, and
29
+ * a `Response` thrown as it came;
30
+ * 3. `err.statusCode` — ofetch's alias, and Node-style errors.
31
+ *
32
+ * `undefined` when none is a whole number.
33
+ */
34
+ export function httpStatusOf(err: unknown): number | undefined {
35
+ if (!isBag(err)) return undefined;
36
+ const response = err.response;
37
+ return (isBag(response) ? statusOf(response.status) : undefined) ?? statusOf(err.status) ?? statusOf(err.statusCode);
38
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * One `Intl.DateTimeFormat` per locale and option set, for every date the kit prints.
3
+ *
4
+ * Constructing the formatter is the expensive part: keksdose measured 392 ms per click on
5
+ * a 270-row register when each cell built its own (dev#632), and kept its own renderer of
6
+ * the date-format preference because the kit's built one per call (refactor audit
7
+ * 2026-10-30, DUP-2). `lib/format` and `lib/date-format` both format through this one.
8
+ *
9
+ * @internal Not part of the barrel — `lib/format` is re-exported whole, so the cache
10
+ * lives apart from it.
11
+ */
12
+
13
+ const dateFormatters = new Map<string, Intl.DateTimeFormat>();
14
+
15
+ /** The cached formatter for `locale` and `options`. Throws as `Intl.DateTimeFormat` does
16
+ * for a tag it refuses — and caches nothing then. */
17
+ export function dateFormatter(locale: string | undefined, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {
18
+ const key = `${locale ?? ""}|${JSON.stringify(options)}`;
19
+ let f = dateFormatters.get(key);
20
+ if (!f) {
21
+ f = new Intl.DateTimeFormat(locale, options);
22
+ dateFormatters.set(key, f);
23
+ }
24
+ return f;
25
+ }
package/src/lib/isin.ts CHANGED
@@ -9,6 +9,10 @@
9
9
  * with every letter expanded to two digits (A = 10 … Z = 35) — which is all that is
10
10
  * checked here. Whether the prefix is an assigned code, and whether the security
11
11
  * exists, is a lookup, not a checksum.
12
+ *
13
+ * Deprecated in 0.52, removed in 0.53 (decision 4 of the refactor audit 2026-10-30,
14
+ * MOD-5): keksdose, which they were written for, never imported them, and no other app
15
+ * does.
12
16
  */
13
17
 
14
18
  /** Letters to their two-digit numbers (A = 10 … Z = 35), digits as they are. */
@@ -36,6 +40,8 @@ function luhnSum(digits: string, doubleRightmost: boolean): number {
36
40
  /**
37
41
  * The ISIN as it is printed: upper case, unbroken (ISO 6166 has no grouping), with
38
42
  * the spaces and hyphens a paste from a broker's statement carries dropped.
43
+ *
44
+ * @deprecated 0.52 — none: no app checks an ISIN with it; copy lib/isin.ts (MOD-5); removed in 0.53.
39
45
  */
40
46
  export function formatIsin(value: string): string {
41
47
  return value.replace(/[\s-]/g, "").toUpperCase();
@@ -44,6 +50,8 @@ export function formatIsin(value: string): string {
44
50
  /**
45
51
  * The check digit for the first eleven characters of an ISIN (prefix and national
46
52
  * number). For BUILDING one — a test fixture, a demo — rather than checking it.
53
+ *
54
+ * @deprecated 0.52 — none: no app checks an ISIN with it; copy lib/isin.ts (MOD-5); removed in 0.53.
47
55
  */
48
56
  export function isinCheckDigit(body: string): string {
49
57
  const sum = luhnSum(expandLetters(formatIsin(body)), true);
@@ -54,6 +62,8 @@ export function isinCheckDigit(body: string): string {
54
62
  * Whether `value` is a valid ISIN: two letters, nine letters or digits, one digit,
55
63
  * and a matching Luhn check digit over the letter-expanded form. Spaces, hyphens and
56
64
  * lower case are fine (see {@link formatIsin}).
65
+ *
66
+ * @deprecated 0.52 — none: no app checks an ISIN with it; copy lib/isin.ts (MOD-5); removed in 0.53.
57
67
  */
58
68
  export function isValidIsin(value: string): boolean {
59
69
  const isin = formatIsin(value);
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The bare ISO calendar day, `"YYYY-MM-DD"` — no time, no zone: the day it names in every
3
+ * zone. `toDate` and `formatDate` (lib/format), the kit's day ladder (`useDayFormatter`,
4
+ * lib/day-format) and the preference's renderers (lib/date-format) each kept a copy of this
5
+ * pattern (0.52 code review, lib/day-format.ts). Were one to learn a new shape (say
6
+ * `YYYY-MM-DDT00:00`) alone, the ladder would ask the provider for a different day than the
7
+ * kit prints. One rule.
8
+ *
9
+ * @internal Not part of the barrel: `lib/format` is re-exported whole, so it lives apart.
10
+ */
11
+ export function isBareIsoDay(value: unknown): value is string {
12
+ return typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value);
13
+ }
@@ -0,0 +1,82 @@
1
+ import { createContext, createElement, lazy, useCallback, useContext, useLayoutEffect, useState } from "react";
2
+ import type { ComponentType, LazyExoticComponent } from "react";
3
+
4
+ /** What a {@link lazyWithFallback} fallback is given besides the component's own props. */
5
+ export interface LazyFallbackProps {
6
+ /** What the import rejected with. Already on `console.error`. */
7
+ error: unknown;
8
+ /** Fetch the module again and draw it here if it comes (back online, the deploy's
9
+ * new chunk). Call it on the person's next attempt, never at once: offline, a retry
10
+ * on mount would fetch in a loop. */
11
+ retry: () => void;
12
+ }
13
+
14
+ interface Attempt<P> {
15
+ Component: LazyExoticComponent<ComponentType<P>>;
16
+ /** Its import failed and its fallback was drawn: the next mount, or `retry`, takes a
17
+ * fresh attempt. Marked when the fallback COMMITS, not when the import rejects: a
18
+ * first mount that suspended is thrown away and rendered anew, and an attempt marked
19
+ * at the rejection would hand that re-render a fresh import — which fails, and so on. */
20
+ spent: boolean;
21
+ }
22
+
23
+ const RetryContext = createContext<() => void>(() => {});
24
+
25
+ /**
26
+ * `React.lazy` for a module the kit loads late (refactor audit 2026-10, MOD-1: the tour
27
+ * overlay, the search palette, the feedback dialog), where an import that fails — a tab
28
+ * left open across a deploy, a local-first app offline — draws `Fallback` instead of
29
+ * throwing.
30
+ *
31
+ * `React.lazy` keeps what its import settled to, so one failed fetch threw on every render
32
+ * for as long as the component stayed mounted, to the nearest error boundary. All three
33
+ * sit above the routes — in the provider every app mounts, in the top bar — where that
34
+ * boundary is the whole app's: a white page because somebody pressed ⌘K or "Take the
35
+ * tour" (0.52 code review, tour.tsx: the tour's own fix, written by hand with a module-level
36
+ * `let`, made shared here).
37
+ *
38
+ * A failure is logged and the next mount (or the fallback's `retry`) fetches again; a
39
+ * re-render of a mounted fallback does not. `load` resolves to the component itself,
40
+ * through a LITERAL relative dynamic import of its module (as feedback-submit's), so an
41
+ * app's bundler can split it off. Render the result under a `Suspense`, as a lazy
42
+ * component. (No import call is spelled out here: the build's fix-esm-extensions step
43
+ * reads specifiers in the .d.ts comments too, and would try to resolve an example.)
44
+ */
45
+ export function lazyWithFallback<P extends object>(
46
+ load: () => Promise<ComponentType<P>>,
47
+ Fallback: ComponentType<P & LazyFallbackProps>,
48
+ ): ComponentType<P> {
49
+ const attempt = (): Attempt<P> => {
50
+ const made: Attempt<P> = {
51
+ spent: false,
52
+ Component: lazy<ComponentType<P>>(() =>
53
+ load().then(
54
+ (Loaded) => ({ default: Loaded }),
55
+ (error: unknown) => {
56
+ console.error(error);
57
+ function Failed(props: P) {
58
+ const retry = useContext(RetryContext);
59
+ useLayoutEffect(() => {
60
+ made.spent = true;
61
+ }, []);
62
+ return createElement(Fallback, { ...props, error, retry });
63
+ }
64
+ return { default: Failed };
65
+ },
66
+ ),
67
+ ),
68
+ };
69
+ return made;
70
+ };
71
+ let latest = attempt();
72
+ /** The attempt a new mount takes: the latest, or a fresh one once that has failed. */
73
+ const take = () => (latest.spent ? (latest = attempt()) : latest);
74
+
75
+ function LazyWithFallback(props: P) {
76
+ // Fixed per mount, so a re-render of a mounted fallback fetches nothing.
77
+ const [current, setCurrent] = useState(take);
78
+ const retry = useCallback(() => setCurrent(take), []);
79
+ return createElement(RetryContext.Provider, { value: retry }, createElement(current.Component, props));
80
+ }
81
+ return LazyWithFallback;
82
+ }