@eifi1/ui-kit 0.51.7 → 0.53.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 (775) hide show
  1. package/README.md +178 -67
  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 +10 -7
  60. package/dist/billing/cancel-subscription.js +6 -6
  61. package/dist/billing/cancel-subscription.js.map +1 -1
  62. package/dist/billing/plan-card.d.ts +5 -3
  63. package/dist/billing/plan-card.js +7 -8
  64. package/dist/billing/plan-card.js.map +1 -1
  65. package/dist/billing/plan-change-labels.d.ts +42 -0
  66. package/dist/billing/plan-change-labels.js +22 -0
  67. package/dist/billing/plan-change-labels.js.map +1 -0
  68. package/dist/billing/plan-switch.d.ts +9 -6
  69. package/dist/billing/plan-switch.js +7 -5
  70. package/dist/billing/plan-switch.js.map +1 -1
  71. package/dist/chart.d.ts +4 -3
  72. package/dist/chart.js +72 -4
  73. package/dist/chart.js.map +1 -1
  74. package/dist/components/account-chips.d.ts +5 -5
  75. package/dist/components/account-chips.js +11 -13
  76. package/dist/components/account-chips.js.map +1 -1
  77. package/dist/components/alert-banner.d.ts +16 -5
  78. package/dist/components/alert-banner.js +46 -1
  79. package/dist/components/alert-banner.js.map +1 -1
  80. package/dist/components/amount-input.d.ts +13 -0
  81. package/dist/components/amount-input.js +1 -0
  82. package/dist/components/amount-input.js.map +1 -1
  83. package/dist/components/autocomplete.js +57 -65
  84. package/dist/components/autocomplete.js.map +1 -1
  85. package/dist/components/bulk-action-bar.d.ts +12 -2
  86. package/dist/components/bulk-action-bar.js +65 -21
  87. package/dist/components/bulk-action-bar.js.map +1 -1
  88. package/dist/components/button-look.d.ts +5 -5
  89. package/dist/components/button-look.js.map +1 -1
  90. package/dist/components/button.d.ts +2 -2
  91. package/dist/components/button.js.map +1 -1
  92. package/dist/components/chart-edge.d.ts +16 -0
  93. package/dist/components/chart-edge.js +14 -1
  94. package/dist/components/chart-edge.js.map +1 -1
  95. package/dist/components/chart-figure.d.ts +13 -0
  96. package/dist/components/chart-figure.js +15 -0
  97. package/dist/components/chart-figure.js.map +1 -0
  98. package/dist/components/chart-zoom-core.js +1 -4
  99. package/dist/components/chart-zoom-core.js.map +1 -1
  100. package/dist/components/chart.d.ts +8 -1
  101. package/dist/components/chart.js +19 -10
  102. package/dist/components/chart.js.map +1 -1
  103. package/dist/components/combobox-core.d.ts +111 -2
  104. package/dist/components/combobox-core.js +148 -42
  105. package/dist/components/combobox-core.js.map +1 -1
  106. package/dist/components/combobox.d.ts +1 -1
  107. package/dist/components/combobox.js +141 -130
  108. package/dist/components/combobox.js.map +1 -1
  109. package/dist/components/copy-button.d.ts +6 -5
  110. package/dist/components/copy-button.js +5 -3
  111. package/dist/components/copy-button.js.map +1 -1
  112. package/dist/components/country-select.js +2 -2
  113. package/dist/components/country-select.js.map +1 -1
  114. package/dist/components/data-table-column-settings.d.ts +1 -1
  115. package/dist/components/data-table-column-settings.js +33 -7
  116. package/dist/components/data-table-column-settings.js.map +1 -1
  117. package/dist/components/data-table-filters.d.ts +4 -2
  118. package/dist/components/data-table-filters.js +2 -2
  119. package/dist/components/data-table-filters.js.map +1 -1
  120. package/dist/components/data-table-fit.d.ts +6 -4
  121. package/dist/components/data-table-fit.js +4 -1
  122. package/dist/components/data-table-fit.js.map +1 -1
  123. package/dist/components/data-table-groups.d.ts +1 -1
  124. package/dist/components/data-table-groups.js.map +1 -1
  125. package/dist/components/data-table-head.d.ts +1 -1
  126. package/dist/components/data-table-head.js +15 -12
  127. package/dist/components/data-table-head.js.map +1 -1
  128. package/dist/components/data-table-mobile.d.ts +12 -7
  129. package/dist/components/data-table-mobile.js +43 -30
  130. package/dist/components/data-table-mobile.js.map +1 -1
  131. package/dist/components/data-table-pagination.js +11 -6
  132. package/dist/components/data-table-pagination.js.map +1 -1
  133. package/dist/components/data-table-resize.d.ts +1 -1
  134. package/dist/components/data-table-resize.js.map +1 -1
  135. package/dist/components/data-table-row-actions.d.ts +2 -2
  136. package/dist/components/data-table-row-actions.js.map +1 -1
  137. package/dist/components/data-table-row.d.ts +6 -2
  138. package/dist/components/data-table-row.js +17 -10
  139. package/dist/components/data-table-row.js.map +1 -1
  140. package/dist/components/data-table-selection.d.ts +1 -1
  141. package/dist/components/data-table-selection.js.map +1 -1
  142. package/dist/components/data-table-shared.d.ts +10 -2
  143. package/dist/components/data-table-shared.js +18 -0
  144. package/dist/components/data-table-shared.js.map +1 -1
  145. package/dist/components/data-table-sort.d.ts +21 -2
  146. package/dist/components/data-table-sort.js +24 -0
  147. package/dist/components/data-table-sort.js.map +1 -1
  148. package/dist/components/data-table-virtual.d.ts +1 -1
  149. package/dist/components/data-table-virtual.js +18 -6
  150. package/dist/components/data-table-virtual.js.map +1 -1
  151. package/dist/components/data-table.d.ts +13 -4
  152. package/dist/components/data-table.js +139 -36
  153. package/dist/components/data-table.js.map +1 -1
  154. package/dist/components/date-field.d.ts +25 -3
  155. package/dist/components/date-field.js +33 -8
  156. package/dist/components/date-field.js.map +1 -1
  157. package/dist/components/date-picker.d.ts +16 -3
  158. package/dist/components/date-picker.js +55 -26
  159. package/dist/components/date-picker.js.map +1 -1
  160. package/dist/components/date-range-picker.d.ts +38 -24
  161. package/dist/components/date-range-picker.js +23 -7
  162. package/dist/components/date-range-picker.js.map +1 -1
  163. package/dist/components/error-boundary.js +37 -30
  164. package/dist/components/error-boundary.js.map +1 -1
  165. package/dist/components/{ui-labels.d.ts → field-base-labels.d.ts} +0 -2
  166. package/dist/components/{ui-labels.js → field-base-labels.js} +2 -9
  167. package/dist/components/field-base-labels.js.map +1 -0
  168. package/dist/components/field-base.d.ts +4 -3
  169. package/dist/components/field-base.js +3 -3
  170. package/dist/components/field-base.js.map +1 -1
  171. package/dist/components/form-actions.js +11 -5
  172. package/dist/components/form-actions.js.map +1 -1
  173. package/dist/components/hover-menu.d.ts +3 -0
  174. package/dist/components/hover-menu.js +5 -3
  175. package/dist/components/hover-menu.js.map +1 -1
  176. package/dist/components/icon-button.js +14 -9
  177. package/dist/components/icon-button.js.map +1 -1
  178. package/dist/components/inline-confirm.d.ts +43 -0
  179. package/dist/components/inline-confirm.js +67 -0
  180. package/dist/components/inline-confirm.js.map +1 -0
  181. package/dist/components/inline-entity-combobox.d.ts +4 -3
  182. package/dist/components/inline-entity-combobox.js +148 -140
  183. package/dist/components/inline-entity-combobox.js.map +1 -1
  184. package/dist/components/input.js +1 -1
  185. package/dist/components/input.js.map +1 -1
  186. package/dist/components/jump-calendar.js +28 -112
  187. package/dist/components/jump-calendar.js.map +1 -1
  188. package/dist/components/legal-page.d.ts +3 -1
  189. package/dist/components/legal-page.js +3 -2
  190. package/dist/components/legal-page.js.map +1 -1
  191. package/dist/components/legal.d.ts +4 -2
  192. package/dist/components/legal.js.map +1 -1
  193. package/dist/components/lightbox.d.ts +2 -2
  194. package/dist/components/lightbox.js +17 -6
  195. package/dist/components/lightbox.js.map +1 -1
  196. package/dist/components/list.d.ts +6 -2
  197. package/dist/components/list.js +3 -2
  198. package/dist/components/list.js.map +1 -1
  199. package/dist/components/measured-grid.d.ts +1 -1
  200. package/dist/components/measured-grid.js +2 -1
  201. package/dist/components/measured-grid.js.map +1 -1
  202. package/dist/components/mini-calendar.js +3 -5
  203. package/dist/components/mini-calendar.js.map +1 -1
  204. package/dist/components/modal.js +3 -1
  205. package/dist/components/modal.js.map +1 -1
  206. package/dist/components/month-grid.d.ts +55 -0
  207. package/dist/components/month-grid.js +148 -0
  208. package/dist/components/month-grid.js.map +1 -0
  209. package/dist/components/month-picker.d.ts +36 -4
  210. package/dist/components/month-picker.js +123 -146
  211. package/dist/components/month-picker.js.map +1 -1
  212. package/dist/components/multi-select.d.ts +2 -2
  213. package/dist/components/multi-select.js +11 -6
  214. package/dist/components/multi-select.js.map +1 -1
  215. package/dist/components/nav-pills.d.ts +1 -1
  216. package/dist/components/nav-pills.js.map +1 -1
  217. package/dist/components/picker-sheet.js +2 -1
  218. package/dist/components/picker-sheet.js.map +1 -1
  219. package/dist/components/pie-chart-labels.d.ts +7 -0
  220. package/dist/components/pie-chart-labels.js +1 -0
  221. package/dist/components/pie-chart-labels.js.map +1 -1
  222. package/dist/components/pie-chart.d.ts +5 -3
  223. package/dist/components/pie-chart.js +7 -22
  224. package/dist/components/pie-chart.js.map +1 -1
  225. package/dist/components/popover.d.ts +3 -0
  226. package/dist/components/popover.js +7 -1
  227. package/dist/components/popover.js.map +1 -1
  228. package/dist/components/row-actions.js +2 -1
  229. package/dist/components/row-actions.js.map +1 -1
  230. package/dist/components/series-chart-axes.d.ts +4 -4
  231. package/dist/components/series-chart-axes.js.map +1 -1
  232. package/dist/components/series-chart-labels.d.ts +7 -4
  233. package/dist/components/series-chart-labels.js.map +1 -1
  234. package/dist/components/series-chart.d.ts +92 -23
  235. package/dist/components/series-chart.js +74 -30
  236. package/dist/components/series-chart.js.map +1 -1
  237. package/dist/components/share-card.js +3 -3
  238. package/dist/components/share-card.js.map +1 -1
  239. package/dist/components/tabs-labels.d.ts +2 -0
  240. package/dist/components/tabs-labels.js +11 -0
  241. package/dist/components/tabs-labels.js.map +1 -0
  242. package/dist/components/tabs.d.ts +1 -1
  243. package/dist/components/tabs.js +1 -1
  244. package/dist/components/tabs.js.map +1 -1
  245. package/dist/components/toggle-legend.d.ts +2 -2
  246. package/dist/components/toggle-legend.js +6 -6
  247. package/dist/components/toggle-legend.js.map +1 -1
  248. package/dist/components/translation-review-editor.d.ts +4 -2
  249. package/dist/components/translation-review-editor.js +2 -3
  250. package/dist/components/translation-review-editor.js.map +1 -1
  251. package/dist/components/translation-review.d.ts +2 -1
  252. package/dist/components/translation-review.js +2 -2
  253. package/dist/components/translation-review.js.map +1 -1
  254. package/dist/components/treemap-labels.d.ts +31 -0
  255. package/dist/components/treemap-labels.js +10 -0
  256. package/dist/components/treemap-labels.js.map +1 -0
  257. package/dist/components/treemap-layout.d.ts +62 -0
  258. package/dist/components/treemap-layout.js +126 -0
  259. package/dist/components/treemap-layout.js.map +1 -0
  260. package/dist/components/treemap.d.ts +167 -19
  261. package/dist/components/treemap.js +340 -100
  262. package/dist/components/treemap.js.map +1 -1
  263. package/dist/components/use-table-state.d.ts +5 -5
  264. package/dist/components/use-table-state.js +4 -1
  265. package/dist/components/use-table-state.js.map +1 -1
  266. package/dist/data-table.d.ts +1 -2
  267. package/dist/data-table.js +1 -4
  268. package/dist/data-table.js.map +1 -1
  269. package/dist/demo/demo-countdown.d.ts +0 -5
  270. package/dist/demo/demo-countdown.js +0 -4
  271. package/dist/demo/demo-countdown.js.map +1 -1
  272. package/dist/eslint/index.js +1 -1
  273. package/dist/eslint/role-utilities.d.ts +36 -7
  274. package/dist/eslint/role-utilities.js +42 -9
  275. package/dist/eslint/role-utilities.js.map +1 -1
  276. package/dist/feedback/feedback-dialog.d.ts +25 -16
  277. package/dist/feedback/feedback-dialog.js +6 -2
  278. package/dist/feedback/feedback-dialog.js.map +1 -1
  279. package/dist/feedback/feedback-mutation.d.ts +18 -0
  280. package/dist/feedback/feedback-mutation.js +8 -0
  281. package/dist/feedback/feedback-mutation.js.map +1 -0
  282. package/dist/feedback/feedback-page-link.d.ts +53 -0
  283. package/dist/feedback/feedback-page-link.js +37 -0
  284. package/dist/feedback/feedback-page-link.js.map +1 -0
  285. package/dist/feedback/feedback-public-list.d.ts +8 -4
  286. package/dist/feedback/feedback-public-list.js +2 -2
  287. package/dist/feedback/feedback-public-list.js.map +1 -1
  288. package/dist/feedback/feedback-replies.d.ts +3 -1
  289. package/dist/feedback/feedback-replies.js +5 -4
  290. package/dist/feedback/feedback-replies.js.map +1 -1
  291. package/dist/feedback/feedback-row-detail-labels.js +0 -3
  292. package/dist/feedback/feedback-row-detail-labels.js.map +1 -1
  293. package/dist/feedback/feedback-row-detail.d.ts +33 -44
  294. package/dist/feedback/feedback-row-detail.js +28 -34
  295. package/dist/feedback/feedback-row-detail.js.map +1 -1
  296. package/dist/feedback/feedback-status-undo.d.ts +17 -14
  297. package/dist/feedback/feedback-status-undo.js +10 -15
  298. package/dist/feedback/feedback-status-undo.js.map +1 -1
  299. package/dist/feedback/feedback-submit-dialog.d.ts +1 -1
  300. package/dist/feedback/feedback-submit-dialog.js +1 -1
  301. package/dist/feedback/feedback-submit-dialog.js.map +1 -1
  302. package/dist/feedback/feedback-submit.js +9 -3
  303. package/dist/feedback/feedback-submit.js.map +1 -1
  304. package/dist/feedback/feedback-swipe.d.ts +1 -1
  305. package/dist/feedback/feedback-swipe.js.map +1 -1
  306. package/dist/feedback/feedback-table.d.ts +21 -9
  307. package/dist/feedback/feedback-table.js +45 -25
  308. package/dist/feedback/feedback-table.js.map +1 -1
  309. package/dist/feedback/feedback-thread-labels.d.ts +2 -2
  310. package/dist/feedback/feedback-thread-labels.js.map +1 -1
  311. package/dist/feedback/feedback-thread.d.ts +15 -23
  312. package/dist/feedback/feedback-thread.js +2 -1
  313. package/dist/feedback/feedback-thread.js.map +1 -1
  314. package/dist/feedback.d.ts +6 -6
  315. package/dist/feedback.js +90 -6
  316. package/dist/feedback.js.map +1 -1
  317. package/dist/hooks/use-focus-trap.d.ts +35 -0
  318. package/dist/hooks/use-focus-trap.js +6 -4
  319. package/dist/hooks/use-focus-trap.js.map +1 -1
  320. package/dist/hooks/use-hotkey.d.ts +5 -2
  321. package/dist/hooks/use-hotkey.js +5 -4
  322. package/dist/hooks/use-hotkey.js.map +1 -1
  323. package/dist/hooks/use-long-press.d.ts +7 -4
  324. package/dist/hooks/use-long-press.js +3 -0
  325. package/dist/hooks/use-long-press.js.map +1 -1
  326. package/dist/hooks/use-media-query.js +12 -4
  327. package/dist/hooks/use-media-query.js.map +1 -1
  328. package/dist/hooks/use-mounted.d.ts +22 -0
  329. package/dist/hooks/use-mounted.js +24 -0
  330. package/dist/hooks/use-mounted.js.map +1 -0
  331. package/dist/hooks/use-overlay-history.js +19 -3
  332. package/dist/hooks/use-overlay-history.js.map +1 -1
  333. package/dist/i18n/defaults.js +4 -9
  334. package/dist/i18n/defaults.js.map +1 -1
  335. package/dist/i18n/german.js +7 -18
  336. package/dist/i18n/german.js.map +1 -1
  337. package/dist/i18n/kit-labels.d.ts +9 -11
  338. package/dist/i18n/kit-labels.js.map +1 -1
  339. package/dist/i18n/locales/en.js +15 -64
  340. package/dist/i18n/locales/en.js.map +3 -3
  341. package/dist/i18n/locales/es.js +7 -18
  342. package/dist/i18n/locales/es.js.map +1 -1
  343. package/dist/i18n/locales/fr.js +20 -27
  344. package/dist/i18n/locales/fr.js.map +1 -1
  345. package/dist/i18n/locales/hu.js +9 -18
  346. package/dist/i18n/locales/hu.js.map +1 -1
  347. package/dist/i18n/locales/it.js +7 -19
  348. package/dist/i18n/locales/it.js.map +1 -1
  349. package/dist/i18n/locales/zh.js +8 -18
  350. package/dist/i18n/locales/zh.js.map +1 -1
  351. package/dist/i18n/review.js +12 -2
  352. package/dist/i18n/review.js.map +1 -1
  353. package/dist/i18n/shared-labels.js +0 -1
  354. package/dist/i18n/shared-labels.js.map +1 -1
  355. package/dist/index.d.ts +21 -23
  356. package/dist/index.js +50 -65
  357. package/dist/index.js.map +1 -1
  358. package/dist/landing/routing.d.ts +3 -1
  359. package/dist/landing/routing.js +4 -7
  360. package/dist/landing/routing.js.map +1 -1
  361. package/dist/lib/broadcast.d.ts +17 -0
  362. package/dist/lib/broadcast.js +30 -0
  363. package/dist/lib/broadcast.js.map +1 -0
  364. package/dist/lib/date-format.d.ts +37 -2
  365. package/dist/lib/date-format.js +34 -8
  366. package/dist/lib/date-format.js.map +1 -1
  367. package/dist/lib/day-format.d.ts +46 -0
  368. package/dist/lib/day-format.js +46 -0
  369. package/dist/lib/day-format.js.map +1 -0
  370. package/dist/lib/describe-failure.d.ts +14 -0
  371. package/dist/lib/describe-failure.js +9 -0
  372. package/dist/lib/describe-failure.js.map +1 -0
  373. package/dist/lib/direction.d.ts +16 -0
  374. package/dist/lib/direction.js +9 -1
  375. package/dist/lib/direction.js.map +1 -1
  376. package/dist/lib/focus-left.d.ts +63 -0
  377. package/dist/lib/focus-left.js +67 -0
  378. package/dist/lib/focus-left.js.map +1 -0
  379. package/dist/lib/format.js +5 -14
  380. package/dist/lib/format.js.map +1 -1
  381. package/dist/lib/http-status.d.ts +24 -0
  382. package/dist/lib/http-status.js +14 -0
  383. package/dist/lib/http-status.js.map +1 -0
  384. package/dist/lib/intl-cache.d.ts +14 -0
  385. package/dist/lib/intl-cache.js +15 -0
  386. package/dist/lib/intl-cache.js.map +1 -0
  387. package/dist/lib/iso-day.d.ts +11 -0
  388. package/dist/lib/iso-day.js +8 -0
  389. package/dist/lib/iso-day.js.map +1 -0
  390. package/dist/lib/lazy-with-fallback.d.ts +31 -0
  391. package/dist/lib/lazy-with-fallback.js +40 -0
  392. package/dist/lib/lazy-with-fallback.js.map +1 -0
  393. package/dist/lib/path-pattern.d.ts +34 -0
  394. package/dist/lib/path-pattern.js +24 -0
  395. package/dist/lib/path-pattern.js.map +1 -0
  396. package/dist/lib/reduced-motion.d.ts +2 -1
  397. package/dist/lib/reduced-motion.js.map +1 -1
  398. package/dist/lib/round.d.ts +2 -1
  399. package/dist/lib/round.js +2 -1
  400. package/dist/lib/round.js.map +1 -1
  401. package/dist/lib/safe-storage.d.ts +24 -5
  402. package/dist/lib/safe-storage.js +27 -2
  403. package/dist/lib/safe-storage.js.map +1 -1
  404. package/dist/lib/session-refresh.js +1 -1
  405. package/dist/lib/session-refresh.js.map +1 -1
  406. package/dist/lib/share-format.d.ts +13 -0
  407. package/dist/lib/share-format.js +10 -0
  408. package/dist/lib/share-format.js.map +1 -0
  409. package/dist/lib/text-case.d.ts +17 -0
  410. package/dist/lib/text-case.js +8 -0
  411. package/dist/lib/text-case.js.map +1 -0
  412. package/dist/lib/text-match.d.ts +29 -0
  413. package/dist/lib/text-match.js +20 -2
  414. package/dist/lib/text-match.js.map +1 -1
  415. package/dist/lib/thenable.d.ts +13 -0
  416. package/dist/lib/thenable.js +8 -0
  417. package/dist/lib/thenable.js.map +1 -0
  418. package/dist/lib/translation-review.d.ts +7 -2
  419. package/dist/lib/translation-review.js +4 -4
  420. package/dist/lib/translation-review.js.map +1 -1
  421. package/dist/notifications/device-zone-report.js +1 -1
  422. package/dist/notifications/device-zone-report.js.map +1 -1
  423. package/dist/notifications/notification-bell.d.ts +2 -1
  424. package/dist/notifications/notification-bell.js +3 -3
  425. package/dist/notifications/notification-bell.js.map +1 -1
  426. package/dist/notifications/notification-inbox.d.ts +10 -6
  427. package/dist/notifications/notification-inbox.js +26 -48
  428. package/dist/notifications/notification-inbox.js.map +1 -1
  429. package/dist/notifications/notification-parts.d.ts +3 -2
  430. package/dist/notifications/notification-parts.js +1 -3
  431. package/dist/notifications/notification-parts.js.map +1 -1
  432. package/dist/notifications/notification-types-setting.js +1 -1
  433. package/dist/notifications/notification-types-setting.js.map +1 -1
  434. package/dist/notifications/notifications-labels.d.ts +6 -0
  435. package/dist/notifications/notifications-labels.js +1 -0
  436. package/dist/notifications/notifications-labels.js.map +1 -1
  437. package/dist/notifications/push-device-setting.js +1 -1
  438. package/dist/notifications/push-device-setting.js.map +1 -1
  439. package/dist/notifications/push-devices-setting.d.ts +2 -1
  440. package/dist/notifications/push-devices-setting.js +27 -49
  441. package/dist/notifications/push-devices-setting.js.map +1 -1
  442. package/dist/notifications/quiet-hours-setting.d.ts +10 -3
  443. package/dist/notifications/quiet-hours-setting.js +65 -26
  444. package/dist/notifications/quiet-hours-setting.js.map +1 -1
  445. package/dist/notifications/unsubscribe-panel.js +4 -7
  446. package/dist/notifications/unsubscribe-panel.js.map +1 -1
  447. package/dist/notifications/use-push-device.d.ts +39 -1
  448. package/dist/notifications/use-push-device.js +28 -7
  449. package/dist/notifications/use-push-device.js.map +1 -1
  450. package/dist/offline/query-persistence.d.ts +3 -1
  451. package/dist/offline/query-persistence.js +19 -2
  452. package/dist/offline/query-persistence.js.map +1 -1
  453. package/dist/rhf/fields.d.ts +11 -4
  454. package/dist/rhf/fields.js.map +1 -1
  455. package/dist/search/command-palette.js +1 -1
  456. package/dist/search/command-palette.js.map +1 -1
  457. package/dist/search/global-search.js +19 -9
  458. package/dist/search/global-search.js.map +1 -1
  459. package/dist/search/search-index.d.ts +0 -6
  460. package/dist/search/search-index.js +0 -4
  461. package/dist/search/search-index.js.map +1 -1
  462. package/dist/search/use-command-key.d.ts +12 -1
  463. package/dist/search/use-command-key.js +3 -12
  464. package/dist/search/use-command-key.js.map +1 -1
  465. package/dist/search.d.ts +1 -1
  466. package/dist/search.js +6 -1
  467. package/dist/search.js.map +1 -1
  468. package/dist/settings/use-settings-focus.js +1 -0
  469. package/dist/settings/use-settings-focus.js.map +1 -1
  470. package/dist/shell/account-menu-language.d.ts +5 -3
  471. package/dist/shell/account-menu-language.js +2 -2
  472. package/dist/shell/account-menu-language.js.map +1 -1
  473. package/dist/shell/account-menu-text-size.d.ts +9 -6
  474. package/dist/shell/account-menu-text-size.js +2 -2
  475. package/dist/shell/account-menu-text-size.js.map +1 -1
  476. package/dist/shell/app-shell.d.ts +0 -10
  477. package/dist/shell/app-shell.js +1 -7
  478. package/dist/shell/app-shell.js.map +1 -1
  479. package/dist/shell/company-switcher.d.ts +1 -1
  480. package/dist/shell/company-switcher.js.map +1 -1
  481. package/dist/shell/dev-menu.d.ts +1 -1
  482. package/dist/shell/dev-menu.js +5 -18
  483. package/dist/shell/dev-menu.js.map +1 -1
  484. package/dist/shell/top-bar-actions.d.ts +1 -1
  485. package/dist/shell/top-bar-actions.js.map +1 -1
  486. package/dist/shell/top-bar-parts-labels.d.ts +1 -3
  487. package/dist/shell/top-bar-parts-labels.js +0 -1
  488. package/dist/shell/top-bar-parts-labels.js.map +1 -1
  489. package/dist/shell.d.ts +7 -10
  490. package/dist/shell.js +14 -23
  491. package/dist/shell.js.map +1 -1
  492. package/dist/sync/engine.d.ts +30 -4
  493. package/dist/sync/engine.js +172 -52
  494. package/dist/sync/engine.js.map +1 -1
  495. package/dist/sync.d.ts +2 -2
  496. package/dist/sync.js +2 -10
  497. package/dist/sync.js.map +1 -1
  498. package/dist/testing/css-variables.js +3 -8
  499. package/dist/testing/css-variables.js.map +1 -1
  500. package/dist/theme/chart-palette.d.ts +0 -5
  501. package/dist/theme/chart-palette.js +0 -2
  502. package/dist/theme/chart-palette.js.map +1 -1
  503. package/dist/theme/contrast.d.ts +2 -1
  504. package/dist/theme/contrast.js +3 -8
  505. package/dist/theme/contrast.js.map +1 -1
  506. package/dist/theme/palette-store.js +6 -6
  507. package/dist/theme/palette-store.js.map +1 -1
  508. package/dist/theme/text-size.js +3 -8
  509. package/dist/theme/text-size.js.map +1 -1
  510. package/dist/theme/theme-store.js +3 -6
  511. package/dist/theme/theme-store.js.map +1 -1
  512. package/dist/tour/tour-catalogue.d.ts +7 -4
  513. package/dist/tour/tour-catalogue.js +12 -10
  514. package/dist/tour/tour-catalogue.js.map +1 -1
  515. package/dist/tour/tour-dock.d.ts +0 -2
  516. package/dist/tour/tour-dock.js +0 -2
  517. package/dist/tour/tour-dock.js.map +1 -1
  518. package/dist/tour/tour-gates.d.ts +4 -0
  519. package/dist/tour/tour-gates.js +14 -0
  520. package/dist/tour/tour-gates.js.map +1 -1
  521. package/dist/tour/tour-overlay.d.ts +27 -0
  522. package/dist/tour/tour-overlay.js +741 -0
  523. package/dist/tour/tour-overlay.js.map +1 -0
  524. package/dist/tour/tour.d.ts +13 -3
  525. package/dist/tour/tour.js +59 -781
  526. package/dist/tour/tour.js.map +1 -1
  527. package/dist/tour/use-tour-progress.js +1 -1
  528. package/dist/tour/use-tour-progress.js.map +1 -1
  529. package/dist/wizard/stepper-nav.d.ts +5 -1
  530. package/dist/wizard/stepper-nav.js.map +1 -1
  531. package/dist/wizard/types.d.ts +6 -2
  532. package/dist/wizard/types.js.map +1 -1
  533. package/dist/wizard/use-wizard.d.ts +3 -1
  534. package/dist/wizard/use-wizard.js.map +1 -1
  535. package/dist/wizard/validation.d.ts +3 -1
  536. package/dist/wizard/validation.js.map +1 -1
  537. package/package.json +10 -6
  538. package/src/account/account-parts.ts +5 -25
  539. package/src/account/data-export-setting-labels.ts +1 -1
  540. package/src/account/delete-account-setting-labels.ts +1 -1
  541. package/src/account/email-change-setting-labels.ts +1 -1
  542. package/src/account/passkeys-setting.tsx +60 -38
  543. package/src/account/sessions-setting.tsx +18 -12
  544. package/src/admin/admin-action-confirm.tsx +1 -5
  545. package/src/admin/admin-parts.ts +11 -25
  546. package/src/admin/mail-test-card-labels.ts +1 -1
  547. package/src/admin/plan-change-labels.ts +5 -23
  548. package/src/admin/plan-change.tsx +7 -44
  549. package/src/admin/reviewer-scope-editor.tsx +3 -3
  550. package/src/auth/auth-errors-labels.ts +23 -0
  551. package/src/auth/auth-errors.ts +11 -38
  552. package/src/auth/complete-name-dialog.tsx +4 -1
  553. package/src/auth/forgot-password-form-labels.ts +1 -1
  554. package/src/auth/forgot-password-form.tsx +11 -6
  555. package/src/auth/register-form-labels.ts +1 -1
  556. package/src/auth/reset-password-form-labels.ts +1 -1
  557. package/src/auth/reset-password-form.tsx +8 -4
  558. package/src/auth/sign-in-form-labels.ts +1 -1
  559. package/src/auth/status-parts.tsx +0 -6
  560. package/src/auth/verify-email-labels.ts +1 -1
  561. package/src/auth/verify-email.tsx +11 -6
  562. package/src/billing/cancel-subscription.tsx +15 -12
  563. package/src/billing/plan-card.tsx +18 -10
  564. package/src/billing/plan-change-labels.ts +66 -0
  565. package/src/billing/plan-switch.tsx +15 -12
  566. package/src/chart.ts +73 -6
  567. package/src/components/account-chips.tsx +20 -23
  568. package/src/components/alert-banner.tsx +82 -5
  569. package/src/components/amount-input.tsx +18 -7
  570. package/src/components/autocomplete.tsx +64 -70
  571. package/src/components/bulk-action-bar.tsx +70 -2
  572. package/src/components/button-look.ts +5 -5
  573. package/src/components/button.tsx +2 -2
  574. package/src/components/chart-edge.ts +34 -1
  575. package/src/components/chart-figure.tsx +35 -0
  576. package/src/components/chart-zoom-core.tsx +6 -5
  577. package/src/components/chart.tsx +26 -5
  578. package/src/components/combobox-core.tsx +293 -62
  579. package/src/components/combobox.tsx +183 -153
  580. package/src/components/copy-button.tsx +34 -23
  581. package/src/components/country-select.tsx +16 -11
  582. package/src/components/data-table-column-settings.tsx +52 -10
  583. package/src/components/data-table-filters.ts +6 -4
  584. package/src/components/data-table-fit.ts +19 -5
  585. package/src/components/data-table-groups.tsx +1 -1
  586. package/src/components/data-table-head.tsx +32 -22
  587. package/src/components/data-table-mobile.tsx +61 -26
  588. package/src/components/data-table-pagination.tsx +21 -6
  589. package/src/components/data-table-resize.ts +1 -1
  590. package/src/components/data-table-row-actions.tsx +3 -3
  591. package/src/components/data-table-row.tsx +25 -14
  592. package/src/components/data-table-selection.ts +1 -1
  593. package/src/components/data-table-shared.tsx +33 -1
  594. package/src/components/data-table-sort.ts +57 -2
  595. package/src/components/data-table-virtual.ts +32 -8
  596. package/src/components/data-table.tsx +239 -68
  597. package/src/components/date-field.tsx +66 -9
  598. package/src/components/date-picker.tsx +125 -49
  599. package/src/components/date-range-picker.tsx +71 -36
  600. package/src/components/error-boundary.tsx +53 -39
  601. package/src/components/field-base-labels.ts +20 -0
  602. package/src/components/field-base.tsx +13 -7
  603. package/src/components/form-actions.tsx +20 -5
  604. package/src/components/hover-menu.tsx +18 -8
  605. package/src/components/icon-button.tsx +14 -9
  606. package/src/components/inline-confirm.tsx +116 -0
  607. package/src/components/inline-entity-combobox.tsx +197 -153
  608. package/src/components/input.tsx +1 -1
  609. package/src/components/jump-calendar.tsx +30 -146
  610. package/src/components/legal-page.tsx +10 -7
  611. package/src/components/legal.tsx +4 -2
  612. package/src/components/lightbox.tsx +21 -8
  613. package/src/components/list.tsx +10 -4
  614. package/src/components/measured-grid.tsx +8 -4
  615. package/src/components/mini-calendar.tsx +6 -5
  616. package/src/components/modal.tsx +6 -1
  617. package/src/components/month-grid.tsx +229 -0
  618. package/src/components/month-picker.tsx +192 -200
  619. package/src/components/multi-select.tsx +21 -9
  620. package/src/components/nav-pills.tsx +1 -1
  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/series-chart-axes.ts +9 -4
  627. package/src/components/series-chart-labels.ts +7 -4
  628. package/src/components/series-chart.tsx +253 -87
  629. package/src/components/share-card.tsx +6 -6
  630. package/src/components/tabs-labels.ts +13 -0
  631. package/src/components/tabs.tsx +2 -2
  632. package/src/components/toggle-legend.tsx +16 -11
  633. package/src/components/translation-review-editor.tsx +6 -5
  634. package/src/components/translation-review.tsx +4 -3
  635. package/src/components/treemap-labels.ts +47 -0
  636. package/src/components/treemap-layout.ts +210 -0
  637. package/src/components/treemap.tsx +780 -138
  638. package/src/components/use-table-state.ts +12 -9
  639. package/src/data-table.ts +1 -4
  640. package/src/demo/demo-countdown.ts +3 -8
  641. package/src/eslint/role-utilities.ts +97 -19
  642. package/src/feedback/feedback-dialog.tsx +30 -19
  643. package/src/feedback/feedback-mutation.ts +20 -0
  644. package/src/feedback/feedback-page-link.ts +90 -0
  645. package/src/feedback/feedback-public-list.tsx +13 -7
  646. package/src/feedback/feedback-replies.tsx +13 -6
  647. package/src/feedback/feedback-row-detail-labels.ts +0 -3
  648. package/src/feedback/feedback-row-detail.tsx +70 -84
  649. package/src/feedback/feedback-status-undo.ts +28 -28
  650. package/src/feedback/feedback-submit-dialog.tsx +2 -2
  651. package/src/feedback/feedback-submit.tsx +21 -7
  652. package/src/feedback/feedback-swipe.tsx +1 -1
  653. package/src/feedback/feedback-table.tsx +86 -38
  654. package/src/feedback/feedback-thread-labels.ts +2 -2
  655. package/src/feedback/feedback-thread.tsx +18 -26
  656. package/src/feedback.ts +89 -6
  657. package/src/hooks/use-focus-trap.ts +8 -24
  658. package/src/hooks/use-hotkey.ts +24 -7
  659. package/src/hooks/use-long-press.ts +16 -2
  660. package/src/hooks/use-media-query.ts +20 -4
  661. package/src/hooks/use-mounted.ts +39 -0
  662. package/src/hooks/use-overlay-history.ts +32 -3
  663. package/src/i18n/defaults.ts +4 -9
  664. package/src/i18n/german.ts +8 -19
  665. package/src/i18n/kit-labels.tsx +9 -11
  666. package/src/i18n/locales/es.ts +8 -19
  667. package/src/i18n/locales/fr.ts +21 -30
  668. package/src/i18n/locales/hu.ts +10 -19
  669. package/src/i18n/locales/it.ts +8 -20
  670. package/src/i18n/locales/zh.ts +9 -19
  671. package/src/i18n/review.ts +12 -2
  672. package/src/i18n/shared-labels.ts +0 -1
  673. package/src/index.ts +57 -49
  674. package/src/landing/routing.tsx +14 -10
  675. package/src/lib/broadcast.ts +52 -0
  676. package/src/lib/date-format.ts +89 -13
  677. package/src/lib/day-format.ts +96 -0
  678. package/src/lib/describe-failure.ts +18 -0
  679. package/src/lib/direction.ts +39 -0
  680. package/src/lib/focus-left.ts +156 -0
  681. package/src/lib/format.ts +5 -17
  682. package/src/lib/http-status.ts +38 -0
  683. package/src/lib/intl-cache.ts +25 -0
  684. package/src/lib/iso-day.ts +13 -0
  685. package/src/lib/lazy-with-fallback.ts +82 -0
  686. package/src/lib/path-pattern.ts +55 -0
  687. package/src/lib/reduced-motion.ts +2 -1
  688. package/src/lib/round.ts +7 -2
  689. package/src/lib/safe-storage.ts +48 -6
  690. package/src/lib/session-refresh.ts +1 -1
  691. package/src/lib/share-format.ts +18 -0
  692. package/src/lib/text-case.ts +19 -0
  693. package/src/lib/text-match.ts +57 -2
  694. package/src/lib/thenable.ts +19 -0
  695. package/src/lib/translation-review.ts +13 -5
  696. package/src/notifications/device-zone-report.ts +1 -1
  697. package/src/notifications/notification-bell.tsx +7 -4
  698. package/src/notifications/notification-inbox.tsx +40 -58
  699. package/src/notifications/notification-parts.tsx +3 -4
  700. package/src/notifications/notification-types-setting.tsx +1 -1
  701. package/src/notifications/notifications-labels.ts +7 -0
  702. package/src/notifications/push-device-setting.tsx +1 -1
  703. package/src/notifications/push-devices-setting.tsx +30 -55
  704. package/src/notifications/quiet-hours-setting.tsx +93 -31
  705. package/src/notifications/unsubscribe-panel.tsx +4 -7
  706. package/src/notifications/use-push-device.ts +76 -10
  707. package/src/offline/query-persistence.ts +35 -3
  708. package/src/rhf/fields.tsx +11 -4
  709. package/src/search/command-palette.tsx +2 -4
  710. package/src/search/global-search.tsx +36 -15
  711. package/src/search/search-index.ts +0 -15
  712. package/src/search/use-command-key.ts +13 -12
  713. package/src/search.ts +10 -1
  714. package/src/settings/use-settings-focus.ts +3 -0
  715. package/src/shell/account-menu-language.tsx +6 -4
  716. package/src/shell/account-menu-text-size.tsx +10 -7
  717. package/src/shell/app-shell.tsx +0 -13
  718. package/src/shell/company-switcher.tsx +1 -1
  719. package/src/shell/dev-menu.tsx +8 -22
  720. package/src/shell/top-bar-actions.tsx +1 -1
  721. package/src/shell/top-bar-parts-labels.ts +1 -4
  722. package/src/shell.ts +21 -17
  723. package/src/sync/engine.ts +339 -61
  724. package/src/sync.ts +2 -8
  725. package/src/testing/css-variables.ts +8 -9
  726. package/src/theme/chart-palette.ts +0 -2
  727. package/src/theme/contrast.ts +8 -9
  728. package/src/theme/palette-store.ts +9 -9
  729. package/src/theme/text-size.ts +6 -8
  730. package/src/theme/theme-store.ts +7 -9
  731. package/src/tour/tour-catalogue.tsx +26 -15
  732. package/src/tour/tour-dock.ts +0 -2
  733. package/src/tour/tour-gates.ts +23 -0
  734. package/src/tour/tour-overlay.tsx +1170 -0
  735. package/src/tour/tour.tsx +108 -1202
  736. package/src/tour/use-tour-progress.ts +1 -1
  737. package/src/wizard/stepper-nav.tsx +3 -1
  738. package/src/wizard/types.ts +11 -2
  739. package/src/wizard/use-wizard.ts +2 -1
  740. package/src/wizard/validation.ts +8 -2
  741. package/tokens.css +6 -5
  742. package/dist/components/field-sync-labels.d.ts +0 -2
  743. package/dist/components/field-sync-labels.js +0 -12
  744. package/dist/components/field-sync-labels.js.map +0 -1
  745. package/dist/components/field-sync.d.ts +0 -164
  746. package/dist/components/field-sync.js +0 -269
  747. package/dist/components/field-sync.js.map +0 -1
  748. package/dist/components/section-nav.d.ts +0 -37
  749. package/dist/components/section-nav.js +0 -33
  750. package/dist/components/section-nav.js.map +0 -1
  751. package/dist/components/sign-chip-labels.d.ts +0 -2
  752. package/dist/components/sign-chip-labels.js +0 -11
  753. package/dist/components/sign-chip-labels.js.map +0 -1
  754. package/dist/components/sign-chip.d.ts +0 -68
  755. package/dist/components/sign-chip.js +0 -47
  756. package/dist/components/sign-chip.js.map +0 -1
  757. package/dist/components/ui-labels.js.map +0 -1
  758. package/dist/lib/isin.d.ts +0 -28
  759. package/dist/lib/isin.js +0 -36
  760. package/dist/lib/isin.js.map +0 -1
  761. package/dist/shell/dev-switchers.d.ts +0 -6
  762. package/dist/shell/dev-switchers.js +0 -12
  763. package/dist/shell/dev-switchers.js.map +0 -1
  764. package/dist/shell/role-switcher.d.ts +0 -21
  765. package/dist/shell/role-switcher.js +0 -31
  766. package/dist/shell/role-switcher.js.map +0 -1
  767. package/src/components/field-sync-labels.ts +0 -13
  768. package/src/components/field-sync.tsx +0 -482
  769. package/src/components/section-nav.tsx +0 -65
  770. package/src/components/sign-chip-labels.ts +0 -12
  771. package/src/components/sign-chip.tsx +0 -124
  772. package/src/components/ui-labels.ts +0 -24
  773. package/src/lib/isin.ts +0 -62
  774. package/src/shell/dev-switchers.tsx +0 -18
  775. package/src/shell/role-switcher.tsx +0 -46
