@eifi1/ui-kit 0.51.7 → 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 (746) hide show
  1. package/README.md +141 -23
  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 +1 -3
  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.js +2 -1
  39. package/dist/auth/complete-name-dialog.js.map +1 -1
  40. package/dist/auth/forgot-password-form-labels.js +1 -1
  41. package/dist/auth/forgot-password-form-labels.js.map +1 -1
  42. package/dist/auth/forgot-password-form.js +7 -2
  43. package/dist/auth/forgot-password-form.js.map +1 -1
  44. package/dist/auth/register-form-labels.js +1 -1
  45. package/dist/auth/register-form-labels.js.map +1 -1
  46. package/dist/auth/reset-password-form-labels.js +1 -1
  47. package/dist/auth/reset-password-form-labels.js.map +1 -1
  48. package/dist/auth/reset-password-form.js +5 -1
  49. package/dist/auth/reset-password-form.js.map +1 -1
  50. package/dist/auth/sign-in-form-labels.js +1 -1
  51. package/dist/auth/sign-in-form-labels.js.map +1 -1
  52. package/dist/auth/status-parts.d.ts +0 -3
  53. package/dist/auth/status-parts.js +0 -4
  54. package/dist/auth/status-parts.js.map +1 -1
  55. package/dist/auth/verify-email-labels.js +1 -1
  56. package/dist/auth/verify-email-labels.js.map +1 -1
  57. package/dist/auth/verify-email.js +7 -2
  58. package/dist/auth/verify-email.js.map +1 -1
  59. package/dist/billing/cancel-subscription.d.ts +20 -8
  60. package/dist/billing/cancel-subscription.js +7 -5
  61. package/dist/billing/cancel-subscription.js.map +1 -1
  62. package/dist/billing/dialog-close.d.ts +29 -0
  63. package/dist/billing/dialog-close.js +8 -0
  64. package/dist/billing/dialog-close.js.map +1 -0
  65. package/dist/billing/plan-card.d.ts +14 -4
  66. package/dist/billing/plan-card.js +15 -8
  67. package/dist/billing/plan-card.js.map +1 -1
  68. package/dist/billing/plan-change-labels.d.ts +42 -0
  69. package/dist/billing/plan-change-labels.js +22 -0
  70. package/dist/billing/plan-change-labels.js.map +1 -0
  71. package/dist/billing/plan-switch.d.ts +19 -7
  72. package/dist/billing/plan-switch.js +8 -4
  73. package/dist/billing/plan-switch.js.map +1 -1
  74. package/dist/chart.d.ts +12 -0
  75. package/dist/chart.js +16 -1
  76. package/dist/chart.js.map +1 -1
  77. package/dist/components/account-chips.d.ts +5 -5
  78. package/dist/components/account-chips.js +11 -13
  79. package/dist/components/account-chips.js.map +1 -1
  80. package/dist/components/alert-banner.d.ts +16 -5
  81. package/dist/components/alert-banner.js +46 -1
  82. package/dist/components/alert-banner.js.map +1 -1
  83. package/dist/components/amount-input.d.ts +13 -0
  84. package/dist/components/amount-input.js +1 -0
  85. package/dist/components/amount-input.js.map +1 -1
  86. package/dist/components/autocomplete.js +57 -65
  87. package/dist/components/autocomplete.js.map +1 -1
  88. package/dist/components/bulk-action-bar.d.ts +12 -2
  89. package/dist/components/bulk-action-bar.js +65 -21
  90. package/dist/components/bulk-action-bar.js.map +1 -1
  91. package/dist/components/button-look.d.ts +5 -5
  92. package/dist/components/button-look.js.map +1 -1
  93. package/dist/components/button.d.ts +2 -2
  94. package/dist/components/button.js.map +1 -1
  95. package/dist/components/chart-edge.d.ts +16 -0
  96. package/dist/components/chart-edge.js +14 -1
  97. package/dist/components/chart-edge.js.map +1 -1
  98. package/dist/components/chart-figure.d.ts +13 -0
  99. package/dist/components/chart-figure.js +15 -0
  100. package/dist/components/chart-figure.js.map +1 -0
  101. package/dist/components/chart-zoom-core.js +1 -4
  102. package/dist/components/chart-zoom-core.js.map +1 -1
  103. package/dist/components/chart.d.ts +8 -1
  104. package/dist/components/chart.js +19 -10
  105. package/dist/components/chart.js.map +1 -1
  106. package/dist/components/combobox-core.d.ts +111 -2
  107. package/dist/components/combobox-core.js +148 -42
  108. package/dist/components/combobox-core.js.map +1 -1
  109. package/dist/components/combobox.d.ts +1 -1
  110. package/dist/components/combobox.js +141 -130
  111. package/dist/components/combobox.js.map +1 -1
  112. package/dist/components/copy-button.d.ts +6 -5
  113. package/dist/components/copy-button.js +5 -3
  114. package/dist/components/copy-button.js.map +1 -1
  115. package/dist/components/country-select.js +2 -2
  116. package/dist/components/country-select.js.map +1 -1
  117. package/dist/components/data-table-column-settings.d.ts +1 -1
  118. package/dist/components/data-table-column-settings.js +33 -7
  119. package/dist/components/data-table-column-settings.js.map +1 -1
  120. package/dist/components/data-table-filters.d.ts +4 -2
  121. package/dist/components/data-table-filters.js +2 -2
  122. package/dist/components/data-table-filters.js.map +1 -1
  123. package/dist/components/data-table-fit.d.ts +6 -4
  124. package/dist/components/data-table-fit.js +4 -1
  125. package/dist/components/data-table-fit.js.map +1 -1
  126. package/dist/components/data-table-groups.d.ts +1 -1
  127. package/dist/components/data-table-groups.js.map +1 -1
  128. package/dist/components/data-table-head.d.ts +1 -1
  129. package/dist/components/data-table-head.js +15 -12
  130. package/dist/components/data-table-head.js.map +1 -1
  131. package/dist/components/data-table-mobile.d.ts +12 -7
  132. package/dist/components/data-table-mobile.js +43 -30
  133. package/dist/components/data-table-mobile.js.map +1 -1
  134. package/dist/components/data-table-pagination.js +11 -6
  135. package/dist/components/data-table-pagination.js.map +1 -1
  136. package/dist/components/data-table-resize.d.ts +1 -1
  137. package/dist/components/data-table-resize.js.map +1 -1
  138. package/dist/components/data-table-row-actions.d.ts +2 -2
  139. package/dist/components/data-table-row-actions.js.map +1 -1
  140. package/dist/components/data-table-row.d.ts +6 -2
  141. package/dist/components/data-table-row.js +17 -10
  142. package/dist/components/data-table-row.js.map +1 -1
  143. package/dist/components/data-table-selection.d.ts +1 -1
  144. package/dist/components/data-table-selection.js.map +1 -1
  145. package/dist/components/data-table-shared.d.ts +10 -2
  146. package/dist/components/data-table-shared.js +18 -0
  147. package/dist/components/data-table-shared.js.map +1 -1
  148. package/dist/components/data-table-sort.d.ts +21 -2
  149. package/dist/components/data-table-sort.js +24 -0
  150. package/dist/components/data-table-sort.js.map +1 -1
  151. package/dist/components/data-table-virtual.d.ts +1 -1
  152. package/dist/components/data-table-virtual.js +18 -6
  153. package/dist/components/data-table-virtual.js.map +1 -1
  154. package/dist/components/data-table.d.ts +13 -4
  155. package/dist/components/data-table.js +139 -36
  156. package/dist/components/data-table.js.map +1 -1
  157. package/dist/components/date-field.d.ts +24 -2
  158. package/dist/components/date-field.js +33 -8
  159. package/dist/components/date-field.js.map +1 -1
  160. package/dist/components/date-picker.d.ts +15 -2
  161. package/dist/components/date-picker.js +55 -26
  162. package/dist/components/date-picker.js.map +1 -1
  163. package/dist/components/date-range-picker.d.ts +47 -20
  164. package/dist/components/date-range-picker.js +23 -7
  165. package/dist/components/date-range-picker.js.map +1 -1
  166. package/dist/components/error-boundary.js +37 -30
  167. package/dist/components/error-boundary.js.map +1 -1
  168. package/dist/components/{ui-labels.d.ts → field-base-labels.d.ts} +0 -2
  169. package/dist/components/{ui-labels.js → field-base-labels.js} +2 -9
  170. package/dist/components/field-base-labels.js.map +1 -0
  171. package/dist/components/field-base.d.ts +4 -3
  172. package/dist/components/field-base.js +3 -3
  173. package/dist/components/field-base.js.map +1 -1
  174. package/dist/components/field-sync-labels.d.ts +1 -0
  175. package/dist/components/field-sync-labels.js.map +1 -1
  176. package/dist/components/field-sync.d.ts +23 -1
  177. package/dist/components/field-sync.js.map +1 -1
  178. package/dist/components/form-actions.js +11 -5
  179. package/dist/components/form-actions.js.map +1 -1
  180. package/dist/components/hover-menu.d.ts +3 -0
  181. package/dist/components/hover-menu.js +5 -3
  182. package/dist/components/hover-menu.js.map +1 -1
  183. package/dist/components/icon-button.js +14 -9
  184. package/dist/components/icon-button.js.map +1 -1
  185. package/dist/components/inline-confirm.d.ts +43 -0
  186. package/dist/components/inline-confirm.js +67 -0
  187. package/dist/components/inline-confirm.js.map +1 -0
  188. package/dist/components/inline-entity-combobox.d.ts +4 -3
  189. package/dist/components/inline-entity-combobox.js +148 -140
  190. package/dist/components/inline-entity-combobox.js.map +1 -1
  191. package/dist/components/input.js +1 -1
  192. package/dist/components/input.js.map +1 -1
  193. package/dist/components/jump-calendar.js +28 -112
  194. package/dist/components/jump-calendar.js.map +1 -1
  195. package/dist/components/legal-page.d.ts +3 -1
  196. package/dist/components/legal-page.js +3 -2
  197. package/dist/components/legal-page.js.map +1 -1
  198. package/dist/components/legal.d.ts +4 -2
  199. package/dist/components/legal.js.map +1 -1
  200. package/dist/components/lightbox.d.ts +2 -2
  201. package/dist/components/lightbox.js +17 -6
  202. package/dist/components/lightbox.js.map +1 -1
  203. package/dist/components/list.d.ts +6 -2
  204. package/dist/components/list.js +3 -2
  205. package/dist/components/list.js.map +1 -1
  206. package/dist/components/measured-grid.d.ts +1 -1
  207. package/dist/components/measured-grid.js +2 -1
  208. package/dist/components/measured-grid.js.map +1 -1
  209. package/dist/components/mini-calendar.js +3 -5
  210. package/dist/components/mini-calendar.js.map +1 -1
  211. package/dist/components/modal.js +3 -1
  212. package/dist/components/modal.js.map +1 -1
  213. package/dist/components/month-grid.d.ts +55 -0
  214. package/dist/components/month-grid.js +148 -0
  215. package/dist/components/month-grid.js.map +1 -0
  216. package/dist/components/month-picker.d.ts +36 -4
  217. package/dist/components/month-picker.js +123 -146
  218. package/dist/components/month-picker.js.map +1 -1
  219. package/dist/components/multi-select.d.ts +2 -2
  220. package/dist/components/multi-select.js +11 -6
  221. package/dist/components/multi-select.js.map +1 -1
  222. package/dist/components/picker-sheet.js +2 -1
  223. package/dist/components/picker-sheet.js.map +1 -1
  224. package/dist/components/pie-chart-labels.d.ts +7 -0
  225. package/dist/components/pie-chart-labels.js +1 -0
  226. package/dist/components/pie-chart-labels.js.map +1 -1
  227. package/dist/components/pie-chart.d.ts +5 -3
  228. package/dist/components/pie-chart.js +7 -22
  229. package/dist/components/pie-chart.js.map +1 -1
  230. package/dist/components/popover.d.ts +3 -0
  231. package/dist/components/popover.js +7 -1
  232. package/dist/components/popover.js.map +1 -1
  233. package/dist/components/row-actions.js +2 -1
  234. package/dist/components/row-actions.js.map +1 -1
  235. package/dist/components/section-nav.d.ts +7 -0
  236. package/dist/components/section-nav.js.map +1 -1
  237. package/dist/components/series-chart-axes.d.ts +3 -3
  238. package/dist/components/series-chart-axes.js.map +1 -1
  239. package/dist/components/series-chart-labels.d.ts +7 -4
  240. package/dist/components/series-chart-labels.js.map +1 -1
  241. package/dist/components/series-chart.d.ts +31 -7
  242. package/dist/components/series-chart.js +72 -29
  243. package/dist/components/series-chart.js.map +1 -1
  244. package/dist/components/share-card.js +3 -3
  245. package/dist/components/share-card.js.map +1 -1
  246. package/dist/components/sign-chip-labels.d.ts +1 -0
  247. package/dist/components/sign-chip-labels.js.map +1 -1
  248. package/dist/components/sign-chip.d.ts +10 -1
  249. package/dist/components/sign-chip.js.map +1 -1
  250. package/dist/components/tabs-labels.d.ts +2 -0
  251. package/dist/components/tabs-labels.js +11 -0
  252. package/dist/components/tabs-labels.js.map +1 -0
  253. package/dist/components/tabs.d.ts +1 -1
  254. package/dist/components/tabs.js +1 -1
  255. package/dist/components/tabs.js.map +1 -1
  256. package/dist/components/toggle-legend.d.ts +2 -2
  257. package/dist/components/toggle-legend.js +6 -6
  258. package/dist/components/toggle-legend.js.map +1 -1
  259. package/dist/components/translation-review-editor.d.ts +4 -2
  260. package/dist/components/translation-review-editor.js +2 -3
  261. package/dist/components/translation-review-editor.js.map +1 -1
  262. package/dist/components/translation-review.d.ts +2 -1
  263. package/dist/components/translation-review.js +2 -2
  264. package/dist/components/translation-review.js.map +1 -1
  265. package/dist/components/treemap-labels.d.ts +26 -0
  266. package/dist/components/treemap-labels.js +10 -0
  267. package/dist/components/treemap-labels.js.map +1 -0
  268. package/dist/components/treemap-layout.d.ts +62 -0
  269. package/dist/components/treemap-layout.js +126 -0
  270. package/dist/components/treemap-layout.js.map +1 -0
  271. package/dist/components/treemap.d.ts +140 -17
  272. package/dist/components/treemap.js +324 -97
  273. package/dist/components/treemap.js.map +1 -1
  274. package/dist/components/use-table-state.d.ts +5 -5
  275. package/dist/components/use-table-state.js +4 -1
  276. package/dist/components/use-table-state.js.map +1 -1
  277. package/dist/data-table.d.ts +6 -2
  278. package/dist/data-table.js +7 -2
  279. package/dist/data-table.js.map +1 -1
  280. package/dist/eslint/index.js +1 -1
  281. package/dist/eslint/role-utilities.d.ts +36 -7
  282. package/dist/eslint/role-utilities.js +42 -9
  283. package/dist/eslint/role-utilities.js.map +1 -1
  284. package/dist/feedback/feedback-dialog.d.ts +25 -16
  285. package/dist/feedback/feedback-dialog.js +6 -2
  286. package/dist/feedback/feedback-dialog.js.map +1 -1
  287. package/dist/feedback/feedback-mutation.d.ts +30 -0
  288. package/dist/feedback/feedback-mutation.js +16 -0
  289. package/dist/feedback/feedback-mutation.js.map +1 -0
  290. package/dist/feedback/feedback-page-link.d.ts +53 -0
  291. package/dist/feedback/feedback-page-link.js +37 -0
  292. package/dist/feedback/feedback-page-link.js.map +1 -0
  293. package/dist/feedback/feedback-public-list.d.ts +12 -3
  294. package/dist/feedback/feedback-public-list.js +2 -1
  295. package/dist/feedback/feedback-public-list.js.map +1 -1
  296. package/dist/feedback/feedback-replies.d.ts +3 -1
  297. package/dist/feedback/feedback-replies.js +5 -4
  298. package/dist/feedback/feedback-replies.js.map +1 -1
  299. package/dist/feedback/feedback-row-detail-labels.js +5 -0
  300. package/dist/feedback/feedback-row-detail-labels.js.map +1 -1
  301. package/dist/feedback/feedback-row-detail.d.ts +64 -28
  302. package/dist/feedback/feedback-row-detail.js +30 -28
  303. package/dist/feedback/feedback-row-detail.js.map +1 -1
  304. package/dist/feedback/feedback-status-undo.d.ts +30 -11
  305. package/dist/feedback/feedback-status-undo.js +10 -15
  306. package/dist/feedback/feedback-status-undo.js.map +1 -1
  307. package/dist/feedback/feedback-submit-dialog.d.ts +1 -1
  308. package/dist/feedback/feedback-submit-dialog.js +1 -1
  309. package/dist/feedback/feedback-submit-dialog.js.map +1 -1
  310. package/dist/feedback/feedback-submit.js +9 -3
  311. package/dist/feedback/feedback-submit.js.map +1 -1
  312. package/dist/feedback/feedback-swipe.d.ts +1 -1
  313. package/dist/feedback/feedback-swipe.js.map +1 -1
  314. package/dist/feedback/feedback-table.d.ts +21 -9
  315. package/dist/feedback/feedback-table.js +45 -25
  316. package/dist/feedback/feedback-table.js.map +1 -1
  317. package/dist/feedback/feedback-thread-labels.d.ts +2 -2
  318. package/dist/feedback/feedback-thread-labels.js.map +1 -1
  319. package/dist/feedback/feedback-thread.d.ts +24 -23
  320. package/dist/feedback/feedback-thread.js +2 -1
  321. package/dist/feedback/feedback-thread.js.map +1 -1
  322. package/dist/feedback.d.ts +34 -0
  323. package/dist/feedback.js +42 -0
  324. package/dist/feedback.js.map +1 -1
  325. package/dist/hooks/use-focus-trap.d.ts +35 -0
  326. package/dist/hooks/use-focus-trap.js +6 -4
  327. package/dist/hooks/use-focus-trap.js.map +1 -1
  328. package/dist/hooks/use-hotkey.d.ts +5 -2
  329. package/dist/hooks/use-hotkey.js +5 -4
  330. package/dist/hooks/use-hotkey.js.map +1 -1
  331. package/dist/hooks/use-long-press.d.ts +7 -4
  332. package/dist/hooks/use-long-press.js +3 -0
  333. package/dist/hooks/use-long-press.js.map +1 -1
  334. package/dist/hooks/use-media-query.js +12 -4
  335. package/dist/hooks/use-media-query.js.map +1 -1
  336. package/dist/hooks/use-mounted.d.ts +22 -0
  337. package/dist/hooks/use-mounted.js +24 -0
  338. package/dist/hooks/use-mounted.js.map +1 -0
  339. package/dist/hooks/use-overlay-history.js +19 -3
  340. package/dist/hooks/use-overlay-history.js.map +1 -1
  341. package/dist/i18n/defaults.js +4 -5
  342. package/dist/i18n/defaults.js.map +1 -1
  343. package/dist/i18n/german.js +7 -1
  344. package/dist/i18n/german.js.map +1 -1
  345. package/dist/i18n/kit-labels.d.ts +9 -2
  346. package/dist/i18n/kit-labels.js.map +1 -1
  347. package/dist/i18n/locales/en.js +20 -41
  348. package/dist/i18n/locales/en.js.map +3 -3
  349. package/dist/i18n/locales/es.js +7 -1
  350. package/dist/i18n/locales/es.js.map +1 -1
  351. package/dist/i18n/locales/fr.js +20 -10
  352. package/dist/i18n/locales/fr.js.map +1 -1
  353. package/dist/i18n/locales/hu.js +9 -1
  354. package/dist/i18n/locales/hu.js.map +1 -1
  355. package/dist/i18n/locales/it.js +7 -1
  356. package/dist/i18n/locales/it.js.map +1 -1
  357. package/dist/i18n/locales/zh.js +8 -1
  358. package/dist/i18n/locales/zh.js.map +1 -1
  359. package/dist/i18n/review.js +5 -0
  360. package/dist/i18n/review.js.map +1 -1
  361. package/dist/index.d.ts +64 -17
  362. package/dist/index.js +77 -12
  363. package/dist/index.js.map +1 -1
  364. package/dist/landing/routing.d.ts +3 -1
  365. package/dist/landing/routing.js +4 -7
  366. package/dist/landing/routing.js.map +1 -1
  367. package/dist/lib/broadcast.d.ts +17 -0
  368. package/dist/lib/broadcast.js +30 -0
  369. package/dist/lib/broadcast.js.map +1 -0
  370. package/dist/lib/date-format.d.ts +37 -2
  371. package/dist/lib/date-format.js +34 -8
  372. package/dist/lib/date-format.js.map +1 -1
  373. package/dist/lib/day-format.d.ts +46 -0
  374. package/dist/lib/day-format.js +46 -0
  375. package/dist/lib/day-format.js.map +1 -0
  376. package/dist/lib/describe-failure.d.ts +14 -0
  377. package/dist/lib/describe-failure.js +9 -0
  378. package/dist/lib/describe-failure.js.map +1 -0
  379. package/dist/lib/direction.d.ts +16 -0
  380. package/dist/lib/direction.js +9 -1
  381. package/dist/lib/direction.js.map +1 -1
  382. package/dist/lib/focus-left.d.ts +63 -0
  383. package/dist/lib/focus-left.js +67 -0
  384. package/dist/lib/focus-left.js.map +1 -0
  385. package/dist/lib/format.js +5 -14
  386. package/dist/lib/format.js.map +1 -1
  387. package/dist/lib/http-status.d.ts +24 -0
  388. package/dist/lib/http-status.js +14 -0
  389. package/dist/lib/http-status.js.map +1 -0
  390. package/dist/lib/intl-cache.d.ts +14 -0
  391. package/dist/lib/intl-cache.js +15 -0
  392. package/dist/lib/intl-cache.js.map +1 -0
  393. package/dist/lib/isin.d.ts +10 -0
  394. package/dist/lib/isin.js.map +1 -1
  395. package/dist/lib/iso-day.d.ts +11 -0
  396. package/dist/lib/iso-day.js +8 -0
  397. package/dist/lib/iso-day.js.map +1 -0
  398. package/dist/lib/lazy-with-fallback.d.ts +31 -0
  399. package/dist/lib/lazy-with-fallback.js +40 -0
  400. package/dist/lib/lazy-with-fallback.js.map +1 -0
  401. package/dist/lib/path-pattern.d.ts +34 -0
  402. package/dist/lib/path-pattern.js +24 -0
  403. package/dist/lib/path-pattern.js.map +1 -0
  404. package/dist/lib/reduced-motion.d.ts +2 -1
  405. package/dist/lib/reduced-motion.js.map +1 -1
  406. package/dist/lib/round.d.ts +2 -1
  407. package/dist/lib/round.js +2 -1
  408. package/dist/lib/round.js.map +1 -1
  409. package/dist/lib/safe-storage.d.ts +24 -5
  410. package/dist/lib/safe-storage.js +27 -2
  411. package/dist/lib/safe-storage.js.map +1 -1
  412. package/dist/lib/session-refresh.js +1 -1
  413. package/dist/lib/session-refresh.js.map +1 -1
  414. package/dist/lib/share-format.d.ts +13 -0
  415. package/dist/lib/share-format.js +10 -0
  416. package/dist/lib/share-format.js.map +1 -0
  417. package/dist/lib/text-case.d.ts +17 -0
  418. package/dist/lib/text-case.js +8 -0
  419. package/dist/lib/text-case.js.map +1 -0
  420. package/dist/lib/text-match.d.ts +29 -0
  421. package/dist/lib/text-match.js +20 -2
  422. package/dist/lib/text-match.js.map +1 -1
  423. package/dist/lib/thenable.d.ts +13 -0
  424. package/dist/lib/thenable.js +8 -0
  425. package/dist/lib/thenable.js.map +1 -0
  426. package/dist/lib/translation-review.d.ts +7 -2
  427. package/dist/lib/translation-review.js +4 -4
  428. package/dist/lib/translation-review.js.map +1 -1
  429. package/dist/notifications/device-zone-report.js +1 -1
  430. package/dist/notifications/device-zone-report.js.map +1 -1
  431. package/dist/notifications/notification-bell.d.ts +2 -1
  432. package/dist/notifications/notification-bell.js +3 -3
  433. package/dist/notifications/notification-bell.js.map +1 -1
  434. package/dist/notifications/notification-inbox.d.ts +10 -6
  435. package/dist/notifications/notification-inbox.js +26 -48
  436. package/dist/notifications/notification-inbox.js.map +1 -1
  437. package/dist/notifications/notification-parts.d.ts +3 -2
  438. package/dist/notifications/notification-parts.js +1 -3
  439. package/dist/notifications/notification-parts.js.map +1 -1
  440. package/dist/notifications/notification-types-setting.js +1 -1
  441. package/dist/notifications/notification-types-setting.js.map +1 -1
  442. package/dist/notifications/notifications-labels.d.ts +6 -0
  443. package/dist/notifications/notifications-labels.js +1 -0
  444. package/dist/notifications/notifications-labels.js.map +1 -1
  445. package/dist/notifications/push-device-setting.js +1 -1
  446. package/dist/notifications/push-device-setting.js.map +1 -1
  447. package/dist/notifications/push-devices-setting.d.ts +2 -1
  448. package/dist/notifications/push-devices-setting.js +27 -49
  449. package/dist/notifications/push-devices-setting.js.map +1 -1
  450. package/dist/notifications/quiet-hours-setting.d.ts +10 -3
  451. package/dist/notifications/quiet-hours-setting.js +65 -26
  452. package/dist/notifications/quiet-hours-setting.js.map +1 -1
  453. package/dist/notifications/unsubscribe-panel.js +4 -7
  454. package/dist/notifications/unsubscribe-panel.js.map +1 -1
  455. package/dist/notifications/use-push-device.d.ts +39 -1
  456. package/dist/notifications/use-push-device.js +28 -7
  457. package/dist/notifications/use-push-device.js.map +1 -1
  458. package/dist/offline/query-persistence.d.ts +3 -1
  459. package/dist/offline/query-persistence.js +19 -2
  460. package/dist/offline/query-persistence.js.map +1 -1
  461. package/dist/rhf/fields.d.ts +11 -4
  462. package/dist/rhf/fields.js.map +1 -1
  463. package/dist/search/command-palette.js +1 -1
  464. package/dist/search/command-palette.js.map +1 -1
  465. package/dist/search/global-search.js +19 -9
  466. package/dist/search/global-search.js.map +1 -1
  467. package/dist/search/use-command-key.d.ts +12 -1
  468. package/dist/search/use-command-key.js +3 -12
  469. package/dist/search/use-command-key.js.map +1 -1
  470. package/dist/search.d.ts +7 -0
  471. package/dist/search.js +10 -0
  472. package/dist/search.js.map +1 -1
  473. package/dist/settings/use-settings-focus.js +1 -0
  474. package/dist/settings/use-settings-focus.js.map +1 -1
  475. package/dist/shell/account-menu-language.d.ts +21 -5
  476. package/dist/shell/account-menu-language.js +3 -1
  477. package/dist/shell/account-menu-language.js.map +1 -1
  478. package/dist/shell/account-menu-text-size.d.ts +26 -9
  479. package/dist/shell/account-menu-text-size.js +3 -2
  480. package/dist/shell/account-menu-text-size.js.map +1 -1
  481. package/dist/shell/dev-menu.js +5 -18
  482. package/dist/shell/dev-menu.js.map +1 -1
  483. package/dist/shell/role-switcher.d.ts +7 -0
  484. package/dist/shell/role-switcher.js.map +1 -1
  485. package/dist/shell/top-bar-actions.d.ts +1 -1
  486. package/dist/shell/top-bar-actions.js.map +1 -1
  487. package/dist/shell/top-bar-parts-labels.d.ts +0 -2
  488. package/dist/shell/top-bar-parts-labels.js +0 -1
  489. package/dist/shell/top-bar-parts-labels.js.map +1 -1
  490. package/dist/shell.d.ts +27 -8
  491. package/dist/shell.js +28 -7
  492. package/dist/shell.js.map +1 -1
  493. package/dist/sync/engine.d.ts +30 -4
  494. package/dist/sync/engine.js +172 -52
  495. package/dist/sync/engine.js.map +1 -1
  496. package/dist/sync.d.ts +6 -2
  497. package/dist/sync.js +6 -1
  498. package/dist/sync.js.map +1 -1
  499. package/dist/testing/css-variables.js +3 -8
  500. package/dist/testing/css-variables.js.map +1 -1
  501. package/dist/theme/contrast.d.ts +2 -1
  502. package/dist/theme/contrast.js +3 -8
  503. package/dist/theme/contrast.js.map +1 -1
  504. package/dist/theme/palette-store.js +6 -6
  505. package/dist/theme/palette-store.js.map +1 -1
  506. package/dist/theme/text-size.js +3 -8
  507. package/dist/theme/text-size.js.map +1 -1
  508. package/dist/theme/theme-store.js +3 -6
  509. package/dist/theme/theme-store.js.map +1 -1
  510. package/dist/tour/tour-catalogue.d.ts +7 -4
  511. package/dist/tour/tour-catalogue.js +12 -10
  512. package/dist/tour/tour-catalogue.js.map +1 -1
  513. package/dist/tour/tour-dock.d.ts +0 -2
  514. package/dist/tour/tour-dock.js +0 -2
  515. package/dist/tour/tour-dock.js.map +1 -1
  516. package/dist/tour/tour-gates.d.ts +4 -0
  517. package/dist/tour/tour-gates.js +14 -0
  518. package/dist/tour/tour-gates.js.map +1 -1
  519. package/dist/tour/tour-overlay.d.ts +27 -0
  520. package/dist/tour/tour-overlay.js +741 -0
  521. package/dist/tour/tour-overlay.js.map +1 -0
  522. package/dist/tour/tour.d.ts +13 -3
  523. package/dist/tour/tour.js +59 -781
  524. package/dist/tour/tour.js.map +1 -1
  525. package/dist/tour/use-tour-progress.js +1 -1
  526. package/dist/tour/use-tour-progress.js.map +1 -1
  527. package/dist/wizard/stepper-nav.d.ts +5 -1
  528. package/dist/wizard/stepper-nav.js.map +1 -1
  529. package/dist/wizard/types.d.ts +6 -2
  530. package/dist/wizard/types.js.map +1 -1
  531. package/dist/wizard/use-wizard.d.ts +3 -1
  532. package/dist/wizard/use-wizard.js.map +1 -1
  533. package/dist/wizard/validation.d.ts +3 -1
  534. package/dist/wizard/validation.js.map +1 -1
  535. package/package.json +10 -6
  536. package/src/account/account-parts.ts +5 -25
  537. package/src/account/data-export-setting-labels.ts +1 -1
  538. package/src/account/delete-account-setting-labels.ts +1 -1
  539. package/src/account/email-change-setting-labels.ts +1 -1
  540. package/src/account/passkeys-setting.tsx +60 -38
  541. package/src/account/sessions-setting.tsx +18 -12
  542. package/src/admin/admin-action-confirm.tsx +1 -5
  543. package/src/admin/admin-parts.ts +11 -25
  544. package/src/admin/mail-test-card-labels.ts +1 -1
  545. package/src/admin/plan-change-labels.ts +5 -23
  546. package/src/admin/plan-change.tsx +7 -44
  547. package/src/admin/reviewer-scope-editor.tsx +3 -3
  548. package/src/auth/auth-errors-labels.ts +23 -0
  549. package/src/auth/auth-errors.ts +11 -38
  550. package/src/auth/complete-name-dialog.tsx +4 -1
  551. package/src/auth/forgot-password-form-labels.ts +1 -1
  552. package/src/auth/forgot-password-form.tsx +11 -6
  553. package/src/auth/register-form-labels.ts +1 -1
  554. package/src/auth/reset-password-form-labels.ts +1 -1
  555. package/src/auth/reset-password-form.tsx +8 -4
  556. package/src/auth/sign-in-form-labels.ts +1 -1
  557. package/src/auth/status-parts.tsx +0 -6
  558. package/src/auth/verify-email-labels.ts +1 -1
  559. package/src/auth/verify-email.tsx +11 -6
  560. package/src/billing/cancel-subscription.tsx +26 -12
  561. package/src/billing/dialog-close.ts +34 -0
  562. package/src/billing/plan-card.tsx +36 -11
  563. package/src/billing/plan-change-labels.ts +66 -0
  564. package/src/billing/plan-switch.tsx +26 -12
  565. package/src/chart.ts +21 -3
  566. package/src/components/account-chips.tsx +20 -23
  567. package/src/components/alert-banner.tsx +82 -5
  568. package/src/components/amount-input.tsx +18 -7
  569. package/src/components/autocomplete.tsx +64 -70
  570. package/src/components/bulk-action-bar.tsx +70 -2
  571. package/src/components/button-look.ts +5 -5
  572. package/src/components/button.tsx +2 -2
  573. package/src/components/chart-edge.ts +34 -1
  574. package/src/components/chart-figure.tsx +35 -0
  575. package/src/components/chart-zoom-core.tsx +6 -5
  576. package/src/components/chart.tsx +26 -5
  577. package/src/components/combobox-core.tsx +293 -62
  578. package/src/components/combobox.tsx +183 -153
  579. package/src/components/copy-button.tsx +34 -23
  580. package/src/components/country-select.tsx +16 -11
  581. package/src/components/data-table-column-settings.tsx +52 -10
  582. package/src/components/data-table-filters.ts +6 -4
  583. package/src/components/data-table-fit.ts +19 -5
  584. package/src/components/data-table-groups.tsx +1 -1
  585. package/src/components/data-table-head.tsx +32 -22
  586. package/src/components/data-table-mobile.tsx +61 -26
  587. package/src/components/data-table-pagination.tsx +21 -6
  588. package/src/components/data-table-resize.ts +1 -1
  589. package/src/components/data-table-row-actions.tsx +3 -3
  590. package/src/components/data-table-row.tsx +25 -14
  591. package/src/components/data-table-selection.ts +1 -1
  592. package/src/components/data-table-shared.tsx +33 -1
  593. package/src/components/data-table-sort.ts +57 -2
  594. package/src/components/data-table-virtual.ts +32 -8
  595. package/src/components/data-table.tsx +239 -68
  596. package/src/components/date-field.tsx +65 -8
  597. package/src/components/date-picker.tsx +125 -48
  598. package/src/components/date-range-picker.tsx +82 -31
  599. package/src/components/error-boundary.tsx +53 -39
  600. package/src/components/field-base-labels.ts +20 -0
  601. package/src/components/field-base.tsx +13 -7
  602. package/src/components/field-sync-labels.ts +1 -0
  603. package/src/components/field-sync.tsx +23 -1
  604. package/src/components/form-actions.tsx +20 -5
  605. package/src/components/hover-menu.tsx +18 -8
  606. package/src/components/icon-button.tsx +14 -9
  607. package/src/components/inline-confirm.tsx +116 -0
  608. package/src/components/inline-entity-combobox.tsx +197 -153
  609. package/src/components/input.tsx +1 -1
  610. package/src/components/jump-calendar.tsx +30 -146
  611. package/src/components/legal-page.tsx +10 -7
  612. package/src/components/legal.tsx +4 -2
  613. package/src/components/lightbox.tsx +21 -8
  614. package/src/components/list.tsx +10 -4
  615. package/src/components/measured-grid.tsx +8 -4
  616. package/src/components/mini-calendar.tsx +6 -5
  617. package/src/components/modal.tsx +6 -1
  618. package/src/components/month-grid.tsx +229 -0
  619. package/src/components/month-picker.tsx +192 -200
  620. package/src/components/multi-select.tsx +21 -9
  621. package/src/components/picker-sheet.tsx +12 -9
  622. package/src/components/pie-chart-labels.ts +8 -0
  623. package/src/components/pie-chart.tsx +22 -28
  624. package/src/components/popover.tsx +18 -1
  625. package/src/components/row-actions.tsx +2 -1
  626. package/src/components/section-nav.tsx +7 -0
  627. package/src/components/series-chart-axes.ts +3 -3
  628. package/src/components/series-chart-labels.ts +7 -4
  629. package/src/components/series-chart.tsx +178 -69
  630. package/src/components/share-card.tsx +6 -6
  631. package/src/components/sign-chip-labels.ts +1 -0
  632. package/src/components/sign-chip.tsx +10 -1
  633. package/src/components/tabs-labels.ts +13 -0
  634. package/src/components/tabs.tsx +2 -2
  635. package/src/components/toggle-legend.tsx +16 -11
  636. package/src/components/translation-review-editor.tsx +6 -5
  637. package/src/components/translation-review.tsx +4 -3
  638. package/src/components/treemap-labels.ts +39 -0
  639. package/src/components/treemap-layout.ts +210 -0
  640. package/src/components/treemap.tsx +722 -133
  641. package/src/components/use-table-state.ts +12 -9
  642. package/src/data-table.ts +9 -2
  643. package/src/eslint/role-utilities.ts +97 -19
  644. package/src/feedback/feedback-dialog.tsx +30 -19
  645. package/src/feedback/feedback-mutation.ts +41 -0
  646. package/src/feedback/feedback-page-link.ts +90 -0
  647. package/src/feedback/feedback-public-list.tsx +17 -5
  648. package/src/feedback/feedback-replies.tsx +13 -6
  649. package/src/feedback/feedback-row-detail-labels.ts +5 -0
  650. package/src/feedback/feedback-row-detail.tsx +103 -67
  651. package/src/feedback/feedback-status-undo.ts +41 -27
  652. package/src/feedback/feedback-submit-dialog.tsx +2 -2
  653. package/src/feedback/feedback-submit.tsx +21 -7
  654. package/src/feedback/feedback-swipe.tsx +1 -1
  655. package/src/feedback/feedback-table.tsx +86 -38
  656. package/src/feedback/feedback-thread-labels.ts +2 -2
  657. package/src/feedback/feedback-thread.tsx +27 -25
  658. package/src/feedback.ts +42 -0
  659. package/src/hooks/use-focus-trap.ts +8 -24
  660. package/src/hooks/use-hotkey.ts +24 -7
  661. package/src/hooks/use-long-press.ts +16 -2
  662. package/src/hooks/use-media-query.ts +20 -4
  663. package/src/hooks/use-mounted.ts +39 -0
  664. package/src/hooks/use-overlay-history.ts +32 -3
  665. package/src/i18n/defaults.ts +4 -5
  666. package/src/i18n/german.ts +8 -2
  667. package/src/i18n/kit-labels.tsx +9 -2
  668. package/src/i18n/locales/es.ts +8 -2
  669. package/src/i18n/locales/fr.ts +21 -13
  670. package/src/i18n/locales/hu.ts +10 -2
  671. package/src/i18n/locales/it.ts +8 -2
  672. package/src/i18n/locales/zh.ts +9 -2
  673. package/src/i18n/review.ts +5 -0
  674. package/src/index.ts +103 -13
  675. package/src/landing/routing.tsx +14 -10
  676. package/src/lib/broadcast.ts +52 -0
  677. package/src/lib/date-format.ts +89 -13
  678. package/src/lib/day-format.ts +96 -0
  679. package/src/lib/describe-failure.ts +18 -0
  680. package/src/lib/direction.ts +39 -0
  681. package/src/lib/focus-left.ts +156 -0
  682. package/src/lib/format.ts +5 -17
  683. package/src/lib/http-status.ts +38 -0
  684. package/src/lib/intl-cache.ts +25 -0
  685. package/src/lib/isin.ts +10 -0
  686. package/src/lib/iso-day.ts +13 -0
  687. package/src/lib/lazy-with-fallback.ts +82 -0
  688. package/src/lib/path-pattern.ts +55 -0
  689. package/src/lib/reduced-motion.ts +2 -1
  690. package/src/lib/round.ts +7 -2
  691. package/src/lib/safe-storage.ts +48 -6
  692. package/src/lib/session-refresh.ts +1 -1
  693. package/src/lib/share-format.ts +18 -0
  694. package/src/lib/text-case.ts +19 -0
  695. package/src/lib/text-match.ts +57 -2
  696. package/src/lib/thenable.ts +19 -0
  697. package/src/lib/translation-review.ts +13 -5
  698. package/src/notifications/device-zone-report.ts +1 -1
  699. package/src/notifications/notification-bell.tsx +7 -4
  700. package/src/notifications/notification-inbox.tsx +40 -58
  701. package/src/notifications/notification-parts.tsx +3 -4
  702. package/src/notifications/notification-types-setting.tsx +1 -1
  703. package/src/notifications/notifications-labels.ts +7 -0
  704. package/src/notifications/push-device-setting.tsx +1 -1
  705. package/src/notifications/push-devices-setting.tsx +30 -55
  706. package/src/notifications/quiet-hours-setting.tsx +93 -31
  707. package/src/notifications/unsubscribe-panel.tsx +4 -7
  708. package/src/notifications/use-push-device.ts +76 -10
  709. package/src/offline/query-persistence.ts +35 -3
  710. package/src/rhf/fields.tsx +11 -4
  711. package/src/search/command-palette.tsx +2 -4
  712. package/src/search/global-search.tsx +36 -15
  713. package/src/search/use-command-key.ts +13 -12
  714. package/src/search.ts +9 -0
  715. package/src/settings/use-settings-focus.ts +3 -0
  716. package/src/shell/account-menu-language.tsx +27 -5
  717. package/src/shell/account-menu-text-size.tsx +32 -10
  718. package/src/shell/dev-menu.tsx +7 -21
  719. package/src/shell/role-switcher.tsx +7 -0
  720. package/src/shell/top-bar-actions.tsx +1 -1
  721. package/src/shell/top-bar-parts-labels.ts +0 -3
  722. package/src/shell.ts +40 -9
  723. package/src/sync/engine.ts +339 -61
  724. package/src/sync.ts +8 -1
  725. package/src/testing/css-variables.ts +8 -9
  726. package/src/theme/contrast.ts +8 -9
  727. package/src/theme/palette-store.ts +9 -9
  728. package/src/theme/text-size.ts +6 -8
  729. package/src/theme/theme-store.ts +7 -9
  730. package/src/tour/tour-catalogue.tsx +26 -15
  731. package/src/tour/tour-dock.ts +0 -2
  732. package/src/tour/tour-gates.ts +23 -0
  733. package/src/tour/tour-overlay.tsx +1170 -0
  734. package/src/tour/tour.tsx +108 -1202
  735. package/src/tour/use-tour-progress.ts +1 -1
  736. package/src/wizard/stepper-nav.tsx +3 -1
  737. package/src/wizard/types.ts +11 -2
  738. package/src/wizard/use-wizard.ts +2 -1
  739. package/src/wizard/validation.ts +8 -2
  740. package/tokens.css +2 -1
  741. package/dist/components/ui-labels.js.map +0 -1
  742. package/dist/shell/dev-switchers.d.ts +0 -6
  743. package/dist/shell/dev-switchers.js +0 -12
  744. package/dist/shell/dev-switchers.js.map +0 -1
  745. package/src/components/ui-labels.ts +0 -24
  746. package/src/shell/dev-switchers.tsx +0 -18
