@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,7 +1,9 @@
1
- import { useRef } from "react";
1
+ import { useId, useLayoutEffect, useRef } from "react";
2
2
  import type { Dispatch, SetStateAction } from "react";
3
3
  import { X } from "lucide-react";
4
4
  import { cn } from "../lib/cn";
5
+ import { claimEscape } from "../hooks/use-dismiss";
6
+ import { firstTabStop } from "../lib/focus-left";
5
7
  import { Tooltip } from "./tooltip";
6
8
  import type { DataTableLabels } from "./data-table-labels";
7
9
  import { isTableOwnColumn } from "./data-table-row-actions";
@@ -26,7 +28,7 @@ export function ColumnSettingsPanel<T>({
26
28
  autoSizeAll,
27
29
  }: {
28
30
  /** Every column, hidden ones included; the actions column is left out here. */
29
- columns: DataTableColumn<T>[];
31
+ columns: readonly DataTableColumn<T>[];
30
32
  hiddenCols: Set<string>;
31
33
  setHiddenCols: Dispatch<SetStateAction<Set<string>>>;
32
34
  /** The columns the table's width leaves out (`fitPriority`, 0.48): unticked, and
@@ -43,15 +45,45 @@ export function ColumnSettingsPanel<T>({
43
45
  }) {
44
46
  // The "Columns" rail button — where the drawer's X hands focus back (BUG-7a).
45
47
  const columnsRail = useRef<HTMLButtonElement | null>(null);
48
+ const drawerRef = useRef<HTMLDivElement | null>(null);
49
+ const drawerId = useId();
50
+ // The opening half (refactor audit 2026-10-30, DSP-13). Opened from the rail, the focus
51
+ // goes into the drawer: the rail it was on turns zero wide and leaves the tab order in
52
+ // the same render, and the focus sat in a control nobody could see. To the first column
53
+ // box — what the drawer is opened for — or, with none, its first control. Only when the
54
+ // rail opened it: a drawer that starts open (its state is the table's) takes nothing.
55
+ const focusOnOpen = useRef(false);
56
+ useLayoutEffect(() => {
57
+ if (!showSettings || !focusOnOpen.current) return;
58
+ focusOnOpen.current = false;
59
+ const drawer = drawerRef.current;
60
+ if (!drawer) return;
61
+ (
62
+ drawer.querySelector<HTMLElement>('input[type="checkbox"]') ?? firstTabStop(drawer, { includeSelf: false })
63
+ )?.focus();
64
+ }, [showSettings]);
65
+ const close = () => {
66
+ setShowSettings(false);
67
+ // Back to the rail that opened it: the drawer is about to go inert, and focus would
68
+ // fall to <body> with it (BUG-7a).
69
+ columnsRail.current?.focus();
70
+ };
46
71
  return (
47
72
  <>
48
73
  <Tooltip label={columnsCountLabel} portal>
49
74
  <button
50
75
  ref={columnsRail}
51
76
  type="button"
52
- onClick={() => setShowSettings(true)}
77
+ onClick={() => {
78
+ focusOnOpen.current = true;
79
+ setShowSettings(true);
80
+ }}
53
81
  aria-label={columnsCountLabel}
54
- aria-hidden={showSettings}
82
+ // A disclosure: it says whether the drawer is open, and never hides itself from
83
+ // a screen reader — `aria-hidden` on it while it held the focus left the reader
84
+ // with nothing to say (DSP-13). Zero wide and out of the tab order while open.
85
+ aria-expanded={showSettings}
86
+ aria-controls={drawerId}
55
87
  tabIndex={showSettings ? -1 : 0}
56
88
  className={cn(
57
89
  "group flex shrink-0 items-start justify-center overflow-hidden pt-3 transition-[width] duration-200 ease-out",
@@ -68,11 +100,26 @@ export function ColumnSettingsPanel<T>({
68
100
  </span>
69
101
  </button>
70
102
  </Tooltip>
103
+ {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- Escape
104
+ for whatever control in the drawer holds the focus; the group itself is no control. */}
71
105
  <div
106
+ ref={drawerRef}
107
+ id={drawerId}
108
+ // Named by its own heading's words, so a reader entering it hears "Columns (4/9),
109
+ // group" before the first box (DSP-13).
110
+ role="group"
111
+ aria-label={columnsCountLabel}
72
112
  // Closed, the drawer is only `w-0`: without `inert` its X, Auto-size and one
73
113
  // checkbox per column stayed tab stops and in the accessibility tree, and Tab
74
114
  // after the last cell walked into controls nobody could see (BUG-7a).
75
115
  inert={!showSettings || undefined}
116
+ // Escape closes it onto the rail, as its X does. Claimed, not handed to the Escape
117
+ // stack: inside a dialog the drawer is what the key closes, not the dialog.
118
+ onKeyDown={(e) => {
119
+ if (e.key !== "Escape" || !showSettings) return;
120
+ claimEscape(e);
121
+ close();
122
+ }}
76
123
  className={cn(
77
124
  "shrink-0 overflow-hidden transition-[width] duration-200 ease-out",
78
125
  showSettings ? "w-56" : "w-0",
@@ -84,12 +131,7 @@ export function ColumnSettingsPanel<T>({
84
131
  <Tooltip label={labels.close} portal>
85
132
  <button
86
133
  type="button"
87
- onClick={() => {
88
- setShowSettings(false);
89
- // Back to the rail that opened it: the X is about to go inert, and
90
- // focus would fall to <body> with it (BUG-7a).
91
- columnsRail.current?.focus();
92
- }}
134
+ onClick={close}
93
135
  aria-label={labels.close}
94
136
  className="rounded p-0.5 text-placeholder hover:bg-hover hover:text-secondary"
95
137
  >
@@ -1,6 +1,6 @@
1
1
  import type { DataTableColumn } from "./data-table";
2
2
  import { toLocalIso } from "../lib/dates";
3
- import { foldForSearch } from "../lib/text-match";
3
+ import { matchesSearch, searchWords } from "../lib/text-match";
4
4
 
5
5
  /** How a column is filtered. `text`/`select`/`date`/`number` each read a value
6
6
  * off the row and compare it against the user's {@link FilterValue}. */
@@ -76,8 +76,10 @@ function localDay(raw: string): string {
76
76
  * `locale` is for the text filter's case folding. Plain `toLowerCase` folds by the
77
77
  * root rules, under which a Turkish user typing "ırmak" does not find "IRMAK";
78
78
  * `toLocaleLowerCase(locale)` does. Optional, and `undefined` is the runtime's default.
79
- * The text filter folds as every kit list does ({@link foldForSearch}, DUP-5): accents
80
- * off too, so "zurich" finds Zürich.
79
+ * The text filter folds as every kit list does (`foldForSearch`, DUP-5): accents off
80
+ * too, so "zurich" finds Zürich. And it matches as the pickers do since 0.51.4 (refactor
81
+ * audit 2026-10-30, DUP-4): every word of the query, anywhere in the value, in any order —
82
+ * "zurich migros" finds "Migros · 8004 Zürich". One word matches as before.
81
83
  */
82
84
  export function rowMatches<T>(col: DataTableColumn<T>, row: T, state: FilterValue, locale?: string): boolean {
83
85
  const filter = resolveFilter(col);
@@ -85,7 +87,7 @@ export function rowMatches<T>(col: DataTableColumn<T>, row: T, state: FilterValu
85
87
  switch (filter.type) {
86
88
  case "text": {
87
89
  if (state.type !== "text" || !state.q.trim()) return true;
88
- return foldForSearch(filter.getValue(row), locale).includes(foldForSearch(state.q.trim(), locale));
90
+ return matchesSearch(searchWords(state.q, locale), [filter.getValue(row)], locale);
89
91
  }
90
92
  case "select": {
91
93
  if (state.type !== "select" || state.values.length === 0) return true;
@@ -48,7 +48,7 @@ export const GROW_PEER_CELL_CLASS = "not-large:whitespace-nowrap";
48
48
  // until kastlan's admin pane scrolled 21px at 1280px (0.48 build review 2, kastlan S1).
49
49
 
50
50
  /** The auto-hide order: lowest `fitPriority` first, the later column first on a tie. */
51
- export function fitHideOrder<T>(columns: DataTableColumn<T>[]): DataTableColumn<T>[] {
51
+ export function fitHideOrder<T>(columns: readonly DataTableColumn<T>[]): DataTableColumn<T>[] {
52
52
  return columns
53
53
  .map((col, index) => ({ col, index }))
54
54
  .filter(({ col }) => col.fitPriority != null)
@@ -72,7 +72,7 @@ export function useColumnFit<T>({
72
72
  enabled,
73
73
  content,
74
74
  }: {
75
- columns: DataTableColumn<T>[];
75
+ columns: readonly DataTableColumn<T>[];
76
76
  /** The user's hidden columns: never candidates (they are out already). */
77
77
  hiddenCols: Set<string>;
78
78
  headRefs: Map<string, HTMLTableCellElement>;
@@ -83,8 +83,10 @@ export function useColumnFit<T>({
83
83
  /**
84
84
  * What can change the columns' widths besides the scroller (0.48.2): the rows on
85
85
  * screen, the columns, the stored widths, the text size. Compared item by item after
86
- * each render, and the table is measured only when one changed — a selection tick no
87
- * longer forces a layout of the whole table. Without it, every render measures.
86
+ * each render (`Object.is`), and the table is measured only when one changed — a
87
+ * selection tick no longer forces a layout of the whole table. Without it, every render
88
+ * measures. So each item must keep its identity while it means the same: the page's
89
+ * rows memoised, the columns as their keys (DSP-19).
88
90
  */
89
91
  content?: readonly unknown[];
90
92
  }): {
@@ -223,11 +225,23 @@ export function useColumnFit<T>({
223
225
  // drawn first. A render that changed none of it (a ticked box, a focused row) skips the
224
226
  // measure, which forces a layout of the whole table (0.48.2, keksdose dev #632).
225
227
  const lastContent = useRef<readonly unknown[] | null>(null);
228
+ // The candidates by their keys, not by identity (refactor audit 2026-10-30, DSP-19):
229
+ // both are memoised on `columns`, which a call site writes inline — a new array, and
230
+ // so a "change", on every render of the page around the table.
231
+ const orderSig = order.map((c) => c.key).join("\u0000");
232
+ const currentSig = current.join("\u0000");
226
233
  useLayoutEffect(() => {
227
234
  // The table the observer watches is this render's (a table drawn after a loading
228
235
  // state, or remounted, is a new element).
229
236
  watchTable();
230
- const now = content ? [...content, order, current, growKey, active] : null;
237
+ // And what the fit measures under the same keys (0.52 code review, data-table.tsx):
238
+ // the headers' text as drawn — a locale switch keeps every key and changes every
239
+ // header, and German → English left out the columns German had no room for, on a
240
+ // table with room to spare (narrower, a `w-full` table keeps the scroller's width,
241
+ // which the observer below watches) — and the grow column's floor. Text is read
242
+ // without a layout.
243
+ const headText = active ? (scroller()?.querySelector("thead")?.textContent ?? "") : "";
244
+ const now = content ? [...content, orderSig, currentSig, growKey, growMin, active, headText] : null;
231
245
  const prev = lastContent.current;
232
246
  lastContent.current = now;
233
247
  if (now && prev && prev.length === now.length && prev.every((v, i) => Object.is(v, now[i]))) return;
@@ -57,7 +57,7 @@ export interface RowGroup<T> {
57
57
  }
58
58
 
59
59
  /** Consecutive runs by `level.key`, nested once for a second level. */
60
- export function groupRows<T>(rows: T[], levels: readonly DataTableGroupBy<T>[], offset = 0): RowGroup<T>[] {
60
+ export function groupRows<T>(rows: readonly T[], levels: readonly DataTableGroupBy<T>[], offset = 0): RowGroup<T>[] {
61
61
  const [level, ...rest] = levels;
62
62
  if (!level) return [];
63
63
  const out: RowGroup<T>[] = [];
@@ -7,6 +7,7 @@ import type { SortState } from "./data-table-sort";
7
7
  import { FilterPopover } from "./data-table-filter-popover";
8
8
  import { Popover } from "./popover";
9
9
  import { Tooltip } from "./tooltip";
10
+ import { Checkbox } from "./checkbox";
10
11
  import type { DataTableLabels } from "./data-table-labels";
11
12
  import { isTableOwnColumn } from "./data-table-row-actions";
12
13
  import { columnLabel, logicalAlign, splitCellProps } from "./data-table-shared";
@@ -59,7 +60,7 @@ export function DataTableHead<T>({
59
60
  hasSortCallback: boolean;
60
61
  /** The caller owns the filters (`onFiltersChange`), likewise. */
61
62
  hasFilterCallback: boolean;
62
- sorts: SortState[];
63
+ sorts: readonly SortState[];
63
64
  filters: FilterState;
64
65
  selectOptionsByKey: Record<string, { value: string; label: string }[]>;
65
66
  multiSort: boolean;
@@ -98,13 +99,16 @@ export function DataTableHead<T>({
98
99
  compact ? "w-8 px-2 py-1" : "w-10 px-3 py-2",
99
100
  )}
100
101
  >
101
- <input
102
- type="checkbox"
103
- className={cn("align-middle accent-indigo-600", compact ? "size-3.5" : "size-4")}
102
+ {/* The kit's Checkbox, as the phone card's (refactor audit 2026-10-30, DSP-14): the
103
+ native box wore `accent-indigo-600` over the kit's `--brand` accent, indigo on
104
+ every palette and, in dark mode, a checked box that read as unchecked. "Some"
105
+ is its `indeterminate` dash, set on the element after every render as the
106
+ ref here did. */}
107
+ <Checkbox
108
+ className="align-middle"
109
+ inputClassName={compact ? "size-3.5" : undefined}
104
110
  checked={selection.allSelected}
105
- ref={(el) => {
106
- if (el) el.indeterminate = selection.someSelected && !selection.allSelected;
107
- }}
111
+ indeterminate={selection.someSelected && !selection.allSelected}
108
112
  onChange={(e) => selection.onToggleAll(e.target.checked)}
109
113
  aria-label={labels.selectAllRows}
110
114
  />
@@ -175,21 +179,27 @@ export function DataTableHead<T>({
175
179
  )}
176
180
  >
177
181
  <div className={cn("flex items-center gap-1", isEndAligned && "flex-row-reverse")}>
178
- <Tooltip label={sortable && multiSort ? labels.sortHint : undefined} portal>
179
- <button
180
- type="button"
181
- onClick={(e) => sortable && toggleSort(col.key, e.shiftKey)}
182
- disabled={!sortable}
183
- className={cn("flex items-center gap-1 text-start", sortable && "hover:text-primary")}
184
- >
185
- <span>{col.header}</span>
186
- {sortable && <Icon className={cn("size-3", active ? "opacity-100" : "opacity-40")} />}
187
- {/* Priority badge, only meaningful with 2+ sort keys */}
188
- {active && sorts.length > 1 && (
189
- <span className="text-micro font-semibold leading-none text-brand">{sortIdx + 1}</span>
190
- )}
191
- </button>
192
- </Tooltip>
182
+ {sortable ? (
183
+ <Tooltip label={multiSort ? labels.sortHint : undefined} portal>
184
+ <button
185
+ type="button"
186
+ onClick={(e) => toggleSort(col.key, e.shiftKey)}
187
+ className="flex items-center gap-1 text-start hover:text-primary"
188
+ >
189
+ <span>{col.header}</span>
190
+ <Icon className={cn("size-3", active ? "opacity-100" : "opacity-40")} />
191
+ {/* Priority badge, only meaningful with 2+ sort keys */}
192
+ {active && sorts.length > 1 && (
193
+ <span className="text-micro font-semibold leading-none text-brand">{sortIdx + 1}</span>
194
+ )}
195
+ </button>
196
+ </Tooltip>
197
+ ) : (
198
+ // Plain text (refactor audit 2026-10-30, DSP-23 a): a `<button disabled>`
199
+ // round it was read out as a dimmed button on every column that cannot
200
+ // be sorted — a control that is not there.
201
+ <span className="text-start">{col.header}</span>
202
+ )}
193
203
  {filter && (
194
204
  <Popover
195
205
  // 420 px at Normal, in rem so the calendar grows with its
@@ -74,7 +74,7 @@ export function StackedFields<T>({
74
74
  compact,
75
75
  liftOwnClicks = false,
76
76
  }: {
77
- columns: DataTableColumn<T>[];
77
+ columns: readonly DataTableColumn<T>[];
78
78
  row: T;
79
79
  compact: boolean;
80
80
  /** On a stretched card (0.50 K4): lift the own-click fields above its title link. */
@@ -137,7 +137,7 @@ export const MOBILE_CARD_FIELDS = 3;
137
137
  * fields and the marks leave it on the card; only `mobileHidden` / `mobile: "hidden"`
138
138
  * (which keep it out of `columns`) remove it.
139
139
  */
140
- export function mobileCardColumns<T>(columns: DataTableColumn<T>[]): {
140
+ export function mobileCardColumns<T>(columns: readonly DataTableColumn<T>[]): {
141
141
  primary: DataTableColumn<T> | null;
142
142
  status: DataTableColumn<T>[];
143
143
  fields: DataTableColumn<T>[];
@@ -181,7 +181,11 @@ function devWarnings(): boolean {
181
181
  * (the table's `storageKey` or `urlSync` prefix) says which table, else its title
182
182
  * column does.
183
183
  */
184
- export function useCardColumnWarnings<T>(columns: DataTableColumn<T>[], enabled: boolean, name?: string): void {
184
+ export function useCardColumnWarnings<T>(
185
+ columns: readonly DataTableColumn<T>[],
186
+ enabled: boolean,
187
+ name?: string,
188
+ ): void {
185
189
  const warned = useRef<Set<string> | null>(null);
186
190
  useEffect(() => {
187
191
  if (!enabled || !devWarnings()) return;
@@ -220,7 +224,10 @@ export function isEmptyCell(value: ReactNode): boolean {
220
224
  }
221
225
 
222
226
  /** Each column's rendered cell, without the empty ones. */
223
- function filledFields<T>(columns: DataTableColumn<T>[], row: T): { col: DataTableColumn<T>; value: ReactNode }[] {
227
+ function filledFields<T>(
228
+ columns: readonly DataTableColumn<T>[],
229
+ row: T,
230
+ ): { col: DataTableColumn<T>; value: ReactNode }[] {
224
231
  return columns.map((col) => ({ col, value: col.cell(row) })).filter(({ value }) => !isEmptyCell(value));
225
232
  }
226
233
 
@@ -261,8 +268,8 @@ export function MobileSort<T>({
261
268
  onPick,
262
269
  onFlip,
263
270
  }: {
264
- columns: DataTableColumn<T>[];
265
- sorts: SortState[];
271
+ columns: readonly DataTableColumn<T>[];
272
+ sorts: readonly SortState[];
266
273
  sortCycle: SortCycle;
267
274
  compact: boolean;
268
275
  labels: DataTableLabels;
@@ -357,6 +364,11 @@ export interface MobileRowProps<T> {
357
364
  large: boolean;
358
365
  /** Phone selection (0.40, keksdose live #421); null without DataTable's `selection`. */
359
366
  select: MobileRowSelect | null;
367
+ /** The card's place in the list, on its `<li>` — where the table finds the card that
368
+ * takes the focus when a focused one leaves (refactor audit 2026-10-30, DSP-4). */
369
+ rowIndex?: number;
370
+ /** The focus came into the card, or into anything it opened (a portal included). */
371
+ onFocusIn?: () => void;
360
372
  }
361
373
 
362
374
  /** A phone card's part in DataTable's `selection` (0.40, keksdose live #421). */
@@ -395,6 +407,8 @@ export function MobileRow<T>({
395
407
  compact,
396
408
  large,
397
409
  select,
410
+ rowIndex,
411
+ onFocusIn,
398
412
  }: MobileRowProps<T>) {
399
413
  const expanded = isExpanded?.(row) ?? false;
400
414
  // Selection mode (#421): the whole card is the row's checkbox — a tap toggles it
@@ -411,6 +425,11 @@ export function MobileRow<T>({
411
425
  // contain their own interactive controls (status toggles, action
412
426
  // icons) don't end up as illegal nested buttons.
413
427
  const interactive = !!onRowClick;
428
+ // `rowHref` without `onRowClick` (refactor audit 2026-10-30, DSP-23 b): nothing opens the
429
+ // row in place, so the card — or its stretched title — is a link that is followed. It
430
+ // was neither, and the phone had no way into the row at all.
431
+ const rowUrl = rowHref?.(row);
432
+ const linkOnly = !interactive && rowUrl !== undefined;
414
433
  // Say that the card OPENS something (Keksdose feedback #163). A phone card had
415
434
  // only a cursor and a tap-tint to advertise its editor — on the invoice review
416
435
  // screen, whose entire purpose is correcting mis-read lines, that read as "these
@@ -428,8 +447,10 @@ export function MobileRow<T>({
428
447
  const swipeEnabled = !!swipe && !selecting;
429
448
  // The stretched card (0.50 K4): the title is the control, the card a plain box.
430
449
  // Selection mode keeps its own card (the whole card is the toggle there).
431
- const stretched = mobileCardStretched && interactive && !selecting && !mobileCard && !!mobilePrimaryCol;
432
- const href = mobileCardLinkable || stretched ? rowHref?.(row) : undefined;
450
+ const stretched = mobileCardStretched && (interactive || linkOnly) && !selecting && !mobileCard && !!mobilePrimaryCol;
451
+ const href = mobileCardLinkable || stretched ? rowUrl : undefined;
452
+ // The card opens something on a tap: the row (`onRowClick`), or its link.
453
+ const opens = interactive || (linkOnly && href !== undefined);
433
454
  const cardClass = cn(
434
455
  "w-full text-start flex items-center",
435
456
  // §4: more room per row at Large — a taller row is a bigger tap target too.
@@ -441,7 +462,7 @@ export function MobileRow<T>({
441
462
  // on every row of a long list, so anything larger becomes the list's personality
442
463
  // rather than feedback. `transition-transform` alone, so the existing background
443
464
  // flip stays instant.
444
- interactive &&
465
+ opens &&
445
466
  "cursor-pointer transition-transform duration-100 active:scale-[0.995] active:bg-active motion-reduce:transition-none motion-reduce:active:scale-100",
446
467
  // The keyboard's frame drawn INSIDE the card, as the desktop row's is (keksdose live
447
468
  // #394): the browser's own ring and tap highlight sit on the card's outer edge, and
@@ -449,7 +470,7 @@ export function MobileRow<T>({
449
470
  // AppShell main's `overflow-x-clip` — so the frame went missing on one side. A press
450
471
  // keeps the fill and the squeeze above; an outline on every tap of a long list would
451
472
  // be louder than the acknowledgement it replaces.
452
- (interactive || selecting) &&
473
+ (opens || selecting) &&
453
474
  !stretched &&
454
475
  cn("[-webkit-tap-highlight-color:transparent] focus-visible:ring-inset", FOCUS_RING),
455
476
  // A stretched card (0.50 K4) draws the same frame, inside the card, while its TITLE
@@ -485,15 +506,20 @@ export function MobileRow<T>({
485
506
  href={href}
486
507
  data-card-link=""
487
508
  data-row-link=""
488
- onActivate={() => onRowClick!(row)}
489
- aria-expanded={opensRow ? expanded : undefined}
509
+ navigate={linkOnly}
510
+ onActivate={interactive ? () => onRowClick!(row) : undefined}
511
+ aria-expanded={opensRow && interactive ? expanded : undefined}
490
512
  className={stretchedClass}
491
513
  // Enter follows RowLink's own onClick; Space opens the row too, not the list's scroll.
492
- onKeyDown={(e) => {
493
- if (e.key !== " ") return;
494
- e.preventDefault();
495
- onRowClick!(row);
496
- }}
514
+ onKeyDown={
515
+ interactive
516
+ ? (e) => {
517
+ if (e.key !== " ") return;
518
+ e.preventDefault();
519
+ onRowClick!(row);
520
+ }
521
+ : undefined
522
+ }
497
523
  >
498
524
  {title}
499
525
  </RowLink>
@@ -686,25 +712,30 @@ export function MobileRow<T>({
686
712
  <div {...press} data-card-stretched="" className={cardClass}>
687
713
  {cardInner}
688
714
  </div>
689
- ) : interactive && href ? (
715
+ ) : opens && href ? (
690
716
  // A card with a URL of its own is a LINK, not a div wearing role="button"
691
717
  // (feedback #451): the phone's long-press "open in new tab" and a screen
692
718
  // reader's link semantics both come free, and the fake role goes away.
693
719
  <RowLink
694
720
  href={href}
695
721
  {...press}
696
- onActivate={() => onRowClick!(row)}
697
- aria-expanded={opensRow ? expanded : undefined}
722
+ navigate={linkOnly}
723
+ onActivate={interactive ? () => onRowClick!(row) : undefined}
724
+ aria-expanded={opensRow && interactive ? expanded : undefined}
698
725
  className={cardClass}
699
726
  // Enter already activates a link natively, and that routes through
700
727
  // RowLink's own onClick — handling it here too would open the row twice.
701
728
  // Space is the only key left, and only so it opens the row instead of
702
729
  // scrolling the list.
703
- onKeyDown={(e) => {
704
- if (e.key !== " ") return;
705
- e.preventDefault();
706
- onRowClick!(row);
707
- }}
730
+ onKeyDown={
731
+ interactive
732
+ ? (e) => {
733
+ if (e.key !== " ") return;
734
+ e.preventDefault();
735
+ onRowClick!(row);
736
+ }
737
+ : undefined
738
+ }
708
739
  >
709
740
  {cardInner}
710
741
  </RowLink>
@@ -746,9 +777,13 @@ export function MobileRow<T>({
746
777
  </div>
747
778
  );
748
779
  return (
780
+ /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- `onFocus`
781
+ only notes that the focus is in this card (DSP-4); the card inside is the control. */
749
782
  <li
750
783
  className={cn(tint)}
751
784
  {...cleanAttrs(rowAttributes?.(row))}
785
+ data-row-index={rowIndex}
786
+ onFocus={onFocusIn}
752
787
  data-selected={selecting && select!.selected ? "" : undefined}
753
788
  onClickCapture={
754
789
  select
@@ -946,7 +981,7 @@ export function MobileFilters<T>({
946
981
  labels,
947
982
  locale,
948
983
  }: {
949
- columns: DataTableColumn<T>[];
984
+ columns: readonly DataTableColumn<T>[];
950
985
  filters: FilterState;
951
986
  selectOptionsByKey: Record<string, { value: string; label: string }[]>;
952
987
  isServer: boolean;
@@ -53,6 +53,17 @@ const PAGE_WINDOW_LARGE_PHONE = 1;
53
53
  const PAGE_STRIP = "flex min-w-0 max-w-full items-center gap-1";
54
54
  const PAGE_NUMBERS = "flex min-w-0 flex-wrap items-center justify-center gap-1";
55
55
 
56
+ /**
57
+ * The arrows at the ends of the strip are `aria-disabled`, not `disabled` (refactor audit
58
+ * 2026-10-30, DSP-12): Next pressed onto the last page — or Previous onto the first —
59
+ * is still the focused button, and a button that turns `disabled` drops the focus it
60
+ * holds to `<body>`. JumpCalendar's arrows keep the same rule, and the table's
61
+ * `isLoading` pager the same reason (`ServerPagination.isLoading`). Dimmed as before; a
62
+ * press there does nothing.
63
+ */
64
+ const ARROW =
65
+ "rounded hover:bg-hover aria-disabled:cursor-not-allowed aria-disabled:opacity-40 aria-disabled:hover:bg-transparent";
66
+
56
67
  /** Footer for {@link DataTable}: range summary, page-size select, and a
57
68
  * windowed page-number strip (first/last + ±2 around the current page, ±1 on a phone
58
69
  * at Large — see {@link PAGE_WINDOW}). */
@@ -137,9 +148,11 @@ export function Pagination({
137
148
  <div data-slot="page-strip" className={PAGE_STRIP}>
138
149
  <button
139
150
  type="button"
140
- onClick={() => onPage(Math.max(0, page - 1))}
141
- disabled={page === 0}
142
- className={cn("rounded hover:bg-hover disabled:opacity-40", compact ? "p-0.5" : "p-1")}
151
+ onClick={() => {
152
+ if (page > 0) onPage(page - 1);
153
+ }}
154
+ aria-disabled={page === 0 || undefined}
155
+ className={cn(ARROW, compact ? "p-0.5" : "p-1")}
143
156
  aria-label={labels.prevPage}
144
157
  >
145
158
  {/* "Previous" points back along the line — left in LTR, right in RTL. */}
@@ -173,9 +186,11 @@ export function Pagination({
173
186
  </div>
174
187
  <button
175
188
  type="button"
176
- onClick={() => onPage(Math.min(totalPages - 1, page + 1))}
177
- disabled={page >= totalPages - 1}
178
- className={cn("rounded hover:bg-hover disabled:opacity-40", compact ? "p-0.5" : "p-1")}
189
+ onClick={() => {
190
+ if (page < totalPages - 1) onPage(page + 1);
191
+ }}
192
+ aria-disabled={page >= totalPages - 1 || undefined}
193
+ className={cn(ARROW, compact ? "p-0.5" : "p-1")}
179
194
  aria-label={labels.nextPage}
180
195
  >
181
196
  <ChevronRight className={cn("rtl:-scale-x-100", compact ? "size-3.5" : "size-4")} />
@@ -65,7 +65,7 @@ export function useColumnResize<T>({
65
65
  /** The widths React renders the columns at. */
66
66
  widths: Record<string, number>;
67
67
  setWidths: Dispatch<SetStateAction<Record<string, number>>>;
68
- columns: DataTableColumn<T>[];
68
+ columns: readonly DataTableColumn<T>[];
69
69
  hiddenCols: Set<string>;
70
70
  }) {
71
71
  const resizing = useRef<Resize | null>(null);
@@ -171,7 +171,7 @@ export function useRowActionColumn<T>({
171
171
  mobileSwipeActions,
172
172
  desktopSwipeActions,
173
173
  }: {
174
- columns: DataTableColumn<T>[];
174
+ columns: readonly DataTableColumn<T>[];
175
175
  rowActions: DataTableProps<T>["rowActions"];
176
176
  rowActionsHeader?: DataTableProps<T>["rowActionsHeader"];
177
177
  rowName: DataTableProps<T>["rowName"];
@@ -180,7 +180,7 @@ export function useRowActionColumn<T>({
180
180
  mobileSwipeActions?: DataTableProps<T>["mobileSwipeActions"];
181
181
  desktopSwipeActions?: DataTableProps<T>["desktopSwipeActions"];
182
182
  }): {
183
- columns: DataTableColumn<T>[];
183
+ columns: readonly DataTableColumn<T>[];
184
184
  swipesFromActions: (row: T) => MobileSwipeActions | null;
185
185
  } {
186
186
  const rowActionsFor = useCallback(
@@ -242,7 +242,7 @@ export function useRowActionColumn<T>({
242
242
  labels.actions,
243
243
  ],
244
244
  );
245
- const actionColumns = useMemo<DataTableColumn<T>[]>(
245
+ const actionColumns = useMemo<readonly DataTableColumn<T>[]>(
246
246
  () =>
247
247
  rowActions
248
248
  ? [