@@ -16,7 +16,7 @@ import type { DataTableColumn, FilterState, ServerPagination } from "./data-tabl
16
16
  interface PersistedState {
17
17
  // Multi-sort array; blobs from before the upgrade hold a single {key, dir}
18
18
  // object (or null) — read back through normalizeSorts.
19
- sort: SortState[] | { key: string; dir: string } | null;
19
+ sort: readonly SortState[] | { key: string; dir: string } | null;
20
20
  filters: FilterState;
21
21
  pageSize: number | "all";
22
22
  widths?: Record<string, number>;
@@ -190,7 +190,7 @@ export interface TableUrlState {
190
190
  */
191
191
  export function readTableUrlState<T>(
192
192
  sp: URLSearchParams,
193
- columns: DataTableColumn<T>[],
193
+ columns: readonly DataTableColumn<T>[],
194
194
  prefix?: string,
195
195
  ): TableUrlState {
196
196
  const keys = urlKeys(prefix);
@@ -232,8 +232,8 @@ export function readTableUrlState<T>(
232
232
  * produces a different one.
233
233
  */
234
234
  function urlSignature<T>(
235
- columns: DataTableColumn<T>[],
236
- sorts: SortState[],
235
+ columns: readonly DataTableColumn<T>[],
236
+ sorts: readonly SortState[],
237
237
  filters: FilterState,
238
238
  pageSize: number,
239
239
  page: number,
@@ -257,8 +257,8 @@ function urlSignature<T>(
257
257
 
258
258
  function writeUrlState<T>(
259
259
  setSearchParams: ReturnType<typeof useSearchParams>[1],
260
- columns: DataTableColumn<T>[],
261
- sorts: SortState[],
260
+ columns: readonly DataTableColumn<T>[],
261
+ sorts: readonly SortState[],
262
262
  filters: FilterState,
263
263
  pageSize: number,
264
264
  page: number,
@@ -334,12 +334,12 @@ export function useTableState<T>({
334
334
  filtersProp,
335
335
  pageSizeProp,
336
336
  }: {
337
- columns: DataTableColumn<T>[];
337
+ columns: readonly DataTableColumn<T>[];
338
338
  storageKey?: string;
339
339
  storageKeyPrefix: string;
340
340
  urlSync?: TableUrlSync;
341
341
  defaultPageSize: number;
342
- sortsProp?: SortState[];
342
+ sortsProp?: readonly SortState[];
343
343
  filtersProp?: FilterState;
344
344
  pageSizeProp?: number;
345
345
  }) {
@@ -574,6 +574,9 @@ export function useSharedTableView({
574
574
  pageSize: next.pageSize === Infinity ? "all" : next.pageSize,
575
575
  widths: stored.widths,
576
576
  hidden: stored.hidden,
577
+ // The `defaultHidden` columns the single table's user ticked back on (0.48): left
578
+ // out, a sort changed here hid them again there (refactor audit 2026-10-30, DSP-23 c).
579
+ ...(stored.shown ? { shown: stored.shown } : {}),
577
580
  };
578
581
  writeStored(prefix + storageKey, serializePersisted(blob));
579
582
  };
@@ -589,7 +592,7 @@ export function useSharedTableView({
589
592
 
590
593
  export interface UseTableUrlStateOptions<T> {
591
594
  /** The table's columns — read for their keys and filter types only. */
592
- columns: DataTableColumn<T>[];
595
+ columns: readonly DataTableColumn<T>[];
593
596
  /** Default 25. A page size equal to it is left out of the URL. */
594
597
  defaultPageSize?: number;
595
598
  /** Mirror the state into the URL and seed it from there on mount. Default true.
package/src/data-table.ts CHANGED
@@ -27,15 +27,12 @@ export type {
27
27
  DataTableRowAction,
28
28
  DataTableDesktopSwipeActions,
29
29
  } from "./components/data-table";
30
- // 0.46.1 (keksdose N3): a swipe plan as `RowActions`' actions — the desktop column's own
31
- // derivation, for an app's hand-built actions column.
32
- export { swipePlanRowActions } from "./components/data-table-row-actions";
33
30
  // 0.48 (keksdose dev #605): a `groupBy` level (also `mobileGroupBy`'s) and the `loadMore` footer.
34
31
  export type { DataTableGroupBy, DataTableLoadMore } from "./components/data-table-groups";
35
32
  // 0.48.2 (keksdose dev #632): `virtualize`'s options.
36
33
  export type { DataTableVirtualize } from "./components/data-table-virtual";
37
34
  export * from "./components/data-table-cells";
38
- export { useTableUrlState, readTableUrlState } from "./components/use-table-state";
35
+ export { useTableUrlState } from "./components/use-table-state";
39
36
  export type {
40
37
  TableUrlState,
41
38
  TableUrlSync,
@@ -50,14 +50,9 @@ function minutesAt(expiry: number, now: number): number | null {
50
50
  return Math.max(0, Math.ceil((expiry - now) / MINUTE));
51
51
  }
52
52
 
53
- /**
54
- * The countdown at `now` — pure, for a test or a server-rendered value. See
55
- * {@link DemoCountdown} for the rounding and the thresholds.
56
- */
57
- export function demoCountdown(expiresAt: DemoExpiry | null | undefined, now: number): DemoCountdown {
58
- return countdownOf(minutesAt(expiryMs(expiresAt), now));
59
- }
60
-
53
+ /** The countdown for `minutesLeft` — see {@link DemoCountdown} for the rounding and the
54
+ * thresholds. (Public as `demoCountdown(expiresAt, now)` until 0.53, deprecated in 0.52,
55
+ * API-4: `useDemoCountdown` with its `now` option is the same countdown.) */
61
56
  function countdownOf(minutesLeft: number | null): DemoCountdown {
62
57
  if (minutesLeft === null) {
63
58
  return { minutesLeft, hours: 0, minutes: 0, lastHour: false, warning: false, ended: false };
@@ -63,9 +63,12 @@ export interface ThemeInlineDeclaration {
63
63
 
64
64
  /** The `@theme inline` block: where it stands, and every declaration in it in block order. */
65
65
  export interface ThemeInlineBlock {
66
- /** Its first and one-past-last offset in `stripCssComments(css)`, not in `css`. */
66
+ /** Its first and one-past-last offset in `stripCssComments(css)`, not in `css`. With
67
+ * several `@theme inline` blocks, the first one's; `ranges` holds each. */
67
68
  start: number;
68
69
  end: number;
70
+ ranges: { start: number; end: number }[];
71
+ /** Every block's, in stylesheet order. */
69
72
  declarations: ThemeInlineDeclaration[];
70
73
  }
71
74
 
@@ -74,19 +77,60 @@ export function stripCssComments(css: string): string {
74
77
  return css.replace(/\/\*[\s\S]*?\*\//g, "");
75
78
  }
76
79
 
80
+ /** One `@theme … { … }` block: its first and one-past-last offset, and what its braces hold. */
81
+ export interface ThemeBlock {
82
+ start: number;
83
+ end: number;
84
+ body: string;
85
+ }
86
+
87
+ /**
88
+ * Every `@theme` block of `css` (comments already stripped) whose prelude names `inline`
89
+ * (`@theme inline`, `@theme inline reference`) — or, with `inline: false`, every other
90
+ * one (`@theme {`, Tailwind's `@theme default {`). Counted brace by brace, so a nested
91
+ * block does not end it early.
92
+ *
93
+ * The one block finder (refactor audit 2026-10-30, DUP-13): this parser read only the
94
+ * first `@theme inline {…}` up to its first `}`, the testing guard's
95
+ * `declaredCustomProperties` every inline block brace-aware, and the README's inventory a
96
+ * plain `@theme {` by a regex of its own — three readers that disagreed on what one block
97
+ * is. It lives here because this module imports nothing, so the scripts load it from
98
+ * source under Node.
99
+ */
100
+ export function themeBlocks(css: string, { inline }: { inline: boolean }): ThemeBlock[] {
101
+ const blocks: ThemeBlock[] = [];
102
+ for (const m of css.matchAll(/@theme\b([^{;]*)\{/g)) {
103
+ if (/\binline\b/.test(m[1]) !== inline) continue;
104
+ const open = m.index + m[0].length - 1;
105
+ let depth = 0;
106
+ let close = open;
107
+ for (; close < css.length; close++) {
108
+ if (css[close] === "{") depth++;
109
+ else if (css[close] === "}" && --depth === 0) break;
110
+ }
111
+ blocks.push({ start: m.index, end: close + 1, body: css.slice(open + 1, close) });
112
+ }
113
+ return blocks;
114
+ }
115
+
77
116
  const PROPERTIES = Object.keys(ROLE_NAMESPACES) as RoleProperty[];
78
117
 
79
118
  /**
80
- * tokens.css's `@theme inline` block, read once for every reader: the table below, and
81
- * the README's (scripts/gen-styling-inventory.mjs), which fails on a `property: null`
82
- * where the table leaves it out. `null` when there is no such block — the role utilities
83
- * are gone, or this parser is. Theme blocks hold only declarations, so the first `}`
84
- * closes it; no namespace is another's prefix, so the first that fits is the one.
119
+ * tokens.css's `@theme inline` block (every one, should there be several), read once for
120
+ * every reader: the table below, and the README's (scripts/gen-styling-inventory.mjs),
121
+ * which fails on a `property: null` where the table leaves it out. `null` when there is
122
+ * no such block — the role utilities are gone, or this parser is. No namespace is
123
+ * another's prefix, so the first that fits is the one.
85
124
  */
86
125
  export function parseThemeInline(css: string): ThemeInlineBlock | null {
87
- const block = /@theme\s+inline\s*\{([^}]*)\}/.exec(stripCssComments(css));
88
- if (!block) return null;
89
- const declarations = [...block[1].matchAll(/--([a-z0-9-]+)\s*:\s*([^;]+);/g)].map(([, variable, raw]) => {
126
+ const blocks = themeBlocks(stripCssComments(css), { inline: true });
127
+ if (blocks.length === 0) return null;
128
+ const declarations = [
129
+ ...blocks
130
+ .map((b) => b.body)
131
+ .join("\n")
132
+ .matchAll(/--([a-z0-9-]+)\s*:\s*([^;]+);/g),
133
+ ].map(([, variable, raw]) => {
90
134
  const value = raw.trim();
91
135
  const property = PROPERTIES.find((p) => variable.startsWith(`${ROLE_NAMESPACES[p]}-`)) ?? null;
92
136
  const name = property && variable.slice(ROLE_NAMESPACES[property].length + 1);
@@ -99,7 +143,8 @@ export function parseThemeInline(css: string): ThemeInlineBlock | null {
99
143
  value,
100
144
  };
101
145
  });
102
- return { start: block.index, end: block.index + block[0].length, declarations };
146
+ const ranges = blocks.map(({ start, end }) => ({ start, end }));
147
+ return { start: ranges[0].start, end: ranges[0].end, ranges, declarations };
103
148
  }
104
149
 
105
150
  /**
@@ -120,12 +165,36 @@ export function roleUtilitiesFromCss(css: string): RoleUtilityTable | null {
120
165
  /**
121
166
  * `text-[var(--text-muted)]`, `hover:bg-[var(--bg-hover)]`, `border-t-[var(--border)]`,
122
167
  * `focus-visible:ring-[var(--brand)]/40`, `ring-offset-[var(--bg-surface)]`,
123
- * `ring-[length:var(--focus-ring-width)]`. Preceded by a start, a space, a quote or a
124
- * variant's colon, which the match does not include — nor the variants before it or an
125
- * opacity or `!` after it — so replacing the match keeps all of them.
168
+ * `ring-[length:var(--focus-ring-width)]` — and, since 0.52, Tailwind v4's own spellings
169
+ * of the same: the shorthand `text-(--text-muted)`, a type hint `text-[color:var(--x)]` /
170
+ * `text-(color:--x)` / `ring-(length:--x)`, and the arbitrary property
171
+ * `[color:var(--text-muted)]`, which is `text-muted` (refactor audit 2026-10-30, DOC-1:
172
+ * all of them passed the check and every app's lint). Preceded by a start, a space, a
173
+ * quote or a variant's colon, which the match does not include — nor the variants before
174
+ * it or an opacity or `!` after it — so replacing the match keeps all of them.
175
+ *
176
+ * Groups: 1 the property; then 2 the hint and 3 the token of `-[…var()]`, or 4 and 5 of
177
+ * `-(…)`; or 6 the CSS property and 7 the token of `[property:var()]`.
126
178
  */
127
- const ROLE_CLASS =
128
- /(?<=^|[\s"'`:])(text|bg|border(?:-[xytrblse])?|divide|ring-offset|ring|outline|fill|stroke)-\[(length:)?var\((--[a-zA-Z0-9-]+)\)\]/g;
179
+ const TOKEN = "(--[a-zA-Z0-9-]+)";
180
+ const ROLE_CLASS = new RegExp(
181
+ "(?<=^|[\\s\"'`:])(?:" +
182
+ "(text|bg|border(?:-[xytrblse])?|divide|ring-offset|ring|outline|fill|stroke)-" +
183
+ `(?:\\[(?:(length|color):)?var\\(${TOKEN}\\)\\]|\\((?:(length|color):)?${TOKEN}\\))` +
184
+ `|\\[(color|background-color|border-color|outline-color|fill|stroke):var\\(${TOKEN}\\)\\]` +
185
+ ")",
186
+ "g",
187
+ );
188
+
189
+ /** The utility prefix an arbitrary property `[property:var(--x)]` is written as. */
190
+ const ARBITRARY_PROPERTY: Record<string, string> = {
191
+ color: "text",
192
+ "background-color": "bg",
193
+ "border-color": "border",
194
+ "outline-color": "outline",
195
+ fill: "fill",
196
+ stroke: "stroke",
197
+ };
129
198
 
130
199
  export interface RoleClassHit {
131
200
  /** Where the class starts in the scanned text, after its variants. */
@@ -137,17 +206,26 @@ export interface RoleClassHit {
137
206
  }
138
207
 
139
208
  /**
140
- * Every `[var(--token)]` class in `text` whose token has a role utility on that property.
209
+ * Every `[var(--token)]` class in `text` (or one of v4's spellings of it, above) whose
210
+ * token has a role utility on that property.
141
211
  * A token with no utility there (`text-[var(--chart-1)]`, `--status-*`,
142
212
  * `bg-[var(--border)]` as a divider's fill) is not a hit: `[var(--…)]` is right for it.
143
213
  */
144
214
  export function findRoleClasses(text: string, table: RoleUtilityTable): RoleClassHit[] {
145
- if (!text.includes("var(--")) return [];
215
+ // Every form names a token: `var(--x)`, or `(--x)` in v4's shorthand.
216
+ if (!text.includes("--")) return [];
146
217
  const hits: RoleClassHit[] = [];
147
218
  for (const m of text.matchAll(ROLE_CLASS)) {
148
- const [found, prop, length, token] = m;
219
+ const [found, utility, bracketHint, bracketToken, parenHint, parenToken, cssProperty, propertyToken] = m;
220
+ const prop = utility ?? ARBITRARY_PROPERTY[cssProperty];
221
+ const token = bracketToken ?? parenToken ?? propertyToken;
149
222
  // `border-t` and `divide` read `border`'s names; a `length:` hint reads the widths.
150
- const key = length ? `${prop}-width` : prop.startsWith("border-") || prop === "divide" ? "border" : prop;
223
+ const key =
224
+ (bracketHint ?? parenHint) === "length"
225
+ ? `${prop}-width`
226
+ : prop.startsWith("border-") || prop === "divide"
227
+ ? "border"
228
+ : prop;
151
229
  const names = (table as Partial<Record<string, Readonly<Record<string, readonly string[]>>>>)[key]?.[token];
152
230
  if (names?.length) hits.push({ index: m.index, found, utilities: names.map((name) => `${prop}-${name}`) });
153
231
  }
@@ -9,6 +9,7 @@ import { Modal } from "../components/modal";
9
9
  import { isApplePlatform } from "../hooks/use-hotkey";
10
10
  import { usePhoneLayout } from "../hooks/use-breakpoint";
11
11
  import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
12
+ import { hasContent } from "../lib/presence";
12
13
  import {
13
14
  DEFAULT_ATTACHMENT_ACCEPT,
14
15
  DEFAULT_FEEDBACK_ATTACHMENT_LABELS,
@@ -19,8 +20,10 @@ import {
19
20
  } from "./feedback-attachment";
20
21
  import { DEFAULT_FEEDBACK_DIALOG_LABELS } from "./feedback-dialog-labels";
21
22
 
22
- export interface FeedbackCategoryOption {
23
- value: string;
23
+ /** One category the dialog offers. `C` (0.52): the app's category type — the kit's
24
+ * `FeedbackCategory`, or `string` (the default) for a vocabulary of the app's own. */
25
+ export interface FeedbackCategoryOption<C extends string = string> {
26
+ value: C;
24
27
  label: string;
25
28
  }
26
29
 
@@ -103,10 +106,10 @@ export interface FeedbackDialogTextLabels {
103
106
  // Defined in ./feedback-dialog-labels, which holds no component code (0.34, KS U8).
104
107
  export { DEFAULT_FEEDBACK_DIALOG_LABELS };
105
108
 
106
- export interface FeedbackSubmission {
109
+ export interface FeedbackSubmission<C extends string = string> {
107
110
  title: string;
108
111
  body: string;
109
- category: string;
112
+ category: C;
110
113
  attachment: File | null;
111
114
  }
112
115
 
@@ -116,22 +119,29 @@ export interface FeedbackSubmission {
116
119
  * attaches the screenshot to the report and the photos as its evidence list. No
117
120
  * `attachment`: there is no one file it could name.
118
121
  */
119
- export interface FeedbackMultipleSubmission {
122
+ export interface FeedbackMultipleSubmission<C extends string = string> {
120
123
  title: string;
121
124
  body: string;
122
- category: string;
125
+ category: C;
123
126
  /** What `onCaptureScreenshot` returned, or `null` — at most one. */
124
127
  screenshot: File | null;
125
128
  /** Picked and pasted files, in the order they were added; at most `maxAttachments`. */
126
129
  attachments: File[];
127
130
  }
128
131
 
129
- interface FeedbackDialogBaseProps {
132
+ /**
133
+ * `C` (0.52, refactor audit 2026-10-30, API-7): the category type, inferred from
134
+ * `categories` and `category` — `FeedbackCategory` hands `onCategoryChange` and
135
+ * `onSubmit` a `FeedbackCategory` back, where a plain `string` had to be cast (the kit's
136
+ * own `useFeedbackSubmit` did). `string` by default, so an app's own vocabulary fits.
137
+ */
138
+ interface FeedbackDialogBaseProps<C extends string = string> {
130
139
  open: boolean;
131
140
  onClose: () => void;
132
- categories: FeedbackCategoryOption[];
133
- category: string;
134
- onCategoryChange: (value: string) => void;
141
+ /** `readonly` since 0.52: the dialog never changes it. */
142
+ categories: readonly FeedbackCategoryOption<C>[];
143
+ category: C;
144
+ onCategoryChange: (value: C) => void;
135
145
  /** Prop > `<UiKitProvider labels={{ feedbackDialog, feedbackAttachment }}>` >
136
146
  * English. Optional since 0.12.0; a whole `FeedbackDialogLabels` still fits. */
137
147
  labels?: LabelOverride<FeedbackDialogLabels>;
@@ -178,9 +188,9 @@ interface FeedbackDialogBaseProps {
178
188
 
179
189
  /** One attachment — a screenshot, a picked or a pasted image; a second replaces
180
190
  * nothing, it has to wait for the first to be removed. The default. */
181
- export interface FeedbackDialogSingleProps extends FeedbackDialogBaseProps {
191
+ export interface FeedbackDialogSingleProps<C extends string = string> extends FeedbackDialogBaseProps<C> {
182
192
  attachments?: "single";
183
- onSubmit: (data: FeedbackSubmission) => void | Promise<void>;
193
+ onSubmit: (data: FeedbackSubmission<C>) => void | Promise<void>;
184
194
  /** `info` (0.23.0) names the refused file and the limit — see
185
195
  * {@link FeedbackAttachmentErrorInfo}. */
186
196
  onAttachmentError?: (kind: "type" | "size", info: FeedbackAttachmentErrorInfo) => void;
@@ -193,17 +203,18 @@ export interface FeedbackDialogSingleProps extends FeedbackDialogBaseProps {
193
203
  * dev#578: "pasted two photos, the second overwrote the first"). The capture button is
194
204
  * offered while there is no screenshot yet; the add button while there is room.
195
205
  */
196
- export interface FeedbackDialogMultipleProps extends FeedbackDialogBaseProps {
206
+ export interface FeedbackDialogMultipleProps<C extends string = string> extends FeedbackDialogBaseProps<C> {
197
207
  attachments: "multiple";
198
208
  /** Default `DEFAULT_MAX_ATTACHMENTS` (5). The screenshot does not count. */
199
209
  maxAttachments?: number;
200
- onSubmit: (data: FeedbackMultipleSubmission) => void | Promise<void>;
210
+ onSubmit: (data: FeedbackMultipleSubmission<C>) => void | Promise<void>;
201
211
  /** `"count"`: more files arrived at once than there was room for; the surplus was
202
212
  * dropped. `info` (0.23.0) names the refused file(s) and the limit. */
203
213
  onAttachmentError?: (kind: FeedbackAttachmentError, info: FeedbackAttachmentErrorInfo) => void;
204
214
  }
205
215
 
206
- export type FeedbackDialogProps = FeedbackDialogSingleProps | FeedbackDialogMultipleProps;
216
+ export type FeedbackDialogProps<C extends string = string> =
217
+ FeedbackDialogSingleProps<C> | FeedbackDialogMultipleProps<C>;
207
218
 
208
219
  /**
209
220
  * The generic feedback form dialog: category + subject + body + an optional image
@@ -225,7 +236,7 @@ export type FeedbackDialogProps = FeedbackDialogSingleProps | FeedbackDialogMult
225
236
  * FeedbackMultipleSubmission}) instead of `attachment`. Opt-in, so a caller typed
226
237
  * against the one-file submission keeps compiling and behaving as before.
227
238
  */
228
- export function FeedbackDialog(props: FeedbackDialogProps) {
239
+ export function FeedbackDialog<C extends string = string>(props: FeedbackDialogProps<C>) {
229
240
  const {
230
241
  open,
231
242
  onClose,
@@ -251,8 +262,7 @@ export function FeedbackDialog(props: FeedbackDialogProps) {
251
262
  const [files, setFiles] = useState<File[]>([]);
252
263
  const isMobile = usePhoneLayout();
253
264
  const noticeId = useId();
254
- const hasNotice =
255
- publicNotice !== undefined && publicNotice !== null && publicNotice !== false && publicNotice !== "";
265
+ const hasNotice = hasContent(publicNotice);
256
266
  const labels = useKitLabels("feedbackDialog", DEFAULT_FEEDBACK_DIALOG_LABELS, labelsProp);
257
267
  const attachmentText = useKitLabels("feedbackAttachment", DEFAULT_FEEDBACK_ATTACHMENT_LABELS, labelsProp);
258
268
  // Under `multiple` the heading is `attachmentList` — a screenshot AND photos — which
@@ -296,7 +306,8 @@ export function FeedbackDialog(props: FeedbackDialogProps) {
296
306
  if (!open) return null;
297
307
 
298
308
  const categoryField = (
299
- <Select label={labels.category} value={category} onChange={(e) => onCategoryChange(e.target.value)}>
309
+ // The select offers exactly `categories`' values, so what it answers is one of them.
310
+ <Select label={labels.category} value={category} onChange={(e) => onCategoryChange(e.target.value as C)}>
300
311
  {categories.map((c) => (
301
312
  <option key={c.value} value={c.value}>
302
313
  {c.label}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * A page's mutation, run once (refactor audit 2026-10-30, FLW-3): TanStack Query's
3
+ * `mutateAsync`, or any `(patch) => Promise` that resolves once the PATCH has landed.
4
+ *
5
+ * The parts took TanStack Query's `mutate` with a per-call `onSuccess` until 0.53
6
+ * (deprecated in 0.52). TanStack v5 calls per-call callbacks for the LATEST `mutate()` on
7
+ * an observer only — it overwrites the options and detaches from the earlier mutation —
8
+ * so a second change sent before the first PATCH answered (another swipe, another pill,
9
+ * the Undo itself) lost the first change's Undo toast, and the detail's editor stayed
10
+ * open. The promise `mutateAsync` returns settles for every call, whatever the observer
11
+ * does next.
12
+ *
13
+ * A rejected promise is the mutation's own to report (its `onError`), so it is caught here
14
+ * and nothing more happens.
15
+ *
16
+ * @internal Not part of `/feedback` or the barrel.
17
+ */
18
+ export function runMutation<P>(call: (patch: P) => Promise<unknown>, patch: P, landed: () => void): void {
19
+ call(patch).then(landed, () => undefined);
20
+ }
@@ -0,0 +1,90 @@
1
+ import type { PathPattern } from "../landing/routing";
2
+ import { matchesPathPattern, routerPathname } from "../lib/path-pattern";
3
+ import type { FeedbackContext } from "./feedback-record";
4
+
5
+ /**
6
+ * The page a report was filed on, and which of it the feedback parts link (refactor audit
7
+ * 2026-10-30, FLW-7).
8
+ *
9
+ * The page comes from the REPORTER's client context: its origin is always this app's
10
+ * (only the path is ever linked), but its path and query are whatever the row says. A
11
+ * signed-in user could file a report whose link takes the admin to a route that acts on
12
+ * load — keksdose's `/join?token=` accepts an invitation through `AcceptInvitation`,
13
+ * kastlan's and Kurvenschmiede's `/register?invite=` likewise.
14
+ *
15
+ * **Only the PATH is linked** (0.52 code review, this file). The tokens and the forward
16
+ * targets travel in the query: a guard on the path alone let `/login?next=%2Fjoin%3Ftoken%3D…`
17
+ * through as a link, and `RedirectIfAuthed` sent the signed-in admin on to the invitation —
18
+ * as `/forgot-password`, `/demo` and `/welcome` would, and whatever forwarder an app adds
19
+ * next (`?returnTo=`, a share target). No list of forwarders can know them all; a link
20
+ * without a query reaches none. The query and hash are shown as text beside it, and "Copy
21
+ * URL" copies the whole address, for whoever wants that exact state and opens it knowingly.
22
+ *
23
+ * **A one-shot PATH is not linked at all** — the kit's `/join`, `/register`,
24
+ * `/verify-email`, `/reset-password` (`/reset-password/<token>` carries it in the path),
25
+ * and the app's `pageLinkExclude` on top: shown as text with Copy.
26
+ *
27
+ * @internal Not part of `/feedback` or the barrel.
28
+ */
29
+
30
+ /** The kit's one-shot routes: the invitation accepts and the two token pages. */
31
+ export const FEEDBACK_ONE_SHOT_PAGES: readonly PathPattern[] = Object.freeze([
32
+ "/join",
33
+ "/register",
34
+ "/verify-email",
35
+ "/reset-password",
36
+ ]);
37
+
38
+ /** Whether `href` (a path, with or without its query) names a one-shot route — the kit's,
39
+ * or one of the app's `exclude` on top. Read as the ROUTER reads it, decoded and
40
+ * case-insensitive: `/Join?token=` and `/j%6Fin?token=` render `/join` too (0.52 code
41
+ * review, this file). */
42
+ export function isOneShotPage(href: string, exclude: readonly PathPattern[] = []): boolean {
43
+ const pathname = routerPathname(href);
44
+ const named = (pattern: PathPattern) => matchesPathPattern(pathname, pattern);
45
+ return FEEDBACK_ONE_SHOT_PAGES.some(named) || exclude.some(named);
46
+ }
47
+
48
+ /** The page a report was filed on, read once — the URL cell and the detail each parsed it
49
+ * three times, once per part (0.52 code review, feedback-table.tsx: 810 `URL`s per render
50
+ * of a 270-row inbox, for one column). */
51
+ export interface FeedbackPage {
52
+ /** The path: what the URL column shows, and the only part ever linked. */
53
+ path: string;
54
+ /** Path + query + hash: the page as the reporter had it (keksdose `localHref`: the query
55
+ * and hash carry the state, `?tab=import`, a drill-down) — shown, never followed. */
56
+ href: string;
57
+ /** What "Copy URL" copies: the FULL `context.url` as the reporter's browser had it —
58
+ * origin included, the one part that says which copy of the app it was (feedback
59
+ * #278) — else `context.route`. */
60
+ url: string;
61
+ }
62
+
63
+ /** Collapses a leading `//` run: `/\/\/evil.example/` as a path would be a
64
+ * protocol-relative link off the app. */
65
+ const localPath = (pathname: string) => pathname.replace(/^\/{2,}/, "/");
66
+
67
+ /** `context.url`, else `context.route`, parsed — or null when neither is set or the value
68
+ * is no http(s) address or path (a `javascript:` value is not a page). */
69
+ export function feedbackPage(context: FeedbackContext | null | undefined): FeedbackPage | null {
70
+ const raw = (context?.url || context?.route || "").trim();
71
+ if (!raw) return null;
72
+ let url: URL;
73
+ try {
74
+ // A base, so a PATH-ONLY value parses too: Kurvenschmiede backfills its old rows
75
+ // with `url = page_path + search` (§3.2), and keksdose's `new URL(raw)` threw on
76
+ // those and dropped the section.
77
+ url = new URL(raw, "http://localhost");
78
+ } catch {
79
+ return null;
80
+ }
81
+ if (url.protocol !== "http:" && url.protocol !== "https:") return null;
82
+ const path = localPath(url.pathname);
83
+ return { path, href: `${path}${url.search}${url.hash}`, url: raw };
84
+ }
85
+
86
+ /** Where a click on the page goes: its path, or `null` — show it as text — when that path
87
+ * is one-shot. */
88
+ export function feedbackPageLinkTarget(page: FeedbackPage, exclude: readonly PathPattern[] = []): string | null {
89
+ return isOneShotPage(page.path, exclude) ? null : page.path;
90
+ }
@@ -143,8 +143,9 @@ function PublicPager({
143
143
  /* ── The list ─────────────────────────────────────────────────────────────── */
144
144
 
145
145
  export interface FeedbackPublicListProps<T extends FeedbackPublicListItem = FeedbackPublicListItem> {
146
- /** `GET /feedback/public?sort=&q=` — the server's page, in the server's order. */
147
- rows: T[];
146
+ /** `GET /feedback/public?sort=&q=` — the server's page, in the server's order.
147
+ * `readonly` since 0.52 (refactor audit 2026-10-30, API-7): the list never changes it. */
148
+ rows: readonly T[];
148
149
  /** How many the query has in all — the line beside the sort. Left out, no line. */
149
150
  total?: number;
150
151
  /** The server sorts (§9.6): the toggle only says which way. */
@@ -169,7 +170,10 @@ export interface FeedbackPublicListProps<T extends FeedbackPublicListItem = Feed
169
170
  /** The opened row's id, when the app keeps it (a `?row=` param). Left out, the list
170
171
  * keeps it itself. */
171
172
  openId?: number | null;
172
- onOpenChange?: (id: number | null) => void;
173
+ /** 0.52: a row was opened (its id) or closed (`null`) — `openId`'s pair. Named for
174
+ * what it carries: every other `onOpenChange` in the kit is a boolean (refactor audit
175
+ * 2026-10-30, API-5). */
176
+ onOpenIdChange?: (id: number | null) => void;
173
177
  /**
174
178
  * 0.38.1: the opened report when it is NOT on this page — a `?row=` link to an older
175
179
  * one (Kurvenschmiede). The app fetches it (`GET /feedback/public/{id}`, a list item's
@@ -239,7 +243,7 @@ export function FeedbackPublicList<T extends FeedbackPublicListItem = FeedbackPu
239
243
  onVote,
240
244
  loading = false,
241
245
  openId: openIdProp,
242
- onOpenChange,
246
+ onOpenIdChange,
243
247
  openRow,
244
248
  page: pageIndex = 0,
245
249
  hasMore = false,
@@ -259,12 +263,14 @@ export function FeedbackPublicList<T extends FeedbackPublicListItem = FeedbackPu
259
263
  const openId = openIdProp !== undefined ? openIdProp : ownOpenId;
260
264
  const setOpen = (id: number | null) => {
261
265
  if (openIdProp === undefined) setOwnOpenId(id);
262
- onOpenChange?.(id);
266
+ onOpenIdChange?.(id);
263
267
  };
264
268
  // A `?row=` report from another page: first, while it is the open one, and only when
265
269
  // the page does not have it itself.
266
- const shownRows =
267
- openRow && openId === openRow.id && !rows.some((row) => row.id === openRow.id) ? [openRow, ...rows] : rows;
270
+ // `as T[]`: DataTable's `rows` is still mutable in its type (API-7), and never mutated.
271
+ const shownRows = (
272
+ openRow && openId === openRow.id && !rows.some((row) => row.id === openRow.id) ? [openRow, ...rows] : rows
273
+ ) as T[];
268
274
 
269
275
  const columns = useMemo<DataTableColumn<T>[]>(
270
276
  () => [
@@ -4,9 +4,9 @@ import { BellOff } from "lucide-react";
4
4
  import { Select } from "../components/select";
5
5
  import type { CommitScope } from "../components/write-lock";
6
6
  import type { AuthedFetcher } from "../hooks/use-authed-src";
7
- import { useKitLabels, useKitLocale, type LabelOverride } from "../i18n/kit-labels";
7
+ import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
8
8
  import { cn } from "../lib/cn";
9
- import { formatDate } from "../lib/format";
9
+ import { useDayFormatter } from "../lib/day-format";
10
10
  import { FeedbackStatusBadge, selectableFeedbackStatuses, type FeedbackStatus } from "./feedback-inbox";
11
11
  import { useFeedbackStatusLabels } from "./feedback-labels";
12
12
  import type { FeedbackReply } from "./feedback-public-types";
@@ -77,10 +77,15 @@ export function feedbackReplyNudge(row: {
77
77
 
78
78
  /* ── The timeline ─────────────────────────────────────────────────────────── */
79
79
 
80
+ /** A reply's time, the kit's own: the medium date and the short clock. */
81
+ const REPLY_TIME_STYLE: Intl.DateTimeFormatOptions = { dateStyle: "medium", timeStyle: "short" };
82
+
80
83
  export interface FeedbackReplyTimelineProps {
81
84
  /** Oldest first, as the server sends them. */
82
85
  replies: readonly FeedbackReply[];
83
- /** How a reply's time reads. Default: the date and time in the provider's locale. */
86
+ /** How a reply's time reads. Default (0.52): the `<UiKitProvider formatDate>`'s day
87
+ * with the language's clock when the app set one, else the date and time in the
88
+ * provider's locale and time zone. */
84
89
  renderDate?: (iso: string) => string;
85
90
  /** Tag bodies and names `data-private` (a host's screen-share blur). Default true. */
86
91
  redact?: boolean;
@@ -142,13 +147,15 @@ export function FeedbackReplyTimeline({
142
147
  }: FeedbackReplyTimelineProps) {
143
148
  const labels = useFeedbackRepliesLabels(labelsProp);
144
149
  const anonymous = useKitLabels("feedbackPublic", DEFAULT_FEEDBACK_PUBLIC_LABELS).anonymous;
145
- const locale = useKitLocale();
150
+ // `renderDate` when it answers, else the provider's `formatDate` for the day with the
151
+ // language's clock, else the kit's date and time in the provider's locale and time zone
152
+ // (0.52, refactor audit 2026-10-30, DUP-2: the provider never reached this one).
153
+ const day = useDayFormatter<string>(renderDate);
146
154
  const priv = redact ? "" : undefined;
147
155
  if (replies.length === 0) {
148
156
  return <p className={cn("text-sm text-placeholder", className)}>{labels.empty}</p>;
149
157
  }
150
- const dateText = (iso: string) =>
151
- renderDate ? renderDate(iso) : formatDate(iso, { dateStyle: "medium", timeStyle: "short" }, { locale });
158
+ const dateText = (iso: string) => day(iso, { time: true, style: REPLY_TIME_STYLE });
152
159
  return (
153
160
  <ol aria-label={labels.replies} className={cn("space-y-3 border-s-2 border-subtle ps-3", className)}>
154
161
  {replies.map((reply) => {
@@ -20,9 +20,6 @@ export const DEFAULT_FEEDBACK_DETAIL_LABELS: FeedbackDetailLabels = {
20
20
  outcome: "Outcome",
21
21
  replies: "Replies",
22
22
  resolvedAt: (date) => `Resolved: ${date}`,
23
- outcomeAdd: "Add outcome",
24
- outcomeUpdate: "Update",
25
- outcomePlaceholder: "What was done, decided, or why this won't be addressed.",
26
23
  rework: "Rework",
27
24
  reworkTitle: "Send for rework",
28
25
  reworkSend: "Send rework",