@@ -1,12 +1,14 @@
1
- import { useMemo } from "react";
1
+ import { useCallback, useMemo } from "react";
2
2
  import type { MouseEvent, ReactElement, ReactNode } from "react";
3
3
  import { ExternalLink, ThumbsUp } from "lucide-react";
4
4
  import { cn } from "../lib/cn";
5
- import { toLocalIso } from "../lib/dates";
6
- import { EMPTY_FORMATTED_VALUE, formatDate, toDate } from "../lib/format";
7
- import { useKitDateFormatter, useKitLabels, useKitLink, useKitLocale, type LabelOverride } from "../i18n/kit-labels";
5
+ import { useDayFormatter } from "../lib/day-format";
6
+ import { EMPTY_FORMATTED_VALUE } from "../lib/format";
7
+ import { useKitLabels, useKitLink, type LabelOverride } from "../i18n/kit-labels";
8
8
  import type { KitLinkProps } from "../i18n/kit-labels";
9
+ import type { PathPattern } from "../landing/routing";
9
10
  import { Chip } from "../components/chip";
11
+ import { CopyButton } from "../components/copy-button";
10
12
  import { Tooltip } from "../components/tooltip";
11
13
  import { FloatingAction, FloatingActionGroup } from "../components/floating-panel";
12
14
  import type { FloatingCorner } from "../components/floating-panel";
