@eifi1/ui-kit 0.51.6 → 0.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (805) hide show
  1. package/README.md +146 -26
  2. package/dist/account/account-parts.d.ts +10 -8
  3. package/dist/account/account-parts.js +1 -18
  4. package/dist/account/account-parts.js.map +1 -1
  5. package/dist/account/data-export-setting-labels.js +1 -1
  6. package/dist/account/data-export-setting-labels.js.map +1 -1
  7. package/dist/account/delete-account-setting-labels.js +1 -1
  8. package/dist/account/delete-account-setting-labels.js.map +1 -1
  9. package/dist/account/email-change-setting-labels.js +1 -1
  10. package/dist/account/email-change-setting-labels.js.map +1 -1
  11. package/dist/account/passkeys-setting.d.ts +9 -2
  12. package/dist/account/passkeys-setting.js +41 -29
  13. package/dist/account/passkeys-setting.js.map +1 -1
  14. package/dist/account/sessions-setting.d.ts +3 -2
  15. package/dist/account/sessions-setting.js +10 -8
  16. package/dist/account/sessions-setting.js.map +1 -1
  17. package/dist/admin/admin-action-confirm.js +3 -7
  18. package/dist/admin/admin-action-confirm.js.map +1 -1
  19. package/dist/admin/admin-parts.d.ts +6 -3
  20. package/dist/admin/admin-parts.js +6 -21
  21. package/dist/admin/admin-parts.js.map +1 -1
  22. package/dist/admin/mail-test-card-labels.js +1 -1
  23. package/dist/admin/mail-test-card-labels.js.map +1 -1
  24. package/dist/admin/plan-change-labels.d.ts +2 -2
  25. package/dist/admin/plan-change-labels.js +1 -17
  26. package/dist/admin/plan-change-labels.js.map +1 -1
  27. package/dist/admin/plan-change.d.ts +3 -42
  28. package/dist/admin/plan-change.js +1 -1
  29. package/dist/admin/plan-change.js.map +1 -1
  30. package/dist/admin/reviewer-scope-editor.js +3 -3
  31. package/dist/admin/reviewer-scope-editor.js.map +1 -1
  32. package/dist/auth/auth-errors-labels.d.ts +11 -0
  33. package/dist/auth/auth-errors-labels.js +13 -0
  34. package/dist/auth/auth-errors-labels.js.map +1 -0
  35. package/dist/auth/auth-errors.d.ts +7 -23
  36. package/dist/auth/auth-errors.js +2 -15
  37. package/dist/auth/auth-errors.js.map +1 -1
  38. package/dist/auth/complete-name-dialog.d.ts +3 -2
  39. package/dist/auth/complete-name-dialog.js +3 -5
  40. package/dist/auth/complete-name-dialog.js.map +1 -1
  41. package/dist/auth/forgot-password-form-labels.js +1 -1
  42. package/dist/auth/forgot-password-form-labels.js.map +1 -1
  43. package/dist/auth/forgot-password-form.js +7 -2
  44. package/dist/auth/forgot-password-form.js.map +1 -1
  45. package/dist/auth/register-form-labels.js +1 -1
  46. package/dist/auth/register-form-labels.js.map +1 -1
  47. package/dist/auth/reset-password-form-labels.js +1 -1
  48. package/dist/auth/reset-password-form-labels.js.map +1 -1
  49. package/dist/auth/reset-password-form.js +5 -1
  50. package/dist/auth/reset-password-form.js.map +1 -1
  51. package/dist/auth/sign-in-form-labels.js +1 -1
  52. package/dist/auth/sign-in-form-labels.js.map +1 -1
  53. package/dist/auth/status-parts.d.ts +0 -3
  54. package/dist/auth/status-parts.js +0 -4
  55. package/dist/auth/status-parts.js.map +1 -1
  56. package/dist/auth/verify-email-labels.js +1 -1
  57. package/dist/auth/verify-email-labels.js.map +1 -1
  58. package/dist/auth/verify-email.js +7 -2
  59. package/dist/auth/verify-email.js.map +1 -1
  60. package/dist/billing/cancel-request.d.ts +11 -2
  61. package/dist/billing/cancel-request.js +15 -3
  62. package/dist/billing/cancel-request.js.map +1 -1
  63. package/dist/billing/cancel-subscription.d.ts +22 -10
  64. package/dist/billing/cancel-subscription.js +8 -11
  65. package/dist/billing/cancel-subscription.js.map +1 -1
  66. package/dist/billing/dialog-close.d.ts +29 -0
  67. package/dist/billing/dialog-close.js +8 -0
  68. package/dist/billing/dialog-close.js.map +1 -0
  69. package/dist/billing/plan-card.d.ts +14 -4
  70. package/dist/billing/plan-card.js +15 -8
  71. package/dist/billing/plan-card.js.map +1 -1
  72. package/dist/billing/plan-change-labels.d.ts +42 -0
  73. package/dist/billing/plan-change-labels.js +22 -0
  74. package/dist/billing/plan-change-labels.js.map +1 -0
  75. package/dist/billing/plan-switch.d.ts +21 -9
  76. package/dist/billing/plan-switch.js +10 -8
  77. package/dist/billing/plan-switch.js.map +1 -1
  78. package/dist/chart.d.ts +12 -0
  79. package/dist/chart.js +16 -1
  80. package/dist/chart.js.map +1 -1
  81. package/dist/components/account-chips.d.ts +5 -5
  82. package/dist/components/account-chips.js +11 -13
  83. package/dist/components/account-chips.js.map +1 -1
  84. package/dist/components/alert-banner.d.ts +16 -5
  85. package/dist/components/alert-banner.js +46 -1
  86. package/dist/components/alert-banner.js.map +1 -1
  87. package/dist/components/amount-input.d.ts +22 -4
  88. package/dist/components/amount-input.js +3 -3
  89. package/dist/components/amount-input.js.map +1 -1
  90. package/dist/components/autocomplete.js +57 -65
  91. package/dist/components/autocomplete.js.map +1 -1
  92. package/dist/components/bulk-action-bar.d.ts +12 -2
  93. package/dist/components/bulk-action-bar.js +65 -21
  94. package/dist/components/bulk-action-bar.js.map +1 -1
  95. package/dist/components/button-look.d.ts +5 -5
  96. package/dist/components/button-look.js.map +1 -1
  97. package/dist/components/button.d.ts +2 -2
  98. package/dist/components/button.js.map +1 -1
  99. package/dist/components/calculator.d.ts +21 -2
  100. package/dist/components/calculator.js +53 -14
  101. package/dist/components/calculator.js.map +1 -1
  102. package/dist/components/chart-edge.d.ts +16 -0
  103. package/dist/components/chart-edge.js +14 -1
  104. package/dist/components/chart-edge.js.map +1 -1
  105. package/dist/components/chart-figure.d.ts +13 -0
  106. package/dist/components/chart-figure.js +15 -0
  107. package/dist/components/chart-figure.js.map +1 -0
  108. package/dist/components/chart-zoom-core.js +1 -4
  109. package/dist/components/chart-zoom-core.js.map +1 -1
  110. package/dist/components/chart.d.ts +8 -1
  111. package/dist/components/chart.js +19 -10
  112. package/dist/components/chart.js.map +1 -1
  113. package/dist/components/combobox-core.d.ts +119 -7
  114. package/dist/components/combobox-core.js +151 -46
  115. package/dist/components/combobox-core.js.map +1 -1
  116. package/dist/components/combobox.d.ts +1 -1
  117. package/dist/components/combobox.js +142 -131
  118. package/dist/components/combobox.js.map +1 -1
  119. package/dist/components/copy-button.d.ts +6 -5
  120. package/dist/components/copy-button.js +5 -3
  121. package/dist/components/copy-button.js.map +1 -1
  122. package/dist/components/country-select.js +2 -2
  123. package/dist/components/country-select.js.map +1 -1
  124. package/dist/components/data-table-column-settings.d.ts +1 -1
  125. package/dist/components/data-table-column-settings.js +33 -7
  126. package/dist/components/data-table-column-settings.js.map +1 -1
  127. package/dist/components/data-table-filters.d.ts +4 -2
  128. package/dist/components/data-table-filters.js +2 -2
  129. package/dist/components/data-table-filters.js.map +1 -1
  130. package/dist/components/data-table-fit.d.ts +6 -4
  131. package/dist/components/data-table-fit.js +4 -1
  132. package/dist/components/data-table-fit.js.map +1 -1
  133. package/dist/components/data-table-groups.d.ts +1 -1
  134. package/dist/components/data-table-groups.js.map +1 -1
  135. package/dist/components/data-table-head.d.ts +1 -1
  136. package/dist/components/data-table-head.js +15 -12
  137. package/dist/components/data-table-head.js.map +1 -1
  138. package/dist/components/data-table-mobile.d.ts +36 -7
  139. package/dist/components/data-table-mobile.js +63 -31
  140. package/dist/components/data-table-mobile.js.map +1 -1
  141. package/dist/components/data-table-pagination.js +11 -6
  142. package/dist/components/data-table-pagination.js.map +1 -1
  143. package/dist/components/data-table-resize.d.ts +1 -1
  144. package/dist/components/data-table-resize.js.map +1 -1
  145. package/dist/components/data-table-row-actions.d.ts +2 -2
  146. package/dist/components/data-table-row-actions.js.map +1 -1
  147. package/dist/components/data-table-row.d.ts +6 -2
  148. package/dist/components/data-table-row.js +17 -10
  149. package/dist/components/data-table-row.js.map +1 -1
  150. package/dist/components/data-table-selection.d.ts +1 -1
  151. package/dist/components/data-table-selection.js.map +1 -1
  152. package/dist/components/data-table-shared.d.ts +10 -2
  153. package/dist/components/data-table-shared.js +18 -0
  154. package/dist/components/data-table-shared.js.map +1 -1
  155. package/dist/components/data-table-sort.d.ts +21 -2
  156. package/dist/components/data-table-sort.js +24 -0
  157. package/dist/components/data-table-sort.js.map +1 -1
  158. package/dist/components/data-table-virtual.d.ts +1 -1
  159. package/dist/components/data-table-virtual.js +18 -6
  160. package/dist/components/data-table-virtual.js.map +1 -1
  161. package/dist/components/data-table.d.ts +25 -8
  162. package/dist/components/data-table.js +154 -25
  163. package/dist/components/data-table.js.map +1 -1
  164. package/dist/components/date-field.d.ts +24 -2
  165. package/dist/components/date-field.js +33 -8
  166. package/dist/components/date-field.js.map +1 -1
  167. package/dist/components/date-picker.d.ts +15 -2
  168. package/dist/components/date-picker.js +55 -26
  169. package/dist/components/date-picker.js.map +1 -1
  170. package/dist/components/date-range-picker.d.ts +47 -20
  171. package/dist/components/date-range-picker.js +23 -7
  172. package/dist/components/date-range-picker.js.map +1 -1
  173. package/dist/components/dialog-frame.d.ts +2 -1
  174. package/dist/components/dialog-frame.js.map +1 -1
  175. package/dist/components/entity-combobox.js +4 -2
  176. package/dist/components/entity-combobox.js.map +1 -1
  177. package/dist/components/error-boundary.js +37 -30
  178. package/dist/components/error-boundary.js.map +1 -1
  179. package/dist/components/{ui-labels.d.ts → field-base-labels.d.ts} +0 -2
  180. package/dist/components/{ui-labels.js → field-base-labels.js} +2 -9
  181. package/dist/components/field-base-labels.js.map +1 -0
  182. package/dist/components/field-base.d.ts +4 -3
  183. package/dist/components/field-base.js +3 -3
  184. package/dist/components/field-base.js.map +1 -1
  185. package/dist/components/field-sync-labels.d.ts +1 -0
  186. package/dist/components/field-sync-labels.js.map +1 -1
  187. package/dist/components/field-sync.d.ts +23 -1
  188. package/dist/components/field-sync.js.map +1 -1
  189. package/dist/components/form-actions.js +11 -5
  190. package/dist/components/form-actions.js.map +1 -1
  191. package/dist/components/hover-menu.d.ts +3 -0
  192. package/dist/components/hover-menu.js +5 -3
  193. package/dist/components/hover-menu.js.map +1 -1
  194. package/dist/components/icon-button.js +14 -9
  195. package/dist/components/icon-button.js.map +1 -1
  196. package/dist/components/inline-confirm.d.ts +43 -0
  197. package/dist/components/inline-confirm.js +67 -0
  198. package/dist/components/inline-confirm.js.map +1 -0
  199. package/dist/components/inline-entity-combobox.d.ts +4 -3
  200. package/dist/components/inline-entity-combobox.js +150 -141
  201. package/dist/components/inline-entity-combobox.js.map +1 -1
  202. package/dist/components/input.js +1 -1
  203. package/dist/components/input.js.map +1 -1
  204. package/dist/components/jump-calendar.js +28 -112
  205. package/dist/components/jump-calendar.js.map +1 -1
  206. package/dist/components/legal-page.d.ts +3 -1
  207. package/dist/components/legal-page.js +3 -2
  208. package/dist/components/legal-page.js.map +1 -1
  209. package/dist/components/legal.d.ts +4 -2
  210. package/dist/components/legal.js.map +1 -1
  211. package/dist/components/lightbox.d.ts +2 -2
  212. package/dist/components/lightbox.js +17 -6
  213. package/dist/components/lightbox.js.map +1 -1
  214. package/dist/components/list.d.ts +6 -2
  215. package/dist/components/list.js +4 -3
  216. package/dist/components/list.js.map +1 -1
  217. package/dist/components/measured-grid.d.ts +1 -1
  218. package/dist/components/measured-grid.js +2 -1
  219. package/dist/components/measured-grid.js.map +1 -1
  220. package/dist/components/mini-calendar.js +3 -5
  221. package/dist/components/mini-calendar.js.map +1 -1
  222. package/dist/components/modal.d.ts +24 -0
  223. package/dist/components/modal.js +12 -4
  224. package/dist/components/modal.js.map +1 -1
  225. package/dist/components/money-draft.js +7 -5
  226. package/dist/components/money-draft.js.map +1 -1
  227. package/dist/components/money-field.d.ts +2 -2
  228. package/dist/components/money-field.js.map +1 -1
  229. package/dist/components/month-grid.d.ts +55 -0
  230. package/dist/components/month-grid.js +148 -0
  231. package/dist/components/month-grid.js.map +1 -0
  232. package/dist/components/month-picker.d.ts +36 -4
  233. package/dist/components/month-picker.js +123 -146
  234. package/dist/components/month-picker.js.map +1 -1
  235. package/dist/components/multi-entity-combobox.js +2 -1
  236. package/dist/components/multi-entity-combobox.js.map +1 -1
  237. package/dist/components/multi-select.d.ts +2 -2
  238. package/dist/components/multi-select.js +11 -6
  239. package/dist/components/multi-select.js.map +1 -1
  240. package/dist/components/number-field.d.ts +6 -4
  241. package/dist/components/number-field.js +3 -2
  242. package/dist/components/number-field.js.map +1 -1
  243. package/dist/components/number-input.d.ts +4 -1
  244. package/dist/components/number-input.js +3 -2
  245. package/dist/components/number-input.js.map +1 -1
  246. package/dist/components/numpad-sheet.js.map +1 -1
  247. package/dist/components/picker-sheet.js +2 -1
  248. package/dist/components/picker-sheet.js.map +1 -1
  249. package/dist/components/pie-chart-labels.d.ts +7 -0
  250. package/dist/components/pie-chart-labels.js +1 -0
  251. package/dist/components/pie-chart-labels.js.map +1 -1
  252. package/dist/components/pie-chart.d.ts +5 -3
  253. package/dist/components/pie-chart.js +7 -22
  254. package/dist/components/pie-chart.js.map +1 -1
  255. package/dist/components/popover.d.ts +3 -0
  256. package/dist/components/popover.js +7 -1
  257. package/dist/components/popover.js.map +1 -1
  258. package/dist/components/reauth-dialog.d.ts +4 -5
  259. package/dist/components/reauth-dialog.js +1 -4
  260. package/dist/components/reauth-dialog.js.map +1 -1
  261. package/dist/components/row-actions.js +2 -1
  262. package/dist/components/row-actions.js.map +1 -1
  263. package/dist/components/section-nav.d.ts +7 -0
  264. package/dist/components/section-nav.js.map +1 -1
  265. package/dist/components/series-chart-axes.d.ts +10 -3
  266. package/dist/components/series-chart-axes.js +1 -0
  267. package/dist/components/series-chart-axes.js.map +1 -1
  268. package/dist/components/series-chart-labels.d.ts +7 -4
  269. package/dist/components/series-chart-labels.js.map +1 -1
  270. package/dist/components/series-chart.d.ts +31 -7
  271. package/dist/components/series-chart.js +72 -29
  272. package/dist/components/series-chart.js.map +1 -1
  273. package/dist/components/share-card.js +3 -3
  274. package/dist/components/share-card.js.map +1 -1
  275. package/dist/components/sign-chip-labels.d.ts +1 -0
  276. package/dist/components/sign-chip-labels.js.map +1 -1
  277. package/dist/components/sign-chip.d.ts +10 -1
  278. package/dist/components/sign-chip.js.map +1 -1
  279. package/dist/components/tabs-labels.d.ts +2 -0
  280. package/dist/components/tabs-labels.js +11 -0
  281. package/dist/components/tabs-labels.js.map +1 -0
  282. package/dist/components/tabs.d.ts +1 -1
  283. package/dist/components/tabs.js +13 -11
  284. package/dist/components/tabs.js.map +1 -1
  285. package/dist/components/toggle-legend.d.ts +2 -2
  286. package/dist/components/toggle-legend.js +6 -6
  287. package/dist/components/toggle-legend.js.map +1 -1
  288. package/dist/components/translation-review-editor.d.ts +4 -2
  289. package/dist/components/translation-review-editor.js +2 -3
  290. package/dist/components/translation-review-editor.js.map +1 -1
  291. package/dist/components/translation-review.d.ts +2 -1
  292. package/dist/components/translation-review.js +2 -2
  293. package/dist/components/translation-review.js.map +1 -1
  294. package/dist/components/treemap-labels.d.ts +26 -0
  295. package/dist/components/treemap-labels.js +10 -0
  296. package/dist/components/treemap-labels.js.map +1 -0
  297. package/dist/components/treemap-layout.d.ts +62 -0
  298. package/dist/components/treemap-layout.js +126 -0
  299. package/dist/components/treemap-layout.js.map +1 -0
  300. package/dist/components/treemap.d.ts +140 -17
  301. package/dist/components/treemap.js +324 -97
  302. package/dist/components/treemap.js.map +1 -1
  303. package/dist/components/use-table-state.d.ts +5 -5
  304. package/dist/components/use-table-state.js +4 -1
  305. package/dist/components/use-table-state.js.map +1 -1
  306. package/dist/data-table.d.ts +6 -2
  307. package/dist/data-table.js +7 -2
  308. package/dist/data-table.js.map +1 -1
  309. package/dist/eslint/index.js +1 -1
  310. package/dist/eslint/role-utilities.d.ts +36 -7
  311. package/dist/eslint/role-utilities.js +42 -9
  312. package/dist/eslint/role-utilities.js.map +1 -1
  313. package/dist/feedback/feedback-dialog.d.ts +25 -16
  314. package/dist/feedback/feedback-dialog.js +6 -2
  315. package/dist/feedback/feedback-dialog.js.map +1 -1
  316. package/dist/feedback/feedback-mutation.d.ts +30 -0
  317. package/dist/feedback/feedback-mutation.js +16 -0
  318. package/dist/feedback/feedback-mutation.js.map +1 -0
  319. package/dist/feedback/feedback-page-link.d.ts +53 -0
  320. package/dist/feedback/feedback-page-link.js +37 -0
  321. package/dist/feedback/feedback-page-link.js.map +1 -0
  322. package/dist/feedback/feedback-public-list.d.ts +12 -3
  323. package/dist/feedback/feedback-public-list.js +2 -1
  324. package/dist/feedback/feedback-public-list.js.map +1 -1
  325. package/dist/feedback/feedback-replies.d.ts +3 -1
  326. package/dist/feedback/feedback-replies.js +5 -4
  327. package/dist/feedback/feedback-replies.js.map +1 -1
  328. package/dist/feedback/feedback-row-detail-labels.js +5 -0
  329. package/dist/feedback/feedback-row-detail-labels.js.map +1 -1
  330. package/dist/feedback/feedback-row-detail.d.ts +64 -28
  331. package/dist/feedback/feedback-row-detail.js +30 -28
  332. package/dist/feedback/feedback-row-detail.js.map +1 -1
  333. package/dist/feedback/feedback-status-undo.d.ts +30 -11
  334. package/dist/feedback/feedback-status-undo.js +10 -15
  335. package/dist/feedback/feedback-status-undo.js.map +1 -1
  336. package/dist/feedback/feedback-submit-dialog.d.ts +1 -1
  337. package/dist/feedback/feedback-submit-dialog.js +1 -1
  338. package/dist/feedback/feedback-submit-dialog.js.map +1 -1
  339. package/dist/feedback/feedback-submit.js +9 -3
  340. package/dist/feedback/feedback-submit.js.map +1 -1
  341. package/dist/feedback/feedback-swipe.d.ts +1 -1
  342. package/dist/feedback/feedback-swipe.js.map +1 -1
  343. package/dist/feedback/feedback-table.d.ts +21 -9
  344. package/dist/feedback/feedback-table.js +45 -25
  345. package/dist/feedback/feedback-table.js.map +1 -1
  346. package/dist/feedback/feedback-thread-labels.d.ts +2 -2
  347. package/dist/feedback/feedback-thread-labels.js.map +1 -1
  348. package/dist/feedback/feedback-thread.d.ts +24 -23
  349. package/dist/feedback/feedback-thread.js +2 -1
  350. package/dist/feedback/feedback-thread.js.map +1 -1
  351. package/dist/feedback.d.ts +34 -0
  352. package/dist/feedback.js +42 -0
  353. package/dist/feedback.js.map +1 -1
  354. package/dist/hooks/use-dismiss.js.map +1 -1
  355. package/dist/hooks/use-focus-trap.d.ts +35 -0
  356. package/dist/hooks/use-focus-trap.js +6 -4
  357. package/dist/hooks/use-focus-trap.js.map +1 -1
  358. package/dist/hooks/use-hotkey.d.ts +5 -2
  359. package/dist/hooks/use-hotkey.js +5 -4
  360. package/dist/hooks/use-hotkey.js.map +1 -1
  361. package/dist/hooks/use-long-press.d.ts +7 -4
  362. package/dist/hooks/use-long-press.js +3 -0
  363. package/dist/hooks/use-long-press.js.map +1 -1
  364. package/dist/hooks/use-media-query.js +12 -4
  365. package/dist/hooks/use-media-query.js.map +1 -1
  366. package/dist/hooks/use-mounted.d.ts +22 -0
  367. package/dist/hooks/use-mounted.js +24 -0
  368. package/dist/hooks/use-mounted.js.map +1 -0
  369. package/dist/hooks/use-overlay-history.d.ts +7 -1
  370. package/dist/hooks/use-overlay-history.js +35 -5
  371. package/dist/hooks/use-overlay-history.js.map +1 -1
  372. package/dist/i18n/defaults.js +4 -5
  373. package/dist/i18n/defaults.js.map +1 -1
  374. package/dist/i18n/german.js +7 -1
  375. package/dist/i18n/german.js.map +1 -1
  376. package/dist/i18n/kit-labels.d.ts +9 -2
  377. package/dist/i18n/kit-labels.js.map +1 -1
  378. package/dist/i18n/locales/en.js +20 -41
  379. package/dist/i18n/locales/en.js.map +3 -3
  380. package/dist/i18n/locales/es.js +7 -1
  381. package/dist/i18n/locales/es.js.map +1 -1
  382. package/dist/i18n/locales/fr.js +20 -10
  383. package/dist/i18n/locales/fr.js.map +1 -1
  384. package/dist/i18n/locales/hu.js +9 -1
  385. package/dist/i18n/locales/hu.js.map +1 -1
  386. package/dist/i18n/locales/it.js +7 -1
  387. package/dist/i18n/locales/it.js.map +1 -1
  388. package/dist/i18n/locales/zh.js +8 -1
  389. package/dist/i18n/locales/zh.js.map +1 -1
  390. package/dist/i18n/review.js +5 -0
  391. package/dist/i18n/review.js.map +1 -1
  392. package/dist/index.d.ts +64 -17
  393. package/dist/index.js +77 -12
  394. package/dist/index.js.map +1 -1
  395. package/dist/landing/routing.d.ts +3 -1
  396. package/dist/landing/routing.js +4 -7
  397. package/dist/landing/routing.js.map +1 -1
  398. package/dist/lib/broadcast.d.ts +17 -0
  399. package/dist/lib/broadcast.js +30 -0
  400. package/dist/lib/broadcast.js.map +1 -0
  401. package/dist/lib/calc.d.ts +7 -1
  402. package/dist/lib/calc.js +3 -1
  403. package/dist/lib/calc.js.map +1 -1
  404. package/dist/lib/clipboard-minus.d.ts +2 -2
  405. package/dist/lib/clipboard-minus.js +1 -1
  406. package/dist/lib/clipboard-minus.js.map +1 -1
  407. package/dist/lib/date-format.d.ts +37 -2
  408. package/dist/lib/date-format.js +34 -8
  409. package/dist/lib/date-format.js.map +1 -1
  410. package/dist/lib/day-format.d.ts +46 -0
  411. package/dist/lib/day-format.js +46 -0
  412. package/dist/lib/day-format.js.map +1 -0
  413. package/dist/lib/decimal-marks.d.ts +7 -1
  414. package/dist/lib/decimal-marks.js +5 -2
  415. package/dist/lib/decimal-marks.js.map +1 -1
  416. package/dist/lib/describe-failure.d.ts +14 -0
  417. package/dist/lib/describe-failure.js +9 -0
  418. package/dist/lib/describe-failure.js.map +1 -0
  419. package/dist/lib/direction.d.ts +16 -0
  420. package/dist/lib/direction.js +9 -1
  421. package/dist/lib/direction.js.map +1 -1
  422. package/dist/lib/focus-left.d.ts +63 -0
  423. package/dist/lib/focus-left.js +67 -0
  424. package/dist/lib/focus-left.js.map +1 -0
  425. package/dist/lib/format.d.ts +5 -3
  426. package/dist/lib/format.js +16 -13
  427. package/dist/lib/format.js.map +1 -1
  428. package/dist/lib/http-status.d.ts +24 -0
  429. package/dist/lib/http-status.js +14 -0
  430. package/dist/lib/http-status.js.map +1 -0
  431. package/dist/lib/intl-cache.d.ts +14 -0
  432. package/dist/lib/intl-cache.js +15 -0
  433. package/dist/lib/intl-cache.js.map +1 -0
  434. package/dist/lib/isin.d.ts +10 -0
  435. package/dist/lib/isin.js.map +1 -1
  436. package/dist/lib/iso-day.d.ts +11 -0
  437. package/dist/lib/iso-day.js +8 -0
  438. package/dist/lib/iso-day.js.map +1 -0
  439. package/dist/lib/lazy-with-fallback.d.ts +31 -0
  440. package/dist/lib/lazy-with-fallback.js +40 -0
  441. package/dist/lib/lazy-with-fallback.js.map +1 -0
  442. package/dist/lib/path-pattern.d.ts +34 -0
  443. package/dist/lib/path-pattern.js +24 -0
  444. package/dist/lib/path-pattern.js.map +1 -0
  445. package/dist/lib/reduced-motion.d.ts +2 -1
  446. package/dist/lib/reduced-motion.js.map +1 -1
  447. package/dist/lib/round.d.ts +2 -1
  448. package/dist/lib/round.js +2 -1
  449. package/dist/lib/round.js.map +1 -1
  450. package/dist/lib/safe-storage.d.ts +24 -5
  451. package/dist/lib/safe-storage.js +27 -2
  452. package/dist/lib/safe-storage.js.map +1 -1
  453. package/dist/lib/session-refresh.js +1 -1
  454. package/dist/lib/session-refresh.js.map +1 -1
  455. package/dist/lib/share-format.d.ts +13 -0
  456. package/dist/lib/share-format.js +10 -0
  457. package/dist/lib/share-format.js.map +1 -0
  458. package/dist/lib/text-case.d.ts +17 -0
  459. package/dist/lib/text-case.js +8 -0
  460. package/dist/lib/text-case.js.map +1 -0
  461. package/dist/lib/text-match.d.ts +38 -0
  462. package/dist/lib/text-match.js +24 -2
  463. package/dist/lib/text-match.js.map +1 -1
  464. package/dist/lib/thenable.d.ts +13 -0
  465. package/dist/lib/thenable.js +8 -0
  466. package/dist/lib/thenable.js.map +1 -0
  467. package/dist/lib/translation-review.d.ts +7 -2
  468. package/dist/lib/translation-review.js +4 -4
  469. package/dist/lib/translation-review.js.map +1 -1
  470. package/dist/notifications/device-zone-report.js +1 -1
  471. package/dist/notifications/device-zone-report.js.map +1 -1
  472. package/dist/notifications/notification-bell.d.ts +2 -1
  473. package/dist/notifications/notification-bell.js +3 -3
  474. package/dist/notifications/notification-bell.js.map +1 -1
  475. package/dist/notifications/notification-inbox.d.ts +10 -6
  476. package/dist/notifications/notification-inbox.js +26 -48
  477. package/dist/notifications/notification-inbox.js.map +1 -1
  478. package/dist/notifications/notification-parts.d.ts +3 -2
  479. package/dist/notifications/notification-parts.js +1 -3
  480. package/dist/notifications/notification-parts.js.map +1 -1
  481. package/dist/notifications/notification-types-setting.js +1 -1
  482. package/dist/notifications/notification-types-setting.js.map +1 -1
  483. package/dist/notifications/notifications-labels.d.ts +6 -0
  484. package/dist/notifications/notifications-labels.js +1 -0
  485. package/dist/notifications/notifications-labels.js.map +1 -1
  486. package/dist/notifications/push-device-setting.js +1 -1
  487. package/dist/notifications/push-device-setting.js.map +1 -1
  488. package/dist/notifications/push-devices-setting.d.ts +2 -1
  489. package/dist/notifications/push-devices-setting.js +27 -49
  490. package/dist/notifications/push-devices-setting.js.map +1 -1
  491. package/dist/notifications/quiet-hours-setting.d.ts +10 -3
  492. package/dist/notifications/quiet-hours-setting.js +65 -26
  493. package/dist/notifications/quiet-hours-setting.js.map +1 -1
  494. package/dist/notifications/unsubscribe-panel.js +4 -7
  495. package/dist/notifications/unsubscribe-panel.js.map +1 -1
  496. package/dist/notifications/use-push-device.d.ts +39 -1
  497. package/dist/notifications/use-push-device.js +28 -7
  498. package/dist/notifications/use-push-device.js.map +1 -1
  499. package/dist/offline/query-persistence.d.ts +3 -1
  500. package/dist/offline/query-persistence.js +19 -2
  501. package/dist/offline/query-persistence.js.map +1 -1
  502. package/dist/rhf/fields.d.ts +11 -4
  503. package/dist/rhf/fields.js.map +1 -1
  504. package/dist/search/command-palette.js +1 -1
  505. package/dist/search/command-palette.js.map +1 -1
  506. package/dist/search/global-search.js +19 -9
  507. package/dist/search/global-search.js.map +1 -1
  508. package/dist/search/use-command-key.d.ts +12 -1
  509. package/dist/search/use-command-key.js +3 -12
  510. package/dist/search/use-command-key.js.map +1 -1
  511. package/dist/search.d.ts +7 -0
  512. package/dist/search.js +10 -0
  513. package/dist/search.js.map +1 -1
  514. package/dist/settings/use-settings-focus.js +1 -0
  515. package/dist/settings/use-settings-focus.js.map +1 -1
  516. package/dist/shell/account-menu-language.d.ts +21 -5
  517. package/dist/shell/account-menu-language.js +3 -1
  518. package/dist/shell/account-menu-language.js.map +1 -1
  519. package/dist/shell/account-menu-text-size.d.ts +26 -9
  520. package/dist/shell/account-menu-text-size.js +3 -2
  521. package/dist/shell/account-menu-text-size.js.map +1 -1
  522. package/dist/shell/dev-menu.js +5 -18
  523. package/dist/shell/dev-menu.js.map +1 -1
  524. package/dist/shell/role-switcher.d.ts +7 -0
  525. package/dist/shell/role-switcher.js.map +1 -1
  526. package/dist/shell/top-bar-actions.d.ts +1 -1
  527. package/dist/shell/top-bar-actions.js.map +1 -1
  528. package/dist/shell/top-bar-parts-labels.d.ts +0 -2
  529. package/dist/shell/top-bar-parts-labels.js +0 -1
  530. package/dist/shell/top-bar-parts-labels.js.map +1 -1
  531. package/dist/shell.d.ts +27 -8
  532. package/dist/shell.js +28 -7
  533. package/dist/shell.js.map +1 -1
  534. package/dist/sync/engine.d.ts +30 -4
  535. package/dist/sync/engine.js +172 -52
  536. package/dist/sync/engine.js.map +1 -1
  537. package/dist/sync.d.ts +6 -2
  538. package/dist/sync.js +6 -1
  539. package/dist/sync.js.map +1 -1
  540. package/dist/testing/css-variables.js +3 -8
  541. package/dist/testing/css-variables.js.map +1 -1
  542. package/dist/theme/contrast.d.ts +2 -1
  543. package/dist/theme/contrast.js +3 -8
  544. package/dist/theme/contrast.js.map +1 -1
  545. package/dist/theme/palette-store.js +6 -6
  546. package/dist/theme/palette-store.js.map +1 -1
  547. package/dist/theme/text-size.js +3 -8
  548. package/dist/theme/text-size.js.map +1 -1
  549. package/dist/theme/theme-store.js +3 -6
  550. package/dist/theme/theme-store.js.map +1 -1
  551. package/dist/tour/tour-catalogue.d.ts +7 -4
  552. package/dist/tour/tour-catalogue.js +12 -10
  553. package/dist/tour/tour-catalogue.js.map +1 -1
  554. package/dist/tour/tour-dock.d.ts +0 -2
  555. package/dist/tour/tour-dock.js +0 -2
  556. package/dist/tour/tour-dock.js.map +1 -1
  557. package/dist/tour/tour-gates.d.ts +4 -0
  558. package/dist/tour/tour-gates.js +14 -0
  559. package/dist/tour/tour-gates.js.map +1 -1
  560. package/dist/tour/tour-overlay.d.ts +27 -0
  561. package/dist/tour/tour-overlay.js +741 -0
  562. package/dist/tour/tour-overlay.js.map +1 -0
  563. package/dist/tour/tour.d.ts +16 -4
  564. package/dist/tour/tour.js +62 -778
  565. package/dist/tour/tour.js.map +1 -1
  566. package/dist/tour/use-tour-progress.js +1 -1
  567. package/dist/tour/use-tour-progress.js.map +1 -1
  568. package/dist/tour/use-tour-url-sync.js +2 -2
  569. package/dist/tour/use-tour-url-sync.js.map +1 -1
  570. package/dist/wizard/stepper-nav.d.ts +5 -1
  571. package/dist/wizard/stepper-nav.js.map +1 -1
  572. package/dist/wizard/types.d.ts +6 -2
  573. package/dist/wizard/types.js.map +1 -1
  574. package/dist/wizard/use-wizard.d.ts +3 -1
  575. package/dist/wizard/use-wizard.js.map +1 -1
  576. package/dist/wizard/validation.d.ts +3 -1
  577. package/dist/wizard/validation.js.map +1 -1
  578. package/package.json +12 -8
  579. package/src/account/account-parts.ts +5 -25
  580. package/src/account/data-export-setting-labels.ts +1 -1
  581. package/src/account/delete-account-setting-labels.ts +1 -1
  582. package/src/account/email-change-setting-labels.ts +1 -1
  583. package/src/account/passkeys-setting.tsx +60 -38
  584. package/src/account/sessions-setting.tsx +18 -12
  585. package/src/admin/admin-action-confirm.tsx +5 -10
  586. package/src/admin/admin-parts.ts +11 -25
  587. package/src/admin/mail-test-card-labels.ts +1 -1
  588. package/src/admin/plan-change-labels.ts +5 -23
  589. package/src/admin/plan-change.tsx +7 -44
  590. package/src/admin/reviewer-scope-editor.tsx +3 -3
  591. package/src/auth/auth-errors-labels.ts +23 -0
  592. package/src/auth/auth-errors.ts +11 -38
  593. package/src/auth/complete-name-dialog.tsx +9 -8
  594. package/src/auth/forgot-password-form-labels.ts +1 -1
  595. package/src/auth/forgot-password-form.tsx +11 -6
  596. package/src/auth/register-form-labels.ts +1 -1
  597. package/src/auth/reset-password-form-labels.ts +1 -1
  598. package/src/auth/reset-password-form.tsx +8 -4
  599. package/src/auth/sign-in-form-labels.ts +1 -1
  600. package/src/auth/status-parts.tsx +0 -6
  601. package/src/auth/verify-email-labels.ts +1 -1
  602. package/src/auth/verify-email.tsx +11 -6
  603. package/src/billing/cancel-request.ts +28 -6
  604. package/src/billing/cancel-subscription.tsx +29 -22
  605. package/src/billing/dialog-close.ts +34 -0
  606. package/src/billing/plan-card.tsx +36 -11
  607. package/src/billing/plan-change-labels.ts +66 -0
  608. package/src/billing/plan-switch.tsx +31 -20
  609. package/src/chart.ts +21 -3
  610. package/src/components/account-chips.tsx +20 -23
  611. package/src/components/alert-banner.tsx +82 -5
  612. package/src/components/amount-input.tsx +32 -14
  613. package/src/components/autocomplete.tsx +64 -70
  614. package/src/components/bulk-action-bar.tsx +70 -2
  615. package/src/components/button-look.ts +5 -5
  616. package/src/components/button.tsx +2 -2
  617. package/src/components/calculator.tsx +98 -17
  618. package/src/components/chart-edge.ts +34 -1
  619. package/src/components/chart-figure.tsx +35 -0
  620. package/src/components/chart-zoom-core.tsx +6 -5
  621. package/src/components/chart.tsx +26 -5
  622. package/src/components/combobox-core.tsx +303 -69
  623. package/src/components/combobox.tsx +184 -155
  624. package/src/components/copy-button.tsx +34 -23
  625. package/src/components/country-select.tsx +16 -11
  626. package/src/components/data-table-column-settings.tsx +52 -10
  627. package/src/components/data-table-filters.ts +6 -4
  628. package/src/components/data-table-fit.ts +19 -5
  629. package/src/components/data-table-groups.tsx +1 -1
  630. package/src/components/data-table-head.tsx +32 -22
  631. package/src/components/data-table-mobile.tsx +110 -27
  632. package/src/components/data-table-pagination.tsx +21 -6
  633. package/src/components/data-table-resize.ts +1 -1
  634. package/src/components/data-table-row-actions.tsx +3 -3
  635. package/src/components/data-table-row.tsx +25 -14
  636. package/src/components/data-table-selection.ts +1 -1
  637. package/src/components/data-table-shared.tsx +33 -1
  638. package/src/components/data-table-sort.ts +57 -2
  639. package/src/components/data-table-virtual.ts +32 -8
  640. package/src/components/data-table.tsx +267 -41
  641. package/src/components/date-field.tsx +65 -8
  642. package/src/components/date-picker.tsx +125 -48
  643. package/src/components/date-range-picker.tsx +82 -31
  644. package/src/components/dialog-frame.tsx +2 -1
  645. package/src/components/entity-combobox.tsx +4 -1
  646. package/src/components/error-boundary.tsx +53 -39
  647. package/src/components/field-base-labels.ts +20 -0
  648. package/src/components/field-base.tsx +13 -7
  649. package/src/components/field-sync-labels.ts +1 -0
  650. package/src/components/field-sync.tsx +23 -1
  651. package/src/components/form-actions.tsx +20 -5
  652. package/src/components/hover-menu.tsx +18 -8
  653. package/src/components/icon-button.tsx +14 -9
  654. package/src/components/inline-confirm.tsx +116 -0
  655. package/src/components/inline-entity-combobox.tsx +198 -152
  656. package/src/components/input.tsx +1 -1
  657. package/src/components/jump-calendar.tsx +30 -146
  658. package/src/components/legal-page.tsx +10 -7
  659. package/src/components/legal.tsx +4 -2
  660. package/src/components/lightbox.tsx +21 -8
  661. package/src/components/list.tsx +14 -5
  662. package/src/components/measured-grid.tsx +8 -4
  663. package/src/components/mini-calendar.tsx +6 -5
  664. package/src/components/modal.tsx +45 -4
  665. package/src/components/money-draft.ts +16 -5
  666. package/src/components/money-field.tsx +2 -2
  667. package/src/components/month-grid.tsx +229 -0
  668. package/src/components/month-picker.tsx +192 -200
  669. package/src/components/multi-entity-combobox.tsx +1 -0
  670. package/src/components/multi-select.tsx +21 -9
  671. package/src/components/number-field.tsx +14 -7
  672. package/src/components/number-input.tsx +9 -3
  673. package/src/components/numpad-sheet.tsx +4 -3
  674. package/src/components/picker-sheet.tsx +12 -9
  675. package/src/components/pie-chart-labels.ts +8 -0
  676. package/src/components/pie-chart.tsx +22 -28
  677. package/src/components/popover.tsx +18 -1
  678. package/src/components/reauth-dialog.tsx +6 -10
  679. package/src/components/row-actions.tsx +2 -1
  680. package/src/components/section-nav.tsx +7 -0
  681. package/src/components/series-chart-axes.ts +11 -3
  682. package/src/components/series-chart-labels.ts +7 -4
  683. package/src/components/series-chart.tsx +178 -69
  684. package/src/components/share-card.tsx +6 -6
  685. package/src/components/sign-chip-labels.ts +1 -0
  686. package/src/components/sign-chip.tsx +10 -1
  687. package/src/components/tabs-labels.ts +13 -0
  688. package/src/components/tabs.tsx +35 -19
  689. package/src/components/toggle-legend.tsx +16 -11
  690. package/src/components/translation-review-editor.tsx +6 -5
  691. package/src/components/translation-review.tsx +4 -3
  692. package/src/components/treemap-labels.ts +39 -0
  693. package/src/components/treemap-layout.ts +210 -0
  694. package/src/components/treemap.tsx +722 -133
  695. package/src/components/use-table-state.ts +12 -9
  696. package/src/data-table.ts +9 -2
  697. package/src/eslint/role-utilities.ts +97 -19
  698. package/src/feedback/feedback-dialog.tsx +30 -19
  699. package/src/feedback/feedback-mutation.ts +41 -0
  700. package/src/feedback/feedback-page-link.ts +90 -0
  701. package/src/feedback/feedback-public-list.tsx +17 -5
  702. package/src/feedback/feedback-replies.tsx +13 -6
  703. package/src/feedback/feedback-row-detail-labels.ts +5 -0
  704. package/src/feedback/feedback-row-detail.tsx +103 -67
  705. package/src/feedback/feedback-status-undo.ts +41 -27
  706. package/src/feedback/feedback-submit-dialog.tsx +2 -2
  707. package/src/feedback/feedback-submit.tsx +21 -7
  708. package/src/feedback/feedback-swipe.tsx +1 -1
  709. package/src/feedback/feedback-table.tsx +86 -38
  710. package/src/feedback/feedback-thread-labels.ts +2 -2
  711. package/src/feedback/feedback-thread.tsx +27 -25
  712. package/src/feedback.ts +42 -0
  713. package/src/hooks/use-dismiss.ts +3 -2
  714. package/src/hooks/use-focus-trap.ts +8 -24
  715. package/src/hooks/use-hotkey.ts +24 -7
  716. package/src/hooks/use-long-press.ts +16 -2
  717. package/src/hooks/use-media-query.ts +20 -4
  718. package/src/hooks/use-mounted.ts +39 -0
  719. package/src/hooks/use-overlay-history.ts +70 -5
  720. package/src/i18n/defaults.ts +4 -5
  721. package/src/i18n/german.ts +8 -2
  722. package/src/i18n/kit-labels.tsx +9 -2
  723. package/src/i18n/locales/es.ts +8 -2
  724. package/src/i18n/locales/fr.ts +21 -13
  725. package/src/i18n/locales/hu.ts +10 -2
  726. package/src/i18n/locales/it.ts +8 -2
  727. package/src/i18n/locales/zh.ts +9 -2
  728. package/src/i18n/review.ts +5 -0
  729. package/src/index.ts +103 -13
  730. package/src/landing/routing.tsx +14 -10
  731. package/src/lib/broadcast.ts +52 -0
  732. package/src/lib/calc.ts +13 -2
  733. package/src/lib/clipboard-minus.ts +14 -4
  734. package/src/lib/date-format.ts +89 -13
  735. package/src/lib/day-format.ts +96 -0
  736. package/src/lib/decimal-marks.ts +12 -3
  737. package/src/lib/describe-failure.ts +18 -0
  738. package/src/lib/direction.ts +39 -0
  739. package/src/lib/focus-left.ts +156 -0
  740. package/src/lib/format.ts +34 -19
  741. package/src/lib/http-status.ts +38 -0
  742. package/src/lib/intl-cache.ts +25 -0
  743. package/src/lib/isin.ts +10 -0
  744. package/src/lib/iso-day.ts +13 -0
  745. package/src/lib/lazy-with-fallback.ts +82 -0
  746. package/src/lib/path-pattern.ts +55 -0
  747. package/src/lib/reduced-motion.ts +2 -1
  748. package/src/lib/round.ts +7 -2
  749. package/src/lib/safe-storage.ts +48 -6
  750. package/src/lib/session-refresh.ts +1 -1
  751. package/src/lib/share-format.ts +18 -0
  752. package/src/lib/text-case.ts +19 -0
  753. package/src/lib/text-match.ts +69 -2
  754. package/src/lib/thenable.ts +19 -0
  755. package/src/lib/translation-review.ts +13 -5
  756. package/src/notifications/device-zone-report.ts +1 -1
  757. package/src/notifications/notification-bell.tsx +7 -4
  758. package/src/notifications/notification-inbox.tsx +40 -58
  759. package/src/notifications/notification-parts.tsx +3 -4
  760. package/src/notifications/notification-types-setting.tsx +1 -1
  761. package/src/notifications/notifications-labels.ts +7 -0
  762. package/src/notifications/push-device-setting.tsx +1 -1
  763. package/src/notifications/push-devices-setting.tsx +30 -55
  764. package/src/notifications/quiet-hours-setting.tsx +93 -31
  765. package/src/notifications/unsubscribe-panel.tsx +4 -7
  766. package/src/notifications/use-push-device.ts +76 -10
  767. package/src/offline/query-persistence.ts +35 -3
  768. package/src/rhf/fields.tsx +11 -4
  769. package/src/search/command-palette.tsx +2 -4
  770. package/src/search/global-search.tsx +36 -15
  771. package/src/search/use-command-key.ts +13 -12
  772. package/src/search.ts +9 -0
  773. package/src/settings/use-settings-focus.ts +3 -0
  774. package/src/shell/account-menu-language.tsx +27 -5
  775. package/src/shell/account-menu-text-size.tsx +32 -10
  776. package/src/shell/dev-menu.tsx +7 -21
  777. package/src/shell/role-switcher.tsx +7 -0
  778. package/src/shell/top-bar-actions.tsx +1 -1
  779. package/src/shell/top-bar-parts-labels.ts +0 -3
  780. package/src/shell.ts +40 -9
  781. package/src/sync/engine.ts +339 -61
  782. package/src/sync.ts +8 -1
  783. package/src/testing/css-variables.ts +8 -9
  784. package/src/theme/contrast.ts +8 -9
  785. package/src/theme/palette-store.ts +9 -9
  786. package/src/theme/text-size.ts +6 -8
  787. package/src/theme/theme-store.ts +7 -9
  788. package/src/tour/tour-catalogue.tsx +26 -15
  789. package/src/tour/tour-dock.ts +0 -2
  790. package/src/tour/tour-gates.ts +23 -0
  791. package/src/tour/tour-overlay.tsx +1170 -0
  792. package/src/tour/tour.tsx +116 -1193
  793. package/src/tour/use-tour-progress.ts +1 -1
  794. package/src/tour/use-tour-url-sync.ts +7 -3
  795. package/src/wizard/stepper-nav.tsx +3 -1
  796. package/src/wizard/types.ts +11 -2
  797. package/src/wizard/use-wizard.ts +2 -1
  798. package/src/wizard/validation.ts +8 -2
  799. package/tokens.css +2 -1
  800. package/dist/components/ui-labels.js.map +0 -1
  801. package/dist/shell/dev-switchers.d.ts +0 -6
  802. package/dist/shell/dev-switchers.js +0 -12
  803. package/dist/shell/dev-switchers.js.map +0 -1
  804. package/src/components/ui-labels.ts +0 -24
  805. package/src/shell/dev-switchers.tsx +0 -18
