@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
@@ -4,6 +4,7 @@ import { Calendar, ChevronDown, ChevronLeft, ChevronRight } from "lucide-react";
4
4
  import { cn } from "../lib/cn";
5
5
  import { dirOf, horizontalStep, type Direction } from "../lib/direction";
6
6
  import { monthKey, pad } from "../lib/dates";
7
+ import { upperFirst } from "../lib/text-case";
7
8
  import { Button } from "./button";
8
9
  import { FIELD_FLOATING_PAD, FIELD_INVALID, FIELD_TRIGGER } from "./field-base";
9
10
  import { IconButton } from "./icon-button";
@@ -17,11 +18,17 @@ import {
17
18
  FieldBox,
18
19
  FieldLabelLine,
19
20
  LABEL_ABOVE_BOX,
21
+ LockedReason,
22
+ mergeDescribedBy,
20
23
  mergeRefs,
21
24
  useFieldMessages,
25
+ useLockReason,
26
+ type DisabledReasonDisplay,
22
27
  type FieldHelpProps,
23
28
  } from "./field-parts";
29
+ import { MonthGrid, clampKey, shiftKey, yearArrowsBlocked } from "./month-grid";
24
30
  import { DEFAULT_MONTH_PICKER_LABELS } from "./month-picker-labels";
31
+ import type { CommitScope } from "./write-lock";
25
32
 
26
33
  /**
27
34
  * Every string the month picker can speak. The month and year names are NOT here —
@@ -89,8 +96,9 @@ export interface MonthPickerProps extends Omit<ComponentPropsWithoutRef<"div">,
89
96
  /**
90
97
  * Inclusive bounds, as `"YYYY-MM"`. A full ISO date (`"YYYY-MM-DD"`) is accepted and
91
98
  * read as its month, so a host holding "the first day we have data for" can pass it
92
- * straight in. Months outside are shown but refuse selection; a year arrow is
93
- * disabled once the whole year beyond it is out of bounds.
99
+ * straight in. Months outside are shown but refuse selection; a year arrow refuses
100
+ * once the whole year beyond it is out of bounds (`aria-disabled`, so the focus stays
101
+ * on the arrow just pressed — 0.52).
94
102
  */
95
103
  min?: string;
96
104
  max?: string;
@@ -99,6 +107,26 @@ export interface MonthPickerProps extends Omit<ComponentPropsWithoutRef<"div">,
99
107
  /** Trigger text when `value` is `""`. */
100
108
  placeholder?: string;
101
109
  disabled?: boolean;
110
+ /**
111
+ * Why the month cannot be changed — {@link Select}'s `disabledReason`, for a picker
112
+ * that SAVES on change (a budget page's month, a calendar view kept per user). The
113
+ * trigger stays focusable and `aria-disabled`, the grid does not open, the stepper's
114
+ * Today and ‹ › refuse, and `onChange` never fires; the reason is a line under the
115
+ * field (or the stepper) at Large and on a touch screen, else in the kit
116
+ * {@link Tooltip} (`disabledReasonDisplay`), and on the trigger's `aria-describedby`.
117
+ * Wins over `disabled`. 0.52 (refactor audit 2026-10-30, API-3).
118
+ */
119
+ disabledReason?: ReactNode;
120
+ /** Where the reason shows — {@link Button}'s `disabledReasonDisplay`: a line under the
121
+ * field at Large and on a touch screen by default, the tooltip otherwise. */
122
+ disabledReasonDisplay?: DisabledReasonDisplay;
123
+ /**
124
+ * This picker COMMITS — picking saves. Under a locked {@link WriteLockProvider} it is
125
+ * locked the `disabledReason` way, with the lock's reason; a {@link CommitScope}, as on
126
+ * every kit control. A month field inside a form with its own Save stays editable
127
+ * under the lock — leave this off there, and put `commit` on the Save. 0.52 (API-3).
128
+ */
129
+ commit?: CommitScope;
102
130
  /** Required and unanswered — {@link FIELD_INVALID}. See {@link Input}'s `invalid`. */
103
131
  invalid?: boolean;
