@eifi1/ui-kit 0.34.0 → 0.36.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 (446) hide show
  1. package/README.md +115 -41
  2. package/dist/admin/role-select.d.ts +3 -2
  3. package/dist/admin/role-select.js +2 -0
  4. package/dist/admin/role-select.js.map +1 -1
  5. package/dist/billing/billing-banner.d.ts +5 -2
  6. package/dist/billing/billing-banner.js.map +1 -1
  7. package/dist/billing/plan-limit-notice.d.ts +5 -2
  8. package/dist/billing/plan-limit-notice.js.map +1 -1
  9. package/dist/chart.js.map +1 -1
  10. package/dist/components/amount-input.d.ts +2 -5
  11. package/dist/components/amount-input.js +2 -2
  12. package/dist/components/amount-input.js.map +1 -1
  13. package/dist/components/autocomplete.d.ts +2 -2
  14. package/dist/components/autocomplete.js +2 -1
  15. package/dist/components/autocomplete.js.map +1 -1
  16. package/dist/components/button-look.d.ts +1 -1
  17. package/dist/components/button-look.js +9 -4
  18. package/dist/components/button-look.js.map +1 -1
  19. package/dist/components/calculator.d.ts +1 -4
  20. package/dist/components/calculator.js +1 -3
  21. package/dist/components/calculator.js.map +1 -1
  22. package/dist/components/chart-zoom.d.ts +0 -37
  23. package/dist/components/chart-zoom.js +1 -28
  24. package/dist/components/chart-zoom.js.map +1 -1
  25. package/dist/components/checkbox-group.d.ts +5 -2
  26. package/dist/components/checkbox-group.js +15 -4
  27. package/dist/components/checkbox-group.js.map +1 -1
  28. package/dist/components/chip-input.d.ts +0 -4
  29. package/dist/components/chip-input.js +1 -5
  30. package/dist/components/chip-input.js.map +1 -1
  31. package/dist/components/column-mapper.d.ts +5 -3
  32. package/dist/components/column-mapper.js +2 -0
  33. package/dist/components/column-mapper.js.map +1 -1
  34. package/dist/components/combobox.d.ts +3 -3
  35. package/dist/components/combobox.js +2 -1
  36. package/dist/components/combobox.js.map +1 -1
  37. package/dist/components/copy-button.d.ts +5 -1
  38. package/dist/components/copy-button.js.map +1 -1
  39. package/dist/components/country-select.d.ts +3 -3
  40. package/dist/components/country-select.js +3 -0
  41. package/dist/components/country-select.js.map +1 -1
  42. package/dist/components/currency-option-list.d.ts +3 -8
  43. package/dist/components/currency-option-list.js +1 -29
  44. package/dist/components/currency-option-list.js.map +1 -1
  45. package/dist/components/currency-select.d.ts +3 -2
  46. package/dist/components/currency-select.js +10 -1
  47. package/dist/components/currency-select.js.map +1 -1
  48. package/dist/components/danger-confirm.d.ts +3 -3
  49. package/dist/components/danger-confirm.js.map +1 -1
  50. package/dist/components/data-table-filter-popover.d.ts +1 -1
  51. package/dist/components/data-table-filter-popover.js +1 -1
  52. package/dist/components/data-table-filter-popover.js.map +1 -1
  53. package/dist/components/data-table-labels.d.ts +1 -42
  54. package/dist/components/data-table-labels.js +2 -31
  55. package/dist/components/data-table-labels.js.map +1 -1
  56. package/dist/components/data-table-shared.d.ts +17 -1
  57. package/dist/components/data-table-shared.js +22 -0
  58. package/dist/components/data-table-shared.js.map +1 -1
  59. package/dist/components/data-table.d.ts +12 -2
  60. package/dist/components/data-table.js +18 -14
  61. package/dist/components/data-table.js.map +1 -1
  62. package/dist/components/date-field.d.ts +2 -1
  63. package/dist/components/date-field.js.map +1 -1
  64. package/dist/components/date-picker.js +3 -0
  65. package/dist/components/date-picker.js.map +1 -1
  66. package/dist/components/date-range-picker.js +3 -0
  67. package/dist/components/date-range-picker.js.map +1 -1
  68. package/dist/components/dialog-frame.d.ts +3 -1
  69. package/dist/components/dialog-frame.js.map +1 -1
  70. package/dist/components/dropdown.d.ts +18 -15
  71. package/dist/components/dropdown.js +11 -3
  72. package/dist/components/dropdown.js.map +1 -1
  73. package/dist/components/entity-combobox.d.ts +3 -3
  74. package/dist/components/entity-combobox.js +2 -1
  75. package/dist/components/entity-combobox.js.map +1 -1
  76. package/dist/components/field-base.d.ts +0 -5
  77. package/dist/components/field-base.js +0 -5
  78. package/dist/components/field-base.js.map +1 -1
  79. package/dist/components/field-parts.d.ts +69 -22
  80. package/dist/components/field-parts.js +33 -19
  81. package/dist/components/field-parts.js.map +1 -1
  82. package/dist/components/field-strip.d.ts +9 -23
  83. package/dist/components/field-strip.js +26 -23
  84. package/dist/components/field-strip.js.map +1 -1
  85. package/dist/components/field-sync.d.ts +0 -4
  86. package/dist/components/field-sync.js +0 -4
  87. package/dist/components/field-sync.js.map +1 -1
  88. package/dist/components/field.d.ts +7 -6
  89. package/dist/components/field.js +24 -15
  90. package/dist/components/field.js.map +1 -1
  91. package/dist/components/full-bleed-dialog.js +2 -2
  92. package/dist/components/full-bleed-dialog.js.map +1 -1
  93. package/dist/components/help-popover.d.ts +9 -7
  94. package/dist/components/help-popover.js.map +1 -1
  95. package/dist/components/hover-menu.d.ts +6 -13
  96. package/dist/components/hover-menu.js +3 -3
  97. package/dist/components/hover-menu.js.map +1 -1
  98. package/dist/components/icon-picker.d.ts +3 -2
  99. package/dist/components/icon-picker.js +3 -0
  100. package/dist/components/icon-picker.js.map +1 -1
  101. package/dist/components/inline-entity-combobox.d.ts +3 -3
  102. package/dist/components/inline-entity-combobox.js +2 -1
  103. package/dist/components/inline-entity-combobox.js.map +1 -1
  104. package/dist/components/input.d.ts +2 -2
  105. package/dist/components/input.js +2 -1
  106. package/dist/components/input.js.map +1 -1
  107. package/dist/components/modal.d.ts +9 -1
  108. package/dist/components/modal.js +7 -4
  109. package/dist/components/modal.js.map +1 -1
  110. package/dist/components/month-picker.d.ts +2 -1
  111. package/dist/components/month-picker.js +8 -1
  112. package/dist/components/month-picker.js.map +1 -1
  113. package/dist/components/multi-entity-combobox.d.ts +2 -2
  114. package/dist/components/multi-entity-combobox.js +2 -1
  115. package/dist/components/multi-entity-combobox.js.map +1 -1
  116. package/dist/components/multi-select.d.ts +7 -18
  117. package/dist/components/multi-select.js +8 -10
  118. package/dist/components/multi-select.js.map +1 -1
  119. package/dist/components/number-input.d.ts +2 -5
  120. package/dist/components/number-input.js +2 -4
  121. package/dist/components/number-input.js.map +1 -1
  122. package/dist/components/numeric-field.d.ts +5 -2
  123. package/dist/components/numeric-field.js +4 -1
  124. package/dist/components/numeric-field.js.map +1 -1
  125. package/dist/components/one-time-code-input.d.ts +2 -1
  126. package/dist/components/one-time-code-input.js +2 -1
  127. package/dist/components/one-time-code-input.js.map +1 -1
  128. package/dist/components/phone-input.d.ts +1 -1
  129. package/dist/components/phone-input.js +4 -0
  130. package/dist/components/phone-input.js.map +1 -1
  131. package/dist/components/popover.js +3 -3
  132. package/dist/components/popover.js.map +1 -1
  133. package/dist/components/select.d.ts +4 -3
  134. package/dist/components/select.js +2 -1
  135. package/dist/components/select.js.map +1 -1
  136. package/dist/components/series-chart.js.map +1 -1
  137. package/dist/components/server-wake.d.ts +0 -6
  138. package/dist/components/server-wake.js.map +1 -1
  139. package/dist/components/settings-fields.d.ts +4 -2
  140. package/dist/components/settings-fields.js.map +1 -1
  141. package/dist/components/slider.d.ts +3 -2
  142. package/dist/components/slider.js +7 -1
  143. package/dist/components/slider.js.map +1 -1
  144. package/dist/components/stat-tile.d.ts +8 -2
  145. package/dist/components/stat-tile.js +2 -11
  146. package/dist/components/stat-tile.js.map +1 -1
  147. package/dist/components/swatch-picker.d.ts +3 -2
  148. package/dist/components/swatch-picker.js +3 -0
  149. package/dist/components/swatch-picker.js.map +1 -1
  150. package/dist/components/swipeable-row.d.ts +2 -17
  151. package/dist/components/swipeable-row.js +11 -16
  152. package/dist/components/swipeable-row.js.map +1 -1
  153. package/dist/components/text-link.js +3 -1
  154. package/dist/components/text-link.js.map +1 -1
  155. package/dist/components/textarea.d.ts +2 -1
  156. package/dist/components/textarea.js +9 -3
  157. package/dist/components/textarea.js.map +1 -1
  158. package/dist/components/toggle-group.d.ts +2 -2
  159. package/dist/components/toggle-group.js +7 -3
  160. package/dist/components/toggle-group.js.map +1 -1
  161. package/dist/components/tooltip.d.ts +9 -1
  162. package/dist/components/tooltip.js +20 -5
  163. package/dist/components/tooltip.js.map +1 -1
  164. package/dist/components/translation-review.d.ts +10 -2
  165. package/dist/components/translation-review.js +11 -3
  166. package/dist/components/translation-review.js.map +1 -1
  167. package/dist/components/use-table-state.d.ts +31 -3
  168. package/dist/components/use-table-state.js +53 -8
  169. package/dist/components/use-table-state.js.map +1 -1
  170. package/dist/components/user-avatar.d.ts +2 -2
  171. package/dist/components/user-avatar.js.map +1 -1
  172. package/dist/components/wizard-stepper.d.ts +1 -4
  173. package/dist/components/wizard-stepper.js +2 -3
  174. package/dist/components/wizard-stepper.js.map +1 -1
  175. package/dist/currencies.d.ts +23 -0
  176. package/dist/currencies.js +38 -0
  177. package/dist/currencies.js.map +1 -0
  178. package/dist/demo/demo-banner.d.ts +7 -2
  179. package/dist/demo/demo-banner.js.map +1 -1
  180. package/dist/eslint/index.d.ts +83 -0
  181. package/dist/eslint/index.js +69 -0
  182. package/dist/eslint/index.js.map +1 -0
  183. package/dist/eslint/role-utilities.d.ts +48 -0
  184. package/dist/eslint/role-utilities.generated.d.ts +2 -0
  185. package/dist/eslint/role-utilities.generated.js +143 -0
  186. package/dist/eslint/role-utilities.generated.js.map +1 -0
  187. package/dist/eslint/role-utilities.js +43 -0
  188. package/dist/eslint/role-utilities.js.map +1 -0
  189. package/dist/feedback/feedback-menu.d.ts +2 -2
  190. package/dist/feedback/feedback-menu.js.map +1 -1
  191. package/dist/feedback/feedback-thread.d.ts +3 -8
  192. package/dist/feedback/feedback-thread.js +0 -2
  193. package/dist/feedback/feedback-thread.js.map +1 -1
  194. package/dist/hooks/use-dismiss.d.ts +16 -3
  195. package/dist/hooks/use-dismiss.js +14 -2
  196. package/dist/hooks/use-dismiss.js.map +1 -1
  197. package/dist/i18n/defaults.js +5 -1
  198. package/dist/i18n/defaults.js.map +1 -1
  199. package/dist/i18n/german.js +97 -1
  200. package/dist/i18n/german.js.map +1 -1
  201. package/dist/i18n/kit-labels.d.ts +29 -4
  202. package/dist/i18n/kit-labels.js +21 -1
  203. package/dist/i18n/kit-labels.js.map +1 -1
  204. package/dist/i18n/locales/en.js +104 -3
  205. package/dist/i18n/locales/en.js.map +3 -3
  206. package/dist/i18n/locales/es.js +95 -1
  207. package/dist/i18n/locales/es.js.map +1 -1
  208. package/dist/i18n/locales/fr.js +99 -3
  209. package/dist/i18n/locales/fr.js.map +1 -1
  210. package/dist/i18n/locales/hu.js +95 -1
  211. package/dist/i18n/locales/hu.js.map +1 -1
  212. package/dist/i18n/locales/it.js +99 -3
  213. package/dist/i18n/locales/it.js.map +1 -1
  214. package/dist/i18n/locales/zh.js +95 -1
  215. package/dist/i18n/locales/zh.js.map +1 -1
  216. package/dist/i18n/review.js +13 -0
  217. package/dist/i18n/review.js.map +1 -1
  218. package/dist/i18n/shared-labels.js +3 -1
  219. package/dist/i18n/shared-labels.js.map +1 -1
  220. package/dist/index.d.ts +23 -1
  221. package/dist/index.js +40 -2
  222. package/dist/index.js.map +1 -1
  223. package/dist/lib/device-settings.d.ts +72 -0
  224. package/dist/lib/device-settings.js +64 -0
  225. package/dist/lib/device-settings.js.map +1 -0
  226. package/dist/lib/plain-text.d.ts +11 -0
  227. package/dist/lib/plain-text.js +16 -0
  228. package/dist/lib/plain-text.js.map +1 -0
  229. package/dist/lib/refs.d.ts +13 -0
  230. package/dist/lib/refs.js +15 -0
  231. package/dist/lib/refs.js.map +1 -0
  232. package/dist/lib/safe-storage.d.ts +6 -0
  233. package/dist/lib/safe-storage.js +11 -0
  234. package/dist/lib/safe-storage.js.map +1 -1
  235. package/dist/notifications/notification-parts.d.ts +39 -0
  236. package/dist/notifications/notification-parts.js +47 -0
  237. package/dist/notifications/notification-parts.js.map +1 -0
  238. package/dist/notifications/notification-types-setting.d.ts +62 -0
  239. package/dist/notifications/notification-types-setting.js +192 -0
  240. package/dist/notifications/notification-types-setting.js.map +1 -0
  241. package/dist/notifications/notification-types.d.ts +75 -0
  242. package/dist/notifications/notification-types.js +2 -0
  243. package/dist/notifications/notification-types.js.map +1 -0
  244. package/dist/notifications/notifications-labels.d.ts +131 -0
  245. package/dist/notifications/notifications-labels.js +83 -0
  246. package/dist/notifications/notifications-labels.js.map +1 -0
  247. package/dist/notifications/push-device-setting.d.ts +37 -0
  248. package/dist/notifications/push-device-setting.js +164 -0
  249. package/dist/notifications/push-device-setting.js.map +1 -0
  250. package/dist/notifications/push-devices-setting.d.ts +44 -0
  251. package/dist/notifications/push-devices-setting.js +203 -0
  252. package/dist/notifications/push-devices-setting.js.map +1 -0
  253. package/dist/notifications/quiet-hours-setting.d.ts +47 -0
  254. package/dist/notifications/quiet-hours-setting.js +131 -0
  255. package/dist/notifications/quiet-hours-setting.js.map +1 -0
  256. package/dist/notifications/time-zone-select.d.ts +50 -0
  257. package/dist/notifications/time-zone-select.js +76 -0
  258. package/dist/notifications/time-zone-select.js.map +1 -0
  259. package/dist/notifications/unsubscribe-panel.d.ts +53 -0
  260. package/dist/notifications/unsubscribe-panel.js +139 -0
  261. package/dist/notifications/unsubscribe-panel.js.map +1 -0
  262. package/dist/notifications/use-push-device.d.ts +122 -0
  263. package/dist/notifications/use-push-device.js +230 -0
  264. package/dist/notifications/use-push-device.js.map +1 -0
  265. package/dist/rhf/fields.d.ts +36 -29
  266. package/dist/rhf/fields.js +51 -22
  267. package/dist/rhf/fields.js.map +1 -1
  268. package/dist/rhf/form-core.d.ts +5 -4
  269. package/dist/rhf/form-core.js.map +1 -1
  270. package/dist/rhf/form.d.ts +7 -36
  271. package/dist/rhf/form.js +1 -16
  272. package/dist/rhf/form.js.map +1 -1
  273. package/dist/rhf/line-items.d.ts +1 -1
  274. package/dist/rhf/line-items.js.map +1 -1
  275. package/dist/rhf/use-rhf-wizard-step.js.map +1 -1
  276. package/dist/rhf.js.map +1 -1
  277. package/dist/settings/device-reset-setting-labels.d.ts +3 -0
  278. package/dist/settings/device-reset-setting-labels.js +15 -0
  279. package/dist/settings/device-reset-setting-labels.js.map +1 -0
  280. package/dist/settings/device-reset-setting.d.ts +58 -0
  281. package/dist/settings/device-reset-setting.js +51 -0
  282. package/dist/settings/device-reset-setting.js.map +1 -0
  283. package/dist/shell/app-shell.js +5 -0
  284. package/dist/shell/app-shell.js.map +1 -1
  285. package/dist/shell/option-switcher-menu.d.ts +5 -17
  286. package/dist/shell/option-switcher-menu.js +1 -3
  287. package/dist/shell/option-switcher-menu.js.map +1 -1
  288. package/dist/shell/role-switcher.d.ts +1 -4
  289. package/dist/shell/role-switcher.js +2 -3
  290. package/dist/shell/role-switcher.js.map +1 -1
  291. package/dist/shell/topbar-action-menu.d.ts +7 -19
  292. package/dist/shell/topbar-action-menu.js +1 -3
  293. package/dist/shell/topbar-action-menu.js.map +1 -1
  294. package/dist/shell/topbar-controls.d.ts +3 -12
  295. package/dist/shell/topbar-controls.js +6 -9
  296. package/dist/shell/topbar-controls.js.map +1 -1
  297. package/dist/testing/index.d.ts +1 -1
  298. package/dist/testing/index.js +2 -0
  299. package/dist/testing/index.js.map +1 -1
  300. package/dist/testing/viewport.d.ts +25 -2
  301. package/dist/testing/viewport.js +61 -10
  302. package/dist/testing/viewport.js.map +1 -1
  303. package/dist/theme/contrast-tokens.d.ts +42 -4
  304. package/dist/theme/contrast-tokens.js +56 -9
  305. package/dist/theme/contrast-tokens.js.map +1 -1
  306. package/dist/theme/contrast.d.ts +4 -2
  307. package/dist/theme/contrast.js +13 -0
  308. package/dist/theme/contrast.js.map +1 -1
  309. package/dist/theme/palette-derive.d.ts +15 -1
  310. package/dist/theme/palette-derive.js +37 -8
  311. package/dist/theme/palette-derive.js.map +1 -1
  312. package/dist/theme/palette-presets.d.ts +2 -8
  313. package/dist/theme/palette-presets.js +5 -284
  314. package/dist/theme/palette-presets.js.map +1 -1
  315. package/dist/theme/palette-store.js +6 -0
  316. package/dist/theme/palette-store.js.map +1 -1
  317. package/dist/theme/text-size.js +6 -0
  318. package/dist/theme/text-size.js.map +1 -1
  319. package/dist/theme/theme-store.js +6 -0
  320. package/dist/theme/theme-store.js.map +1 -1
  321. package/dist/wizard/types.d.ts +0 -5
  322. package/dist/wizard/types.js +1 -5
  323. package/dist/wizard/types.js.map +1 -1
  324. package/package.json +9 -1
  325. package/src/admin/role-select.tsx +4 -1
  326. package/src/billing/billing-banner.tsx +5 -2
  327. package/src/billing/plan-limit-notice.tsx +5 -2
  328. package/src/chart.ts +5 -3
  329. package/src/components/amount-input.tsx +4 -7
  330. package/src/components/autocomplete.tsx +5 -2
  331. package/src/components/button-look.ts +15 -5
  332. package/src/components/calculator.tsx +2 -7
  333. package/src/components/chart-zoom.tsx +4 -47
  334. package/src/components/checkbox-group.tsx +22 -4
  335. package/src/components/chip-input.tsx +0 -7
  336. package/src/components/column-mapper.tsx +6 -2
  337. package/src/components/combobox.tsx +6 -3
  338. package/src/components/copy-button.tsx +5 -1
  339. package/src/components/country-select.tsx +6 -1
  340. package/src/components/currency-option-list.tsx +8 -42
  341. package/src/components/currency-select.tsx +12 -3
  342. package/src/components/danger-confirm.tsx +3 -3
  343. package/src/components/data-table-filter-popover.tsx +2 -1
  344. package/src/components/data-table-labels.ts +2 -84
  345. package/src/components/data-table-shared.tsx +55 -2
  346. package/src/components/data-table.tsx +29 -17
  347. package/src/components/date-field.tsx +2 -2
  348. package/src/components/date-picker.tsx +3 -0
  349. package/src/components/date-range-picker.tsx +3 -0
  350. package/src/components/dialog-frame.tsx +3 -1
  351. package/src/components/dropdown.tsx +42 -18
  352. package/src/components/entity-combobox.tsx +6 -3
  353. package/src/components/field-base.tsx +0 -11
  354. package/src/components/field-parts.tsx +112 -38
  355. package/src/components/field-strip.tsx +12 -27
  356. package/src/components/field-sync.tsx +0 -7
  357. package/src/components/field.tsx +32 -19
  358. package/src/components/full-bleed-dialog.tsx +4 -3
  359. package/src/components/help-popover.tsx +9 -7
  360. package/src/components/hover-menu.tsx +12 -16
  361. package/src/components/icon-picker.tsx +8 -3
  362. package/src/components/inline-entity-combobox.tsx +6 -3
  363. package/src/components/input.tsx +4 -2
  364. package/src/components/modal.tsx +20 -4
  365. package/src/components/month-picker.tsx +10 -3
  366. package/src/components/multi-entity-combobox.tsx +5 -2
  367. package/src/components/multi-select.tsx +19 -31
  368. package/src/components/number-input.tsx +5 -10
  369. package/src/components/numeric-field.ts +10 -2
  370. package/src/components/one-time-code-input.tsx +5 -3
  371. package/src/components/phone-input.tsx +4 -0
  372. package/src/components/popover.tsx +8 -4
  373. package/src/components/select.tsx +6 -3
  374. package/src/components/series-chart.tsx +1 -1
  375. package/src/components/server-wake.tsx +0 -6
  376. package/src/components/settings-fields.tsx +4 -2
  377. package/src/components/slider.tsx +10 -3
  378. package/src/components/stat-tile.tsx +11 -20
  379. package/src/components/swatch-picker.tsx +9 -4
  380. package/src/components/swipeable-row.tsx +15 -37
  381. package/src/components/text-link.tsx +3 -1
  382. package/src/components/textarea.tsx +11 -4
  383. package/src/components/toggle-group.tsx +21 -5
  384. package/src/components/tooltip.tsx +37 -6
  385. package/src/components/translation-review.tsx +25 -7
  386. package/src/components/use-table-state.ts +91 -10
  387. package/src/components/user-avatar.tsx +2 -2
  388. package/src/components/wizard-stepper.tsx +2 -6
  389. package/src/currencies.ts +70 -0
  390. package/src/demo/demo-banner.tsx +7 -2
  391. package/src/eslint/index.ts +161 -0
  392. package/src/eslint/role-utilities.generated.ts +146 -0
  393. package/src/eslint/role-utilities.ts +99 -0
  394. package/src/feedback/feedback-menu.tsx +2 -2
  395. package/src/feedback/feedback-thread.tsx +3 -8
  396. package/src/hooks/use-dismiss.ts +39 -4
  397. package/src/i18n/defaults.ts +4 -0
  398. package/src/i18n/german.ts +113 -0
  399. package/src/i18n/kit-labels.tsx +66 -6
  400. package/src/i18n/locales/en.ts +6 -0
  401. package/src/i18n/locales/es.ts +106 -0
  402. package/src/i18n/locales/fr.ts +109 -2
  403. package/src/i18n/locales/hu.ts +104 -0
  404. package/src/i18n/locales/it.ts +108 -2
  405. package/src/i18n/locales/zh.ts +96 -0
  406. package/src/i18n/review.ts +13 -0
  407. package/src/i18n/shared-labels.ts +2 -0
  408. package/src/index.ts +53 -1
  409. package/src/lib/device-settings.ts +146 -0
  410. package/src/lib/plain-text.ts +22 -0
  411. package/src/lib/refs.ts +22 -0
  412. package/src/lib/safe-storage.ts +16 -0
  413. package/src/notifications/notification-parts.tsx +83 -0
  414. package/src/notifications/notification-types-setting.tsx +309 -0
  415. package/src/notifications/notification-types.ts +80 -0
  416. package/src/notifications/notifications-labels.ts +238 -0
  417. package/src/notifications/push-device-setting.tsx +224 -0
  418. package/src/notifications/push-devices-setting.tsx +306 -0
  419. package/src/notifications/quiet-hours-setting.tsx +185 -0
  420. package/src/notifications/time-zone-select.tsx +126 -0
  421. package/src/notifications/unsubscribe-panel.tsx +203 -0
  422. package/src/notifications/use-push-device.ts +392 -0
  423. package/src/rhf/fields.tsx +87 -39
  424. package/src/rhf/form-core.tsx +5 -4
  425. package/src/rhf/form.tsx +7 -43
  426. package/src/rhf/line-items.tsx +1 -1
  427. package/src/rhf/use-rhf-wizard-step.ts +4 -4
  428. package/src/rhf.ts +3 -2
  429. package/src/settings/device-reset-setting-labels.ts +20 -0
  430. package/src/settings/device-reset-setting.tsx +119 -0
  431. package/src/shell/app-shell.tsx +8 -0
  432. package/src/shell/option-switcher-menu.tsx +5 -22
  433. package/src/shell/role-switcher.tsx +2 -6
  434. package/src/shell/topbar-action-menu.tsx +7 -24
  435. package/src/shell/topbar-controls.tsx +6 -18
  436. package/src/testing/index.ts +3 -1
  437. package/src/testing/viewport.ts +125 -19
  438. package/src/theme/contrast-tokens.ts +106 -12
  439. package/src/theme/contrast.ts +30 -4
  440. package/src/theme/palette-derive.ts +68 -7
  441. package/src/theme/palette-presets.ts +16 -299
  442. package/src/theme/palette-store.ts +12 -0
  443. package/src/theme/text-size.ts +8 -0
  444. package/src/theme/theme-store.ts +10 -0
  445. package/src/wizard/types.ts +0 -8
  446. package/tokens.css +38 -4