@@ -1,5 +1,5 @@
1
- import { Fragment, useId, useMemo, useRef, useState } from "react";
2
- import type { ComponentPropsWithoutRef, ReactNode, Ref } from "react";
1
+ import { useId, useMemo, useRef, useState } from "react";
2
+ import type { ComponentPropsWithoutRef, KeyboardEvent, ReactNode, Ref } from "react";
3
3
  import { ChevronDown } from "lucide-react";
4
4
  import { FIELD_BASE, FIELD_FLOATING_PAD, FIELD_INVALID } from "./field-base";
5
5
  import { cn } from "../lib/cn";
@@ -9,9 +9,18 @@ import { isImeEnter } from "../lib/ime";
9
9
  import { isQuietFocus } from "../lib/quiet-focus";
10
10
  import { usePhoneLayout } from "../hooks/use-breakpoint";
11
11
  import { PickerSheet, SHEET_ROW_CLASS } from "./picker-sheet";
12
- import { ComboboxFieldLabel, endHintRowProps, GROUP_HEADING_STICKY, useActiveOptionScroll } from "./combobox-core";
13
- import { useKitLocale } from "../i18n/kit-labels";
14
- import { rankMatch } from "../lib/text-match";
12
+ import {
13
+ anchoredHeadingClass,
14
+ ComboboxFieldLabel,
15
+ endHintRowProps,
16
+ GroupedOptions,
17
+ groupRuns,
18
+ SHEET_HEADING_CLASS,
19
+ useTypedListStatus,
20
+ type GroupRun,
21
+ } from "./combobox-core";
22
+ import { DEFAULT_COMBOBOX_LABELS, useKitLabels, useKitLocale } from "../i18n/kit-labels";
23
+ import { sameName, searchRanked } from "../lib/text-match";
15
24
  import {
16
25
  EndHintRow,
17
26
  FieldCaption,
@@ -44,7 +53,7 @@ export interface ComboboxProps
44
53
  value: string;
45
54
  onChange: (v: string) => void;
46
55
  /** Suggestion pool (e.g. existing payee names). */
47
- options: string[];
56
+ options: readonly string[];
48
57
  /** The visible label, a `<label for>` above the field: a ReactNode, as on every kit
49
58
  * field (a string until 0.34, refactor audit 2026-10, API-9). Without one, name the
50
59
  * field with `aria-label`. */
@@ -223,6 +232,12 @@ export function Combobox(props: ComboboxProps) {
223
232
  const { open, setOpen, wrapperRef, panelRef } = useDropdown({ backCloses: !isPhone, escapeLayer: false });
224
233
  const primaryOnly = usePrimaryPressOnly();
225
234
  const [active, setActive] = useState(-1);
235
+ // A closed list has no row the keyboard is on, however it closed — the sheet's X,
236
+ // Escape or Back, a press outside — adjusted while rendering. The arrows' row outlived
237
+ // it: the list reopens on the whole pool, so the row the arrows had put on "Migros"
238
+ // showed "Aldi" highlighted, and Enter took it over the typed value (0.52 code review,
239
+ // combobox.tsx). An ArrowDown that opens the list sets both at once, and keeps its row.
240
+ if (!open && active !== -1) setActive(-1);
226
241
  // The lock (see `lockedKeyDown`): a lock arriving while the list is up closes it,
227
242
  // adjusted while rendering so no frame offers a row that can no longer be taken.
228
243
  const lock = useLockReason(commit, disabledReason);
@@ -264,6 +279,9 @@ export function Combobox(props: ComboboxProps) {
264
279
  const query = typing ? value.trim() : "";
265
280
  // Folded as every kit list folds (DUP-5): "zurich" finds Zürich, by the locale's case.
266
281
  const locale = useKitLocale();
282
+ // The live status's words (INP-6): the result count and "No results", as the panel
283
+ // pickers say them.
284
+ const labels = useKitLabels("combobox", DEFAULT_COMBOBOX_LABELS);
267
285
  const matches = useMemo(() => {
268
286
  const seen = new Set<string>();
269
287
  const uniq = options.filter((o) => o && !seen.has(o) && seen.add(o));
@@ -272,13 +290,14 @@ export function Combobox(props: ComboboxProps) {
272
290
  if (!query) {
273
291
  ranked = uniq.slice(0, cap);
274
292
  } else {
275
- // The whole name, then prefix matches, then substring matches — most relevant on
276
- // top (`rankMatch`; a stable sort keeps the pool's order within a rank).
277
- ranked = uniq
278
- .map((o) => ({ o, rank: rankMatch(o, query, { locale }) }))
279
- .filter((x) => x.rank >= 0)
293
+ // Every word of the query somewhere in the name (0.51.4's rule, which this list
294
+ // was said to have and did not: refactor audit 2026-10-30, DUP-4), ranked by the
295
+ // WHOLE query — the whole name, then prefix matches, then substring matches, then
296
+ // the names that hold the words apart (`searchRanked`, each name folded once). A
297
+ // stable sort keeps the pool's order within a rank.
298
+ ranked = searchRanked(uniq, query, (o) => [o], { locale })
280
299
  .sort((a, b) => a.rank - b.rank)
281
- .map((x) => x.o)
300
+ .map((x) => x.row)
282
301
  .slice(0, cap);
283
302
  }
284
303
  if (!groupBy) return ranked;
@@ -296,27 +315,22 @@ export function Combobox(props: ComboboxProps) {
296
315
  }, [options, query, groupBy, maxSuggestions, isPhone, locale]);
297
316
 
298
317
  /**
299
- * Which rows OPEN a group, and with what heading — computed once for both lists.
318
+ * The rows cut into their groups — computed once for both lists, each run a
319
+ * `role="group"` its heading names (INP-8). Without `groupBy`, one bare run.
300
320
  *
301
- * The desktop list had this as `matches[i - 1]`, which is free; the sheet had it as
302
- * `matches[matches.indexOf(o) - 1]`, which is a scan of the list per row and another
303
- * per heading test. That is quadratic in the sheet's own cap of 50, on the branch
304
- * that runs on the slowest hardware we ship to — and it answers the wrong question
305
- * besides: `indexOf` finds the FIRST row with that string, so a duplicated option
306
- * would have compared against a neighbour it is not next to. (`matches` de-duplicates
307
- * today; that is a property of the memo above, not of the row being rendered.)
321
+ * The desktop list had the boundaries as `matches[i - 1]`, which is free; the sheet had
322
+ * them as `matches[matches.indexOf(o) - 1]`, which is a scan of the list per row and
323
+ * another per heading test. That is quadratic in the sheet's own cap of 50, on the
324
+ * branch that runs on the slowest hardware we ship to — and it answers the wrong
325
+ * question besides: `indexOf` finds the FIRST row with that string, so a duplicated
326
+ * option would have compared against a neighbour it is not next to. (`matches`
327
+ * de-duplicates today; that is a property of the memo above, not of the row being
328
+ * rendered.)
308
329
  */
309
- const groupHeadings = useMemo(() => {
310
- if (!groupBy) return null;
311
- const heads = new Map<number, string>();
312
- let prev: string | undefined;
313
- matches.forEach((o, i) => {
314
- const group = groupBy(o);
315
- if (group != null && group !== prev) heads.set(i, group);
316
- prev = group;
317
- });
318
- return heads;
319
- }, [matches, groupBy]);
330
+ const runs = useMemo<GroupRun<string>[]>(
331
+ () => (groupBy ? groupRuns(matches, groupBy) : [{ group: null, start: 0, rows: matches }]),
332
+ [matches, groupBy],
333
+ );
320
334
 
321
335
  const take = (v: string) => {
322
336
  if (locked) return;
@@ -328,17 +342,6 @@ export function Combobox(props: ComboboxProps) {
328
342
  setTyping(false);
329
343
  };
330
344
 
331
- // Offered only when the typed text is genuinely NOT in the pool: an exact
332
- // (case-insensitive) match is an existing entry the list is already showing, and a
333
- // second way to pick it would be noise. Compared against `options`, not `matches` —
334
- // `matches` is capped, so a pool of 300 payees would otherwise offer to "add" one
335
- // that exists but fell off the end of the list.
336
- // What the field claims the keyboard is on. Only on a pointer device: the phone
337
- // renders its rows in a {@link PickerSheet} whose own search box owns focus, and a
338
- // field pointing at an id that is not there is worse than one pointing nowhere.
339
- const activeId = !isPhone && active >= 0 && active < matches.length ? optionId(active) : undefined;
340
- useActiveOptionScroll(activeId);
341
-
342
345
  // While locked the field sits in the reason's Tooltip — in a fragment with a hidden
343
346
  // copy of the reason, Button's anatomy; `block` so a full-width field stays full width.
344
347
  const withLock = (box: ReactNode) =>
@@ -350,21 +353,81 @@ export function Combobox(props: ComboboxProps) {
350
353
  box
351
354
  );
352
355
 
356
+ // Offered only when the typed text is genuinely NOT in the pool: an exact match —
357
+ // folded as the list matches, so "cafe" is Café ({@link sameName}, DUP-5 in the
358
+ // 2026-10-30 refactor audit) — is an existing entry the list is already showing, and a
359
+ // second way to pick it would be noise. Compared against `options`, not `matches` —
360
+ // `matches` is capped, so a pool of 300 payees would otherwise offer to "add" one
361
+ // that exists but fell off the end of the list.
353
362
  const typed = value.trim();
354
363
  const createRow =
355
- createLabel && typed.length > 0 && !options.some((o) => o.toLowerCase() === typed.toLowerCase())
356
- ? createLabel(typed)
357
- : null;
364
+ createLabel && typed.length > 0 && !options.some((o) => sameName(o, typed, locale)) ? createLabel(typed) : null;
358
365
 
366
+ // Whether a list shows, the row the keyboard is on — named by the field, or on a phone
367
+ // by the sheet's own search box, which takes the same keys (INP-6, 0.34's BUG-5 for
368
+ // this field) — and the live status: the family's one rule for a typed list.
369
+ const { showing, expanded, activeOption, statusRegion } = useTypedListStatus({
370
+ isPhone,
371
+ open,
372
+ inert,
373
+ rowCount: matches.length,
374
+ extraRow: Boolean(createRow),
375
+ query,
376
+ active: active < matches.length ? active : -1,
377
+ optionId,
378
+ labels,
379
+ });
359
380
  // The list is a layer on the Escape stack while it SHOWS (Wave 2, DUP-1): an Escape
360
381
  // over an empty "open" list is the dialog's, as it always was. On a phone the sheet
361
382
  // is the layer.
362
- const showing = !isPhone && open && !inert && (matches.length > 0 || Boolean(createRow));
363
383
  useDismissLayer(showing, () => {
364
384
  setOpen(false);
365
385
  setActive(-1);
366
386
  });
367
387
 
388
+ /** The list's keys — in the field and, on a phone, in the sheet's search box. Enter
389
+ * with no row highlighted is "I mean what I typed" in both. */
390
+ const listKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
391
+ if (e.key === "ArrowDown") {
392
+ e.preventDefault();
393
+ setOpen(true);
394
+ setActive((i) => Math.min(i + 1, matches.length - 1));
395
+ } else if (e.key === "ArrowUp") {
396
+ e.preventDefault();
397
+ setActive((i) => Math.max(i - 1, 0));
398
+ } else if (e.key === "Enter") {
399
+ // The Enter that confirms an IME composition is the IME's: it picks no row and
400
+ // submits nothing (BUG-9).
401
+ if (isImeEnter(e)) return;
402
+ if (open && active >= 0 && active < matches.length) {
403
+ e.preventDefault();
404
+ take(matches[active]);
405
+ } else {
406
+ // No row highlighted: the typed text is the answer. `preventDefault` only when a
407
+ // caller is taking Enter, so a plain form submit is otherwise left alone.
408
+ if (onSubmit) e.preventDefault();
409
+ setOpen(false);
410
+ onSubmit?.();
411
+ }
412
+ }
413
+ };
414
+
415
+ /** The rows in their runs — each group a `role="group"` its heading names (INP-8) —
416
+ * for the sheet or the anchored list; `row` draws one option, `grouped` when it
417
+ * stands under a heading. `matches` is group-contiguous, so the boundaries are a
418
+ * property of the list rather than of the branch drawing it (see `runs`). */
419
+ const groupedRows = (sheet: boolean, row: (o: string, i: number, grouped: boolean) => ReactNode) => (
420
+ <GroupedOptions
421
+ runs={runs}
422
+ listboxId={listboxId}
423
+ rowKey={(o) => o}
424
+ row={row}
425
+ // The list's first item sits closer to its top edge; the create row comes first
426
+ // when there is one.
427
+ headingClassName={(run) => (sheet ? SHEET_HEADING_CLASS : anchoredHeadingClass(run, !createRow))}
428
+ />
429
+ );
430
+
368
431
  return (
369
432
  // `rest` dresses the outer box — a `data-tour` anchor, a test id. Not the NAME,
370
433
  // description, invalid or required state: those belong on the <input> below,
@@ -401,13 +464,15 @@ export function Combobox(props: ComboboxProps) {
401
464
  // field otherwise (dev#477: a field with neither announces only its text).
402
465
  aria-label={ariaLabel}
403
466
  role="combobox"
404
- aria-expanded={open}
467
+ aria-expanded={expanded}
405
468
  // The list this field is the mouth of. Required by the role, and the half
406
469
  // that was missing: the field said it was expanded and never said what it
407
470
  // had expanded, so a reader had no way from the box to the options
408
471
  // (ESLint's `role-has-required-aria-props`, the audit's §a11y).
409
472
  aria-controls={listboxId}
410
- aria-activedescendant={activeId}
473
+ // Only on a pointer device: on a phone the sheet's own search box holds
474
+ // focus and names the row, and the field behind it says nothing.
475
+ aria-activedescendant={isPhone ? undefined : activeOption}
411
476
  aria-autocomplete="list"
412
477
  aria-invalid={field.isInvalid || undefined}
413
478
  aria-describedby={mergeDescribedBy(field.describedBy, locked && lock.reasonId)}
@@ -431,6 +496,7 @@ export function Combobox(props: ComboboxProps) {
431
496
  if (isQuietFocus(e.currentTarget)) return;
432
497
  setOpen(true);
433
498
  setTyping(false);
499
+ setActive(-1);
434
500
  // The sheet carries its own input, so the field behind it must not also
435
501
  // pull up the keyboard and scroll the page under the dialog.
436
502
  if (isPhone) sheetInputRef.current?.focus();
@@ -443,7 +509,10 @@ export function Combobox(props: ComboboxProps) {
443
509
  onClick={() => {
444
510
  if (locked) return;
445
511
  setOpen(true);
512
+ // The whole pool again, so no row of the typed list is the keyboard's
513
+ // (0.52 code review, combobox.tsx — see `active`).
446
514
  setTyping(false);
515
+ setActive(-1);
447
516
  }}
448
517
  // `inputMode="none"` rather than readOnly: the field must not look
449
518
  // uneditable (FIELD_BASE greys a read-only field since dev#468) and must
@@ -459,29 +528,8 @@ export function Combobox(props: ComboboxProps) {
459
528
  }}
460
529
  onKeyDown={(e) => {
461
530
  if (locked) return lockedKeyDown(e);
462
- if (e.key === "ArrowDown") {
463
- e.preventDefault();
464
- setOpen(true);
465
- setActive((i) => Math.min(i + 1, matches.length - 1));
466
- } else if (e.key === "ArrowUp") {
467
- e.preventDefault();
468
- setActive((i) => Math.max(i - 1, 0));
469
- } else if (e.key === "Enter") {
470
- // The Enter that confirms an IME composition is the IME's: it picks no
471
- // row and submits nothing (BUG-9).
472
- if (isImeEnter(e)) return;
473
- if (open && active >= 0 && active < matches.length) {
474
- e.preventDefault();
475
- take(matches[active]);
476
- } else {
477
- // No row highlighted: the typed text is the answer. `preventDefault`
478
- // only when a caller is taking Enter, so a plain form submit is
479
- // otherwise left alone.
480
- if (onSubmit) e.preventDefault();
481
- setOpen(false);
482
- onSubmit?.();
483
- }
484
- } else if (e.key === "Escape") {
531
+ listKeyDown(e);
532
+ if (e.key === "Escape") {
485
533
  // A list that is SHOWING is the top of the Escape stack, and the key
486
534
  // closes it and stops here: a Modal or FullBleedDialog around the field
487
535
  // otherwise closed with it, form and all (round 0.34 BUG-1). With no
@@ -536,6 +584,8 @@ export function Combobox(props: ComboboxProps) {
536
584
  )}
537
585
  <FieldCaption parts={hintParts} />
538
586
  {field.errorEl}
587
+ {/* The live status — see `useTypedListStatus` for where it goes and why. */}
588
+ {!isPhone && statusRegion}
539
589
  {isPhone && (
540
590
  <PickerSheet
541
591
  open={open && !inert}
@@ -547,11 +597,17 @@ export function Combobox(props: ComboboxProps) {
547
597
  query={value}
548
598
  onQueryChange={(v) => {
549
599
  onChange(v);
600
+ setActive(-1);
550
601
  setTyping(true);
551
602
  }}
552
603
  searchPlaceholder={searchPlaceholder ?? placeholder}
553
604
  inputRef={sheetInputRef}
554
605
  closeLabel={closeLabel}
606
+ // The field's own keys, in the box focus is in while the sheet is up: arrows
607
+ // and Enter there did nothing (INP-6, as BUG-5 gave the panel pickers).
608
+ onSearchKeyDown={listKeyDown}
609
+ listboxId={listboxId}
610
+ activeId={activeOption}
555
611
  >
556
612
  <ul id={listboxId} role="listbox">
557
613
  {createRow && (
@@ -570,37 +626,28 @@ export function Combobox(props: ComboboxProps) {
570
626
  </button>
571
627
  </li>
572
628
  )}
573
- {matches.map((o, i) => {
574
- const group = groupHeadings?.get(i);
575
- return (
576
- <Fragment key={o}>
577
- {group !== undefined && (
578
- <li
579
- role="presentation"
580
- className={cn(
581
- GROUP_HEADING_STICKY,
582
- "px-4 pb-0.5 pt-3 text-caption font-semibold uppercase tracking-wide text-muted",
583
- )}
584
- >
585
- {group}
586
- </li>
629
+ {groupedRows(true, (o, i) => (
630
+ <li role="presentation">
631
+ <button
632
+ type="button"
633
+ id={optionId(i)}
634
+ role="option"
635
+ aria-selected={o === value}
636
+ onClick={() => take(o)}
637
+ className={cn(
638
+ SHEET_ROW_CLASS,
639
+ // The row the sheet's arrows are on.
640
+ i === active && "bg-active",
641
+ optionAdornment && "flex items-center justify-between gap-2",
587
642
  )}
588
- <li role="presentation">
589
- <button
590
- type="button"
591
- role="option"
592
- aria-selected={o === value}
593
- onClick={() => take(o)}
594
- className={cn(SHEET_ROW_CLASS, optionAdornment && "flex items-center justify-between gap-2")}
595
- >
596
- {optionAdornment ? <span className="truncate-until-large">{o}</span> : o}
597
- {optionAdornment?.(o)}
598
- </button>
599
- </li>
600
- </Fragment>
601
- );
602
- })}
643
+ >
644
+ {optionAdornment ? <span className="truncate-until-large">{o}</span> : o}
645
+ {optionAdornment?.(o)}
646
+ </button>
647
+ </li>
648
+ ))}
603
649
  </ul>
650
+ {statusRegion}
604
651
  </PickerSheet>
605
652
  )}
606
653
  {showing && (
@@ -624,62 +671,44 @@ export function Combobox(props: ComboboxProps) {
624
671
  </button>
625
672
  </li>
626
673
  )}
627
- {matches.map((o, i) => {
628
- // Heading at each group boundary only — `matches` is group-contiguous, so
629
- // the boundaries are a property of the list rather than of the branch
630
- // drawing it. See `groupHeadings`.
631
- const group = groupHeadings?.get(i);
632
- return (
633
- <Fragment key={o}>
634
- {group !== undefined && (
635
- <li
636
- role="presentation"
637
- className={cn(
638
- GROUP_HEADING_STICKY,
639
- "px-3 pb-0.5 pt-2 text-caption font-semibold uppercase tracking-wide text-muted first:pt-1",
640
- )}
641
- >
642
- {group}
643
- </li>
674
+ {groupedRows(false, (o, i, grouped) => (
675
+ <li role="presentation">
676
+ <button
677
+ type="button"
678
+ id={optionId(i)}
679
+ role="option"
680
+ // CHOSEN, not highlighted. The row the arrows are on is named by the
681
+ // field's `aria-activedescendant`; saying "selected" for it would tell a
682
+ // reader that the row they are passing over is already the answer.
683
+ aria-selected={o === value}
684
+ // Focus stays in the field — that is what `aria-activedescendant` is
685
+ // for — so the rows are not tab stops.
686
+ tabIndex={-1}
687
+ onMouseDown={(e) => {
688
+ // mousedown (not click) so the blur from the input firing first
689
+ // doesn't close the list before the selection registers.
690
+ e.preventDefault();
691
+ take(o);
692
+ }}
693
+ onMouseEnter={() => setActive(i)}
694
+ className={cn(
695
+ rowClass(i === active),
696
+ // Every row of a group indented under its heading — it was the first
697
+ // row of each group only.
698
+ grouped && "ps-6",
699
+ // A row with a badge is a flex row so the label truncates and the
700
+ // badge keeps its width; without one it stays the plain block the
701
+ // other lists render, so nothing shifts for callers that pass none.
702
+ // From Large up the label wraps instead (`truncate-until-large`,
703
+ // text size §10.17, round 0.34 T1), as the badge-less row does.
704
+ optionAdornment && "flex items-center justify-between gap-2",
644
705
  )}
645
- <li role="presentation">
646
- <button
647
- type="button"
648
- id={optionId(i)}
649
- role="option"
650
- // CHOSEN, not highlighted. The row the arrows are on is named by
651
- // the field's `aria-activedescendant`; saying "selected" for it
652
- // would tell a reader that the row they are passing over is
653
- // already the answer.
654
- aria-selected={o === value}
655
- // Focus stays in the field — that is what
656
- // `aria-activedescendant` is for — so the rows are not tab stops.
657
- tabIndex={-1}
658
- onMouseDown={(e) => {
659
- // mousedown (not click) so the blur from the input firing first
660
- // doesn't close the list before the selection registers.
661
- e.preventDefault();
662
- take(o);
663
- }}
664
- onMouseEnter={() => setActive(i)}
665
- className={cn(
666
- rowClass(i === active),
667
- group != null && "ps-6",
668
- // A row with a badge is a flex row so the label truncates and the
669
- // badge keeps its width; without one it stays the plain block the
670
- // other lists render, so nothing shifts for callers that pass none.
671
- // From Large up the label wraps instead (`truncate-until-large`,
672
- // text size §10.17, round 0.34 T1), as the badge-less row does.
673
- optionAdornment && "flex items-center justify-between gap-2",
674
- )}
675
- >
676
- {optionAdornment ? <span className="truncate-until-large">{o}</span> : o}
677
- {optionAdornment?.(o)}
678
- </button>
679
- </li>
680
- </Fragment>
681
- );
682
- })}
706
+ >
707
+ {optionAdornment ? <span className="truncate-until-large">{o}</span> : o}
708
+ {optionAdornment?.(o)}
709
+ </button>
710
+ </li>
711
+ ))}
683
712
  </SuggestionList>
684
713
  )}
685
714
  </div>
@@ -9,7 +9,6 @@ import { Button } from "./button";
9
9
  import { IconButton } from "./icon-button";
10
10
  import type { ButtonSize, ButtonTone, ButtonVariant } from "./button-look";
11
11
  import type { IconButtonSize, IconButtonTone } from "./icon-button";
12
- import { Tooltip } from "./tooltip";
13
12
  import type { TooltipSide } from "./tooltip";
14
13
  import { DEFAULT_COPY_BUTTON_LABELS } from "./copy-button-labels";
15
14
 
@@ -31,8 +30,9 @@ export interface CopyButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonEle
31
30
  /** What to copy. A function is read at click time — for a value that is expensive
32
31
  * to build (a CSV of the table) or that changes under the button. */
33
32
  text: string | (() => string);
34
- /** `icon` (default): a square icon button whose tooltip states the result.
35
- * `label`: a text button whose words change to the result. */
33
+ /** `icon` (default): a square icon button whose glyph and colour show the result — its
34
+ * words in a bubble, and from Large up beside the glyph, as every labelled IconButton
35
+ * shows them. `label`: a text button whose words change to the result. */
36
36
  variant?: "icon" | "label";
37
37
  /** The idle accessible name — and, in the `label` variant, the visible text:
38
38
  * "Copy IBAN" says WHAT is copied, which a row of three copy icons needs. Default
@@ -82,9 +82,9 @@ const ICONS: Record<CopyState, typeof Copy> = { idle: Copy, copied: Check, faile
82
82
  * failure goes through an ASSERTIVE region and a success through a polite one — the
83
83
  * failure is the news that changes what they do next.
84
84
  *
85
- * The icon variant keeps the SAME accessible name in every state. A button renaming
86
- * itself under the focus is announced inconsistently across readers; the live region
87
- * is the channel that is actually heard.
85
+ * The icon variant keeps the SAME accessible name in every state, and the same words on
86
+ * screen. A button renaming itself under the focus is announced inconsistently across
87
+ * readers; the live region is the channel that is actually heard.
88
88
  */
89
89
  export function CopyButton({
90
90
  text,
@@ -156,25 +156,36 @@ export function CopyButton({
156
156
  );
157
157
  }
158
158
 
159
+ // IconButton names itself (0.52, refactor audit 2026-10-30, DSP-21): `label` is the
160
+ // bubble — and the text beside the glyph at Large, as on every labelled IconButton —
161
+ // and `aria-label` keeps the name steady. A Tooltip of our own round it cloned
162
+ // `aria-describedby` onto the button, which then read "Copy, button, Copy".
163
+ //
164
+ // The idle words, in every state (0.52 code review, deep, charts, finding 8). As the
165
+ // state, "Copied" stood at Large beside the glyph of a button named "Copy IBAN": the pill
166
+ // changed width on every copy, and the words on screen were not in the name a voice
167
+ // user says to press it (WCAG 2.5.3, label in name). The glyph and its colour show the
168
+ // result, and the live regions say it.
159
169
  return (
160
170
  <>
161
- <Tooltip label={stateText} side={tooltipSide} portal={tooltipPortal}>
162
- <IconButton
163
- type="button"
164
- {...rest}
165
- disabled={disabled}
166
- aria-label={idleText}
167
- variant={buttonVariant ?? "ghost"}
168
- size={(size ?? "sm") as IconButtonSize}
169
- tone={tone as IconButtonTone | undefined}
170
- stopPropagation={stopPropagation}
171
- data-state={state}
172
- onClick={() => void onClick()}
173
- className={cn(iconTone, className)}
174
- >
175
- <Icon aria-hidden />
176
- </IconButton>
177
- </Tooltip>
171
+ <IconButton
172
+ type="button"
173
+ {...rest}
174
+ disabled={disabled}
175
+ label={idleText}
176
+ aria-label={idleText}
177
+ tooltipSide={tooltipSide}
178
+ tooltipPortal={tooltipPortal}
179
+ variant={buttonVariant ?? "ghost"}
180
+ size={(size ?? "sm") as IconButtonSize}
181
+ tone={tone as IconButtonTone | undefined}
182
+ stopPropagation={stopPropagation}
183
+ data-state={state}
184
+ onClick={() => void onClick()}
185
+ className={cn(iconTone, className)}
186
+ >
187
+ <Icon aria-hidden />
188
+ </IconButton>
178
189
  {regions}
179
190
  </>
180
191
  );
@@ -3,7 +3,7 @@ import type { ComponentPropsWithoutRef, ReactNode, Ref } from "react";
3
3
  import { X } from "lucide-react";
4
4
  import { cn } from "../lib/cn";
5
5
  import { COUNTRY_CODES, countryName, normalizeCountryCode } from "../lib/countries";
6
- import { rankMatch } from "../lib/text-match";
6
+ import { searchRanked } from "../lib/text-match";
7
7
  import { FieldChevron, FIELD_FLOATING_PAD, FIELD_INVALID, FIELD_TRIGGER, FloatingField } from "./field-base";
8
8
  import {
9
9
  assignRef,
@@ -178,17 +178,22 @@ interface Entry {
178
178
  name: string;
179
179
  }
180
180
 
181
- /** Best rank first; a stable sort, so equal ranks keep the collated (or preferred)
182
- * order they came in. The rank is the kit's one (`rankMatch`, DUP-5 — written here
183
- * first): the code itself (a two-letter query "ch" means Switzerland before it means
184
- * Chad), then the start of the name, then anywhere in it, with accents and case folded
185
- * — "osterreich" finds Österreich, "cote" Côte d'Ivoire. */
181
+ /** Every word of the query in the name, or the whole code (0.51.4's rule: "kinshasa
182
+ * congo" finds Congo - Kinshasa; refactor audit 2026-10-30, DUP-4), best rank first; a
183
+ * stable sort, so equal ranks keep the collated (or preferred) order they came in. The
184
+ * rank is the kit's one, for the WHOLE query (`rankMatch`, DUP-5 — written here first):
185
+ * the code itself (a two-letter query "ch" means Switzerland before it means Chad), then
186
+ * the start of the name, then anywhere in it, then the words apart (`searchRanked`, each
187
+ * name and code folded once), with accents and case folded — "osterreich" finds
188
+ * Österreich, "cote" Côte d'Ivoire.
189
+ *
190
+ * A word is the code or it is not: searched INSIDE the code, as one more text, "w"
191
+ * listed Aruba (AW) and Samoa (WS) and "d" Germany (DE), names with nothing of the
192
+ * query in them (0.52 code review, country-select.tsx). */
186
193
  function search(entries: Entry[], q: string, locale: string): Entry[] {
187
- return entries
188
- .map((e) => ({ e, r: rankMatch(e.name, q, { code: e.code, locale }) }))
189
- .filter((x) => x.r >= 0)
190
- .sort((a, b) => a.r - b.r)
191
- .map((x) => x.e);
194
+ return searchRanked(entries, q, (e) => [e.name], { code: (e) => e.code, locale })
195
+ .sort((a, b) => a.rank - b.rank)
196
+ .map((x) => x.row);
192
197
  }
193
198
 
194
199
  function toOption(e: Entry, flags: boolean, group?: string): ComboOption<string> {