104
132
  /**
@@ -217,7 +245,6 @@ function firstOf({ year, month }: YearMonth): Date {
217
245
  }
218
246
 
219
247
  const DEFAULT_TRIGGER_FORMAT: Intl.DateTimeFormatOptions = { month: "long", year: "numeric" };
220
- const MONTH_NAME_FORMAT: Intl.DateTimeFormatOptions = { month: "long", year: "numeric" };
221
248
  const YEAR_FORMAT: Intl.DateTimeFormatOptions = { year: "numeric" };
222
249
 
223
250
  // ── Year keys ─────────────────────────────────────────────────────────────
@@ -268,6 +295,7 @@ function MonthHeadingTrigger({
268
295
  text,
269
296
  panelId,
270
297
  disabled,
298
+ locked,
271
299
  aria,
272
300
  }: {
273
301
  open: boolean;
@@ -277,6 +305,8 @@ function MonthHeadingTrigger({
277
305
  text: string;
278
306
  panelId: string;
279
307
  disabled?: boolean;
308
+ /** The write lock: the focusable kind of disabled. */
309
+ locked: boolean;
280
310
  aria: TriggerAria;
281
311
  }) {
282
312
  useFocusBackOnClose(open, triggerRef);
@@ -285,8 +315,11 @@ function MonthHeadingTrigger({
285
315
  <button
286
316
  ref={setTrigger}
287
317
  type="button"
288
- disabled={disabled}
289
- onClick={toggle}
318
+ disabled={locked ? undefined : disabled}
319
+ aria-disabled={locked || undefined}
320
+ onClick={() => {
321
+ if (!locked) toggle();
322
+ }}
290
323
  aria-haspopup="dialog"
291
324
  aria-controls={panelId}
292
325
  aria-expanded={open}
@@ -298,7 +331,7 @@ function MonthHeadingTrigger({
298
331
  "-ms-1.5 inline-flex h-9 min-w-0 items-center gap-1 rounded-md px-1.5 text-lg font-semibold text-primary transition-colors",
299
332
  "hover:bg-hover",
300
333
  FOCUS_RING,
301
- disabled && "cursor-not-allowed opacity-50",
334
+ (disabled || locked) && "cursor-not-allowed opacity-50",
302
335
  )}
303
336
  >
304
337
  <span aria-live="polite" className="truncate">
@@ -328,6 +361,7 @@ function MonthFieldTrigger({
328
361
  padded,
329
362
  small,
330
363
  disabled,
364
+ locked,
331
365
  invalid,
332
366
  className,
333
367
  aria,
@@ -347,6 +381,9 @@ function MonthFieldTrigger({
347
381
  /** `size="sm"`: the 36px, content-wide toolbar trigger. */
348
382
  small: boolean;
349
383
  disabled?: boolean;
384
+ /** The write lock: the focusable kind of disabled (Button's rule — native `disabled`
385
+ * would take the field out of the tab order, and the reason with it). */
386
+ locked: boolean;
350
387
  invalid?: boolean;
351
388
  className?: string;
352
389
  }) {
@@ -357,8 +394,13 @@ function MonthFieldTrigger({
357
394
  <button
358
395
  ref={setTrigger}
359
396
  type="button"
360
- disabled={disabled}
361
- onClick={toggle}
397
+ disabled={locked ? undefined : disabled}
398
+ aria-disabled={locked || undefined}
399
+ onClick={() => {
400
+ // Locked, the grid does not open. One open when the lock arrives closes: the
401
+ // field moves into the reason's frame, which remounts it, as Select's does.
402
+ if (!locked) toggle();
403
+ }}
362
404
  role="combobox"
363
405
  aria-haspopup="dialog"
364
406
  aria-controls={panelId}
@@ -377,7 +419,7 @@ function MonthFieldTrigger({
377
419
  // month — `py-0` with a fixed height so the box is 36px whatever the type's
378
420
  // line height. `pe-9` stays: the calendar glyph still sits at the end.
379
421
  small && "h-9 w-auto py-0",
380
- disabled && "cursor-not-allowed opacity-50",
422
+ (disabled || locked) && "cursor-not-allowed opacity-50",
381
423
  invalid && FIELD_INVALID,
382
424
  className,
383
425
  )}
@@ -400,19 +442,32 @@ function MonthFieldTrigger({
400
442
  const COLUMNS = 3;
401
443
 
402
444
  /**
403
- * The panel: a year caption between ‹ › arrows, over a 4×3 grid of months.
445
+ * A year arrow over a grid (the month grid's ‹ › years, the year grid's pages). At a
446
+ * bound it refuses rather than turning `disabled`, JumpCalendar's rule (refactor audit
447
+ * 2026-10-30, INP-4): the press that reaches the bound is made with the focus ON the
448
+ * arrow, and a focused button that turns `disabled` drops the focus to <body>, mid-panel
449
+ * (keksdose's budget MonthPicker passes `min`). `aria-disabled`, a click that does
450
+ * nothing, and the look through `aria-disabled:`.
451
+ */
452
+ const PANEL_ARROW =
453
+ "flex size-7 items-center justify-center rounded text-muted hover:bg-hover aria-disabled:cursor-not-allowed aria-disabled:opacity-30 aria-disabled:hover:bg-transparent";
454
+
455
+ /** The stepper's Today and ‹ › while refused: Button's look for its focusable kind of
456
+ * disabled — the kit's `disabled:` classes cannot match an `aria-disabled` button. The
457
+ * arrows, ghost IconButtons, also pin their resting fill under hover, as
458
+ * `disabled:hover:` does for them. */
459
+ const STEPPER_REFUSED = "aria-disabled:cursor-not-allowed aria-disabled:opacity-50";
460
+ const STEPPER_ARROW_REFUSED = `${STEPPER_REFUSED} aria-disabled:hover:bg-transparent`;
461
+
462
+ /**
463
+ * The panel: a year caption between ‹ › arrows, over the year's {@link MonthGrid} (4×3,
464
+ * its keys and its bounds — one with JumpCalendar's since 0.52, DUP-11).
404
465
  *
405
466
  * Mounted only while the popover is open, so every opening starts from the current
406
467
  * value's year — a value moved from outside (a prev/next-month button beside the
407
468
  * field) is where the grid lands, with no effect needed to snap it back.
408
- *
409
- * A grid in the APG sense, like `MiniCalendar`: one tab stop (the roving tabindex),
410
- * the arrows walk the months — left/right by one, up/down by a row of three — and
411
- * walking off either end of the year MOVES the year rather than stopping. PageUp /
412
- * PageDown step a whole year. Out-of-bounds months are `aria-disabled`, not
413
- * `disabled`, so the roving tab stop never falls into a hole.
414
469
  */
415
- function MonthGrid({
470
+ function MonthPanel({
416
471
  value,
417
472
  onPick,
418
473
  locale,
@@ -429,97 +484,15 @@ function MonthGrid({
429
484
  currentKey: string;
430
485
  labels: MonthPickerLabels;
431
486
  }) {
432
- const outOfBounds = (key: string) => Boolean((minKey && key < minKey) || (maxKey && key > maxKey));
433
-
487
+ const selectedKey = value ? toKey(value) : null;
434
488
  // The month holding the tab order, and with it the year on screen — one piece of
435
489
  // state, as in MiniCalendar, so the two cannot disagree. Opens on the value, or on
436
490
  // the current month, pulled inside the bounds.
437
- const [active, setActive] = useState<YearMonth>(() => {
438
- const start = value ? toKey(value) : currentKey;
439
- if (minKey && start < minKey) return parseMonth(minKey)!;
440
- if (maxKey && start > maxKey) return parseMonth(maxKey)!;
441
- return parseMonth(start)!;
442
- });
443
- const year = active.year;
444
-
445
- const gridRef = useRef<HTMLDivElement>(null);
491
+ const [active, setActive] = useState(() => clampKey(selectedKey ?? currentKey, minKey, maxKey));
492
+ const year = Number(active.slice(0, 4));
446
493
  const captionId = `${useId()}-year`;
447
-
448
- // Short names for the cells, long "Month YYYY" for their accessible names.
449
- const shortNames = useMemo(() => {
450
- const fmt = new Intl.DateTimeFormat(locale, { month: "short" });
451
- return Array.from({ length: 12 }, (_, i) => fmt.format(new Date(2000, i, 1)));
452
- }, [locale]);
453
- const longName = useMemo(() => new Intl.DateTimeFormat(locale, MONTH_NAME_FORMAT), [locale]);
454
- const yearCaption = new Intl.DateTimeFormat(locale, { year: "numeric" }).format(firstOf({ year, month: 1 }));
455
-
456
- // A month whose cell must take focus after the next commit. Arrowing across a year
457
- // boundary re-labels the same twelve buttons, so the one to focus is a DIFFERENT
458
- // button from the one the key landed on.
459
- const pendingFocus = useRef<string | null>(null);
460
- useEffect(() => {
461
- const key = pendingFocus.current;
462
- if (!key) return;
463
- pendingFocus.current = null;
464
- gridRef.current?.querySelector<HTMLElement>(`[data-month="${key}"]`)?.focus();
465
- });
466
-
467
- // Opened because the user asked to pick a month: land them on it. Runs before the
468
- // popover's focus trap (a child's effect fires first), which then keeps this focus.
469
- useEffect(() => {
470
- gridRef.current?.querySelector<HTMLElement>('[tabindex="0"]')?.focus();
471
- }, []);
472
-
473
- const moveTo = (next: YearMonth, focus: boolean) => {
474
- if (focus) pendingFocus.current = toKey(next);
475
- setActive(next);
476
- };
477
-
478
- const onCellKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {
479
- // Left and right are VISUAL directions: in a right-to-left page the grid runs the
480
- // other way, so "right" is the previous month there. The panel is portalled, but
481
- // it carries the field's `dir` (see MonthPicker), so the nearest `dir` is right.
482
- const step = horizontalStep(e.key, e.currentTarget);
483
- const col = (active.month - 1) % COLUMNS;
484
- let delta: number;
485
- switch (step ? "horizontal" : e.key) {
486
- case "horizontal":
487
- delta = step;
488
- break;
489
- case "ArrowUp":
490
- delta = -COLUMNS;
491
- break;
492
- case "ArrowDown":
493
- delta = COLUMNS;
494
- break;
495
- case "Home":
496
- delta = -col;
497
- break;
498
- case "End":
499
- delta = COLUMNS - 1 - col;
500
- break;
501
- case "PageUp":
502
- delta = -12;
503
- break;
504
- case "PageDown":
505
- delta = 12;
506
- break;
507
- default:
508
- return;
509
- }
510
- // Before any no-op check: these keys also scroll the panel, and a month that
511
- // cannot move still must not move the page.
512
- e.preventDefault();
513
- if (delta !== 0) moveTo(shiftMonth(active, delta), true);
514
- };
515
-
516
- // An arrow is dead once EVERY month of the year it leads to is out of bounds.
517
- const prevBlocked = Boolean(minKey && toKey({ year: year - 1, month: 12 }) < minKey);
518
- const nextBlocked = Boolean(maxKey && toKey({ year: year + 1, month: 1 }) > maxKey);
519
- const selectedKey = value ? toKey(value) : null;
520
-
521
- const arrow =
522
- "flex size-7 items-center justify-center rounded text-muted hover:bg-hover disabled:cursor-not-allowed disabled:opacity-30 disabled:hover:bg-transparent";
494
+ const yearCaption = new Intl.DateTimeFormat(locale, YEAR_FORMAT).format(new Date(year, 0, 1));
495
+ const blocked = yearArrowsBlocked(active, minKey, maxKey);
523
496
 
524
497
  return (
525
498
  <div className="select-none">
@@ -527,10 +500,12 @@ function MonthGrid({
527
500
  <button
528
501
  type="button"
529
502
  aria-label={labels.previousYear}
530
- disabled={prevBlocked}
503
+ aria-disabled={blocked.previous || undefined}
531
504
  // Focus stays on the arrow being pressed — only the grid moves.
532
- onClick={() => moveTo(shiftMonth(active, -12), false)}
533
- className={arrow}
505
+ onClick={() => {
506
+ if (!blocked.previous) setActive(shiftKey(active, -12));
507
+ }}
508
+ className={PANEL_ARROW}
534
509
  >
535
510
  {/* Mirrored in RTL, where "previous" points the other way. */}
536
511
  <ChevronLeft className="size-4 rtl:-scale-x-100" />
@@ -543,61 +518,28 @@ function MonthGrid({
543
518
  <button
544
519
  type="button"
545
520
  aria-label={labels.nextYear}
546
- disabled={nextBlocked}
547
- onClick={() => moveTo(shiftMonth(active, 12), false)}
548
- className={arrow}
521
+ aria-disabled={blocked.next || undefined}
522
+ onClick={() => {
523
+ if (!blocked.next) setActive(shiftKey(active, 12));
524
+ }}
525
+ className={PANEL_ARROW}
549
526
  >
550
527
  <ChevronRight className="size-4 rtl:-scale-x-100" />
551
528
  </button>
552
529
  </div>
553
- <div ref={gridRef} role="grid" aria-labelledby={captionId} className="grid gap-1">
554
- {Array.from({ length: 12 / COLUMNS }, (_, row) => (
555
- <div key={row} role="row" className="grid grid-cols-3 gap-1">
556
- {Array.from({ length: COLUMNS }, (_, c) => {
557
- const ym = { year, month: row * COLUMNS + c + 1 };
558
- const key = toKey(ym);
559
- const disabled = outOfBounds(key);
560
- const selected = key === selectedKey;
561
- const current = key === currentKey;
562
- return (
563
- <button
564
- key={c}
565
- type="button"
566
- role="gridcell"
567
- data-month={key}
568
- tabIndex={ym.month === active.month ? 0 : -1}
569
- aria-label={labels.month(longName.format(firstOf(ym)))}
570
- aria-selected={selected}
571
- aria-disabled={disabled || undefined}
572
- aria-current={current ? "date" : undefined}
573
- onClick={() => {
574
- // The guard `disabled` would have been; see the component note.
575
- if (disabled) return;
576
- setActive(ym);
577
- onPick(key);
578
- }}
579
- onKeyDown={onCellKeyDown}
580
- className={cn(
581
- "rounded px-2 py-1.5 text-sm capitalize transition-colors",
582
- FOCUS_RING_WIDTH,
583
- "focus-visible:outline-none focus-visible:ring-inset",
584
- // A --brand ring on a --brand fill exists only in the DOM.
585
- selected && !disabled ? "focus-visible:ring-brand-contrast" : "focus-visible:ring-brand",
586
- disabled
587
- ? "cursor-not-allowed text-placeholder"
588
- : selected
589
- ? "bg-brand text-brand-contrast hover:bg-brand-hover"
590
- : "text-primary hover:bg-hover",
591
- current && !selected && !disabled && "ring-1 ring-inset ring-strong",
592
- )}
593
- >
594
- {shortNames[ym.month - 1]}
595
- </button>
596
- );
597
- })}
598
- </div>
599
- ))}
600
- </div>
530
+ <MonthGrid
531
+ active={active}
532
+ onActiveChange={setActive}
533
+ onPick={onPick}
534
+ from={selectedKey}
535
+ to={selectedKey}
536
+ minKey={minKey}
537
+ maxKey={maxKey}
538
+ currentKey={currentKey}
539
+ locale={locale}
540
+ cellName={labels.month}
541
+ labelledBy={captionId}
542
+ />
601
543
  </div>
602
544
  );
603
545
  }
@@ -645,7 +587,7 @@ function YearGrid({
645
587
  ? { first: minYear, count: maxYear - minYear + 1 }
646
588
  : null;
647
589
  // The year holding the tab order, and with it the page on screen — one piece of
648
- // state, as in MonthGrid. Opens on the value, or on this year, inside the bounds.
590
+ // state, as in MonthPanel. Opens on the value, or on this year, inside the bounds.
649
591
  const [active, setActive] = useState(() => clamp(value ?? currentYear));
650
592
  const anchor = minYear ?? (maxYear !== null ? maxYear - (YEAR_PAGE - 1) : 0);
651
593
  const first = whole ? whole.first : anchor + Math.floor((active - anchor) / YEAR_PAGE) * YEAR_PAGE;
@@ -712,8 +654,6 @@ function YearGrid({
712
654
 
713
655
  const prevBlocked = minYear !== null && first - 1 < minYear;
714
656
  const nextBlocked = maxYear !== null && first + count > maxYear;
715
- const arrow =
716
- "flex size-7 items-center justify-center rounded text-muted hover:bg-hover disabled:cursor-not-allowed disabled:opacity-30 disabled:hover:bg-transparent";
717
657
 
718
658
  return (
719
659
  <div className="select-none">
@@ -722,9 +662,11 @@ function YearGrid({
722
662
  <button
723
663
  type="button"
724
664
  aria-label={labels.earlierYears}
725
- disabled={prevBlocked}
726
- onClick={() => moveTo(active - YEAR_PAGE, false)}
727
- className={arrow}
665
+ aria-disabled={prevBlocked || undefined}
666
+ onClick={() => {
667
+ if (!prevBlocked) moveTo(active - YEAR_PAGE, false);
668
+ }}
669
+ className={PANEL_ARROW}
728
670
  >
729
671
  <ChevronLeft className="size-4 rtl:-scale-x-100" />
730
672
  </button>
@@ -736,9 +678,11 @@ function YearGrid({
736
678
  <button
737
679
  type="button"
738
680
  aria-label={labels.laterYears}
739
- disabled={nextBlocked}
740
- onClick={() => moveTo(active + YEAR_PAGE, false)}
741
- className={arrow}
681
+ aria-disabled={nextBlocked || undefined}
682
+ onClick={() => {
683
+ if (!nextBlocked) moveTo(active + YEAR_PAGE, false);
684
+ }}
685
+ className={PANEL_ARROW}
742
686
  >
743
687
  <ChevronRight className="size-4 rtl:-scale-x-100" />
744
688
  </button>
@@ -768,7 +712,8 @@ function YearGrid({
768
712
  }}
769
713
  onKeyDown={onCellKeyDown}
770
714
  className={cn(
771
- "rounded px-2 py-1.5 text-sm tabular-nums transition-colors",
715
+ // The month grid's 44px rows (DUP-11): one picker, one row height.
716
+ "h-11 rounded px-1 text-sm tabular-nums transition-colors",
772
717
  FOCUS_RING_WIDTH,
773
718
  "focus-visible:outline-none focus-visible:ring-inset",
774
719
  selected && !disabled ? "focus-visible:ring-brand-contrast" : "focus-visible:ring-brand",
@@ -803,14 +748,6 @@ function YearGrid({
803
748
  * and a year list in two popovers). The grid does both jobs — the year arrows and
804
749
  * PageUp/PageDown cover what the year list did, without a fixed ±5-year window.
805
750
  */
806
- /** Upper-case the first letter only, in `locale`. Several locales (fr, es, it, pt, …)
807
- * write month names in lower case, which at the start of a field reads as a typo —
808
- * but only the FIRST letter is the field's business: "septiembre de 2026" becomes
809
- * "Septiembre de 2026", not "Septiembre De 2026". */
810
- function upperFirst(text: string, locale: string | undefined): string {
811
- return text.charAt(0).toLocaleUpperCase(locale) + text.slice(1);
812
- }
813
-
814
751
  export function MonthPicker(props: MonthPickerProps) {
815
752
  const {
816
753
  value,
@@ -821,6 +758,9 @@ export function MonthPicker(props: MonthPickerProps) {
821
758
  label,
822
759
  placeholder,
823
760
  disabled,
761
+ disabledReason,
762
+ disabledReasonDisplay,
763
+ commit,
824
764
  invalid,
825
765
  error,
826
766
  hint,
@@ -868,20 +808,44 @@ export function MonthPicker(props: MonthPickerProps) {
868
808
  : (placeholder ?? "");
869
809
 
870
810
  const id = useId();
811
+ // The write lock (API-3): Select's — the trigger stays reachable and says why.
812
+ const lock = useLockReason(commit, disabledReason);
813
+ const locked = lock.locked;
814
+ const reasonId = locked ? lock.reasonId : undefined;
815
+ const change = (key: string) => {
816
+ if (!locked) onChange(key);
817
+ };
871
818
  // keksdose K4: the caption and the error, on the trigger after the caller's own
872
- // description. Painted for `invalid` and a message — not for a bare `aria-invalid`,
873
- // which this field has never painted for.
819
+ // description; a lock's reason between the two, as on Select. Painted for `invalid`
820
+ // and a message — not for a bare `aria-invalid`, which this field has never painted for.
874
821
  const messages = useFieldMessages({
875
822
  hint,
876
823
  help,
877
824
  name: label ?? rest["aria-label"],
878
825
  error,
879
826
  describedBy: rest["aria-describedby"],
827
+ reasonId,
880
828
  });
881
829
  const [ownAria, wrapperRest] = splitTriggerAria(rest);
882
830
  // The field's trigger is described by the caption and the error too; the stepper
883
- // draws neither, so its heading keeps the caller's own description.
831
+ // draws neither, so its heading keeps the caller's own description — and a lock's.
884
832
  const aria: TriggerAria = { ...ownAria, "aria-describedby": messages.describedBy };
833
+ const headingAria: TriggerAria = {
834
+ ...ownAria,
835
+ "aria-describedby": mergeDescribedBy(ownAria["aria-describedby"], reasonId),
836
+ };
837
+ // Locked, the field (or the stepper) sits in the reason's frame — the line, or the
838
+ // Tooltip — which becomes the outermost box and takes the caller's classes, as on
839
+ // Select, so a lock does not reflow the page.
840
+ const rootClass = locked ? undefined : className;
841
+ const withReason = (box: ReactNode) =>
842
+ locked ? (
843
+ <LockedReason lock={lock} display={disabledReasonDisplay} className={cn("block", className)}>
844
+ {box}
845
+ </LockedReason>
846
+ ) : (
847
+ box
848
+ );
885
849
  const labelId = `${id}-label`;
886
850
  const valueId = `${id}-value`;
887
851
  const panelId = `${id}-panel`;
@@ -906,12 +870,12 @@ export function MonthPicker(props: MonthPickerProps) {
906
870
  currentYear={currentYear}
907
871
  labels={labels}
908
872
  onPick={(key) => {
909
- onChange(key);
873
+ change(key);
910
874
  close();
911
875
  }}
912
876
  />
913
877
  ) : (
914
- <MonthGrid
878
+ <MonthPanel
915
879
  value={selected}
916
880
  locale={locale}
917
881
  minKey={minKey}
@@ -919,7 +883,7 @@ export function MonthPicker(props: MonthPickerProps) {
919
883
  currentKey={currentKey}
920
884
  labels={labels}
921
885
  onPick={(key) => {
922
- onChange(key);
886
+ change(key);
923
887
  close();
924
888
  }}
925
889
  />
@@ -967,51 +931,76 @@ export function MonthPicker(props: MonthPickerProps) {
967
931
  text={triggerText}
968
932
  panelId={panelId}
969
933
  disabled={disabled}
970
- aria={ownAria}
934
+ locked={locked}
935
+ aria={headingAria}
971
936
  />
972
937
  )}
973
938
  >
974
939
  {grid}
975
940
  </Popover>
976
941
  );
977
- return (
942
+ // ‹ › at a bound refuse rather than turn `disabled` (refactor audit 2026-10-30,
943
+ // INP-4): the press that reaches the bound is made with the focus on the arrow, and
944
+ // a focused button that turns `disabled` drops the focus to <body>. A lock refuses
945
+ // them, and Today, the same focusable way — its reason is the frame's, so no name
946
+ // bubble of their own beside it. `disabled` (a lock's reason wins over it) and
947
+ // Today's "now is out of bounds", which no press here changes, stay native.
948
+ const off = Boolean(disabled) && !locked;
949
+ const prevRefused = locked || outside(prevKey);
950
+ const nextRefused = locked || outside(nextKey);
951
+ return withReason(
978
952
  // `flex-wrap`: where the heading and the buttons do not fit one row, the buttons
979
953
  // take the next line, at the end (0.32.1, the 360 px Extra-large sweep;
980
954
  // docs/text-size-harmonization.md §4). In one row at 150 % "Today ‹ ›" left the
981
955
  // heading 30 px on a 360 px phone, and "October 2026" was drawn under "Today".
982
956
  // Where they fit, nothing changes.
983
- <div {...wrapperRest} ref={rootRef} className={cn("flex min-w-0 flex-wrap items-center gap-2", className)}>
957
+ <div {...wrapperRest} ref={rootRef} className={cn("flex min-w-0 flex-wrap items-center gap-2", rootClass)}>
984
958
  {Heading ? <Heading className="m-0 min-w-0 text-lg font-semibold">{trigger}</Heading> : trigger}
985
959
  <div className="ms-auto flex shrink-0 items-center gap-1">
986
960
  {showToday && (
987
961
  <Button
988
962
  variant="secondary"
989
963
  size="sm"
990
- disabled={disabled || outside(nowKey)}
964
+ disabled={!locked && (disabled || outside(nowKey))}
965
+ aria-disabled={locked || undefined}
966
+ aria-describedby={reasonId}
991
967
  onClick={() => {
992
- if (nowKey !== shownKey) onChange(nowKey);
968
+ if (nowKey !== shownKey) change(nowKey);
993
969
  }}
970
+ className={STEPPER_REFUSED}
994
971
  >
995
972
  {years ? labels.thisYear : labels.today}
996
973
  </Button>
997
974
  )}
998
975
  <IconButton
999
976
  aria-label={years ? labels.previousYear : labels.previousMonth}
1000
- disabled={disabled || outside(prevKey)}
1001
- onClick={() => onChange(prevKey)}
977
+ disabled={off}
978
+ aria-disabled={(!off && prevRefused) || undefined}
979
+ aria-describedby={reasonId}
980
+ tooltip={!locked}
981
+ onClick={() => {
982
+ if (!prevRefused) change(prevKey);
983
+ }}
984
+ className={STEPPER_ARROW_REFUSED}
1002
985
  >
1003
986
  {/* Mirrored in RTL, where "previous" points the other way. */}
1004
987
  <ChevronLeft className="rtl:-scale-x-100" />
1005
988
  </IconButton>
1006
989
  <IconButton
1007
990
  aria-label={years ? labels.nextYear : labels.nextMonth}
1008
- disabled={disabled || outside(nextKey)}
1009
- onClick={() => onChange(nextKey)}
991
+ disabled={off}
992
+ aria-disabled={(!off && nextRefused) || undefined}
993
+ aria-describedby={reasonId}
994
+ tooltip={!locked}
995
+ onClick={() => {
996
+ if (!nextRefused) change(nextKey);
997
+ }}
998
+ className={STEPPER_ARROW_REFUSED}
1010
999
  >
1011
1000
  <ChevronRight className="rtl:-scale-x-100" />
1012
1001
  </IconButton>
1013
1002
  </div>
1014
- </div>
1003
+ </div>,
1015
1004
  );
1016
1005
  }
1017
1006
 
@@ -1023,7 +1012,7 @@ export function MonthPicker(props: MonthPickerProps) {
1023
1012
  <div
1024
1013
  {...wrapperRest}
1025
1014
  ref={rootRef}
1026
- className={cn("relative", small && "w-fit max-w-full", label !== undefined && LABEL_ABOVE_BOX, className)}
1015
+ className={cn("relative", small && "w-fit max-w-full", label !== undefined && LABEL_ABOVE_BOX, rootClass)}
1027
1016
  >
1028
1017
  {label !== undefined && <FieldLabelLine label={label} hint={messages.labelHint} />}
1029
1018
  {/* The hidden twin the trigger is named by — see DateField. `sr-only-fixed`,
@@ -1064,6 +1053,7 @@ export function MonthPicker(props: MonthPickerProps) {
1064
1053
  padded={label !== undefined}
1065
1054
  small={small}
1066
1055
  disabled={disabled}
1056
+ locked={locked}
1067
1057
  invalid={invalid || hasContent(error)}
1068
1058
  className={triggerClassName}
1069
1059
  />
@@ -1082,13 +1072,15 @@ export function MonthPicker(props: MonthPickerProps) {
1082
1072
  const endHint = label === undefined ? messages.labelHint : undefined;
1083
1073
  return (
1084
1074
  <FieldBox below={messages.below} reserve={"error" in props || "hint" in props}>
1085
- {endHint === undefined ? (
1086
- field
1087
- ) : (
1088
- <div className="flex items-center gap-1.5">
1089
- <div className={cn("min-w-0", !small && "flex-1")}>{field}</div>
1090
- <span className="flex shrink-0 items-center">{endHint}</span>
1091
- </div>
1075
+ {withReason(
1076
+ endHint === undefined ? (
1077
+ field
1078
+ ) : (
1079
+ <div className="flex items-center gap-1.5">
1080
+ <div className={cn("min-w-0", !small && "flex-1")}>{field}</div>
1081
+ <span className="flex shrink-0 items-center">{endHint}</span>
1082
+ </div>
1083
+ ),
1092
1084
  )}
1093
1085
  </FieldBox>
1094
1086
  );