@@ -36,7 +38,8 @@ import {
36
38
  type FeedbackRecord,
37
39
  } from "./feedback-record";
38
40
  import type { FeedbackStatusChange } from "./feedback-status-undo";
39
- import { feedbackPageHref, feedbackPagePath } from "./feedback-row-detail";
41
+ import { feedbackPagePath, useFeedbackDetailLabels } from "./feedback-row-detail";
42
+ import { feedbackPage, feedbackPageLinkTarget } from "./feedback-page-link";
40
43
  import type { CommitScope } from "../components/write-lock";
41
44
  import { DEFAULT_FEEDBACK_PAGE_LABELS } from "./feedback-table-labels";
42
45
  import { DEFAULT_FEEDBACK_PUBLIC_LABELS } from "./feedback-public-labels";
@@ -235,25 +238,16 @@ const FEEDBACK_DATE_STYLE: Intl.DateTimeFormatOptions = {
235
238
  };
236
239
 
237
240
  /**
238
- * `renderDate` when the app gave one, else the kit's: the `<UiKitProvider formatDate>`
239
- * when the app set one (called with the LOCAL calendar day and `weekday: true`, as
240
- * `DateMark` calls it), else `Intl` in the provider's locale with the weekday. An
241
- * unparseable value is passed through rather than hidden.
241
+ * `renderDate` when the app gave one (and it answers), else the kit's: the
242
+ * `<UiKitProvider formatDate>` when the app set one (called with the calendar day and
243
+ * `weekday: true`, as `DateMark` calls it), else `Intl` in the provider's locale and
244
+ * (0.52) time zone, with the weekday. An unparseable value is passed through rather than
245
+ * hidden. The kit's one day ladder since 0.52 (refactor audit 2026-10-30, DUP-2), which
246
+ * every date a kit component prints goes down.
242
247
  */