@@ -12,6 +12,7 @@ import {
12
12
  LockedReason,
13
13
  mergeDescribedBy,
14
14
  type DisabledReasonDisplay,
15
+ type FieldHelpProps,
15
16
  useFieldError,
16
17
  useFieldHint,
17
18
  useLockReason,
@@ -38,7 +39,7 @@ import {
38
39
  // open the picker on a click anywhere in the field instead (feedback #224).
39
40
  const PICKER_TYPES = new Set(["date", "datetime-local", "month", "time", "week"]);
40
41
 
41
- export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
42
+ export interface InputProps extends InputHTMLAttributes<HTMLInputElement>, FieldHelpProps {
42
43
  label?: ReactNode;
43
44
  /** Classes for the `<input>` itself, as distinct from `className`, which
44
45
  * styles the field WRAPPER once a `label` turns this into a FloatingField.
@@ -156,6 +157,7 @@ export function Input(props: InputProps) {
156
157
  invalid,
157
158
  error,
158
159
  hint,
160
+ help,
159
161
  showCount,
160
162
  countLabels,
161
163
  passwordLabels,
@@ -171,7 +173,7 @@ export function Input(props: InputProps) {
171
173
  const generated = useId();
172
174
  const fieldId = id ?? generated;
173
175
  const countId = useId();
174
- const hintParts = useFieldHint(hint, rest["aria-describedby"]);
176
+ const hintParts = useFieldHint(hint, rest["aria-describedby"], { help, name: label ?? rest["aria-label"] });
175
177
  const maxLength = rest.maxLength;
176
178
  const counting = Boolean(showCount) && typeof maxLength === "number" && maxLength > 0;
177
179
  const length = useTypedLength(rest.value, rest.defaultValue);
@@ -1,4 +1,4 @@
1
- import { createContext, useEffect, useRef, useState } from "react";
1
+ import { createContext, useEffect, useMemo, useRef, useState } from "react";
2
2
  import { createPortal } from "react-dom";
3
3
  import type {
4
4
  ComponentPropsWithoutRef,
@@ -6,8 +6,10 @@ import type {
6
6
  MouseEvent as ReactMouseEvent,
7
7
  PointerEvent as ReactPointerEvent,
8
8
  ReactNode,
9
+ Ref,
9
10
  } from "react";
10
11
  import { cn } from "../lib/cn";
12
+ import { mergeRefs } from "./field-parts";
11
13
  import { useFocusTrap } from "../hooks/use-focus-trap";
12
14
  import { useBodyScrollLock } from "../hooks/use-body-scroll-lock";
13
15
  import { useOverlayHistory } from "../hooks/use-overlay-history";
@@ -228,6 +230,14 @@ export interface ModalProps extends Omit<ComponentPropsWithoutRef<"div">, "role"
228
230
  * `onClose` still runs, after the param is cleared. Requires a react-router Router.
229
231
  */
230
232
  urlParam?: DialogParam;
233
+ /**
234
+ * The PANEL — the `role="dialog"` element the rest of the props go on, not the
235
+ * backdrop around it (0.35, round 0.35 R4, the follow-up to API-2; as on
236
+ * `FullBleedDialog`). Merged with the panel's own ref, which the focus
237
+ * trap holds. Set while the panel is in the document: `null` while a dialog with
238
+ * `open={false}` is closed, and after a `urlParam` dialog's param is cleared.
239
+ */
240
+ ref?: Ref<HTMLDivElement>;
231
241
  }
232
242
 
233
243
  /**
@@ -286,12 +296,16 @@ function ModalPanel({
286
296
  role = "dialog",
287
297
  urlParam: _urlParam,
288
298
  ownHistoryEntry = true,
299
+ ref,
289
300
  ...rest
290
301
  }: ModalProps & {
291
302
  /** False when the URL already holds an entry for this dialog — see `urlParam`. */
292
303
  ownHistoryEntry?: boolean;
293
304
  }) {
294
305
  const panelRef = useRef<HTMLDivElement>(null);
306
+ // The caller's `ref` beside the trap's (round 0.35 R4): memoised, so the panel is not
307
+ // detached and re-attached on every render.
308
+ const setPanel = useMemo(() => mergeRefs(panelRef, ref), [ref]);
295
309
  const drag = useDragOffset(Boolean(draggable));
296
310
  // Without `open`, mounted means open — the constant `true` every hook below used to
297
311
  // be given. With it, `open` itself.
@@ -357,9 +371,11 @@ function ModalPanel({
357
371
  // One layer on the Escape stack while open (Wave 2, DUP-1): a list, a popover or a
358
372
  // tooltip opened inside takes the key before the dialog does, wherever focus is —
359
373
  // and the dialog gets it even when focus is not in the panel.
360
- useDismissLayer(active, requestClose);
374
+ const layer = useDismissLayer(active, requestClose);
361
375
  const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {
362
- runOwnKeyDown(e, onKeyDown);
376
+ // The caller's handler sees Escape only while this dialog is the layer on top: a
377
+ // tooltip or a list open over it takes that press first (0.35, KS's gear wizard).
378
+ runOwnKeyDown(e, onKeyDown, layer);
363
379
  // To whatever is on top — this dialog, unless something opened over it — and
364
380
  // stopped here. Tab containment lives in useFocusTrap, which listens on the panel.
365
381
  takeEscape(e);
@@ -399,7 +415,7 @@ function ModalPanel({
399
415
  // losing any of the three is silent, and the symptom (a dialog a screen reader
400
416
  // walks straight out of) shows up nowhere near the call site that caused it.
401
417
  {...rest}
402
- ref={panelRef}
418
+ ref={setPanel}
403
419
  // Normalised at runtime too: an untyped caller's `role="presentation"` must not
404
420
  // take the dialog role away (props-passthrough pins that).
405
421
  role={role === "alertdialog" ? "alertdialog" : "dialog"}
@@ -13,7 +13,7 @@ import { splitTriggerAria } from "./trigger-aria";
13
13
  import type { TriggerAria } from "./trigger-aria";
14
14
  import { useKitDateFormatter, useKitLabels, useKitLocale, type LabelOverride } from "../i18n/kit-labels";
15
15
  import { hasContent } from "../lib/presence";
16
- import { FieldBox, FieldLabelLine, LABEL_ABOVE_BOX, mergeRefs, useFieldMessages } from "./field-parts";
16
+ import { FieldBox, FieldLabelLine, LABEL_ABOVE_BOX, mergeRefs, useFieldMessages, type FieldHelpProps } from "./field-parts";
17
17
  import { DEFAULT_MONTH_PICKER_LABELS } from "./month-picker-labels";
18
18
 
19
19
  /**
@@ -63,7 +63,7 @@ function useMonthPickerLabels(partial?: Partial<MonthPickerLabels>): MonthPicker
63
63
  * a `FormEvent`, and this one answers with a month key. Everything else reaches the
64
64
  * field's root, so a test id or a `data-tour` anchor can find it.
65
65
  */
66
- export interface MonthPickerProps extends Omit<ComponentPropsWithoutRef<"div">, "onChange"> {
66
+ export interface MonthPickerProps extends Omit<ComponentPropsWithoutRef<"div">, "onChange">, FieldHelpProps {
67
67
  /**
68
68
  * The selected month as a `"YYYY-MM"` key, or `""` for none.
69
69
  *
@@ -831,6 +831,7 @@ export function MonthPicker(props: MonthPickerProps) {
831
831
  invalid,
832
832
  error,
833
833
  hint,
834
+ help,
834
835
  size = "md",
835
836
  mode = "month",
836
837
  formatOptions,
@@ -877,7 +878,13 @@ export function MonthPicker(props: MonthPickerProps) {
877
878
  // keksdose K4: the caption and the error, on the trigger after the caller's own
878
879
  // description. Painted for `invalid` and a message — not for a bare `aria-invalid`,
879
880
  // which this field has never painted for.
880
- const messages = useFieldMessages({ hint, error, describedBy: rest["aria-describedby"] });
881
+ const messages = useFieldMessages({
882
+ hint,
883
+ help,
884
+ name: label ?? rest["aria-label"],
885
+ error,
886
+ describedBy: rest["aria-describedby"],
887
+ });
881
888
  const [ownAria, wrapperRest] = splitTriggerAria(rest);
882
889
  // The field's trigger is described by the caption and the error too; the stepper
883
890
  // draws neither, so its heading keeps the caller's own description.
@@ -28,13 +28,15 @@ import {
28
28
  useFieldHint,
29
29
  useLockReason,
30
30
  type DisabledReasonDisplay,
31
+ type FieldHelpProps,
31
32
  } from "./field-parts";
32
33
  import { useCommitReason, type CommitScope } from "./write-lock";
33
34
 
34
35
  /** `onChange` is the kit's — "a selection was made", carrying values — rather
35
36
  * than the div's form event, so the DOM's spelling of it is omitted. */
36
37
  export interface MultiEntityComboboxProps<V extends string | number>
37
- extends Omit<ComponentPropsWithoutRef<"div">, "onChange"> {
38
+ extends Omit<ComponentPropsWithoutRef<"div">, "onChange">,
39
+ FieldHelpProps {
38
40
  /** Selected ids. */
39
41
  value: V[];
40
42
  onChange: (value: V[]) => void;
@@ -144,6 +146,7 @@ export function MultiEntityCombobox<V extends string | number>(props: MultiEntit
144
146
  invalid,
145
147
  error,
146
148
  hint,
149
+ help,
147
150
  filter,
148
151
  minChars,
149
152
  debounceMs,
@@ -169,7 +172,7 @@ export function MultiEntityCombobox<V extends string | number>(props: MultiEntit
169
172
  minChars,
170
173
  debounceMs,
171
174
  });
172
- const hintParts = useFieldHint(hint, ariaDescribedBy);
175
+ const hintParts = useFieldHint(hint, ariaDescribedBy, { help, name: label ?? ariaLabel });
173
176
  const field = useFieldError(error, invalid, hintParts.describedBy, ariaInvalid);
174
177
  // The props are the per-instance overrides, the provider the app-wide ones; a
175
178
  // prop left `undefined` falls through to the provider rather than masking it.
@@ -13,6 +13,7 @@ import {
13
13
  useFieldMessages,
14
14
  useLockReason,
15
15
  type DisabledReasonDisplay,
16
+ type FieldHelpProps,
16
17
  } from "./field-parts";
17
18
  import type { CommitScope } from "./write-lock";
18
19
  import {
@@ -46,36 +47,26 @@ export interface MultiSelectOption<V extends string | number = string | number>
46
47
  * inferred from `options` and `value`, so `onChange` hands back `number[]` for number
47
48
  * ids and `string[]` for string ones, and no call site casts. */
48
49
  export interface MultiSelectProps<V extends string | number = string | number>
49
- extends Omit<ComponentPropsWithoutRef<"div">, "onChange"> {
50
+ extends Omit<ComponentPropsWithoutRef<"div">, "onChange">,
51
+ FieldHelpProps {
50
52
  options: MultiSelectOption<V>[];
51
53
  /** The chosen values — the select family's `value` (API-4). */
52
54
  value?: V[];
53
- /** @deprecated 0.34 — use `value`; removed in 0.35 (refactor audit 2026-10, API-4). */
54
- values?: V[];
55
55
  onChange: (next: V[]) => void;
56
- /** @deprecated 0.34 — use `labels.all`; removed in 0.35 (API-4). Displayed when no
57
- * value is selected (i.e. "all"); wins over `placeholder`, as `labels.all` does. */
58
- allLabel?: string;
59
56
  /** Singular/plural countable label, used when 1+ items are selected. Default:
60
57
  * `labels.selectedCount`, else `multiSelect.selectedCount` from the provider — the
61
58
  * bare count in English. */
62
59
  itemLabel?: (count: number) => string;
63
- /** Shown when nothing is picked, unless `labels.all` (or `allLabel`) says otherwise —
64
- * it has always doubled as the "nothing picked" text. */
60
+ /** Shown when nothing is picked, unless `labels.all` says otherwise — it has always
61
+ * doubled as the "nothing picked" text. */
65
62
  placeholder?: string;
66
63
  /** Embedded top-boundary label, matching the native Input/Select fields. */
67
64
  label?: ReactNode;
68
- /** @deprecated 0.34 — use `labels.search`; removed in 0.35 (API-4). */
69
- searchLabel?: string;
70
- /** @deprecated 0.34 — use `labels.selectAll`; removed in 0.35 (API-4). */
71
- selectAllLabel?: string;
72
- /** @deprecated 0.34 — use `labels.clear`; removed in 0.35 (API-4). */
73
- clearLabel?: string;
74
65
  /**
75
66
  * Per-instance overrides of the provider's `multiSelect` namespace, over English — the
76
- * kit's `labels` shape, where this took four string props (API-4). `all` is the trigger
77
- * when nothing is picked: `labels.all`, then `allLabel`, then `placeholder`, then the
78
- * provider's.
67
+ * kit's `labels` shape, where this took four string props until 0.35 (API-4: `allLabel`,
68
+ * `searchLabel`, `selectAllLabel`, `clearLabel`). `all` is the trigger when nothing is
69
+ * picked: `labels.all`, then `placeholder`, then the provider's.
79
70
  */
80
71
  labels?: LabelOverride<MultiSelectLabels>;
81
72
  /**
@@ -141,21 +132,17 @@ export function MultiSelect<V extends string | number = string | number>(props:
141
132
  const {
142
133
  options,
143
134
  value: valueProp,
144
- values,
145
135
  onChange,
146
- allLabel,
147
136
  itemLabel,
148
137
  placeholder,
149
138
  label,
150
- searchLabel,
151
- selectAllLabel,
152
- clearLabel,
153
139
  labels: labelsProp,
154
140
  className,
155
141
  panelClassName,
156
142
  invalid,
157
143
  error,
158
144
  hint,
145
+ help,
159
146
  disabled,
160
147
  disabledReason,
161
148
  disabledReasonDisplay,
@@ -172,7 +159,7 @@ export function MultiSelect<V extends string | number = string | number>(props:
172
159
  "aria-required": ariaRequired,
173
160
  ...rest
174
161
  } = props;
175
- const value = useMemo<V[]>(() => valueProp ?? values ?? [], [valueProp, values]);
162
+ const value = useMemo<V[]>(() => valueProp ?? [], [valueProp]);
176
163
  // The rows as the family's options — the hint is the sublabel, searched like the label.
177
164
  const comboOptions = useMemo(
178
165
  () => options.map((o): ComboOption<V> => ({ value: o.value, label: o.label, sublabel: o.hint, disabled: o.disabled })),
@@ -190,14 +177,13 @@ export function MultiSelect<V extends string | number = string | number>(props:
190
177
  },
191
178
  [ref, triggerRef],
192
179
  );
193
- // `labels` > the deprecated string props > the provider's `multiSelect` > English. `all`
194
- // is resolved apart below: between the instance's and the provider's sits `placeholder`,
195
- // which has always doubled as the "nothing picked" text, and a caller who set it must
196
- // keep seeing it.
180
+ // `labels` > the provider's `multiSelect` > English. `all` is resolved apart below:
181
+ // between the instance's and the provider's sits `placeholder`, which has always
182
+ // doubled as the "nothing picked" text, and a caller who set it must keep seeing it.
197
183
  const text = useKitLabels("multiSelect", DEFAULT_MULTI_SELECT_LABELS, {
198
- search: labelsProp?.search ?? searchLabel,
199
- selectAll: labelsProp?.selectAll ?? selectAllLabel,
200
- clear: labelsProp?.clear ?? clearLabel,
184
+ search: labelsProp?.search,
185
+ selectAll: labelsProp?.selectAll,
186
+ clear: labelsProp?.clear,
201
187
  selectedCount: labelsProp?.selectedCount ?? itemLabel,
202
188
  });
203
189
  const common = useKitLabels("common", DEFAULT_COMMON_LABELS);
@@ -212,6 +198,8 @@ export function MultiSelect<V extends string | number = string | number>(props:
212
198
  // The caller's ids, the caption, a lock's reason, the error — Select's order.
213
199
  const field = useFieldMessages({
214
200
  hint,
201
+ help,
202
+ name: label ?? ariaLabel,
215
203
  error,
216
204
  invalid,
217
205
  describedBy: ariaDescribedBy,
@@ -226,7 +214,7 @@ export function MultiSelect<V extends string | number = string | number>(props:
226
214
  const allChecked = options.length > 0 && options.every((o) => valueSet.has(o.value));
227
215
  const selectedSummary =
228
216
  value.length === 0 || allChecked
229
- ? (labelsProp?.all ?? allLabel ?? placeholder ?? text.all)
217
+ ? (labelsProp?.all ?? placeholder ?? text.all)
230
218
  : text.selectedCount(value.length);
231
219
 
232
220
  const toggle = (o: ComboOption<V>) => {
@@ -9,8 +9,9 @@ import {
9
9
  FLOATING_INPUT_CLASS,
10
10
  FloatingField,
11
11
  } from "./field-base";
12
- import { CURRENCIES } from "./currency-select";
13
- import { FieldCaption, LockedReason, mergeRefs, type DisabledReasonDisplay } from "./field-parts";
12
+ // The data alone (0.35): not the picker, which this field does not render.
13
+ import { CURRENCIES } from "../currencies";
14
+ import { FieldCaption, LockedReason, mergeRefs, type DisabledReasonDisplay, type FieldHelpProps } from "./field-parts";
14
15
  import { useEndWidth, useNumericField } from "./numeric-field";
15
16
  import type { CommitScope } from "./write-lock";
16
17
  import { cn } from "../lib/cn";
@@ -18,7 +19,7 @@ import { commitExpression, formatResult } from "../lib/calc";
18
19
 
19
20
  /** {@link NumberInput}'s props — exported since 0.34 (refactor audit 2026-10, API-9): a
20
21
  * wrapper typed itself off `ComponentProps<typeof NumberInput>` until then. */
21
- export interface NumberInputProps {
22
+ export interface NumberInputProps extends FieldHelpProps {
22
23
  /** The text, DOT-decimal ("1234.5", or a calculation being typed: "12+5"), as
23
24
  * `onChange` reports it — so a caller's `Number(value)` reads it. The field SHOWS it
24
25
  * in the locale's mark (see `locale`). A comma here is read as the decimal mark too,
@@ -35,9 +36,6 @@ export interface NumberInputProps {
35
36
  /** Names the field when it has no visible `label` (a table cell, a phone's display
36
37
  * shape). */
37
38
  "aria-label"?: string;
38
- /** @deprecated 0.34 — use `aria-label`; removed in 0.35 (refactor audit 2026-10, API-1).
39
- * Names the field only when `aria-label` is absent. */
40
- ariaLabel?: string;
41
39
  /** Names for the calculator this field renders — its trigger, and the controls
42
40
  * inside the popover — and for the numpad sheet it opens on a phone. Overrides
43
41
  * for THIS field only: both resolve the `calculator` namespace of
@@ -319,8 +317,7 @@ export function NumberInput(props: NumberInputProps) {
319
317
  onChange,
320
318
  onCommit,
321
319
  label,
322
- "aria-label": ariaLabelAttr,
323
- ariaLabel: ariaLabelProp,
320
+ "aria-label": ariaLabel,
324
321
  labels,
325
322
  placeholder,
326
323
  autoFocus,
@@ -334,8 +331,6 @@ export function NumberInput(props: NumberInputProps) {
334
331
  max,
335
332
  disabledReasonDisplay,
336
333
  } = props;
337
- // The DOM spelling wins; `ariaLabel` is the fallback for call sites not moved yet.
338
- const ariaLabel = ariaLabelAttr ?? ariaLabelProp;
339
334
  const generatedId = useId();
340
335
  const fieldId = id ?? generatedId;
341
336
  // The engine AmountInput shares (DUP-10): the lock (focusable, `readOnly`, nothing
@@ -8,6 +8,7 @@ import {
8
8
  useFieldError,
9
9
  useFieldHint,
10
10
  useLockReason,
11
+ type FieldHelpProps,
11
12
  type FieldHintParts,
12
13
  type LockReason,
13
14
  } from "./field-parts";
@@ -28,7 +29,9 @@ import type { CommitScope } from "./write-lock";
28
29
  */
29
30
 
30
31
  /** The props both fields take and this engine reads. */
31
- export interface NumericFieldProps {
32
+ export interface NumericFieldProps extends FieldHelpProps {
33
+ /** What names the `help` "?" — "About <label>" — with the `aria-label`. */
34
+ label?: ReactNode;
32
35
  hint?: ReactNode;
33
36
  error?: ReactNode;
34
37
  invalid?: boolean;
@@ -39,6 +42,7 @@ export interface NumericFieldProps {
39
42
  calculator?: boolean;
40
43
  variant?: "field" | "display";
41
44
  locale?: string;
45
+ "aria-label"?: string;
42
46
  "aria-describedby"?: string;
43
47
  "aria-invalid"?: boolean | "true" | "false";
44
48
  }
@@ -94,7 +98,11 @@ export function useNumericField(props: NumericFieldProps, { settle, display }: N
94
98
  const lock = useLockReason(props.commit, props.disabledReason);
95
99
  const locked = lock.locked;
96
100
  // §4: a FieldHint is the caption at Large and on touch, as on every field.
97
- const hint = useFieldHint(props.hint, props["aria-describedby"]);
101
+ // A `help` is the label line's one "?" and turns the hint into the caption (0.36).
102
+ const hint = useFieldHint(props.hint, props["aria-describedby"], {
103
+ help: props.help,
104
+ name: props.label ?? props["aria-label"],
105
+ });
98
106
  // The standing advice first, the news second: the caller's ids, the caption, the
99
107
  // error — a lock's reason between the last two, as on Select.
100
108
  const field = useFieldError(
@@ -1,7 +1,7 @@
1
1
  import { useId, useState } from "react";
2
2
  import type { ChangeEvent, ClipboardEvent, FocusEvent, InputHTMLAttributes, ReactNode, Ref } from "react";
3
3
  import { cn } from "../lib/cn";
4
- import { EndHintRow, FieldCaption, useFieldError, useFieldHint } from "./field-parts";
4
+ import { EndHintRow, FieldCaption, useFieldError, useFieldHint, type FieldHelpProps } from "./field-parts";
5
5
  import {
6
6
  FIELD_BASE,
7
7
  FIELD_INVALID,
@@ -60,7 +60,8 @@ export interface OneTimeCodeInputProps
60
60
  extends Omit<
61
61
  InputHTMLAttributes<HTMLInputElement>,
62
62
  "value" | "defaultValue" | "onChange" | "type" | "inputMode" | "autoComplete" | "maxLength" | "pattern"
63
- > {
63
+ >,
64
+ FieldHelpProps {
64
65
  /** The digits so far — a string, so leading zeros survive. */
65
66
  value: string;
66
67
  /** The cleaned code after every edit: digits only, never longer than `length`. */
@@ -130,6 +131,7 @@ export function OneTimeCodeInput(props: OneTimeCodeInputProps) {
130
131
  onComplete,
131
132
  label,
132
133
  hint,
134
+ help,
133
135
  error,
134
136
  invalid: invalidProp,
135
137
  className,
@@ -151,7 +153,7 @@ export function OneTimeCodeInput(props: OneTimeCodeInputProps) {
151
153
  // Text is a caption under the field; a FieldHint rides the label line, and is that
152
154
  // caption at Large and on touch (§4). See `hint`. Through useFieldHint and
153
155
  // useFieldError since 0.34, not copies of their rules (DUP-2, DUP-8).
154
- const hintParts = useFieldHint(hint, ariaDescribedBy);
156
+ const hintParts = useFieldHint(hint, ariaDescribedBy, { help, name: label ?? rest["aria-label"] });
155
157
  const {
156
158
  isInvalid: invalid,
157
159
  describedBy,
@@ -148,6 +148,7 @@ export function PhoneInput({
148
148
  inputClassName,
149
149
  label,
150
150
  hint,
151
+ help,
151
152
  error,
152
153
  invalid,
153
154
  disabled,
@@ -225,6 +226,9 @@ export function PhoneInput({
225
226
  // since 0.34, not a copy of its rule (DUP-2, DUP-8).
226
227
  const messages = useFieldMessages({
227
228
  hint,
229
+ // The number's label line takes the help's "?" (0.36); the hint is then the caption.
230
+ help,
231
+ name: label ?? rest["aria-label"],
228
232
  error,
229
233
  invalid,
230
234
  describedBy: ariaDescribedBy,
@@ -10,7 +10,9 @@ import { dirOf } from "../lib/direction";
10
10
  import type { Direction } from "../lib/direction";
11
11
  import { useKitLabels, type LabelOverride } from "../i18n/kit-labels";
12
12
  import { DEFAULT_POPOVER_LABELS } from "./popover-labels";
13
- import { mergeRefs } from "./field-parts";
13
+ // From ../lib/refs, not field-parts (round 0.36): field-parts renders a HelpPopover for a
14
+ // field's `help`, so importing from there would close a cycle, as it did for Tooltip.
15
+ import { mergeRefs } from "../lib/refs";
14
16
 
15
17
  /** The panel's accessible name. A `role="dialog"` with no name announces as "dialog"
16
18
  * and nothing else, which is worse than the unlabelled div it replaced — so it is a
@@ -159,7 +161,7 @@ export function Popover({
159
161
  // A layer on the Escape stack while open (Wave 2, DUP-1): a list opened inside closes
160
162
  // first, and the dialog this popover sits in only after it — the calculator on an
161
163
  // amount field in a Modal is exactly that.
162
- useDismissLayer(open, close);
164
+ const layer = useDismissLayer(open, close);
163
165
 
164
166
  useFocusTrap(panelRef, {
165
167
  active: open && pos !== null,
@@ -178,8 +180,10 @@ export function Popover({
178
180
  const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {
179
181
  // A caller's own handler first (0.32.2: RowActions stops Enter / Space at the panel);
180
182
  // it used to be dropped, overwritten by this one. A `preventDefault()` on Escape
181
- // there keeps the popover open — the owner's claim, as on the dialogs.
182
- runOwnKeyDown(e, onKeyDownProp);
183
+ // there keeps the popover open — the owner's claim, as on the dialogs. And as there,
184
+ // the handler sees Escape only while this popover is the layer on top: a tooltip or a
185
+ // menu open over it takes that press first (round 0.35 R2, the dialogs' rule).
186
+ runOwnKeyDown(e, onKeyDownProp, layer);
183
187
  // Focus is in here, the normal case: the key is handed to the top layer and STOPPED,
184
188
  // so it does not travel on up the React tree to a dialog around the popover.
185
189
  takeEscape(e);
@@ -6,6 +6,7 @@ import {
6
6
  LockedReason,
7
7
  mergeDescribedBy,
8
8
  type DisabledReasonDisplay,
9
+ type FieldHelpProps,
9
10
  useFieldError,
10
11
  useFieldHint,
11
12
  useLockReason,
@@ -20,7 +21,7 @@ import {
20
21
  fieldBelow,
21
22
  } from "./field-base";
22
23
 
23
- export interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "size"> {
24
+ export interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "size">, FieldHelpProps {
24
25
  label?: ReactNode;
25
26
  /** See {@link Input}'s `invalid`. */
26
27
  invalid?: boolean;
@@ -33,7 +34,8 @@ export interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement
33
34
  * set in the value's type on top of both the label and the value. On an
34
35
  * UNLABELLED Select (no label line) a FieldHint sits at the field's end edge,
35
36
  * outside the box. Since 0.34 a FieldHint is the caption at Large and on a touch
36
- * screen, as on Input (`useInlineHint`); a `HelpPopover` stays a "?". */
37
+ * screen, as on Input (`useInlineHint`); a `HelpPopover` stays a "?". Beside a
38
+ * `help` (0.36) the hint is the caption at every size: the help's "?" is the only one. */
37
39
  hint?: ReactNode;
38
40
  /**
39
41
  * `"sm"`: a 28px, 12px-type select for a toolbar or a table header, where the
@@ -109,6 +111,7 @@ export function Select(props: SelectProps) {
109
111
  invalid,
110
112
  error,
111
113
  hint: hintProp,
114
+ help,
112
115
  size,
113
116
  selectClassName,
114
117
  disabledReason,
@@ -138,7 +141,7 @@ export function Select(props: SelectProps) {
138
141
  // and on a touch screen is its words, a caption like any text (§4; a HelpPopover stays
139
142
  // on the label line, §10.23). See `hint` above. Through useFieldHint since 0.34, not a
140
143
  // copy of its rule (DUP-2, refactor audit 2026-10).
141
- const hintParts = useFieldHint(hintProp, rest["aria-describedby"]);
144
+ const hintParts = useFieldHint(hintProp, rest["aria-describedby"], { help, name: label ?? rest["aria-label"] });
142
145
  const hint = hintParts.labelHint;
143
146
  const { isInvalid, describedBy, errorEl } = useFieldError(
144
147
  error,
@@ -25,7 +25,7 @@
25
25
  // "area"` (and `stack`), and the abscissa may be a row of PERIODS (`x.type:
26
26
  // "category"`) or real dates (`x.type: "time"`) instead of a number the app had to
27
27
  // invent. What each of those does to the zoom is decided in one place,
28
- // `defaultZoomAxes` in `chart-zoom.tsx`.
28
+ // `defaultZoomAxes` in `chart-zoom-core.tsx`.
29
29
  //
30
30
  // **An axis budget (0.15.1).** Every visible axis reserves its band, and four of them
31
31
  // leave a phone nothing to plot. A chart draws at most `maxVisibleAxes`, and — on its
@@ -69,12 +69,6 @@ export interface ServerWakeNoticeProps {
69
69
  * label says "the app". */
70
70
  appName?: string;
71
71
  labels?: LabelOverride<ServerWakeLabels>;
72
- /**
73
- * @deprecated 0.34 — drop it; removed in 0.35. The notice sits at the TOP of the
74
- * screen since 0.34, so there is no bottom nav to clear and this does nothing. It was
75
- * the height kept clear at the bottom (AppShell's `--app-nav-h`).
76
- */
77
- navOffset?: string | number;
78
72
  /** Extra classes on the fixed anchor — a different width (`max-w-*`), or another
79
73
  * `top-*` for an app that wants it under its top bar rather than over it. Merged, so
80
74
  * a class given here replaces the kit's of the same kind. */
@@ -52,7 +52,8 @@ export interface ThemeSettingSelectProps
52
52
  * choice visible without opening anything, in every app (keksdose offered light and dark
53
53
  * only; its store already knew "system"). A {@link ToggleGroup}'s props pass through —
54
54
  * `labelPlacement`, `disabledReason`, `commit`, `size`, `overflow` — minus the options
55
- * and the value, which this owns.
55
+ * and the value, which this owns. `ref` too: the group, whose `focus()` lands on the
56
+ * checked option (pinned in round 0.35 R4; the select variant's `ref` is the `<select>`).
56
57
  *
57
58
  * The options wrap rather than truncate (`overflow="wrap"`), as in its two siblings
58
59
  * {@link TextSizeSetting} and {@link ContrastSetting} (0.32.1, Kurvenschmiede's 0.32
@@ -161,7 +162,8 @@ export function LanguageSetting({ options, ...rest }: LanguageSettingProps) {
161
162
  /**
162
163
  * What {@link TextSizeSetting} and {@link ContrastSetting} take: a {@link ToggleGroup}'s
163
164
  * props — `labelPlacement`, `disabledReason`, `commit`, `size`, `overflow` — minus the
164
- * options and the value, which they own, as {@link ThemeSettingToggleProps} does.
165
+ * options and the value, which they own, as {@link ThemeSettingToggleProps} does. `ref`
166
+ * is the group's, as there (round 0.35 R4).
165
167
  */
166
168
  type AppearanceToggleProps<T extends string> = Omit<ToggleGroupBaseProps<T>, "options" | "label"> & {
167
169
  value: T;
@@ -1,7 +1,7 @@
1
1
  import { useId } from "react";
2
2
  import type { CSSProperties, ChangeEvent, InputHTMLAttributes, ReactNode, Ref } from "react";
3
3
  import { cn } from "../lib/cn";
4
- import { useFieldMessages } from "./field-parts";
4
+ import { useFieldMessages, type FieldHelpProps } from "./field-parts";
5
5
 
6
6
  /**
7
7
  * A range control on a native `<input type="range">`.
@@ -123,7 +123,8 @@ export interface SliderProps
123
123
  extends Omit<
124
124
  InputHTMLAttributes<HTMLInputElement>,
125
125
  "type" | "value" | "defaultValue" | "onChange" | "min" | "max" | "step" | "children"
126
- > {
126
+ >,
127
+ FieldHelpProps {
127
128
  /** The value. On a log scale this is the real value, not the track position. */
128
129
  value: number;
129
130
  /** The new value — a number, not the DOM event, like `ToggleGroup`. Fired on every
@@ -201,6 +202,7 @@ export function Slider({
201
202
  formatValue,
202
203
  label,
203
204
  hint,
205
+ help,
204
206
  readout,
205
207
  marks,
206
208
  className,
@@ -254,7 +256,12 @@ export function Slider({
254
256
  const hasMarkLabels = normalizedMarks.some((m) => m.label !== undefined);
255
257
 
256
258
  // The label line's "?", or the caption under the track (DUP-2).
257
- const messages = useFieldMessages({ hint, describedBy: rest["aria-describedby"] });
259
+ const messages = useFieldMessages({
260
+ hint,
261
+ help,
262
+ name: label ?? rest["aria-label"],
263
+ describedBy: rest["aria-describedby"],
264
+ });
258
265
  const labelHint = messages.labelHint;
259
266
  const hasHeader = label !== undefined || labelHint !== undefined || readout !== undefined;
260
267
  const plainReadout = typeof readout === "string" || typeof readout === "number";