243
248
  export function useFeedbackRenderDate(renderDate?: FeedbackRenderDate, locale?: string): FeedbackRenderDate {
244
- const kitLocale = useKitLocale(locale);
245
- const fromProvider = useKitDateFormatter();
246
- return useMemo<FeedbackRenderDate>(() => {
247
- if (renderDate) return renderDate;
248
- return (iso) => {
249
- const date = toDate(iso);
250
- if (!date) return iso || EMPTY_FORMATTED_VALUE;
251
- const own = fromProvider
252
- ? fromProvider(toLocalIso(date), { unit: "day", source: "dateMark", locale: kitLocale, weekday: true })
253
- : "";
254
- return own || formatDate(date, FEEDBACK_DATE_STYLE, { locale: kitLocale });
255
- };
256
- }, [renderDate, fromProvider, kitLocale]);
249
+ const day = useDayFormatter<string>(renderDate, locale);
250
+ return useCallback<FeedbackRenderDate>((iso) => day(iso, { weekday: true, style: FEEDBACK_DATE_STYLE }), [day]);
257
251
  }
258
252
 
259
253
  /** A date in a cell: `<time>`, nowrap, tabular figures; "—" when there is none. */
@@ -339,29 +333,44 @@ export function FeedbackSubject({ row, wrap = false, labels: labelsProp, classNa
339
333
 
340
334
  /**
341
335
  * The page a report was filed from, as a link — the cell keksdose's column 7 draws
342
- * (:850): the path as text, path + query + hash as the `href`, read from `context.url`
343
- * else `context.route` by the row detail's own readers (`feedbackPagePath` /
344
- * `feedbackPageHref`, feedback-row-detail.tsx), so the column and the detail link the
345
- * same page the same way. A real link through the `<UiKitProvider linkComponent>` (the app's router, so it
346
- * does not reload the app; keksdose's plain `<a>` did), and its click stops at the cell so
347
- * the row does not open as well.
336
+ * (:850): the path as text and as the `href`, read from `context.url` else
337
+ * `context.route` by the row detail's own reader (`feedbackPage`, feedback-page-link.ts),
338
+ * so the column and the detail link the same page the same way. A real link through the
339
+ * `<UiKitProvider linkComponent>` (the app's router, so it does not reload the app;
340
+ * keksdose's plain `<a>` did), and its click stops at the cell so the row does not open
341
+ * as well.
348
342
  *
349
343
  * Its name is the path, as on screen, with "Open page" said before it — keksdose's
350
344
  * `aria-label="Open page"` replaced the path, so a screen reader heard forty identical
351
345
  * links down the column.
346
+ *
347
+ * The PATH alone (0.52 code review, feedback-page-link.ts): the query is the reporter's to
348
+ * write, and `/login?next=%2Fjoin%3Ftoken%3D…` forwarded the admin's click to an
349
+ * invitation. A one-shot route — `/join`, `/register`, `/verify-email`, `/reset-password`
350
+ * and the app's `pageLinkExclude` — is the path as text with Copy, never a link (0.52,
351
+ * refactor audit 2026-10-30, FLW-7): those routes act on load.
352
352
  */
353
- function FeedbackPageLinkCell({ context, openPage }: { context: FeedbackContext | null; openPage: string }) {
353
+ function FeedbackPageLinkCell({
354
+ context,
355
+ openPage,
356
+ exclude,
357
+ }: {
358
+ context: FeedbackContext | null;
359
+ openPage: string;
360
+ exclude: readonly PathPattern[] | undefined;
361
+ }) {
354
362
  const kitLink = useKitLink();
355
- const href = feedbackPageHref(context);
356
- const path = feedbackPagePath(context);
357
- if (!href || !path) return <span className="text-placeholder">{EMPTY_FORMATTED_VALUE}</span>;
363
+ const page = feedbackPage(context);
364
+ if (!page) return <span className="text-placeholder">{EMPTY_FORMATTED_VALUE}</span>;
365
+ const href = feedbackPageLinkTarget(page, exclude);
366
+ if (!href) return <FeedbackPageText path={page.path} url={page.url} />;
358
367
  const className =
359
368
  "inline-flex min-w-0 max-w-full items-center gap-1 text-secondary hover:text-primary hover:underline";
360
369
  const children = (
361
370
  <>
362
371
  {/* The space outside the hidden span: a flex container drops it from the layout,
363
372
  and the accessible name keeps it ("Open page /accounts"). */}
364
- <span className="sr-only">{openPage}</span> <code className="min-w-0 truncate text-xs">{path}</code>
373
+ <span className="sr-only">{openPage}</span> <code className="min-w-0 truncate text-xs">{page.path}</code>
365
374
  <ExternalLink className="size-3 shrink-0" aria-hidden />
366
375
  </>
367
376
  );
@@ -378,6 +387,19 @@ function FeedbackPageLinkCell({ context, openPage }: { context: FeedbackContext
378
387
  );
379
388
  }
380
389
 
390
+ /** A one-shot page in the URL column: its path to read, and Copy. A component of its own
391
+ * so only such a row resolves the `feedbackDetail` words — every cell of a 270-row inbox
392
+ * did, for a button only a one-shot row shows (0.52 code review, efficiency). */
393
+ function FeedbackPageText({ path, url }: { path: string; url: string }) {
394
+ const { copyUrl } = useFeedbackDetailLabels();
395
+ return (
396
+ <span className="inline-flex min-w-0 max-w-full items-center gap-1 text-secondary" data-feedback-page-unlinked="">
397
+ <code className="min-w-0 truncate text-xs">{path}</code>
398
+ <CopyButton size="xs" className="shrink-0" text={url} label={copyUrl} stopPropagation />
399
+ </span>
400
+ );
401
+ }
402
+
381
403
  /** The provider's link, drawn by a component declared once (as FloatingAction's). */
382
404
  function RenderedLink({ render, ...props }: KitLinkProps & { render: (props: KitLinkProps) => ReactElement }) {
383
405
  return render(props);
@@ -395,8 +417,8 @@ export interface FeedbackColumnsOptions {
395
417
  /** The admin on `/feedback` — the status cell offers its steps. Otherwise it shows them
396
418
  * read-only. */
397
419
  canEdit: boolean;
398
- /** The undoable status change, `useFeedbackStatusUndo(update.mutate)` (§4.5) — the
399
- * same one the row detail and the swipes use. */
420
+ /** The undoable status change, `useFeedbackStatusUndo(update.mutateAsync)` (§4.5) —
421
+ * the same one the row detail and the swipes use. */
400
422
  onStatus: FeedbackStatusChange;
401
423
  /** See {@link FeedbackRenderDate}. */
402
424
  renderDate: FeedbackRenderDate;
@@ -414,6 +436,15 @@ export interface FeedbackColumnsOptions {
414
436
  /** The Votes header — `feedbackPublic.columnVotes`, so the inbox and the public list
415
437
  * say the same ({@link useFeedbackColumns} reads it). Default "Votes". */
416
438
  votesHeader?: string;
439
+ /**
440
+ * 0.52 (FLW-7): the app's one-shot routes, ON TOP of the kit's — `/join`, `/register`,
441
+ * `/verify-email`, `/reset-password` (a string is that path and everything under it, a
442
+ * RegExp is tested on the path, as `useLastVisitedPage`'s `exclude`). The URL cell
443
+ * shows such a page as text with Copy, never as a link; any other page links its path
444
+ * alone. Keep it stable (module scope): it is a dependency of {@link useFeedbackColumns}'
445
+ * memo.
446
+ */
447
+ pageLinkExclude?: readonly PathPattern[];
417
448
  }
418
449
 
419
450
  /** The vote count, a quiet chip with the thumb (§9.6) — the Votes cell and the card's. */
@@ -479,6 +510,7 @@ export function feedbackColumns<T extends FeedbackTableRow>({
479
510
  categoryLabels,
480
511
  votes = false,
481
512
  votesHeader = DEFAULT_FEEDBACK_PUBLIC_LABELS.columnVotes,
513
+ pageLinkExclude,
482
514
  }: FeedbackColumnsOptions): DataTableColumn<T>[] {
483
515
  const editable = canEdit && !mine;
484
516
  const votesColumn: DataTableColumn<T>[] = votes
@@ -608,7 +640,9 @@ export function feedbackColumns<T extends FeedbackTableRow>({
608
640
  // The cell IS a link, so the row's own permalink must never wrap it (keksdose
609
641
  // feedback #451: <a> in <a>, and "open the page" silently did nothing).
610
642
  noRowLink: true,
611
- cell: (row) => <FeedbackPageLinkCell context={row.context} openPage={labels.openPage} />,
643
+ cell: (row) => (
644
+ <FeedbackPageLinkCell context={row.context} openPage={labels.openPage} exclude={pageLinkExclude} />
645
+ ),
612
646
  sortBy: (row) => feedbackPagePath(row.context) ?? "",
613
647
  filterBy: (row) => feedbackPagePath(row.context) ?? "",
614
648
  mobileHidden: true,
@@ -670,7 +704,7 @@ export interface UseFeedbackColumnsOptions extends Omit<
670
704
  /**
671
705
  * {@link feedbackColumns} with the `feedbackPage`, `feedbackStatus` and
672
706
  * `feedbackCategory` words from the provider, memoised on what it reads — pass
673
- * `update.mutate` through `useFeedbackStatusUndo` (stable) rather than a fresh function
707
+ * `update.mutateAsync` through `useFeedbackStatusUndo` (stable) rather than a fresh function
674
708
  * per render, or every row's columns are rebuilt on each render (keksdose :667).
675
709
  */
676
710
  export function useFeedbackColumns<T extends FeedbackTableRow>({
@@ -680,6 +714,7 @@ export function useFeedbackColumns<T extends FeedbackTableRow>({
680
714
  renderDate: renderDateProp,
681
715
  commit,
682
716
  votes,
717
+ pageLinkExclude,
683
718
  labels: labelsProp,
684
719
  }: UseFeedbackColumnsOptions): DataTableColumn<T>[] {
685
720
  const labels = useFeedbackPageLabels(labelsProp);
@@ -700,8 +735,21 @@ export function useFeedbackColumns<T extends FeedbackTableRow>({
700
735
  categoryLabels,
701
736
  votes,
702
737
  votesHeader,
738
+ pageLinkExclude,
703
739
  }),
704
- [mine, canEdit, onStatus, renderDate, commit, labels, statusLabels, categoryLabels, votes, votesHeader],
740
+ [
741
+ mine,
742
+ canEdit,
743
+ onStatus,
744
+ renderDate,
745
+ commit,
746
+ labels,
747
+ statusLabels,
748
+ categoryLabels,
749
+ votes,
750
+ votesHeader,
751
+ pageLinkExclude,
752
+ ],
705
753
  );
706
754
  }
707
755
 
@@ -2,7 +2,7 @@
2
2
  // catalogue (src/i18n/defaults.ts) imports them without the component, so `en` loads as one
3
3
  // chunk like the other languages (0.34, KS U8). ./feedback-thread re-exports them.
4
4
 
5
- import type { FeedbackComposerLabels, FeedbackThreadLabels } from "./feedback-thread";
5
+ import type { ChatComposerLabels, FeedbackThreadLabels } from "./feedback-thread";
6
6
 
7
7
  export const DEFAULT_FEEDBACK_THREAD_LABELS: FeedbackThreadLabels = {
8
8
  thread: "Comments",
@@ -13,7 +13,7 @@ export const DEFAULT_FEEDBACK_THREAD_LABELS: FeedbackThreadLabels = {
13
13
  attachments: "Attachments",
14
14
  };
15
15
 
16
- export const DEFAULT_FEEDBACK_COMPOSER_LABELS: FeedbackComposerLabels = {
16
+ export const DEFAULT_FEEDBACK_COMPOSER_LABELS: ChatComposerLabels = {
17
17
  field: "Write a comment",
18
18
  placeholder: "Write a comment…",
19
19
  send: "Send",
@@ -3,6 +3,7 @@ import type { ReactNode, Ref, RefObject } from "react";
3
3
  import { ImageIcon, ImageOff, Paperclip, Send } from "lucide-react";
4
4
  import { cn } from "../lib/cn";
5
5
  import { formatDate, formatRelativeTime } from "../lib/format";
6
+ import { upperFirst } from "../lib/text-case";
6
7
  import { hasContent } from "../lib/presence";
7
8
  import { Button } from "../components/button";
8
9
  import { EmptyState } from "../components/empty-state";
@@ -74,7 +75,7 @@ export { DEFAULT_FEEDBACK_THREAD_LABELS };
74
75
 
75
76
  /** The `feedbackComposer` namespace of `<UiKitProvider labels>`. The attach buttons'
76
77
  * words are `feedbackAttachment`'s, shared with the dialog and the note editor. */
77
- export interface FeedbackComposerLabels {
78
+ export interface ChatComposerLabels {
78
79
  /** Accessible name of the text box. */
79
80
  field: string;
80
81
  placeholder: string;
@@ -436,7 +437,7 @@ function DaySeparator({ date, now, locale }: { date: Date; now: number; locale:
436
437
  let label: string;
437
438
  if (days === 0 || days === -1) {
438
439
  const word = new Intl.RelativeTimeFormat(locale, { numeric: "auto" }).format(days + 0, "day");
439
- label = word.charAt(0).toLocaleUpperCase(locale) + word.slice(1);
440
+ label = upperFirst(word, locale);
440
441
  } else {
441
442
  label = formatDate(
442
443
  date,
@@ -482,7 +483,7 @@ export type FeedbackComposerAttachment = Omit<FeedbackNoteAttachment, "labels" |
482
483
  } & Pick<FeedbackAttachmentFieldSingleProps, "buttonVariant" | "buttonSize">;
483
484
 
484
485
  /**
485
- * What a render-prop {@link FeedbackComposerProps.attachmentSlot} is handed (0.24.0,
486
+ * What a render-prop {@link ChatComposerProps.attachmentSlot} is handed (0.24.0,
486
487
  * keksdose).
487
488
  *
488
489
  * keksdose's support chat put `<FeedbackAttachmentField refs>` in the slot and a
@@ -492,7 +493,7 @@ export type FeedbackComposerAttachment = Omit<FeedbackNoteAttachment, "labels" |
492
493
  * to itself, so keksdose wrapped the whole composer in a ref'd `<div>` of its own just
493
494
  * to have an element to hand over.
494
495
  */
495
- export interface FeedbackComposerSlotContext {
496
+ export interface ChatComposerSlotContext {
496
497
  /**
497
498
  * The composer's root, round the text box and this slot — the field's `pasteFrom`,
498
499
  * as it is: `pasteFrom={slot.root}`.
@@ -514,7 +515,7 @@ export interface FeedbackComposerSlotContext {
514
515
  pending: boolean;
515
516
  }
516
517
 
517
- export interface FeedbackComposerProps {
518
+ export interface ChatComposerProps {
518
519
  /**
519
520
  * Send the comment. Return the promise: the box clears when it RESOLVES, and only of
520
521
  * what was sent — text typed while it was in flight stays. A rejection keeps
@@ -538,7 +539,7 @@ export interface FeedbackComposerProps {
538
539
  * refs and clearing them once `onSend` resolves stay with the host. Pair it with
539
540
  * `canSend`.
540
541
  *
541
- * A node, or (0.24.0) a function of {@link FeedbackComposerSlotContext} that returns
542
+ * A node, or (0.24.0) a function of {@link ChatComposerSlotContext} that returns
542
543
  * one — for a field that wants the composer's root as its `pasteFrom`, so a
543
544
  * screenshot pasted into the box reaches it, and `pending` for its `disabled`:
544
545
  *
@@ -551,7 +552,7 @@ export interface FeedbackComposerProps {
551
552
  * Called once per render of the composer, and not at all while `disabledReason`
552
553
  * stands in for it.
553
554
  */
554
- attachmentSlot?: ReactNode | ((slot: FeedbackComposerSlotContext) => ReactNode);
555
+ attachmentSlot?: ReactNode | ((slot: ChatComposerSlotContext) => ReactNode);
555
556
  /**
556
557
  * Whether Send is enabled, over the composer's own rule (some text in the box) —
557
558
  * for state the composer cannot see, i.e. `attachmentSlot`'s (keksdose G5): `true`
@@ -592,7 +593,7 @@ export interface FeedbackComposerProps {
592
593
  * Textarea's `maxLength` + `showCount` since 0.22; the reply box, a composer, could
593
594
  * not). The box's own `maxLength`, so typing and pasting stop at it.
594
595
  *
595
- * {@link FeedbackComposerHandle.insertText} is not stopped by it — the browser limits
596
+ * {@link ChatComposerHandle.insertText} is not stopped by it — the browser limits
596
597
  * typing, not a script — and a canned reply is not cut mid-sentence to fit. A draft
597
598
  * past the limit therefore holds Send back (whatever `canSend` says, as `pending`
598
599
  * does) until it is trimmed; with `showCount` the counter, red at the limit, says by
@@ -623,13 +624,13 @@ export interface FeedbackComposerProps {
623
624
  * is still the one that went out.
624
625
  */
625
626
  value?: string;
626
- /** Every change to the draft — typing, {@link FeedbackComposerHandle.insertText}, the
627
+ /** Every change to the draft — typing, {@link ChatComposerHandle.insertText}, the
627
628
  * clear after a send. Required to change a controlled `value`. */
628
629
  onValueChange?: (value: string) => void;
629
- /** {@link FeedbackComposerHandle}: put text into the draft from outside (canned-reply
630
+ /** {@link ChatComposerHandle}: put text into the draft from outside (canned-reply
630
631
  * chips) or focus the box. */
631
- ref?: Ref<FeedbackComposerHandle>;
632
- labels?: LabelOverride<FeedbackComposerLabels>;
632
+ ref?: Ref<ChatComposerHandle>;
633
+ labels?: LabelOverride<ChatComposerLabels>;
633
634
  className?: string;
634
635
  /**
635
636
  * `"sm"` for a narrow host — keksdose's assistant launcher, a small floating panel
@@ -659,7 +660,7 @@ export interface FeedbackComposerProps {
659
660
  * the string, not the caret, so it could only append — so the composer, which owns
660
661
  * the textarea, does the splice.
661
662
  */
662
- export interface FeedbackComposerHandle {
663
+ export interface ChatComposerHandle {
663
664
  /**
664
665
  * Insert `text` at the caret, replacing any selection (the caret the box last had:
665
666
  * a click on a chip blurs it, and the selection survives the blur), then focus the
@@ -685,7 +686,8 @@ const isApple = () =>
685
686
  * feedback-specific — a textarea, an optional picture or a host's upload slot, Send,
686
687
  * `sendOn="enter"` for the chat way — and keksdose's assistant and support chat are
687
688
  * chats, not reports. `FeedbackComposer`, its old name, was removed in 0.35 (refactor
688
- * audit 2026-10, API-6d; deprecated in 0.34); its types keep theirs.
689
+ * audit 2026-10, API-6d; deprecated in 0.34); its types are `ChatComposer*` too since 0.52
690
+ * (refactor audit 2026-10-30, API-6), the `FeedbackComposer*` names deprecated aliases.
689
691
  */
690
692
  export function ChatComposer({
691
693
  onSend,
@@ -709,7 +711,7 @@ export function ChatComposer({
709
711
  id,
710
712
  size = "md",
711
713
  ...rest
712
- }: FeedbackComposerProps) {
714
+ }: ChatComposerProps) {
713
715
  const labels = useKitLabels("feedbackComposer", DEFAULT_FEEDBACK_COMPOSER_LABELS, labelsProp);
714
716
  // The lock as Send sees it, with its scope (§12.36). Send's Button reads the same
715
717
  // through its own `commit`; this holds the keyboard's send back with it.
@@ -797,7 +799,7 @@ export function ChatComposer({
797
799
  const config = attachment === true ? {} : attachment || null;
798
800
  // The slot is handed the ref OBJECT, for a field's `pasteFrom`, which reads `.current`
799
801
  // in an effect once the root is attached — nothing reads it during this render (see
800
- // FeedbackComposerSlotContext.root).
802
+ // ChatComposerSlotContext.root).
801
803
  const slot =
802
804
  typeof attachmentSlot === "function"
803
805
  ? // eslint-disable-next-line react-hooks/refs -- handed on for an effect, not read here
@@ -902,12 +904,12 @@ function dataAttributes(props: object): Record<string, unknown> {
902
904
  return out;
903
905
  }
904
906
 
905
- /** {@link FeedbackComposerProps}, for {@link ChatComposer}. */
906
- export type ChatComposerProps = FeedbackComposerProps;
907
- /** {@link FeedbackComposerHandle}, for {@link ChatComposer}. */
908
- export type ChatComposerHandle = FeedbackComposerHandle;
909
- /** {@link FeedbackComposerLabels}, for {@link ChatComposer} — still the `feedbackComposer`
910
- * namespace of the provider. */
911
- export type ChatComposerLabels = FeedbackComposerLabels;
912
- /** {@link FeedbackComposerSlotContext}, for {@link ChatComposer}'s `attachmentSlot`. */
913
- export type ChatComposerSlotContext = FeedbackComposerSlotContext;
907
+ /** @deprecated 0.52 — {@link ChatComposerProps}, the same type; removed in 0.53 */
908
+ export type FeedbackComposerProps = ChatComposerProps;
909
+ /** @deprecated 0.52 — {@link ChatComposerHandle}, the same type; removed in 0.53 */
910
+ export type FeedbackComposerHandle = ChatComposerHandle;
911
+ /** @deprecated 0.52 — {@link ChatComposerLabels}, the same type (still the provider's
912
+ * `feedbackComposer` namespace); removed in 0.53 */
913
+ export type FeedbackComposerLabels = ChatComposerLabels;
914
+ /** @deprecated 0.52 — {@link ChatComposerSlotContext}, the same type; removed in 0.53 */
915
+ export type FeedbackComposerSlotContext = ChatComposerSlotContext;
package/src/feedback.ts CHANGED
@@ -31,3 +31,45 @@ export * from "./feedback/feedback-vote-button";
31
31
  export * from "./feedback/feedback-comment-thread";
32
32
  export * from "./feedback/feedback-replies";
33
33
  export * from "./feedback/feedback-entry-file";
34
+ // 0.52: the slice's share of the 55 names no app reads (refactor audit 2026-10-30, API-4,
35
+ // decision 4), tagged on their specifiers as the barrel's are — the modules keep them.
36
+ export {
37
+ /** @deprecated 0.52 — `appendRework`, which writes the line (API-4); removed in 0.53 */
38
+ feedbackAttachmentLine,
39
+ } from "./feedback/feedback-record";
40
+ export {
41
+ /** @deprecated 0.52 — `useFeedbackStatusUndo`, which keeps its Undo that long (API-4); removed in 0.53 */
42
+ FEEDBACK_UNDO_DURATION,
43
+ } from "./feedback/feedback-status-undo";
44
+ export {
45
+ /** @deprecated 0.52 — `DEFAULT_FEEDBACK_SWIPE` and `feedbackSwipePlan`, which name the actions (API-4); removed in 0.53 */
46
+ FEEDBACK_SWIPE_ACTIONS,
47
+ } from "./feedback/feedback-swipe";
48
+ export {
49
+ /** @deprecated 0.52 — `useFeedbackColumns`, the same columns in the provider's words (API-4); removed in 0.53 */
50
+ feedbackColumns,
51
+ /** @deprecated 0.52 — `useFeedbackColumns`, whose submitter cell reads it (API-4); removed in 0.53 */
52
+ feedbackSubmitter,
53
+ /** @deprecated 0.52 — `useFeedbackColumns`, whose submitter cell reads it (API-4); removed in 0.53 */
54
+ feedbackSubmitterEmail,
55
+ /** @deprecated 0.52 — `useFeedbackColumns`, whose environment cell reads it (API-4); removed in 0.53 */
56
+ feedbackEnvironment,
57
+ } from "./feedback/feedback-table";
58
+ export {
59
+ /** @deprecated 0.52 — `FeedbackRowDetail`, which links the page itself (API-4); removed in 0.53 */
60
+ feedbackPageUrl,
61
+ /** @deprecated 0.52 — `FeedbackRowDetail` and the table's URL cell, which link only a page's path and keep one-shot pages as text (the 0.52 code review's guard, which an app has no helper for); removed in 0.53 */
62
+ feedbackPageHref,
63
+ /** @deprecated 0.52 — `FeedbackRowDetail` and the table's URL cell, which show the page themselves; removed in 0.53 */
64
+ feedbackPagePath,
65
+ /** @deprecated 0.52 — `FeedbackRowDetail`, which lists the attachments itself (API-4); removed in 0.53 */
66
+ feedbackAttachmentUrls,
67
+ /** @deprecated 0.52 — `FeedbackRowDetail`, which decides who may edit what (API-4); removed in 0.53 */
68
+ feedbackRowAccess,
69
+ /** @deprecated 0.52 — `FeedbackRowDetail`, which resolves its words itself (API-4); removed in 0.53 */
70
+ useFeedbackDetailLabels,
71
+ } from "./feedback/feedback-row-detail";
72
+ export {
73
+ /** @deprecated 0.52 — `FeedbackPublicSwitch`, which asks it (API-4); removed in 0.53 */
74
+ feedbackPublicSwitchAllowed,
75
+ } from "./feedback/feedback-public-switch";
@@ -1,4 +1,5 @@
1
1
  import { useEffect, useLayoutEffect, useRef, useState } from "react";
2
+ import { tabStops } from "../lib/focus-left";
2
3
 
3
4
  /**
4
5
  * Keep keyboard focus inside an open overlay, and give it back when it closes.
@@ -35,28 +36,11 @@ import { useEffect, useLayoutEffect, useRef, useState } from "react";
35
36
  * button; this is the focus half of it.
36
37
  */
37
38
 
38
- /**
39
- * Candidate tab stops, in DOM order — narrowed by {@link isTabStop} to the ones a Tab
40
- * really reaches.
41
- *
42
- * The selector is the one `Modal` used. On its own it was not enough (round 0.34
43
- * BUG-4): only the bare `[tabindex]` clause excluded `-1`, so a `button`, an `input` or
44
- * a link taken out of the tab order still counted. A panel that ends in a roving grid —
45
- * the calendar's days, the month grid, the picker sheet's rows, every one of them `-1`
46
- * but the active cell — then had a "last" stop no Tab ever reaches: Tab from the real
47
- * last stop was not wrapped and walked out of the open panel, and Shift+Tab from the
48
- * first landed on a cell that is not a stop at all.
49
- */
50
- const FOCUSABLE =
51
- 'a[href],button:not([disabled]),textarea:not([disabled]),input:not([disabled]),select:not([disabled]),[tabindex]:not([tabindex="-1"])';
52
-
53
- /**
54
- * A stop the browser's own Tab would land on: in the tab order (`tabIndex` ≥ 0) and not
55
- * inside something `hidden` or `inert`. Removes only elements a native Tab never
56
- * reaches, so no correct order changes. `visibility: hidden` and closed `<details>` are
57
- * still not walked — they need layout, which this list has never read.
58
- */
59
- const isTabStop = (el: HTMLElement): boolean => el.tabIndex >= 0 && !el.closest("[hidden],[inert]");
39
+ // The trap's reading of "a Tab lands here" is lib/focus-left's `tabStops` — the kit's one
40
+ // copy of the rule since the 0.52 code review (round 0.34 BUG-4's history is there).
41
+ // Re-exported where refactor audit 2026-10-30, DUP-9 put them, for a part that walks Tab
42
+ // over something that is not a trap (the tour's field + card ring).
43
+ export { firstTabStop, tabStops } from "../lib/focus-left";
60
44
 
61
45
  /**
62
46
  * Marks a container whose trap is currently active.
@@ -146,11 +130,11 @@ export function useFocusTrap(
146
130
  };
147
131
 
148
132
  const tabbables = () =>
149
- Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(
133
+ tabStops(container, { includeSelf: false }).filter(
150
134
  // A tabbable inside a NESTED open overlay belongs to that overlay's trap, not
151
135
  // to this one — otherwise the outer list spans both panels and Tab from the
152
136
  // inner panel's last control wraps to the OUTER panel's first.
153
- (el) => isTabStop(el) && !inNestedTrap(el),
137
+ (el) => !inNestedTrap(el),
154
138
  );
155
139
 
156
140
  const { initialFocus: how } = optsRef.current;
@@ -94,18 +94,28 @@ const KEY_ALIASES: Record<string, string> = {
94
94
  right: "arrowright",
95
95
  };
96
96
 
97
+ /** One letter of a script other than Latin: what a Russian, Greek or Hebrew layout's letter keys type. */
98
+ const NON_LATIN_LETTER = /^(?!\p{Script=Latin})\p{L}$/u;
99
+
97
100
  /** Whether `e` is `combo` — every modifier as named (no more, no fewer), and the key. */
98
101
  export function matchesHotkey(e: KeyboardEvent, combo: ParsedHotkey): boolean {
99
102
  if (e.ctrlKey !== combo.ctrl || e.metaKey !== combo.meta || e.altKey !== combo.alt) return false;
100
103
  const want = KEY_ALIASES[combo.key.toLowerCase()] ?? combo.key.toLowerCase();
101
104
  const key = (e.key ?? "").toLowerCase();
102
105
  const code = (e.code ?? "").toLowerCase();
103
- const keyMatches = key === want || code === want;
104
- if (!keyMatches) return false;
106
+ // On a non-Latin layout `key` is the local letter — Ctrl+K types "л" on a Russian one —
107
+ // so a letter chord never fired there, ⌘K included (0.52 code review, use-hotkey.ts; the
108
+ // hand-written ⌘K listener before 0.52 compared `key` alone and missed it too). The
109
+ // physical key stands in for the letter there, and only there: a Latin layout's letter
110
+ // is wherever it types (Dvorak's K is on QWERTY's V).
111
+ const physical = /^[a-z]$/.test(want) && NON_LATIN_LETTER.test(e.key ?? "") && code === `key${want}`;
112
+ if (key !== want && code !== want && !physical) return false;
105
113
  // Shift must match exactly for a letter or a named key; for a symbol it is how the
106
114
  // symbol is typed ("?" is Shift+/ on a US layout, a plain key on others), so an
107
- // unnamed Shift is not held against it.
108
- const symbol = want.length === 1 && !/[a-z0-9]/.test(want);
115
+ // unnamed Shift is not held against it. Space is a named key, not a symbol, though its
116
+ // alias is one character: "Space" fired on Shift+Space, the browser's page-up, and
117
+ // cancelled it (0.52 code review, use-hotkey.ts).
118
+ const symbol = want.length === 1 && !/[a-z0-9 ]/.test(want);
109
119
  return symbol && !combo.shift ? true : e.shiftKey === combo.shift;
110
120
  }
111
121
 
@@ -128,10 +138,13 @@ function isTypingTarget(target: EventTarget | null): boolean {
128
138
  * - Modifiers match EXACTLY: `"Ctrl+K"` does not fire on Ctrl+Shift+K.
129
139
  * - Typing in a field is left alone unless `allowInInputs`, except for a combo with
130
140
  * Ctrl / Meta / Alt, which no one types as text.
131
- * - A key held down fires once, not on every repeat.
141
+ * - A key held down fires once, not on every repeat — and its repeats are cancelled as
142
+ * the first press was, or the browser acts on them.
132
143
  * - The newest `handler` is always called; changing it does not re-attach the listener.
133
144
  *
134
- * `useCommandKey` (the ⌘K palette hook) is unchanged; this is its general form.
145
+ * `useCommandKey` (the ⌘K palette hook) is this with `"Mod+K"` and `allowInInputs`
146
+ * since 0.52, and FormActions' Ctrl/Cmd+Enter is {@link matchesHotkey} (refactor audit
147
+ * 2026-10-30, DUP-12): one reading of a chord.
135
148
  */
136
149
  export function useHotkey(
137
150
  combo: Hotkey | ReadonlyArray<Hotkey>,
@@ -156,7 +169,6 @@ export function useHotkey(
156
169
  const parsed = key.split("\u0000").map((c) => parseHotkey(c, apple));
157
170
  const listener = (raw: Event) => {
158
171
  const e = raw as KeyboardEvent;
159
- if (e.repeat) return;
160
172
  const hit = parsed.find((p) => matchesHotkey(e, p));
161
173
  if (!hit) return;
162
174
  if (allowInInputs !== true && isTypingTarget(e.target)) {
@@ -164,6 +176,11 @@ export function useHotkey(
164
176
  if (allowInInputs === "never" || !chorded) return;
165
177
  }
166
178
  if (preventDefault) e.preventDefault();
179
+ // A held key's repeats are cancelled like its first press, and call nothing. They
180
+ // returned before the `preventDefault` once, so a held Ctrl+K's repeats reached the
181
+ // browser's own Ctrl+K and took the focus out of the palette ⌘K had just opened
182
+ // (0.52 code review, use-hotkey.ts; the hand-written ⌘K listener cancelled them).
183
+ if (e.repeat) return;
167
184
  handlerRef.current(e);
168
185
  };
169
186
  node.addEventListener(event, listener);
@@ -4,7 +4,8 @@ import { useCallback, useEffect, useRef, type PointerEvent as ReactPointerEvent
4
4
  // keksdose live #421). Taken over from keksdose's register list
5
5
  // (frontend/src/shared/hooks/use-long-press.ts, its feedback #153) so the kit's cards
6
6
  // and kk's register answer the same gesture the same way: 500 ms, an 8 px dead zone,
7
- // cancelled by a scroll, the trailing click swallowed.
7
+ // cancelled by a scroll, the trailing click swallowed. Public since 0.52 (DUP-8, refactor
8
+ // audit 2026-10-30): private, it left keksdose keeping the original beside the copy.
8
9
 
9
10
  const LONG_PRESS_MS = 500;
10
11
  /** The same 8 px dead zone `useRowSwipe` locks its axis at: the press is dead by the
@@ -14,6 +15,13 @@ const SLOP_PX = 8;
14
15
  const movedBeyondSlop = (from: { x: number; y: number }, x: number, y: number) =>
15
16
  Math.hypot(x - from.x, y - from.y) > SLOP_PX;
16
17
 
18
+ export interface LongPressOptions {
19
+ /** Default `true`. Off, a press does nothing and the context menu is the browser's. */
20
+ enabled?: boolean;
21
+ /** How long a press is held, in ms. Default 500. */
22
+ delay?: number;
23
+ }
24
+
17
25
  export interface LongPressResult {
18
26
  handlers: {
19
27
  onPointerDown: (e: ReactPointerEvent) => void;
@@ -40,7 +48,7 @@ export interface LongPressResult {
40
48
  */
41
49
  export function useLongPress(
42
50
  onLongPress: () => void,
43
- { enabled = true, delay = LONG_PRESS_MS }: { enabled?: boolean; delay?: number } = {},
51
+ { enabled = true, delay = LONG_PRESS_MS }: LongPressOptions = {},
44
52
  ): LongPressResult {
45
53
  const timer = useRef<number | null>(null);
46
54
  const start = useRef({ x: 0, y: 0 });
@@ -120,6 +128,12 @@ export function useLongPress(
120
128
  return true;
121
129
  }, []);
122
130
 
131
+ // Turned off mid-press: the armed timer still fired, entering selection mode against the
132
+ // caller's wish and arming `consumeClick` for the next click (0.52 code review).
133
+ useEffect(() => {
134
+ if (!enabled) cancel();
135
+ }, [enabled, cancel]);
136
+
123
137
  useEffect(() => cancel, [cancel]);
124
138
 
125
139
  return { handlers: { onPointerDown, onPointerMove, onContextMenu }, consumeClick };
@@ -1,4 +1,4 @@
1
- import { useEffect, useState } from "react";
1
+ import { useEffect, useEffectEvent, useState } from "react";
2
2
 
3
3
  /**
4
4
  * Subscribe to a CSS media query, returning whether it currently matches and
@@ -10,12 +10,28 @@ export function useMediaQuery(query: string, fallback: boolean): boolean {
10
10
  typeof window !== "undefined" && typeof window.matchMedia === "function"
11
11
  ? window.matchMedia(query).matches
12
12
  : fallback;
13
- const [matches, setMatches] = useState<boolean>(get);
13
+ // The answer is kept with the query it answers, and a new query is asked during the
14
+ // render that brings it. Read at mount only, the first commit after a new query still
15
+ // answered the OLD one, until the effect corrected it: `useBreakpoint` asks a new query
16
+ // when the text size changes, and at Large in a 700 px window the tour card was drawn
17
+ // un-docked for a frame before it docked (0.52 code review, use-breakpoint.ts).
18
+ const [state, setState] = useState(() => ({ query, matches: get() }));
19
+ let matches = state.matches;
20
+ if (state.query !== query) {
21
+ matches = get();
22
+ setState({ query, matches });
23
+ }
24
+ const answered = useEffectEvent(() => matches);
14
25
  useEffect(() => {
15
26
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
16
27
  const mql = window.matchMedia(query);
17
- const update = () => setMatches(mql.matches);
18
- update();
28
+ const update = () =>
29
+ setState((prev) =>
30
+ prev.query === query && prev.matches === mql.matches ? prev : { query, matches: mql.matches },
31
+ );
32
+ // A change between the render and this subscription. Only then: an update that
33
+ // changes nothing still costs a render (and a commit) right after a new query.
34
+ if (mql.matches !== answered()) update();
19
35
  mql.addEventListener("change", update);
20
36
  return () => mql.removeEventListener("change", update);
21
37
  }, [query]);