@eifi1/ui-kit 0.51.6 → 0.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (805) hide show
  1. package/README.md +146 -26
  2. package/dist/account/account-parts.d.ts +10 -8
  3. package/dist/account/account-parts.js +1 -18
  4. package/dist/account/account-parts.js.map +1 -1
  5. package/dist/account/data-export-setting-labels.js +1 -1
  6. package/dist/account/data-export-setting-labels.js.map +1 -1
  7. package/dist/account/delete-account-setting-labels.js +1 -1
  8. package/dist/account/delete-account-setting-labels.js.map +1 -1
  9. package/dist/account/email-change-setting-labels.js +1 -1
  10. package/dist/account/email-change-setting-labels.js.map +1 -1
  11. package/dist/account/passkeys-setting.d.ts +9 -2
  12. package/dist/account/passkeys-setting.js +41 -29
  13. package/dist/account/passkeys-setting.js.map +1 -1
  14. package/dist/account/sessions-setting.d.ts +3 -2
  15. package/dist/account/sessions-setting.js +10 -8
  16. package/dist/account/sessions-setting.js.map +1 -1
  17. package/dist/admin/admin-action-confirm.js +3 -7
  18. package/dist/admin/admin-action-confirm.js.map +1 -1
  19. package/dist/admin/admin-parts.d.ts +6 -3
  20. package/dist/admin/admin-parts.js +6 -21
  21. package/dist/admin/admin-parts.js.map +1 -1
  22. package/dist/admin/mail-test-card-labels.js +1 -1
  23. package/dist/admin/mail-test-card-labels.js.map +1 -1
  24. package/dist/admin/plan-change-labels.d.ts +2 -2
  25. package/dist/admin/plan-change-labels.js +1 -17
  26. package/dist/admin/plan-change-labels.js.map +1 -1
  27. package/dist/admin/plan-change.d.ts +3 -42
  28. package/dist/admin/plan-change.js +1 -1
  29. package/dist/admin/plan-change.js.map +1 -1
  30. package/dist/admin/reviewer-scope-editor.js +3 -3
  31. package/dist/admin/reviewer-scope-editor.js.map +1 -1
  32. package/dist/auth/auth-errors-labels.d.ts +11 -0
  33. package/dist/auth/auth-errors-labels.js +13 -0
  34. package/dist/auth/auth-errors-labels.js.map +1 -0
  35. package/dist/auth/auth-errors.d.ts +7 -23
  36. package/dist/auth/auth-errors.js +2 -15
  37. package/dist/auth/auth-errors.js.map +1 -1
  38. package/dist/auth/complete-name-dialog.d.ts +3 -2
  39. package/dist/auth/complete-name-dialog.js +3 -5
  40. package/dist/auth/complete-name-dialog.js.map +1 -1
  41. package/dist/auth/forgot-password-form-labels.js +1 -1
  42. package/dist/auth/forgot-password-form-labels.js.map +1 -1
  43. package/dist/auth/forgot-password-form.js +7 -2
  44. package/dist/auth/forgot-password-form.js.map +1 -1
  45. package/dist/auth/register-form-labels.js +1 -1
  46. package/dist/auth/register-form-labels.js.map +1 -1
  47. package/dist/auth/reset-password-form-labels.js +1 -1
  48. package/dist/auth/reset-password-form-labels.js.map +1 -1
  49. package/dist/auth/reset-password-form.js +5 -1
  50. package/dist/auth/reset-password-form.js.map +1 -1
  51. package/dist/auth/sign-in-form-labels.js +1 -1
  52. package/dist/auth/sign-in-form-labels.js.map +1 -1
  53. package/dist/auth/status-parts.d.ts +0 -3
  54. package/dist/auth/status-parts.js +0 -4
  55. package/dist/auth/status-parts.js.map +1 -1
  56. package/dist/auth/verify-email-labels.js +1 -1
  57. package/dist/auth/verify-email-labels.js.map +1 -1
  58. package/dist/auth/verify-email.js +7 -2
  59. package/dist/auth/verify-email.js.map +1 -1
  60. package/dist/billing/cancel-request.d.ts +11 -2
  61. package/dist/billing/cancel-request.js +15 -3
  62. package/dist/billing/cancel-request.js.map +1 -1
  63. package/dist/billing/cancel-subscription.d.ts +22 -10
  64. package/dist/billing/cancel-subscription.js +8 -11
  65. package/dist/billing/cancel-subscription.js.map +1 -1
  66. package/dist/billing/dialog-close.d.ts +29 -0
  67. package/dist/billing/dialog-close.js +8 -0
  68. package/dist/billing/dialog-close.js.map +1 -0
  69. package/dist/billing/plan-card.d.ts +14 -4
  70. package/dist/billing/plan-card.js +15 -8
  71. package/dist/billing/plan-card.js.map +1 -1
  72. package/dist/billing/plan-change-labels.d.ts +42 -0
  73. package/dist/billing/plan-change-labels.js +22 -0
  74. package/dist/billing/plan-change-labels.js.map +1 -0
  75. package/dist/billing/plan-switch.d.ts +21 -9
  76. package/dist/billing/plan-switch.js +10 -8
  77. package/dist/billing/plan-switch.js.map +1 -1
  78. package/dist/chart.d.ts +12 -0
  79. package/dist/chart.js +16 -1
  80. package/dist/chart.js.map +1 -1
  81. package/dist/components/account-chips.d.ts +5 -5
  82. package/dist/components/account-chips.js +11 -13
  83. package/dist/components/account-chips.js.map +1 -1
  84. package/dist/components/alert-banner.d.ts +16 -5
  85. package/dist/components/alert-banner.js +46 -1
  86. package/dist/components/alert-banner.js.map +1 -1
  87. package/dist/components/amount-input.d.ts +22 -4
  88. package/dist/components/amount-input.js +3 -3
  89. package/dist/components/amount-input.js.map +1 -1
  90. package/dist/components/autocomplete.js +57 -65
  91. package/dist/components/autocomplete.js.map +1 -1
  92. package/dist/components/bulk-action-bar.d.ts +12 -2
  93. package/dist/components/bulk-action-bar.js +65 -21
  94. package/dist/components/bulk-action-bar.js.map +1 -1
  95. package/dist/components/button-look.d.ts +5 -5
  96. package/dist/components/button-look.js.map +1 -1
  97. package/dist/components/button.d.ts +2 -2
  98. package/dist/components/button.js.map +1 -1
  99. package/dist/components/calculator.d.ts +21 -2
  100. package/dist/components/calculator.js +53 -14
  101. package/dist/components/calculator.js.map +1 -1
  102. package/dist/components/chart-edge.d.ts +16 -0
  103. package/dist/components/chart-edge.js +14 -1
  104. package/dist/components/chart-edge.js.map +1 -1
  105. package/dist/components/chart-figure.d.ts +13 -0
  106. package/dist/components/chart-figure.js +15 -0
  107. package/dist/components/chart-figure.js.map +1 -0
  108. package/dist/components/chart-zoom-core.js +1 -4
  109. package/dist/components/chart-zoom-core.js.map +1 -1
  110. package/dist/components/chart.d.ts +8 -1
  111. package/dist/components/chart.js +19 -10
  112. package/dist/components/chart.js.map +1 -1
  113. package/dist/components/combobox-core.d.ts +119 -7
  114. package/dist/components/combobox-core.js +151 -46
  115. package/dist/components/combobox-core.js.map +1 -1
  116. package/dist/components/combobox.d.ts +1 -1
  117. package/dist/components/combobox.js +142 -131
  118. package/dist/components/combobox.js.map +1 -1
  119. package/dist/components/copy-button.d.ts +6 -5
  120. package/dist/components/copy-button.js +5 -3
  121. package/dist/components/copy-button.js.map +1 -1
  122. package/dist/components/country-select.js +2 -2
  123. package/dist/components/country-select.js.map +1 -1
  124. package/dist/components/data-table-column-settings.d.ts +1 -1
  125. package/dist/components/data-table-column-settings.js +33 -7
  126. package/dist/components/data-table-column-settings.js.map +1 -1
  127. package/dist/components/data-table-filters.d.ts +4 -2
  128. package/dist/components/data-table-filters.js +2 -2
  129. package/dist/components/data-table-filters.js.map +1 -1
  130. package/dist/components/data-table-fit.d.ts +6 -4
  131. package/dist/components/data-table-fit.js +4 -1
  132. package/dist/components/data-table-fit.js.map +1 -1
  133. package/dist/components/data-table-groups.d.ts +1 -1
  134. package/dist/components/data-table-groups.js.map +1 -1
  135. package/dist/components/data-table-head.d.ts +1 -1
  136. package/dist/components/data-table-head.js +15 -12
  137. package/dist/components/data-table-head.js.map +1 -1
  138. package/dist/components/data-table-mobile.d.ts +36 -7
  139. package/dist/components/data-table-mobile.js +63 -31
  140. package/dist/components/data-table-mobile.js.map +1 -1
  141. package/dist/components/data-table-pagination.js +11 -6
  142. package/dist/components/data-table-pagination.js.map +1 -1
  143. package/dist/components/data-table-resize.d.ts +1 -1
  144. package/dist/components/data-table-resize.js.map +1 -1
  145. package/dist/components/data-table-row-actions.d.ts +2 -2
  146. package/dist/components/data-table-row-actions.js.map +1 -1
  147. package/dist/components/data-table-row.d.ts +6 -2
  148. package/dist/components/data-table-row.js +17 -10
  149. package/dist/components/data-table-row.js.map +1 -1
  150. package/dist/components/data-table-selection.d.ts +1 -1
  151. package/dist/components/data-table-selection.js.map +1 -1
  152. package/dist/components/data-table-shared.d.ts +10 -2
  153. package/dist/components/data-table-shared.js +18 -0
  154. package/dist/components/data-table-shared.js.map +1 -1
  155. package/dist/components/data-table-sort.d.ts +21 -2
  156. package/dist/components/data-table-sort.js +24 -0
  157. package/dist/components/data-table-sort.js.map +1 -1
  158. package/dist/components/data-table-virtual.d.ts +1 -1
  159. package/dist/components/data-table-virtual.js +18 -6
  160. package/dist/components/data-table-virtual.js.map +1 -1
  161. package/dist/components/data-table.d.ts +25 -8
  162. package/dist/components/data-table.js +154 -25
  163. package/dist/components/data-table.js.map +1 -1
  164. package/dist/components/date-field.d.ts +24 -2
  165. package/dist/components/date-field.js +33 -8
  166. package/dist/components/date-field.js.map +1 -1
  167. package/dist/components/date-picker.d.ts +15 -2
  168. package/dist/components/date-picker.js +55 -26
  169. package/dist/components/date-picker.js.map +1 -1
  170. package/dist/components/date-range-picker.d.ts +47 -20
  171. package/dist/components/date-range-picker.js +23 -7
  172. package/dist/components/date-range-picker.js.map +1 -1
  173. package/dist/components/dialog-frame.d.ts +2 -1
  174. package/dist/components/dialog-frame.js.map +1 -1
  175. package/dist/components/entity-combobox.js +4 -2
  176. package/dist/components/entity-combobox.js.map +1 -1
  177. package/dist/components/error-boundary.js +37 -30
  178. package/dist/components/error-boundary.js.map +1 -1
  179. package/dist/components/{ui-labels.d.ts → field-base-labels.d.ts} +0 -2
  180. package/dist/components/{ui-labels.js → field-base-labels.js} +2 -9
  181. package/dist/components/field-base-labels.js.map +1 -0
  182. package/dist/components/field-base.d.ts +4 -3
  183. package/dist/components/field-base.js +3 -3
  184. package/dist/components/field-base.js.map +1 -1
  185. package/dist/components/field-sync-labels.d.ts +1 -0
  186. package/dist/components/field-sync-labels.js.map +1 -1
  187. package/dist/components/field-sync.d.ts +23 -1
  188. package/dist/components/field-sync.js.map +1 -1
  189. package/dist/components/form-actions.js +11 -5
  190. package/dist/components/form-actions.js.map +1 -1
  191. package/dist/components/hover-menu.d.ts +3 -0
  192. package/dist/components/hover-menu.js +5 -3
  193. package/dist/components/hover-menu.js.map +1 -1
  194. package/dist/components/icon-button.js +14 -9
  195. package/dist/components/icon-button.js.map +1 -1
  196. package/dist/components/inline-confirm.d.ts +43 -0
  197. package/dist/components/inline-confirm.js +67 -0
  198. package/dist/components/inline-confirm.js.map +1 -0
  199. package/dist/components/inline-entity-combobox.d.ts +4 -3
  200. package/dist/components/inline-entity-combobox.js +150 -141
  201. package/dist/components/inline-entity-combobox.js.map +1 -1
  202. package/dist/components/input.js +1 -1
  203. package/dist/components/input.js.map +1 -1
  204. package/dist/components/jump-calendar.js +28 -112
  205. package/dist/components/jump-calendar.js.map +1 -1
  206. package/dist/components/legal-page.d.ts +3 -1
  207. package/dist/components/legal-page.js +3 -2
  208. package/dist/components/legal-page.js.map +1 -1
  209. package/dist/components/legal.d.ts +4 -2
  210. package/dist/components/legal.js.map +1 -1
  211. package/dist/components/lightbox.d.ts +2 -2
  212. package/dist/components/lightbox.js +17 -6
  213. package/dist/components/lightbox.js.map +1 -1
  214. package/dist/components/list.d.ts +6 -2
  215. package/dist/components/list.js +4 -3
  216. package/dist/components/list.js.map +1 -1
  217. package/dist/components/measured-grid.d.ts +1 -1
  218. package/dist/components/measured-grid.js +2 -1
  219. package/dist/components/measured-grid.js.map +1 -1
  220. package/dist/components/mini-calendar.js +3 -5
  221. package/dist/components/mini-calendar.js.map +1 -1
  222. package/dist/components/modal.d.ts +24 -0
  223. package/dist/components/modal.js +12 -4
  224. package/dist/components/modal.js.map +1 -1
  225. package/dist/components/money-draft.js +7 -5
  226. package/dist/components/money-draft.js.map +1 -1
  227. package/dist/components/money-field.d.ts +2 -2
  228. package/dist/components/money-field.js.map +1 -1
  229. package/dist/components/month-grid.d.ts +55 -0
  230. package/dist/components/month-grid.js +148 -0
  231. package/dist/components/month-grid.js.map +1 -0
  232. package/dist/components/month-picker.d.ts +36 -4
  233. package/dist/components/month-picker.js +123 -146
  234. package/dist/components/month-picker.js.map +1 -1
  235. package/dist/components/multi-entity-combobox.js +2 -1
  236. package/dist/components/multi-entity-combobox.js.map +1 -1
  237. package/dist/components/multi-select.d.ts +2 -2
  238. package/dist/components/multi-select.js +11 -6
  239. package/dist/components/multi-select.js.map +1 -1
  240. package/dist/components/number-field.d.ts +6 -4
  241. package/dist/components/number-field.js +3 -2
  242. package/dist/components/number-field.js.map +1 -1
  243. package/dist/components/number-input.d.ts +4 -1
  244. package/dist/components/number-input.js +3 -2
  245. package/dist/components/number-input.js.map +1 -1
  246. package/dist/components/numpad-sheet.js.map +1 -1
  247. package/dist/components/picker-sheet.js +2 -1
  248. package/dist/components/picker-sheet.js.map +1 -1
  249. package/dist/components/pie-chart-labels.d.ts +7 -0
  250. package/dist/components/pie-chart-labels.js +1 -0
  251. package/dist/components/pie-chart-labels.js.map +1 -1
  252. package/dist/components/pie-chart.d.ts +5 -3
  253. package/dist/components/pie-chart.js +7 -22
  254. package/dist/components/pie-chart.js.map +1 -1
  255. package/dist/components/popover.d.ts +3 -0
  256. package/dist/components/popover.js +7 -1
  257. package/dist/components/popover.js.map +1 -1
  258. package/dist/components/reauth-dialog.d.ts +4 -5
  259. package/dist/components/reauth-dialog.js +1 -4
  260. package/dist/components/reauth-dialog.js.map +1 -1
  261. package/dist/components/row-actions.js +2 -1
  262. package/dist/components/row-actions.js.map +1 -1
  263. package/dist/components/section-nav.d.ts +7 -0
  264. package/dist/components/section-nav.js.map +1 -1
  265. package/dist/components/series-chart-axes.d.ts +10 -3
  266. package/dist/components/series-chart-axes.js +1 -0
  267. package/dist/components/series-chart-axes.js.map +1 -1
  268. package/dist/components/series-chart-labels.d.ts +7 -4
  269. package/dist/components/series-chart-labels.js.map +1 -1
  270. package/dist/components/series-chart.d.ts +31 -7
  271. package/dist/components/series-chart.js +72 -29
  272. package/dist/components/series-chart.js.map +1 -1
  273. package/dist/components/share-card.js +3 -3
  274. package/dist/components/share-card.js.map +1 -1
  275. package/dist/components/sign-chip-labels.d.ts +1 -0
  276. package/dist/components/sign-chip-labels.js.map +1 -1
  277. package/dist/components/sign-chip.d.ts +10 -1
  278. package/dist/components/sign-chip.js.map +1 -1
  279. package/dist/components/tabs-labels.d.ts +2 -0
  280. package/dist/components/tabs-labels.js +11 -0
  281. package/dist/components/tabs-labels.js.map +1 -0
  282. package/dist/components/tabs.d.ts +1 -1
  283. package/dist/components/tabs.js +13 -11
  284. package/dist/components/tabs.js.map +1 -1
  285. package/dist/components/toggle-legend.d.ts +2 -2
  286. package/dist/components/toggle-legend.js +6 -6
  287. package/dist/components/toggle-legend.js.map +1 -1
  288. package/dist/components/translation-review-editor.d.ts +4 -2
  289. package/dist/components/translation-review-editor.js +2 -3
  290. package/dist/components/translation-review-editor.js.map +1 -1
  291. package/dist/components/translation-review.d.ts +2 -1
  292. package/dist/components/translation-review.js +2 -2
  293. package/dist/components/translation-review.js.map +1 -1
  294. package/dist/components/treemap-labels.d.ts +26 -0
  295. package/dist/components/treemap-labels.js +10 -0
  296. package/dist/components/treemap-labels.js.map +1 -0
  297. package/dist/components/treemap-layout.d.ts +62 -0
  298. package/dist/components/treemap-layout.js +126 -0
  299. package/dist/components/treemap-layout.js.map +1 -0
  300. package/dist/components/treemap.d.ts +140 -17
  301. package/dist/components/treemap.js +324 -97
  302. package/dist/components/treemap.js.map +1 -1
  303. package/dist/components/use-table-state.d.ts +5 -5
  304. package/dist/components/use-table-state.js +4 -1
  305. package/dist/components/use-table-state.js.map +1 -1
  306. package/dist/data-table.d.ts +6 -2
  307. package/dist/data-table.js +7 -2
  308. package/dist/data-table.js.map +1 -1
  309. package/dist/eslint/index.js +1 -1
  310. package/dist/eslint/role-utilities.d.ts +36 -7
  311. package/dist/eslint/role-utilities.js +42 -9
  312. package/dist/eslint/role-utilities.js.map +1 -1
  313. package/dist/feedback/feedback-dialog.d.ts +25 -16
  314. package/dist/feedback/feedback-dialog.js +6 -2
  315. package/dist/feedback/feedback-dialog.js.map +1 -1
  316. package/dist/feedback/feedback-mutation.d.ts +30 -0
  317. package/dist/feedback/feedback-mutation.js +16 -0
  318. package/dist/feedback/feedback-mutation.js.map +1 -0
  319. package/dist/feedback/feedback-page-link.d.ts +53 -0
  320. package/dist/feedback/feedback-page-link.js +37 -0
  321. package/dist/feedback/feedback-page-link.js.map +1 -0
  322. package/dist/feedback/feedback-public-list.d.ts +12 -3
  323. package/dist/feedback/feedback-public-list.js +2 -1
  324. package/dist/feedback/feedback-public-list.js.map +1 -1
  325. package/dist/feedback/feedback-replies.d.ts +3 -1
  326. package/dist/feedback/feedback-replies.js +5 -4
  327. package/dist/feedback/feedback-replies.js.map +1 -1
  328. package/dist/feedback/feedback-row-detail-labels.js +5 -0
  329. package/dist/feedback/feedback-row-detail-labels.js.map +1 -1
  330. package/dist/feedback/feedback-row-detail.d.ts +64 -28
  331. package/dist/feedback/feedback-row-detail.js +30 -28
  332. package/dist/feedback/feedback-row-detail.js.map +1 -1
  333. package/dist/feedback/feedback-status-undo.d.ts +30 -11
  334. package/dist/feedback/feedback-status-undo.js +10 -15
  335. package/dist/feedback/feedback-status-undo.js.map +1 -1
  336. package/dist/feedback/feedback-submit-dialog.d.ts +1 -1
  337. package/dist/feedback/feedback-submit-dialog.js +1 -1
  338. package/dist/feedback/feedback-submit-dialog.js.map +1 -1
  339. package/dist/feedback/feedback-submit.js +9 -3
  340. package/dist/feedback/feedback-submit.js.map +1 -1
  341. package/dist/feedback/feedback-swipe.d.ts +1 -1
  342. package/dist/feedback/feedback-swipe.js.map +1 -1
  343. package/dist/feedback/feedback-table.d.ts +21 -9
  344. package/dist/feedback/feedback-table.js +45 -25
  345. package/dist/feedback/feedback-table.js.map +1 -1
  346. package/dist/feedback/feedback-thread-labels.d.ts +2 -2
  347. package/dist/feedback/feedback-thread-labels.js.map +1 -1
  348. package/dist/feedback/feedback-thread.d.ts +24 -23
  349. package/dist/feedback/feedback-thread.js +2 -1
  350. package/dist/feedback/feedback-thread.js.map +1 -1
  351. package/dist/feedback.d.ts +34 -0
  352. package/dist/feedback.js +42 -0
  353. package/dist/feedback.js.map +1 -1
  354. package/dist/hooks/use-dismiss.js.map +1 -1
  355. package/dist/hooks/use-focus-trap.d.ts +35 -0
  356. package/dist/hooks/use-focus-trap.js +6 -4
  357. package/dist/hooks/use-focus-trap.js.map +1 -1
  358. package/dist/hooks/use-hotkey.d.ts +5 -2
  359. package/dist/hooks/use-hotkey.js +5 -4
  360. package/dist/hooks/use-hotkey.js.map +1 -1
  361. package/dist/hooks/use-long-press.d.ts +7 -4
  362. package/dist/hooks/use-long-press.js +3 -0
  363. package/dist/hooks/use-long-press.js.map +1 -1
  364. package/dist/hooks/use-media-query.js +12 -4
  365. package/dist/hooks/use-media-query.js.map +1 -1
  366. package/dist/hooks/use-mounted.d.ts +22 -0
  367. package/dist/hooks/use-mounted.js +24 -0
  368. package/dist/hooks/use-mounted.js.map +1 -0
  369. package/dist/hooks/use-overlay-history.d.ts +7 -1
  370. package/dist/hooks/use-overlay-history.js +35 -5
  371. package/dist/hooks/use-overlay-history.js.map +1 -1
  372. package/dist/i18n/defaults.js +4 -5
  373. package/dist/i18n/defaults.js.map +1 -1
  374. package/dist/i18n/german.js +7 -1
  375. package/dist/i18n/german.js.map +1 -1
  376. package/dist/i18n/kit-labels.d.ts +9 -2
  377. package/dist/i18n/kit-labels.js.map +1 -1
  378. package/dist/i18n/locales/en.js +20 -41
  379. package/dist/i18n/locales/en.js.map +3 -3
  380. package/dist/i18n/locales/es.js +7 -1
  381. package/dist/i18n/locales/es.js.map +1 -1
  382. package/dist/i18n/locales/fr.js +20 -10
  383. package/dist/i18n/locales/fr.js.map +1 -1
  384. package/dist/i18n/locales/hu.js +9 -1
  385. package/dist/i18n/locales/hu.js.map +1 -1
  386. package/dist/i18n/locales/it.js +7 -1
  387. package/dist/i18n/locales/it.js.map +1 -1
  388. package/dist/i18n/locales/zh.js +8 -1
  389. package/dist/i18n/locales/zh.js.map +1 -1
  390. package/dist/i18n/review.js +5 -0
  391. package/dist/i18n/review.js.map +1 -1
  392. package/dist/index.d.ts +64 -17
  393. package/dist/index.js +77 -12
  394. package/dist/index.js.map +1 -1
  395. package/dist/landing/routing.d.ts +3 -1
  396. package/dist/landing/routing.js +4 -7
  397. package/dist/landing/routing.js.map +1 -1
  398. package/dist/lib/broadcast.d.ts +17 -0
  399. package/dist/lib/broadcast.js +30 -0
  400. package/dist/lib/broadcast.js.map +1 -0
  401. package/dist/lib/calc.d.ts +7 -1
  402. package/dist/lib/calc.js +3 -1
  403. package/dist/lib/calc.js.map +1 -1
  404. package/dist/lib/clipboard-minus.d.ts +2 -2
  405. package/dist/lib/clipboard-minus.js +1 -1
  406. package/dist/lib/clipboard-minus.js.map +1 -1
  407. package/dist/lib/date-format.d.ts +37 -2
  408. package/dist/lib/date-format.js +34 -8
  409. package/dist/lib/date-format.js.map +1 -1
  410. package/dist/lib/day-format.d.ts +46 -0
  411. package/dist/lib/day-format.js +46 -0
  412. package/dist/lib/day-format.js.map +1 -0
  413. package/dist/lib/decimal-marks.d.ts +7 -1
  414. package/dist/lib/decimal-marks.js +5 -2
  415. package/dist/lib/decimal-marks.js.map +1 -1
  416. package/dist/lib/describe-failure.d.ts +14 -0
  417. package/dist/lib/describe-failure.js +9 -0
  418. package/dist/lib/describe-failure.js.map +1 -0
  419. package/dist/lib/direction.d.ts +16 -0
  420. package/dist/lib/direction.js +9 -1
  421. package/dist/lib/direction.js.map +1 -1
  422. package/dist/lib/focus-left.d.ts +63 -0
  423. package/dist/lib/focus-left.js +67 -0
  424. package/dist/lib/focus-left.js.map +1 -0
  425. package/dist/lib/format.d.ts +5 -3
  426. package/dist/lib/format.js +16 -13
  427. package/dist/lib/format.js.map +1 -1
  428. package/dist/lib/http-status.d.ts +24 -0
  429. package/dist/lib/http-status.js +14 -0
  430. package/dist/lib/http-status.js.map +1 -0
  431. package/dist/lib/intl-cache.d.ts +14 -0
  432. package/dist/lib/intl-cache.js +15 -0
  433. package/dist/lib/intl-cache.js.map +1 -0
  434. package/dist/lib/isin.d.ts +10 -0
  435. package/dist/lib/isin.js.map +1 -1
  436. package/dist/lib/iso-day.d.ts +11 -0
  437. package/dist/lib/iso-day.js +8 -0
  438. package/dist/lib/iso-day.js.map +1 -0
  439. package/dist/lib/lazy-with-fallback.d.ts +31 -0
  440. package/dist/lib/lazy-with-fallback.js +40 -0
  441. package/dist/lib/lazy-with-fallback.js.map +1 -0
  442. package/dist/lib/path-pattern.d.ts +34 -0
  443. package/dist/lib/path-pattern.js +24 -0
  444. package/dist/lib/path-pattern.js.map +1 -0
  445. package/dist/lib/reduced-motion.d.ts +2 -1
  446. package/dist/lib/reduced-motion.js.map +1 -1
  447. package/dist/lib/round.d.ts +2 -1
  448. package/dist/lib/round.js +2 -1
  449. package/dist/lib/round.js.map +1 -1
  450. package/dist/lib/safe-storage.d.ts +24 -5
  451. package/dist/lib/safe-storage.js +27 -2
  452. package/dist/lib/safe-storage.js.map +1 -1
  453. package/dist/lib/session-refresh.js +1 -1
  454. package/dist/lib/session-refresh.js.map +1 -1
  455. package/dist/lib/share-format.d.ts +13 -0
  456. package/dist/lib/share-format.js +10 -0
  457. package/dist/lib/share-format.js.map +1 -0
  458. package/dist/lib/text-case.d.ts +17 -0
  459. package/dist/lib/text-case.js +8 -0
  460. package/dist/lib/text-case.js.map +1 -0
  461. package/dist/lib/text-match.d.ts +38 -0
  462. package/dist/lib/text-match.js +24 -2
  463. package/dist/lib/text-match.js.map +1 -1
  464. package/dist/lib/thenable.d.ts +13 -0
  465. package/dist/lib/thenable.js +8 -0
  466. package/dist/lib/thenable.js.map +1 -0
  467. package/dist/lib/translation-review.d.ts +7 -2
  468. package/dist/lib/translation-review.js +4 -4
  469. package/dist/lib/translation-review.js.map +1 -1
  470. package/dist/notifications/device-zone-report.js +1 -1
  471. package/dist/notifications/device-zone-report.js.map +1 -1
  472. package/dist/notifications/notification-bell.d.ts +2 -1
  473. package/dist/notifications/notification-bell.js +3 -3
  474. package/dist/notifications/notification-bell.js.map +1 -1
  475. package/dist/notifications/notification-inbox.d.ts +10 -6
  476. package/dist/notifications/notification-inbox.js +26 -48
  477. package/dist/notifications/notification-inbox.js.map +1 -1
  478. package/dist/notifications/notification-parts.d.ts +3 -2
  479. package/dist/notifications/notification-parts.js +1 -3
  480. package/dist/notifications/notification-parts.js.map +1 -1
  481. package/dist/notifications/notification-types-setting.js +1 -1
  482. package/dist/notifications/notification-types-setting.js.map +1 -1
  483. package/dist/notifications/notifications-labels.d.ts +6 -0
  484. package/dist/notifications/notifications-labels.js +1 -0
  485. package/dist/notifications/notifications-labels.js.map +1 -1
  486. package/dist/notifications/push-device-setting.js +1 -1
  487. package/dist/notifications/push-device-setting.js.map +1 -1
  488. package/dist/notifications/push-devices-setting.d.ts +2 -1
  489. package/dist/notifications/push-devices-setting.js +27 -49
  490. package/dist/notifications/push-devices-setting.js.map +1 -1
  491. package/dist/notifications/quiet-hours-setting.d.ts +10 -3
  492. package/dist/notifications/quiet-hours-setting.js +65 -26
  493. package/dist/notifications/quiet-hours-setting.js.map +1 -1
  494. package/dist/notifications/unsubscribe-panel.js +4 -7
  495. package/dist/notifications/unsubscribe-panel.js.map +1 -1
  496. package/dist/notifications/use-push-device.d.ts +39 -1
  497. package/dist/notifications/use-push-device.js +28 -7
  498. package/dist/notifications/use-push-device.js.map +1 -1
  499. package/dist/offline/query-persistence.d.ts +3 -1
  500. package/dist/offline/query-persistence.js +19 -2
  501. package/dist/offline/query-persistence.js.map +1 -1
  502. package/dist/rhf/fields.d.ts +11 -4
  503. package/dist/rhf/fields.js.map +1 -1
  504. package/dist/search/command-palette.js +1 -1
  505. package/dist/search/command-palette.js.map +1 -1
  506. package/dist/search/global-search.js +19 -9
  507. package/dist/search/global-search.js.map +1 -1
  508. package/dist/search/use-command-key.d.ts +12 -1
  509. package/dist/search/use-command-key.js +3 -12
  510. package/dist/search/use-command-key.js.map +1 -1
  511. package/dist/search.d.ts +7 -0
  512. package/dist/search.js +10 -0
  513. package/dist/search.js.map +1 -1
  514. package/dist/settings/use-settings-focus.js +1 -0
  515. package/dist/settings/use-settings-focus.js.map +1 -1
  516. package/dist/shell/account-menu-language.d.ts +21 -5
  517. package/dist/shell/account-menu-language.js +3 -1
  518. package/dist/shell/account-menu-language.js.map +1 -1
  519. package/dist/shell/account-menu-text-size.d.ts +26 -9
  520. package/dist/shell/account-menu-text-size.js +3 -2
  521. package/dist/shell/account-menu-text-size.js.map +1 -1
  522. package/dist/shell/dev-menu.js +5 -18
  523. package/dist/shell/dev-menu.js.map +1 -1
  524. package/dist/shell/role-switcher.d.ts +7 -0
  525. package/dist/shell/role-switcher.js.map +1 -1
  526. package/dist/shell/top-bar-actions.d.ts +1 -1
  527. package/dist/shell/top-bar-actions.js.map +1 -1
  528. package/dist/shell/top-bar-parts-labels.d.ts +0 -2
  529. package/dist/shell/top-bar-parts-labels.js +0 -1
  530. package/dist/shell/top-bar-parts-labels.js.map +1 -1
  531. package/dist/shell.d.ts +27 -8
  532. package/dist/shell.js +28 -7
  533. package/dist/shell.js.map +1 -1
  534. package/dist/sync/engine.d.ts +30 -4
  535. package/dist/sync/engine.js +172 -52
  536. package/dist/sync/engine.js.map +1 -1
  537. package/dist/sync.d.ts +6 -2
  538. package/dist/sync.js +6 -1
  539. package/dist/sync.js.map +1 -1
  540. package/dist/testing/css-variables.js +3 -8
  541. package/dist/testing/css-variables.js.map +1 -1
  542. package/dist/theme/contrast.d.ts +2 -1
  543. package/dist/theme/contrast.js +3 -8
  544. package/dist/theme/contrast.js.map +1 -1
  545. package/dist/theme/palette-store.js +6 -6
  546. package/dist/theme/palette-store.js.map +1 -1
  547. package/dist/theme/text-size.js +3 -8
  548. package/dist/theme/text-size.js.map +1 -1
  549. package/dist/theme/theme-store.js +3 -6
  550. package/dist/theme/theme-store.js.map +1 -1
  551. package/dist/tour/tour-catalogue.d.ts +7 -4
  552. package/dist/tour/tour-catalogue.js +12 -10
  553. package/dist/tour/tour-catalogue.js.map +1 -1
  554. package/dist/tour/tour-dock.d.ts +0 -2
  555. package/dist/tour/tour-dock.js +0 -2
  556. package/dist/tour/tour-dock.js.map +1 -1
  557. package/dist/tour/tour-gates.d.ts +4 -0
  558. package/dist/tour/tour-gates.js +14 -0
  559. package/dist/tour/tour-gates.js.map +1 -1
  560. package/dist/tour/tour-overlay.d.ts +27 -0
  561. package/dist/tour/tour-overlay.js +741 -0
  562. package/dist/tour/tour-overlay.js.map +1 -0
  563. package/dist/tour/tour.d.ts +16 -4
  564. package/dist/tour/tour.js +62 -778
  565. package/dist/tour/tour.js.map +1 -1
  566. package/dist/tour/use-tour-progress.js +1 -1
  567. package/dist/tour/use-tour-progress.js.map +1 -1
  568. package/dist/tour/use-tour-url-sync.js +2 -2
  569. package/dist/tour/use-tour-url-sync.js.map +1 -1
  570. package/dist/wizard/stepper-nav.d.ts +5 -1
  571. package/dist/wizard/stepper-nav.js.map +1 -1
  572. package/dist/wizard/types.d.ts +6 -2
  573. package/dist/wizard/types.js.map +1 -1
  574. package/dist/wizard/use-wizard.d.ts +3 -1
  575. package/dist/wizard/use-wizard.js.map +1 -1
  576. package/dist/wizard/validation.d.ts +3 -1
  577. package/dist/wizard/validation.js.map +1 -1
  578. package/package.json +12 -8
  579. package/src/account/account-parts.ts +5 -25
  580. package/src/account/data-export-setting-labels.ts +1 -1
  581. package/src/account/delete-account-setting-labels.ts +1 -1
  582. package/src/account/email-change-setting-labels.ts +1 -1
  583. package/src/account/passkeys-setting.tsx +60 -38
  584. package/src/account/sessions-setting.tsx +18 -12
  585. package/src/admin/admin-action-confirm.tsx +5 -10
  586. package/src/admin/admin-parts.ts +11 -25
  587. package/src/admin/mail-test-card-labels.ts +1 -1
  588. package/src/admin/plan-change-labels.ts +5 -23
  589. package/src/admin/plan-change.tsx +7 -44
  590. package/src/admin/reviewer-scope-editor.tsx +3 -3
  591. package/src/auth/auth-errors-labels.ts +23 -0
  592. package/src/auth/auth-errors.ts +11 -38
  593. package/src/auth/complete-name-dialog.tsx +9 -8
  594. package/src/auth/forgot-password-form-labels.ts +1 -1
  595. package/src/auth/forgot-password-form.tsx +11 -6
  596. package/src/auth/register-form-labels.ts +1 -1
  597. package/src/auth/reset-password-form-labels.ts +1 -1
  598. package/src/auth/reset-password-form.tsx +8 -4
  599. package/src/auth/sign-in-form-labels.ts +1 -1
  600. package/src/auth/status-parts.tsx +0 -6
  601. package/src/auth/verify-email-labels.ts +1 -1
  602. package/src/auth/verify-email.tsx +11 -6
  603. package/src/billing/cancel-request.ts +28 -6
  604. package/src/billing/cancel-subscription.tsx +29 -22
  605. package/src/billing/dialog-close.ts +34 -0
  606. package/src/billing/plan-card.tsx +36 -11
  607. package/src/billing/plan-change-labels.ts +66 -0
  608. package/src/billing/plan-switch.tsx +31 -20
  609. package/src/chart.ts +21 -3
  610. package/src/components/account-chips.tsx +20 -23
  611. package/src/components/alert-banner.tsx +82 -5
  612. package/src/components/amount-input.tsx +32 -14
  613. package/src/components/autocomplete.tsx +64 -70
  614. package/src/components/bulk-action-bar.tsx +70 -2
  615. package/src/components/button-look.ts +5 -5
  616. package/src/components/button.tsx +2 -2
  617. package/src/components/calculator.tsx +98 -17
  618. package/src/components/chart-edge.ts +34 -1
  619. package/src/components/chart-figure.tsx +35 -0
  620. package/src/components/chart-zoom-core.tsx +6 -5
  621. package/src/components/chart.tsx +26 -5
  622. package/src/components/combobox-core.tsx +303 -69
  623. package/src/components/combobox.tsx +184 -155
  624. package/src/components/copy-button.tsx +34 -23
  625. package/src/components/country-select.tsx +16 -11
  626. package/src/components/data-table-column-settings.tsx +52 -10
  627. package/src/components/data-table-filters.ts +6 -4
  628. package/src/components/data-table-fit.ts +19 -5
  629. package/src/components/data-table-groups.tsx +1 -1
  630. package/src/components/data-table-head.tsx +32 -22
  631. package/src/components/data-table-mobile.tsx +110 -27
  632. package/src/components/data-table-pagination.tsx +21 -6
  633. package/src/components/data-table-resize.ts +1 -1
  634. package/src/components/data-table-row-actions.tsx +3 -3
  635. package/src/components/data-table-row.tsx +25 -14
  636. package/src/components/data-table-selection.ts +1 -1
  637. package/src/components/data-table-shared.tsx +33 -1
  638. package/src/components/data-table-sort.ts +57 -2
  639. package/src/components/data-table-virtual.ts +32 -8
  640. package/src/components/data-table.tsx +267 -41
  641. package/src/components/date-field.tsx +65 -8
  642. package/src/components/date-picker.tsx +125 -48
  643. package/src/components/date-range-picker.tsx +82 -31
  644. package/src/components/dialog-frame.tsx +2 -1
  645. package/src/components/entity-combobox.tsx +4 -1
  646. package/src/components/error-boundary.tsx +53 -39
  647. package/src/components/field-base-labels.ts +20 -0
  648. package/src/components/field-base.tsx +13 -7
  649. package/src/components/field-sync-labels.ts +1 -0
  650. package/src/components/field-sync.tsx +23 -1
  651. package/src/components/form-actions.tsx +20 -5
  652. package/src/components/hover-menu.tsx +18 -8
  653. package/src/components/icon-button.tsx +14 -9
  654. package/src/components/inline-confirm.tsx +116 -0
  655. package/src/components/inline-entity-combobox.tsx +198 -152
  656. package/src/components/input.tsx +1 -1
  657. package/src/components/jump-calendar.tsx +30 -146
  658. package/src/components/legal-page.tsx +10 -7
  659. package/src/components/legal.tsx +4 -2
  660. package/src/components/lightbox.tsx +21 -8
  661. package/src/components/list.tsx +14 -5
  662. package/src/components/measured-grid.tsx +8 -4
  663. package/src/components/mini-calendar.tsx +6 -5
  664. package/src/components/modal.tsx +45 -4
  665. package/src/components/money-draft.ts +16 -5
  666. package/src/components/money-field.tsx +2 -2
  667. package/src/components/month-grid.tsx +229 -0
  668. package/src/components/month-picker.tsx +192 -200
  669. package/src/components/multi-entity-combobox.tsx +1 -0
  670. package/src/components/multi-select.tsx +21 -9
  671. package/src/components/number-field.tsx +14 -7
  672. package/src/components/number-input.tsx +9 -3
  673. package/src/components/numpad-sheet.tsx +4 -3
  674. package/src/components/picker-sheet.tsx +12 -9
  675. package/src/components/pie-chart-labels.ts +8 -0
  676. package/src/components/pie-chart.tsx +22 -28
  677. package/src/components/popover.tsx +18 -1
  678. package/src/components/reauth-dialog.tsx +6 -10
  679. package/src/components/row-actions.tsx +2 -1
  680. package/src/components/section-nav.tsx +7 -0
  681. package/src/components/series-chart-axes.ts +11 -3
  682. package/src/components/series-chart-labels.ts +7 -4
  683. package/src/components/series-chart.tsx +178 -69
  684. package/src/components/share-card.tsx +6 -6
  685. package/src/components/sign-chip-labels.ts +1 -0
  686. package/src/components/sign-chip.tsx +10 -1
  687. package/src/components/tabs-labels.ts +13 -0
  688. package/src/components/tabs.tsx +35 -19
  689. package/src/components/toggle-legend.tsx +16 -11
  690. package/src/components/translation-review-editor.tsx +6 -5
  691. package/src/components/translation-review.tsx +4 -3
  692. package/src/components/treemap-labels.ts +39 -0
  693. package/src/components/treemap-layout.ts +210 -0
  694. package/src/components/treemap.tsx +722 -133
  695. package/src/components/use-table-state.ts +12 -9
  696. package/src/data-table.ts +9 -2
  697. package/src/eslint/role-utilities.ts +97 -19
  698. package/src/feedback/feedback-dialog.tsx +30 -19
  699. package/src/feedback/feedback-mutation.ts +41 -0
  700. package/src/feedback/feedback-page-link.ts +90 -0
  701. package/src/feedback/feedback-public-list.tsx +17 -5
  702. package/src/feedback/feedback-replies.tsx +13 -6
  703. package/src/feedback/feedback-row-detail-labels.ts +5 -0
  704. package/src/feedback/feedback-row-detail.tsx +103 -67
  705. package/src/feedback/feedback-status-undo.ts +41 -27
  706. package/src/feedback/feedback-submit-dialog.tsx +2 -2
  707. package/src/feedback/feedback-submit.tsx +21 -7
  708. package/src/feedback/feedback-swipe.tsx +1 -1
  709. package/src/feedback/feedback-table.tsx +86 -38
  710. package/src/feedback/feedback-thread-labels.ts +2 -2
  711. package/src/feedback/feedback-thread.tsx +27 -25
  712. package/src/feedback.ts +42 -0
  713. package/src/hooks/use-dismiss.ts +3 -2
  714. package/src/hooks/use-focus-trap.ts +8 -24
  715. package/src/hooks/use-hotkey.ts +24 -7
  716. package/src/hooks/use-long-press.ts +16 -2
  717. package/src/hooks/use-media-query.ts +20 -4
  718. package/src/hooks/use-mounted.ts +39 -0
  719. package/src/hooks/use-overlay-history.ts +70 -5
  720. package/src/i18n/defaults.ts +4 -5
  721. package/src/i18n/german.ts +8 -2
  722. package/src/i18n/kit-labels.tsx +9 -2
  723. package/src/i18n/locales/es.ts +8 -2
  724. package/src/i18n/locales/fr.ts +21 -13
  725. package/src/i18n/locales/hu.ts +10 -2
  726. package/src/i18n/locales/it.ts +8 -2
  727. package/src/i18n/locales/zh.ts +9 -2
  728. package/src/i18n/review.ts +5 -0
  729. package/src/index.ts +103 -13
  730. package/src/landing/routing.tsx +14 -10
  731. package/src/lib/broadcast.ts +52 -0
  732. package/src/lib/calc.ts +13 -2
  733. package/src/lib/clipboard-minus.ts +14 -4
  734. package/src/lib/date-format.ts +89 -13
  735. package/src/lib/day-format.ts +96 -0
  736. package/src/lib/decimal-marks.ts +12 -3
  737. package/src/lib/describe-failure.ts +18 -0
  738. package/src/lib/direction.ts +39 -0
  739. package/src/lib/focus-left.ts +156 -0
  740. package/src/lib/format.ts +34 -19
  741. package/src/lib/http-status.ts +38 -0
  742. package/src/lib/intl-cache.ts +25 -0
  743. package/src/lib/isin.ts +10 -0
  744. package/src/lib/iso-day.ts +13 -0
  745. package/src/lib/lazy-with-fallback.ts +82 -0
  746. package/src/lib/path-pattern.ts +55 -0
  747. package/src/lib/reduced-motion.ts +2 -1
  748. package/src/lib/round.ts +7 -2
  749. package/src/lib/safe-storage.ts +48 -6
  750. package/src/lib/session-refresh.ts +1 -1
  751. package/src/lib/share-format.ts +18 -0
  752. package/src/lib/text-case.ts +19 -0
  753. package/src/lib/text-match.ts +69 -2
  754. package/src/lib/thenable.ts +19 -0
  755. package/src/lib/translation-review.ts +13 -5
  756. package/src/notifications/device-zone-report.ts +1 -1
  757. package/src/notifications/notification-bell.tsx +7 -4
  758. package/src/notifications/notification-inbox.tsx +40 -58
  759. package/src/notifications/notification-parts.tsx +3 -4
  760. package/src/notifications/notification-types-setting.tsx +1 -1
  761. package/src/notifications/notifications-labels.ts +7 -0
  762. package/src/notifications/push-device-setting.tsx +1 -1
  763. package/src/notifications/push-devices-setting.tsx +30 -55
  764. package/src/notifications/quiet-hours-setting.tsx +93 -31
  765. package/src/notifications/unsubscribe-panel.tsx +4 -7
  766. package/src/notifications/use-push-device.ts +76 -10
  767. package/src/offline/query-persistence.ts +35 -3
  768. package/src/rhf/fields.tsx +11 -4
  769. package/src/search/command-palette.tsx +2 -4
  770. package/src/search/global-search.tsx +36 -15
  771. package/src/search/use-command-key.ts +13 -12
  772. package/src/search.ts +9 -0
  773. package/src/settings/use-settings-focus.ts +3 -0
  774. package/src/shell/account-menu-language.tsx +27 -5
  775. package/src/shell/account-menu-text-size.tsx +32 -10
  776. package/src/shell/dev-menu.tsx +7 -21
  777. package/src/shell/role-switcher.tsx +7 -0
  778. package/src/shell/top-bar-actions.tsx +1 -1
  779. package/src/shell/top-bar-parts-labels.ts +0 -3
  780. package/src/shell.ts +40 -9
  781. package/src/sync/engine.ts +339 -61
  782. package/src/sync.ts +8 -1
  783. package/src/testing/css-variables.ts +8 -9
  784. package/src/theme/contrast.ts +8 -9
  785. package/src/theme/palette-store.ts +9 -9
  786. package/src/theme/text-size.ts +6 -8
  787. package/src/theme/theme-store.ts +7 -9
  788. package/src/tour/tour-catalogue.tsx +26 -15
  789. package/src/tour/tour-dock.ts +0 -2
  790. package/src/tour/tour-gates.ts +23 -0
  791. package/src/tour/tour-overlay.tsx +1170 -0
  792. package/src/tour/tour.tsx +116 -1193
  793. package/src/tour/use-tour-progress.ts +1 -1
  794. package/src/tour/use-tour-url-sync.ts +7 -3
  795. package/src/wizard/stepper-nav.tsx +3 -1
  796. package/src/wizard/types.ts +11 -2
  797. package/src/wizard/use-wizard.ts +2 -1
  798. package/src/wizard/validation.ts +8 -2
  799. package/tokens.css +2 -1
  800. package/dist/components/ui-labels.js.map +0 -1
  801. package/dist/shell/dev-switchers.d.ts +0 -6
  802. package/dist/shell/dev-switchers.js +0 -12
  803. package/dist/shell/dev-switchers.js.map +0 -1
  804. package/src/components/ui-labels.ts +0 -24
  805. package/src/shell/dev-switchers.tsx +0 -18
@@ -18,13 +18,11 @@ export interface AccountMenuLanguageOption {
18
18
  */
19
19
  country?: string;
20
20
  }
21
- export interface AccountMenuLanguageProps {
21
+ /** {@link AccountMenuLanguageProps} but the handler. */
22
+ interface AccountMenuLanguageBaseProps {
22
23
  languages: readonly AccountMenuLanguageOption[];
23
24
  /** The active language's code. */
24
25
  value: string | undefined;
25
- /** A pick: the app sets the device's language and, signed in, the account's
26
- * (settings §6.2). */
27
- onPick: (code: string) => void;
28
26
  /** The account menu's `close` (from `TopBarActionMenu`'s `children`): a pick shuts it. */
29
27
  close?: () => void;
30
28
  /** The row's name. Default: `topBar.language` ("Language"). */
@@ -32,6 +30,23 @@ export interface AccountMenuLanguageProps {
32
30
  /** Open the sub-list at first. Default `false`. */
33
31
  defaultOpen?: boolean;
34
32
  }
33
+ /**
34
+ * `onChange`, or the deprecated `onPick`, is required: with both optional, a row an app
35
+ * moved off `onPick` without adding `onChange` — or with it misspelt — compiled, and a
36
+ * pick only closed the menu (0.52 code review, account-menu-language.tsx).
37
+ */
38
+ export type AccountMenuLanguageProps = AccountMenuLanguageBaseProps & ({
39
+ /** A pick: the app sets the device's language and, signed in, the account's
40
+ * (settings §6.2). `value` + `onChange`, as every kit control pairs them
41
+ * (CONTRIBUTING §4; refactor audit 2026-10-30, API-5). */
42
+ onChange: (code: string) => void;
43
+ /** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */
44
+ onPick?: (code: string) => void;
45
+ } | {
46
+ onChange?: undefined;
47
+ /** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */
48
+ onPick: (code: string) => void;
49
+ });
35
50
  /**
36
51
  * The language choice INSIDE the account menu (docs/top-bar-harmonization.md §2.3),
37
52
  * keksdose's sub-list: a `Disclosure variant="menu"` row — the globe, "Language", the
@@ -43,4 +58,5 @@ export interface AccountMenuLanguageProps {
43
58
  * app's context rows (§6.5). Signed out there is no account menu; `LanguageMenu` stays
44
59
  * the bar's button (§2.3).
45
60
  */
46
- export declare function AccountMenuLanguage({ languages, value, onPick, close, label, defaultOpen, }: AccountMenuLanguageProps): import("react").JSX.Element;
61
+ export declare function AccountMenuLanguage({ languages, value, onChange, onPick, close, label, defaultOpen, }: AccountMenuLanguageProps): import("react").JSX.Element;
62
+ export {};
@@ -21,11 +21,13 @@ function flagOf(lang) {
21
21
  function AccountMenuLanguage({
22
22
  languages,
23
23
  value,
24
+ onChange,
24
25
  onPick,
25
26
  close,
26
27
  label,
27
28
  defaultOpen = false
28
29
  }) {
30
+ const change = onChange ?? onPick;
29
31
  const words = useKitLabels("topBar", DEFAULT_TOP_BAR_LABELS);
30
32
  const [open, setOpen] = useState(defaultOpen);
31
33
  const active = languages.find((l) => l.code === value);
@@ -54,7 +56,7 @@ function AccountMenuLanguage({
54
56
  {
55
57
  checked: lang.code === value,
56
58
  onClick: () => {
57
- onPick(lang.code);
59
+ change?.(lang.code);
58
60
  setOpen(false);
59
61
  close?.();
60
62
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/shell/account-menu-language.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Globe } from \"lucide-react\";\nimport { Disclosure } from \"../components/disclosure\";\nimport { MenuItem } from \"../components/menu-item\";\nimport { DEFAULT_TOP_BAR_LABELS, useKitLabels } from \"../i18n/kit-labels\";\nimport { languageCodeLabel } from \"./language-code\";\n\n/** One offered language in the account menu's sub-list. */\nexport interface AccountMenuLanguageOption {\n code: string;\n /** Its name, in its own language (\"Deutsch\", \"Français\"). */\n label: ReactNode;\n /**\n * A flag before the name, as the app draws it — keksdose's flag-icons span\n * (`<span aria-hidden className=\"fi fi-ch …\" />`). A node rather than a country code, so\n * the kit ships no flag set; decorative, so give it `aria-hidden`.\n */\n flag?: ReactNode;\n /**\n * Or the ISO 3166-1 alpha-2 country (lowercase) whose flag-icons flag to draw, as\n * `LanguageMenu`'s `LanguageOption` takes it — so one language list feeds both\n * (Kurvenschmiede's `LANGUAGES`). Needs the app's flag-icons CSS, as `LanguageMenu`\n * does. `flag` wins when both are given.\n */\n country?: string;\n}\n\n/** The option's flag: its own node, else the flag-icons flag of its country. */\nfunction flagOf(lang: AccountMenuLanguageOption): ReactNode {\n if (lang.flag !== undefined) return lang.flag;\n if (!lang.country) return undefined;\n return (\n <span\n aria-hidden\n data-country={lang.country}\n className={`fi fi-${lang.country} inline-block h-[0.9375rem] w-5 shrink-0 rounded-sm shadow-[0_0_0_1px_rgba(0,0,0,0.08)]`}\n />\n );\n}\n\nexport interface AccountMenuLanguageProps {\n languages: readonly AccountMenuLanguageOption[];\n /** The active language's code. */\n value: string | undefined;\n /** A pick: the app sets the device's language and, signed in, the account's\n * (settings §6.2). */\n onPick: (code: string) => void;\n /** The account menu's `close` (from `TopBarActionMenu`'s `children`): a pick shuts it. */\n close?: () => void;\n /** The row's name. Default: `topBar.language` (\"Language\"). */\n label?: string;\n /** Open the sub-list at first. Default `false`. */\n defaultOpen?: boolean;\n}\n\n/**\n * The language choice INSIDE the account menu (docs/top-bar-harmonization.md §2.3),\n * keksdose's sub-list: a `Disclosure variant=\"menu\"` row — the globe, \"Language\", the\n * active language's flag and code (\"DE\") and the chevron — that opens in place onto one checked\n * `MenuItem` per language. Inline rather than a nested popover: a popover inside a\n * popover fights the outside click and has nowhere to go on a phone (keksdose #140).\n *\n * It renders its own `<li>`: drop it into `TopBarActionMenu`'s `children` first after the\n * app's context rows (§6.5). Signed out there is no account menu; `LanguageMenu` stays\n * the bar's button (§2.3).\n */\nexport function AccountMenuLanguage({\n languages,\n value,\n onPick,\n close,\n label,\n defaultOpen = false,\n}: AccountMenuLanguageProps) {\n const words = useKitLabels(\"topBar\", DEFAULT_TOP_BAR_LABELS);\n const [open, setOpen] = useState(defaultOpen);\n const active = languages.find((l) => l.code === value);\n return (\n <li>\n <Disclosure\n variant=\"menu\"\n open={open}\n onOpenChange={setOpen}\n title={\n <span className=\"flex items-center justify-between gap-3\">\n <span className=\"flex items-center gap-2\">\n <Globe aria-hidden className=\"size-4\" />\n {label ?? words.language}\n </span>\n {active && (\n // The flag alone could not tell de-CH, fr-CH and it-CH apart (one Swiss\n // flag each), so the code sits beside it (0.49 KIT-10); the row's name\n // carries the language's own name.\n <span className=\"flex items-center gap-1.5\">\n {flagOf(active)}\n <span aria-hidden className=\"text-xs font-semibold tabular-nums tracking-wide text-secondary\">\n {languageCodeLabel(active.code)}\n </span>\n <span className=\"sr-only\">{active.label}</span>\n </span>\n )}\n </span>\n }\n >\n <ul>\n {languages.map((lang) => (\n <li key={lang.code}>\n <MenuItem\n checked={lang.code === value}\n onClick={() => {\n onPick(lang.code);\n setOpen(false);\n close?.();\n }}\n leading={flagOf(lang)}\n // Under the row's own text, past the globe.\n className=\"ps-9\"\n >\n {lang.label}\n </MenuItem>\n </li>\n ))}\n </ul>\n </Disclosure>\n </li>\n );\n}\n"],"mappings":";AAiCI,cAqDQ,YArDR;AAjCJ,SAAS,gBAAgB;AAEzB,SAAS,aAAa;AACtB,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,wBAAwB,oBAAoB;AACrD,SAAS,yBAAyB;AAuBlC,SAAS,OAAO,MAA4C;AAC1D,MAAI,KAAK,SAAS,OAAW,QAAO,KAAK;AACzC,MAAI,CAAC,KAAK,QAAS,QAAO;AAC1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAW;AAAA,MACX,gBAAc,KAAK;AAAA,MACnB,WAAW,SAAS,KAAK,OAAO;AAAA;AAAA,EAClC;AAEJ;AA4BO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAChB,GAA6B;AAC3B,QAAM,QAAQ,aAAa,UAAU,sBAAsB;AAC3D,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,WAAW;AAC5C,QAAM,SAAS,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,KAAK;AACrD,SACE,oBAAC,QACC;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR;AAAA,MACA,cAAc;AAAA,MACd,OACE,qBAAC,UAAK,WAAU,2CACd;AAAA,6BAAC,UAAK,WAAU,2BACd;AAAA,8BAAC,SAAM,eAAW,MAAC,WAAU,UAAS;AAAA,UACrC,SAAS,MAAM;AAAA,WAClB;AAAA,QACC;AAAA;AAAA;AAAA,QAIC,qBAAC,UAAK,WAAU,6BACb;AAAA,iBAAO,MAAM;AAAA,UACd,oBAAC,UAAK,eAAW,MAAC,WAAU,mEACzB,4BAAkB,OAAO,IAAI,GAChC;AAAA,UACA,oBAAC,UAAK,WAAU,WAAW,iBAAO,OAAM;AAAA,WAC1C;AAAA,SAEJ;AAAA,MAGF,8BAAC,QACE,oBAAU,IAAI,CAAC,SACd,oBAAC,QACC;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,KAAK,SAAS;AAAA,UACvB,SAAS,MAAM;AACb,mBAAO,KAAK,IAAI;AAChB,oBAAQ,KAAK;AACb,oBAAQ;AAAA,UACV;AAAA,UACA,SAAS,OAAO,IAAI;AAAA,UAEpB,WAAU;AAAA,UAET,eAAK;AAAA;AAAA,MACR,KAbO,KAAK,IAcd,CACD,GACH;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/shell/account-menu-language.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Globe } from \"lucide-react\";\nimport { Disclosure } from \"../components/disclosure\";\nimport { MenuItem } from \"../components/menu-item\";\nimport { DEFAULT_TOP_BAR_LABELS, useKitLabels } from \"../i18n/kit-labels\";\nimport { languageCodeLabel } from \"./language-code\";\n\n/** One offered language in the account menu's sub-list. */\nexport interface AccountMenuLanguageOption {\n code: string;\n /** Its name, in its own language (\"Deutsch\", \"Français\"). */\n label: ReactNode;\n /**\n * A flag before the name, as the app draws it — keksdose's flag-icons span\n * (`<span aria-hidden className=\"fi fi-ch …\" />`). A node rather than a country code, so\n * the kit ships no flag set; decorative, so give it `aria-hidden`.\n */\n flag?: ReactNode;\n /**\n * Or the ISO 3166-1 alpha-2 country (lowercase) whose flag-icons flag to draw, as\n * `LanguageMenu`'s `LanguageOption` takes it — so one language list feeds both\n * (Kurvenschmiede's `LANGUAGES`). Needs the app's flag-icons CSS, as `LanguageMenu`\n * does. `flag` wins when both are given.\n */\n country?: string;\n}\n\n/** The option's flag: its own node, else the flag-icons flag of its country. */\nfunction flagOf(lang: AccountMenuLanguageOption): ReactNode {\n if (lang.flag !== undefined) return lang.flag;\n if (!lang.country) return undefined;\n return (\n <span\n aria-hidden\n data-country={lang.country}\n className={`fi fi-${lang.country} inline-block h-[0.9375rem] w-5 shrink-0 rounded-sm shadow-[0_0_0_1px_rgba(0,0,0,0.08)]`}\n />\n );\n}\n\n/** {@link AccountMenuLanguageProps} but the handler. */\ninterface AccountMenuLanguageBaseProps {\n languages: readonly AccountMenuLanguageOption[];\n /** The active language's code. */\n value: string | undefined;\n /** The account menu's `close` (from `TopBarActionMenu`'s `children`): a pick shuts it. */\n close?: () => void;\n /** The row's name. Default: `topBar.language` (\"Language\"). */\n label?: string;\n /** Open the sub-list at first. Default `false`. */\n defaultOpen?: boolean;\n}\n\n/**\n * `onChange`, or the deprecated `onPick`, is required: with both optional, a row an app\n * moved off `onPick` without adding `onChange` — or with it misspelt — compiled, and a\n * pick only closed the menu (0.52 code review, account-menu-language.tsx).\n */\nexport type AccountMenuLanguageProps = AccountMenuLanguageBaseProps &\n (\n | {\n /** A pick: the app sets the device's language and, signed in, the account's\n * (settings §6.2). `value` + `onChange`, as every kit control pairs them\n * (CONTRIBUTING §4; refactor audit 2026-10-30, API-5). */\n onChange: (code: string) => void;\n /** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */\n onPick?: (code: string) => void;\n }\n | {\n onChange?: undefined;\n /** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */\n onPick: (code: string) => void;\n }\n );\n\n/**\n * The language choice INSIDE the account menu (docs/top-bar-harmonization.md §2.3),\n * keksdose's sub-list: a `Disclosure variant=\"menu\"` row — the globe, \"Language\", the\n * active language's flag and code (\"DE\") and the chevron — that opens in place onto one checked\n * `MenuItem` per language. Inline rather than a nested popover: a popover inside a\n * popover fights the outside click and has nowhere to go on a phone (keksdose #140).\n *\n * It renders its own `<li>`: drop it into `TopBarActionMenu`'s `children` first after the\n * app's context rows (§6.5). Signed out there is no account menu; `LanguageMenu` stays\n * the bar's button (§2.3).\n */\nexport function AccountMenuLanguage({\n languages,\n value,\n onChange,\n onPick,\n close,\n label,\n defaultOpen = false,\n}: AccountMenuLanguageProps) {\n const change = onChange ?? onPick;\n const words = useKitLabels(\"topBar\", DEFAULT_TOP_BAR_LABELS);\n const [open, setOpen] = useState(defaultOpen);\n const active = languages.find((l) => l.code === value);\n return (\n <li>\n <Disclosure\n variant=\"menu\"\n open={open}\n onOpenChange={setOpen}\n title={\n <span className=\"flex items-center justify-between gap-3\">\n <span className=\"flex items-center gap-2\">\n <Globe aria-hidden className=\"size-4\" />\n {label ?? words.language}\n </span>\n {active && (\n // The flag alone could not tell de-CH, fr-CH and it-CH apart (one Swiss\n // flag each), so the code sits beside it (0.49 KIT-10); the row's name\n // carries the language's own name.\n <span className=\"flex items-center gap-1.5\">\n {flagOf(active)}\n <span aria-hidden className=\"text-xs font-semibold tabular-nums tracking-wide text-secondary\">\n {languageCodeLabel(active.code)}\n </span>\n <span className=\"sr-only\">{active.label}</span>\n </span>\n )}\n </span>\n }\n >\n <ul>\n {languages.map((lang) => (\n <li key={lang.code}>\n <MenuItem\n checked={lang.code === value}\n onClick={() => {\n change?.(lang.code);\n setOpen(false);\n close?.();\n }}\n leading={flagOf(lang)}\n // Under the row's own text, past the globe.\n className=\"ps-9\"\n >\n {lang.label}\n </MenuItem>\n </li>\n ))}\n </ul>\n </Disclosure>\n </li>\n );\n}\n"],"mappings":";AAiCI,cA2EQ,YA3ER;AAjCJ,SAAS,gBAAgB;AAEzB,SAAS,aAAa;AACtB,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,wBAAwB,oBAAoB;AACrD,SAAS,yBAAyB;AAuBlC,SAAS,OAAO,MAA4C;AAC1D,MAAI,KAAK,SAAS,OAAW,QAAO,KAAK;AACzC,MAAI,CAAC,KAAK,QAAS,QAAO;AAC1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAW;AAAA,MACX,gBAAc,KAAK;AAAA,MACnB,WAAW,SAAS,KAAK,OAAO;AAAA;AAAA,EAClC;AAEJ;AAgDO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAChB,GAA6B;AAC3B,QAAM,SAAS,YAAY;AAC3B,QAAM,QAAQ,aAAa,UAAU,sBAAsB;AAC3D,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,WAAW;AAC5C,QAAM,SAAS,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,KAAK;AACrD,SACE,oBAAC,QACC;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR;AAAA,MACA,cAAc;AAAA,MACd,OACE,qBAAC,UAAK,WAAU,2CACd;AAAA,6BAAC,UAAK,WAAU,2BACd;AAAA,8BAAC,SAAM,eAAW,MAAC,WAAU,UAAS;AAAA,UACrC,SAAS,MAAM;AAAA,WAClB;AAAA,QACC;AAAA;AAAA;AAAA,QAIC,qBAAC,UAAK,WAAU,6BACb;AAAA,iBAAO,MAAM;AAAA,UACd,oBAAC,UAAK,eAAW,MAAC,WAAU,mEACzB,4BAAkB,OAAO,IAAI,GAChC;AAAA,UACA,oBAAC,UAAK,WAAU,WAAW,iBAAO,OAAM;AAAA,WAC1C;AAAA,SAEJ;AAAA,MAGF,8BAAC,QACE,oBAAU,IAAI,CAAC,SACd,oBAAC,QACC;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,KAAK,SAAS;AAAA,UACvB,SAAS,MAAM;AACb,qBAAS,KAAK,IAAI;AAClB,oBAAQ,KAAK;AACb,oBAAQ;AAAA,UACV;AAAA,UACA,SAAS,OAAO,IAAI;AAAA,UAEpB,WAAU;AAAA,UAET,eAAK;AAAA;AAAA,MACR,KAbO,KAAK,IAcd,CACD,GACH;AAAA;AAAA,EACF,GACF;AAEJ;","names":[]}
@@ -1,22 +1,38 @@
1
1
  import { type AppearanceLabels } from "../components/appearance-labels.js";
2
2
  import type { LabelOverride } from "../i18n/kit-labels.js";
3
3
  import { type TextSize } from "../theme/text-size.js";
4
- export interface AccountMenuTextSizeProps {
4
+ /** {@link AccountMenuTextSizeProps} but the handler. */
5
+ interface AccountMenuTextSizeBaseProps {
5
6
  /** The size in force. Default: the one on `<html>` ({@link useTextSize}), which is the
6
7
  * size whoever applied it put there. */
7
8
  value?: TextSize;
8
- /**
9
- * A step: the next size down or up. The app applies it and keeps it as its Settings ▸
10
- * Appearance does — `useAccountAppearance`'s `pickTextSize` (this device, and the
11
- * account when signed in), with `appearance.saveFailed` as the toast when the account
12
- * refused. The kit does not apply it itself, so the two places can never disagree.
13
- */
14
- onPick: (size: TextSize) => void;
15
9
  /** The row's name. Default: `appearance.textSize` ("Text size"). */
16
10
  label?: string;
17
11
  /** The `appearance` words (`textSize`, `textSizes`, `textSmaller`, `textLarger`). */
18
12
  labels?: LabelOverride<AppearanceLabels>;
19
13
  }
14
+ /**
15
+ * `onChange`, or the deprecated `onPick`, is required: with both optional, a row an app
16
+ * moved off `onPick` without adding `onChange` — or with it misspelt — compiled, and A− /
17
+ * A+ stayed enabled and changed nothing (0.52 code review, account-menu-language.tsx).
18
+ */
19
+ export type AccountMenuTextSizeProps = AccountMenuTextSizeBaseProps & ({
20
+ /**
21
+ * A step: the next size down or up. The app applies it and keeps it as its
22
+ * Settings ▸ Appearance does — `useAccountAppearance`'s `pickTextSize` (this
23
+ * device, and the account when signed in), with `appearance.saveFailed` as the
24
+ * toast when the account refused. The kit does not apply it itself, so the two
25
+ * places can never disagree. `value` + `onChange`, as every kit control pairs them
26
+ * (CONTRIBUTING §4; refactor audit 2026-10-30, API-5).
27
+ */
28
+ onChange: (size: TextSize) => void;
29
+ /** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */
30
+ onPick?: (size: TextSize) => void;
31
+ } | {
32
+ onChange?: undefined;
33
+ /** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */
34
+ onPick: (size: TextSize) => void;
35
+ });
20
36
  /**
21
37
  * The text size one tap away, INSIDE the account menu (0.46, keksdose live #426, its
22
38
  * `TextSizeRow`): the row's icon and name, the size in force, and A− / A+, which step
@@ -30,4 +46,5 @@ export interface AccountMenuTextSizeProps {
30
46
  * behind it and can step again. The size's name is a polite live region, so a step is
31
47
  * announced.
32
48
  */
33
- export declare function AccountMenuTextSize({ value, onPick, label, labels: labelsProp }: AccountMenuTextSizeProps): import("react").JSX.Element;
49
+ export declare function AccountMenuTextSize({ value, onChange, onPick, label, labels: labelsProp }: AccountMenuTextSizeProps): import("react").JSX.Element;
50
+ export {};
@@ -4,14 +4,15 @@ import { AArrowDown, AArrowUp, ALargeSmall } from "lucide-react";
4
4
  import { IconButton } from "../components/icon-button.js";
5
5
  import { useAppearanceLabels } from "../components/appearance-labels.js";
6
6
  import { TEXT_SIZES, useTextSize } from "../theme/text-size.js";
7
- function AccountMenuTextSize({ value, onPick, label, labels: labelsProp }) {
7
+ function AccountMenuTextSize({ value, onChange, onPick, label, labels: labelsProp }) {
8
+ const change = onChange ?? onPick;
8
9
  const labels = useAppearanceLabels(labelsProp);
9
10
  const onHtml = useTextSize().size;
10
11
  const size = value ?? onHtml;
11
12
  const index = TEXT_SIZES.indexOf(size);
12
13
  const step = (by) => {
13
14
  const next = TEXT_SIZES[index + by];
14
- if (next) onPick(next);
15
+ if (next) change?.(next);
15
16
  };
16
17
  return /* @__PURE__ */ jsxs("li", { "data-account-menu-text-size": "", className: "flex items-center gap-2 px-3 py-1.5 text-sm", children: [
17
18
  /* @__PURE__ */ jsx(ALargeSmall, { "aria-hidden": true, className: "size-4 shrink-0 text-muted" }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/shell/account-menu-text-size.tsx"],"sourcesContent":["import { AArrowDown, AArrowUp, ALargeSmall } from \"lucide-react\";\nimport { IconButton } from \"../components/icon-button\";\nimport { useAppearanceLabels, type AppearanceLabels } from \"../components/appearance-labels\";\nimport type { LabelOverride } from \"../i18n/kit-labels\";\nimport { TEXT_SIZES, useTextSize, type TextSize } from \"../theme/text-size\";\n\nexport interface AccountMenuTextSizeProps {\n /** The size in force. Default: the one on `<html>` ({@link useTextSize}), which is the\n * size whoever applied it put there. */\n value?: TextSize;\n /**\n * A step: the next size down or up. The app applies it and keeps it as its Settings ▸\n * Appearance does — `useAccountAppearance`'s `pickTextSize` (this device, and the\n * account when signed in), with `appearance.saveFailed` as the toast when the account\n * refused. The kit does not apply it itself, so the two places can never disagree.\n */\n onPick: (size: TextSize) => void;\n /** The row's name. Default: `appearance.textSize` (\"Text size\"). */\n label?: string;\n /** The `appearance` words (`textSize`, `textSizes`, `textSmaller`, `textLarger`). */\n labels?: LabelOverride<AppearanceLabels>;\n}\n\n/**\n * The text size one tap away, INSIDE the account menu (0.46, keksdose live #426, its\n * `TextSizeRow`): the row's icon and name, the size in force, and A− / A+, which step\n * through {@link TEXT_SIZES} (Normal → Large → Extra large). A− is disabled at the\n * smallest, A+ at the largest. The browser's pinch zoom stays as it is — this is the\n * quick path to the setting, not a replacement for zoom.\n *\n * It renders its own `<li>`: drop it into `TopBarActionMenu`'s `children` beside\n * `AccountMenuLanguage`. The menu promotes the two buttons to `menuitem`s, so ↑/↓ reach\n * them like every other row, and it stays open on a step: the person sees the page grow\n * behind it and can step again. The size's name is a polite live region, so a step is\n * announced.\n */\nexport function AccountMenuTextSize({ value, onPick, label, labels: labelsProp }: AccountMenuTextSizeProps) {\n const labels = useAppearanceLabels(labelsProp);\n const onHtml = useTextSize().size;\n const size = value ?? onHtml;\n const index = TEXT_SIZES.indexOf(size);\n const step = (by: -1 | 1) => {\n const next = TEXT_SIZES[index + by];\n if (next) onPick(next);\n };\n return (\n <li data-account-menu-text-size=\"\" className=\"flex items-center gap-2 px-3 py-1.5 text-sm\">\n <ALargeSmall aria-hidden className=\"size-4 shrink-0 text-muted\" />\n <span className=\"min-w-0 flex-1 truncate\">\n {label ?? labels.textSize}\n <span className=\"ms-2 text-xs text-muted\" aria-live=\"polite\">\n {labels.textSizes[size]}\n </span>\n </span>\n <IconButton\n size=\"sm\"\n label={labels.textSmaller}\n labelVisible={false}\n tooltip={false}\n disabled={index <= 0}\n onClick={() => step(-1)}\n >\n <AArrowDown />\n </IconButton>\n <IconButton\n size=\"sm\"\n label={labels.textLarger}\n labelVisible={false}\n tooltip={false}\n disabled={index >= TEXT_SIZES.length - 1}\n onClick={() => step(1)}\n >\n <AArrowUp />\n </IconButton>\n </li>\n );\n}\n"],"mappings":";AA+CM,cACA,YADA;AA/CN,SAAS,YAAY,UAAU,mBAAmB;AAClD,SAAS,kBAAkB;AAC3B,SAAS,2BAAkD;AAE3D,SAAS,YAAY,mBAAkC;AAgChD,SAAS,oBAAoB,EAAE,OAAO,QAAQ,OAAO,QAAQ,WAAW,GAA6B;AAC1G,QAAM,SAAS,oBAAoB,UAAU;AAC7C,QAAM,SAAS,YAAY,EAAE;AAC7B,QAAM,OAAO,SAAS;AACtB,QAAM,QAAQ,WAAW,QAAQ,IAAI;AACrC,QAAM,OAAO,CAAC,OAAe;AAC3B,UAAM,OAAO,WAAW,QAAQ,EAAE;AAClC,QAAI,KAAM,QAAO,IAAI;AAAA,EACvB;AACA,SACE,qBAAC,QAAG,+BAA4B,IAAG,WAAU,+CAC3C;AAAA,wBAAC,eAAY,eAAW,MAAC,WAAU,8BAA6B;AAAA,IAChE,qBAAC,UAAK,WAAU,2BACb;AAAA,eAAS,OAAO;AAAA,MACjB,oBAAC,UAAK,WAAU,2BAA0B,aAAU,UACjD,iBAAO,UAAU,IAAI,GACxB;AAAA,OACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAO,OAAO;AAAA,QACd,cAAc;AAAA,QACd,SAAS;AAAA,QACT,UAAU,SAAS;AAAA,QACnB,SAAS,MAAM,KAAK,EAAE;AAAA,QAEtB,8BAAC,cAAW;AAAA;AAAA,IACd;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAO,OAAO;AAAA,QACd,cAAc;AAAA,QACd,SAAS;AAAA,QACT,UAAU,SAAS,WAAW,SAAS;AAAA,QACvC,SAAS,MAAM,KAAK,CAAC;AAAA,QAErB,8BAAC,YAAS;AAAA;AAAA,IACZ;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/shell/account-menu-text-size.tsx"],"sourcesContent":["import { AArrowDown, AArrowUp, ALargeSmall } from \"lucide-react\";\nimport { IconButton } from \"../components/icon-button\";\nimport { useAppearanceLabels, type AppearanceLabels } from \"../components/appearance-labels\";\nimport type { LabelOverride } from \"../i18n/kit-labels\";\nimport { TEXT_SIZES, useTextSize, type TextSize } from \"../theme/text-size\";\n\n/** {@link AccountMenuTextSizeProps} but the handler. */\ninterface AccountMenuTextSizeBaseProps {\n /** The size in force. Default: the one on `<html>` ({@link useTextSize}), which is the\n * size whoever applied it put there. */\n value?: TextSize;\n /** The row's name. Default: `appearance.textSize` (\"Text size\"). */\n label?: string;\n /** The `appearance` words (`textSize`, `textSizes`, `textSmaller`, `textLarger`). */\n labels?: LabelOverride<AppearanceLabels>;\n}\n\n/**\n * `onChange`, or the deprecated `onPick`, is required: with both optional, a row an app\n * moved off `onPick` without adding `onChange` — or with it misspelt — compiled, and A− /\n * A+ stayed enabled and changed nothing (0.52 code review, account-menu-language.tsx).\n */\nexport type AccountMenuTextSizeProps = AccountMenuTextSizeBaseProps &\n (\n | {\n /**\n * A step: the next size down or up. The app applies it and keeps it as its\n * Settings ▸ Appearance does — `useAccountAppearance`'s `pickTextSize` (this\n * device, and the account when signed in), with `appearance.saveFailed` as the\n * toast when the account refused. The kit does not apply it itself, so the two\n * places can never disagree. `value` + `onChange`, as every kit control pairs them\n * (CONTRIBUTING §4; refactor audit 2026-10-30, API-5).\n */\n onChange: (size: TextSize) => void;\n /** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */\n onPick?: (size: TextSize) => void;\n }\n | {\n onChange?: undefined;\n /** @deprecated 0.52 — `onChange` (the same call); removed in 0.53. */\n onPick: (size: TextSize) => void;\n }\n );\n\n/**\n * The text size one tap away, INSIDE the account menu (0.46, keksdose live #426, its\n * `TextSizeRow`): the row's icon and name, the size in force, and A− / A+, which step\n * through {@link TEXT_SIZES} (Normal → Large → Extra large). A− is disabled at the\n * smallest, A+ at the largest. The browser's pinch zoom stays as it is — this is the\n * quick path to the setting, not a replacement for zoom.\n *\n * It renders its own `<li>`: drop it into `TopBarActionMenu`'s `children` beside\n * `AccountMenuLanguage`. The menu promotes the two buttons to `menuitem`s, so ↑/↓ reach\n * them like every other row, and it stays open on a step: the person sees the page grow\n * behind it and can step again. The size's name is a polite live region, so a step is\n * announced.\n */\nexport function AccountMenuTextSize({ value, onChange, onPick, label, labels: labelsProp }: AccountMenuTextSizeProps) {\n const change = onChange ?? onPick;\n const labels = useAppearanceLabels(labelsProp);\n const onHtml = useTextSize().size;\n const size = value ?? onHtml;\n const index = TEXT_SIZES.indexOf(size);\n const step = (by: -1 | 1) => {\n const next = TEXT_SIZES[index + by];\n if (next) change?.(next);\n };\n return (\n <li data-account-menu-text-size=\"\" className=\"flex items-center gap-2 px-3 py-1.5 text-sm\">\n <ALargeSmall aria-hidden className=\"size-4 shrink-0 text-muted\" />\n <span className=\"min-w-0 flex-1 truncate\">\n {label ?? labels.textSize}\n <span className=\"ms-2 text-xs text-muted\" aria-live=\"polite\">\n {labels.textSizes[size]}\n </span>\n </span>\n <IconButton\n size=\"sm\"\n label={labels.textSmaller}\n labelVisible={false}\n tooltip={false}\n disabled={index <= 0}\n onClick={() => step(-1)}\n >\n <AArrowDown />\n </IconButton>\n <IconButton\n size=\"sm\"\n label={labels.textLarger}\n labelVisible={false}\n tooltip={false}\n disabled={index >= TEXT_SIZES.length - 1}\n onClick={() => step(1)}\n >\n <AArrowUp />\n </IconButton>\n </li>\n );\n}\n"],"mappings":";AAqEM,cACA,YADA;AArEN,SAAS,YAAY,UAAU,mBAAmB;AAClD,SAAS,kBAAkB;AAC3B,SAAS,2BAAkD;AAE3D,SAAS,YAAY,mBAAkC;AAqDhD,SAAS,oBAAoB,EAAE,OAAO,UAAU,QAAQ,OAAO,QAAQ,WAAW,GAA6B;AACpH,QAAM,SAAS,YAAY;AAC3B,QAAM,SAAS,oBAAoB,UAAU;AAC7C,QAAM,SAAS,YAAY,EAAE;AAC7B,QAAM,OAAO,SAAS;AACtB,QAAM,QAAQ,WAAW,QAAQ,IAAI;AACrC,QAAM,OAAO,CAAC,OAAe;AAC3B,UAAM,OAAO,WAAW,QAAQ,EAAE;AAClC,QAAI,KAAM,UAAS,IAAI;AAAA,EACzB;AACA,SACE,qBAAC,QAAG,+BAA4B,IAAG,WAAU,+CAC3C;AAAA,wBAAC,eAAY,eAAW,MAAC,WAAU,8BAA6B;AAAA,IAChE,qBAAC,UAAK,WAAU,2BACb;AAAA,eAAS,OAAO;AAAA,MACjB,oBAAC,UAAK,WAAU,2BAA0B,aAAU,UACjD,iBAAO,UAAU,IAAI,GACxB;AAAA,OACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAO,OAAO;AAAA,QACd,cAAc;AAAA,QACd,SAAS;AAAA,QACT,UAAU,SAAS;AAAA,QACnB,SAAS,MAAM,KAAK,EAAE;AAAA,QAEtB,8BAAC,cAAW;AAAA;AAAA,IACd;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAO,OAAO;AAAA,QACd,cAAc;AAAA,QACd,SAAS;AAAA,QACT,UAAU,SAAS,WAAW,SAAS;AAAA,QACvC,SAAS,MAAM,KAAK,CAAC;AAAA,QAErB,8BAAC,YAAS;AAAA;AAAA,IACZ;AAAA,KACF;AAEJ;","names":[]}
@@ -5,21 +5,8 @@ import { FlaskConical, Undo2 } from "lucide-react";
5
5
  import { DEFAULT_TOP_BAR_LABELS, useKitLabels } from "../i18n/kit-labels.js";
6
6
  import { TopBarActionMenu } from "./topbar-action-menu.js";
7
7
  import { useTopBarPartsLabels } from "./top-bar-parts-labels.js";
8
+ import { readSessionStored, writeSessionStored } from "../lib/safe-storage.js";
8
9
  const DEV_ORIGINAL_ROLE_KEY = "ui-kit:dev-original-role";
9
- function readKey(key) {
10
- try {
11
- return sessionStorage.getItem(key);
12
- } catch {
13
- return null;
14
- }
15
- }
16
- function writeKey(key, value) {
17
- try {
18
- if (value === null) sessionStorage.removeItem(key);
19
- else sessionStorage.setItem(key, value);
20
- } catch {
21
- }
22
- }
23
10
  const flask = /* @__PURE__ */ jsx(FlaskConical, { className: "size-5 text-warning" });
24
11
  const textOf = (label, value) => typeof label === "string" || typeof label === "number" ? String(label) : value;
25
12
  const isRow = (entry) => entry.kind !== "heading" && entry.kind !== "divider";
@@ -42,21 +29,21 @@ function DevMenu({
42
29
  }) {
43
30
  const bar = useKitLabels("topBar", DEFAULT_TOP_BAR_LABELS);
44
31
  const words = useTopBarPartsLabels(labelsProp ? { dev: labelsProp } : void 0).dev;
45
- const [kept, setKept] = useState(() => enabled ? readKey(storageKey) : null);
32
+ const [kept, setKept] = useState(() => enabled ? readSessionStored(storageKey) : null);
46
33
  const [wasEnabled, setWasEnabled] = useState(enabled);
47
34
  if (wasEnabled !== enabled) {
48
35
  setWasEnabled(enabled);
49
- if (enabled) setKept(readKey(storageKey));
36
+ if (enabled) setKept(readSessionStored(storageKey));
50
37
  }
51
38
  if (!enabled) return null;
52
39
  const original = originalRole ?? kept ?? void 0;
53
40
  const pickRole = (next) => {
54
41
  if (originalRole === void 0) {
55
42
  if (next === original) {
56
- writeKey(storageKey, null);
43
+ writeSessionStored(storageKey, null);
57
44
  setKept(null);
58
45
  } else if (kept === null && role !== void 0 && next !== role) {
59
- writeKey(storageKey, role);
46
+ writeSessionStored(storageKey, role);
60
47
  setKept(role);
61
48
  }
62
49
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/shell/dev-menu.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { FlaskConical, Undo2 } from \"lucide-react\";\nimport { DEFAULT_TOP_BAR_LABELS, useKitLabels, type LabelOverride } from \"../i18n/kit-labels\";\nimport { TopBarActionMenu, type TopBarMenuEntry } from \"./topbar-action-menu\";\nimport { useTopBarPartsLabels, type DevSwitchersLabels } from \"./top-bar-parts-labels\";\n\n/** Where the role the session started with is kept, unless the app names its own key. */\nexport const DEV_ORIGINAL_ROLE_KEY = \"ui-kit:dev-original-role\";\n\nfunction readKey(key: string): string | null {\n try {\n return sessionStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\nfunction writeKey(key: string, value: string | null): void {\n try {\n if (value === null) sessionStorage.removeItem(key);\n else sessionStorage.setItem(key, value);\n } catch {\n /* storage blocked: \"Back to\" lasts as long as this page */\n }\n}\n\n/**\n * One of the app's own groups in the {@link DevMenu} (docs/top-bar-harmonization.md\n * §2.7.1): keksdose's budget role, its \"today\" override, its resets.\n *\n * The rows are plain {@link TopBarMenuEntry}s, and there is no dev item type beside them\n * (the contract with keksdose, 0.51): a choice of one is radio rows (`checked`), a toggle\n * is a `checkable: \"checkbox\"` row, an action is a plain row. No form fields — a menu is\n * a `role=\"menu\"`, where a text or date input has no place in the arrow keys; a free\n * value is a \"Custom…\" row that opens the app's own dialog.\n */\nexport interface DevMenuSection {\n /** Unique among the sections. The rows' keys need be unique only within theirs: the\n * menu prefixes them with this. */\n key: string;\n /** The group's heading, drawn above its rows and announced as the group's name. */\n title: ReactNode;\n /** The rows, as `TopBarActionMenu` takes them. A `divider` ends the group, as there. */\n entries: readonly TopBarMenuEntry[];\n}\n\nexport interface DevMenuProps<R extends string, P extends string> {\n /**\n * Draw anything at all. The app passes `import.meta.env.DEV` AND its probe of the dev\n * route (§2.7.1): the constant keeps the menu off a production build's screen, the\n * probe off a dev build whose server has the route shut (§6.1) — flasks with nothing\n * behind them. Neither takes code out of the bundle; see `sections`.\n */\n enabled: boolean;\n roles?: readonly R[];\n /** The role the server enforces now. Named `currentRole`, not `role`, because `role` on\n * a JSX element is the ARIA role (as `RoleChip`'s `value`). */\n currentRole?: R;\n /** Apply a role — the app calls server-kit's `POST /dev/switch {role}` and re-reads\n * `/auth/me` (§2.7, §6.2). */\n onRole?: (role: R) => void;\n plans?: readonly P[];\n /** The plan the server enforces now. Left out (not known yet — kastlan's overview is a\n * 404 while billing is off), the plan group still renders, with no row checked; a\n * `GET /dev/switch` answers it. */\n currentPlan?: P;\n /** Apply a plan — `POST /dev/switch {plan}`, then the overview (§6.3). */\n onPlan?: (plan: P) => void;\n /**\n * The role to offer \"Back to {role}\" for. Left out, the kit keeps it itself: the role\n * before the first switch of this browser session, in `sessionStorage` under\n * `storageKey` — the server answers with the NEW role after a switch, so only the\n * browser still knows the old one.\n */\n originalRole?: R;\n /** The `sessionStorage` key for the kept role. Default {@link DEV_ORIGINAL_ROLE_KEY};\n * an app with several accounts on one browser may scope it per user. */\n storageKey?: string;\n /** Billing is off locally: the plan group says plans change nothing, and stays usable\n * (§6.3). */\n billingOff?: boolean;\n /** A role's or a plan's words in the menu. Default: the value itself. */\n roleLabel?: (role: R) => ReactNode;\n planLabel?: (plan: P) => ReactNode;\n /** Prop > `<UiKitProvider labels={{ topBarParts: { dev } }}>` > English. */\n labels?: LabelOverride<DevSwitchersLabels>;\n /** 0.51: the app's own dev groups, after the kit's role and plan, in this order. Their\n * DEFINITIONS belong in a module only a dev build imports (§2.7.1): `enabled={false}`\n * hides the menu, but the code of a section built inline stays in the bundle. */\n sections?: readonly DevMenuSection[];\n /**\n * 0.51: an override is on that the developer could forget — a \"today\" that is not\n * today, a simulated slow server. The flask wears a dot, and its name says so (\"Dev\n * tools · Role: ADMIN · Plan: free Overrides on\"), since a dot alone tells a screen\n * reader nothing. The app decides what counts; the kit cannot see into its sections.\n */\n active?: boolean;\n}\n\nconst flask = <FlaskConical className=\"size-5 text-warning\" />;\n\n/** A label's text for a sentence, or the raw value when the label is not text. */\nconst textOf = (label: ReactNode, value: string) =>\n typeof label === \"string\" || typeof label === \"number\" ? String(label) : value;\n\n/** A row someone can pick — what makes a menu worth drawing. */\nconst isRow = (entry: TopBarMenuEntry) => entry.kind !== \"heading\" && entry.kind !== \"divider\";\n\n/**\n * The top bar's local-dev menu (docs/top-bar-harmonization.md §2.7, §2.7.1, §6.2, §6.3):\n * ONE amber flask, `RoleSwitcher`'s, over the kit's Account section and the app's own.\n *\n * 0.42's `DevSwitchers` drew a flask per switcher and had no place for anything else,\n * and an app has more dev controls than a role and a plan — keksdose's budget role, a\n * \"today\" override, resets (agreed with keksdose for 0.51). So the kit's part is now the\n * menu, and the app's rows go in it.\n *\n * - **The Account section** comes first: the role group, ending in \"Back to {role}\" once\n * the role differs from the one the session started with (the dev route needs only a\n * signed-in user, so a switch to a lesser role can always switch back); then the plan\n * group, which with `billingOff` notes that plans change nothing. Each renders only\n * with its list and handler.\n * - **The app's `sections`** follow, each a group under its own heading.\n * - **`active`** puts a dot on the flask for an override that is easy to forget.\n *\n * Nothing renders unless `enabled`, and nothing with no row to show. The panel scrolls\n * (`TopBarActionMenu`'s `scrollable`): some 25 rows ran off a 390×844 phone.\n *\n * From `md` up the groups stand side by side, one column each, in that order (0.51.4,\n * `TopBarActionMenu`'s `columns`; keksdose dev #640, Marcel: \"Each group gets a column\").\n * \"Back to {role}\" stays under the roles. A desktop too narrow for all of them wraps\n * the columns onto a second row; a phone keeps the one scrolling column.\n */\nexport function DevMenu<R extends string, P extends string>({\n enabled,\n roles,\n currentRole: role,\n onRole,\n plans,\n currentPlan: plan,\n onPlan,\n originalRole,\n storageKey = DEV_ORIGINAL_ROLE_KEY,\n billingOff = false,\n roleLabel = (r) => r,\n planLabel = (p) => p,\n labels: labelsProp,\n sections = [],\n active = false,\n}: DevMenuProps<R, P>) {\n const bar = useKitLabels(\"topBar\", DEFAULT_TOP_BAR_LABELS);\n const words = useTopBarPartsLabels(labelsProp ? { dev: labelsProp } : undefined).dev;\n const [kept, setKept] = useState<string | null>(() => (enabled ? readKey(storageKey) : null));\n // 0.43 (keksdose): `enabled` may start false and turn true — an app's GET probe of the\n // dev route — so the kept role is read again then, or \"Back to {role}\" is lost after a\n // reload. Adjusted during render, React's pattern for state that follows a prop.\n const [wasEnabled, setWasEnabled] = useState(enabled);\n if (wasEnabled !== enabled) {\n setWasEnabled(enabled);\n if (enabled) setKept(readKey(storageKey));\n }\n if (!enabled) return null;\n\n const original = (originalRole ?? kept ?? undefined) as R | undefined;\n\n const pickRole = (next: R) => {\n if (originalRole === undefined) {\n if (next === original) {\n // Back where the session began: nothing left to go back to.\n writeKey(storageKey, null);\n setKept(null);\n } else if (kept === null && role !== undefined && next !== role) {\n writeKey(storageKey, role);\n setKept(role);\n }\n }\n onRole?.(next);\n };\n\n const roleGroup: TopBarMenuEntry[] =\n roles && roles.length > 0 && role !== undefined && onRole\n ? [\n { kind: \"heading\", key: \"head-role\", label: words.roleHeading },\n ...roles.map((r): TopBarMenuEntry => ({\n key: `role-${r}`,\n label: roleLabel(r),\n checked: r === role,\n onSelect: () => pickRole(r),\n })),\n // Behind a rule, which ends the role group: \"Back to\" is a way out, not a role.\n ...(original !== undefined && original !== role\n ? ([\n { kind: \"divider\", key: \"sep-back\" },\n {\n key: \"back\",\n icon: <Undo2 className=\"size-4\" />,\n label: words.backTo(textOf(roleLabel(original), original)),\n onSelect: () => pickRole(original),\n },\n ] satisfies TopBarMenuEntry[])\n : []),\n ]\n : [];\n\n const planGroup: TopBarMenuEntry[] =\n plans && plans.length > 0 && onPlan\n ? [\n {\n kind: \"heading\",\n key: \"head-plan\",\n // The billing-off note is part of the group's NAME, under the heading. In 0.42's\n // own plan menu it was a trailing `<li>`: not a row, so the arrow keys passed\n // over it and a screen reader moving through the menu never reached it. Named,\n // it is read on the way into the plans. And in one menu a trailing note would\n // sit under the app's sections, not under the plans.\n label: billingOff ? (\n <>\n {words.planHeading}{\" \"}\n <span\n data-dev-billing-off=\"\"\n className=\"mt-0.5 block font-normal normal-case tracking-normal text-xs text-muted\"\n >\n {words.billingOff}\n </span>\n </>\n ) : (\n words.planHeading\n ),\n },\n ...plans.map((p): TopBarMenuEntry => ({\n key: `plan-${p}`,\n label: planLabel(p),\n checked: p === plan,\n onSelect: () => onPlan(p),\n })),\n ]\n : [];\n\n // The app's rows keyed under their section: two sections may well both have a \"reset\".\n const appGroups = sections.flatMap((section): TopBarMenuEntry[] => [\n { kind: \"heading\", key: `section:${section.key}`, label: section.title },\n ...section.entries.map((entry): TopBarMenuEntry => ({ ...entry, key: `${section.key}:${entry.key}` })),\n ]);\n\n const entries = [...roleGroup, ...planGroup, ...appGroups];\n if (!entries.some(isRow)) return null;\n\n // The menu, then the role and the plan, as 0.42's two triggers named them: the bar\n // shows the flask only, so its name (and tooltip) is where they are read.\n const name = [\n words.menu,\n roleGroup.length > 0 && role !== undefined ? bar.role(role) : null,\n planGroup.length > 0 && plan !== undefined ? words.plan(plan) : null,\n ]\n .filter((part): part is string => part !== null)\n .join(\" · \");\n\n return (\n <TopBarActionMenu\n icon={flask}\n // The badge's words join the trigger's name, as the tours compass's NEW dot does.\n // `danger`, the badge's default: an amber dot would vanish into the amber flask.\n iconBadge={active ? { label: words.overridesOn } : null}\n aria-label={name}\n entries={entries}\n scrollable\n columns\n />\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/shell/dev-menu.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { FlaskConical, Undo2 } from \"lucide-react\";\nimport { DEFAULT_TOP_BAR_LABELS, useKitLabels, type LabelOverride } from \"../i18n/kit-labels\";\nimport { TopBarActionMenu, type TopBarMenuEntry } from \"./topbar-action-menu\";\nimport { useTopBarPartsLabels, type DevSwitchersLabels } from \"./top-bar-parts-labels\";\n// The kit's one storage guard, which 0.51 wrote here again by hand (DUP-8, refactor audit\n// 2026-10-30). Storage blocked, \"Back to\" lasts as long as this page.\nimport { readSessionStored, writeSessionStored } from \"../lib/safe-storage\";\n\n/** Where the role the session started with is kept, unless the app names its own key. */\nexport const DEV_ORIGINAL_ROLE_KEY = \"ui-kit:dev-original-role\";\n\n/**\n * One of the app's own groups in the {@link DevMenu} (docs/top-bar-harmonization.md\n * §2.7.1): keksdose's budget role, its \"today\" override, its resets.\n *\n * The rows are plain {@link TopBarMenuEntry}s, and there is no dev item type beside them\n * (the contract with keksdose, 0.51): a choice of one is radio rows (`checked`), a toggle\n * is a `checkable: \"checkbox\"` row, an action is a plain row. No form fields — a menu is\n * a `role=\"menu\"`, where a text or date input has no place in the arrow keys; a free\n * value is a \"Custom…\" row that opens the app's own dialog.\n */\nexport interface DevMenuSection {\n /** Unique among the sections. The rows' keys need be unique only within theirs: the\n * menu prefixes them with this. */\n key: string;\n /** The group's heading, drawn above its rows and announced as the group's name. */\n title: ReactNode;\n /** The rows, as `TopBarActionMenu` takes them. A `divider` ends the group, as there. */\n entries: readonly TopBarMenuEntry[];\n}\n\nexport interface DevMenuProps<R extends string, P extends string> {\n /**\n * Draw anything at all. The app passes `import.meta.env.DEV` AND its probe of the dev\n * route (§2.7.1): the constant keeps the menu off a production build's screen, the\n * probe off a dev build whose server has the route shut (§6.1) — flasks with nothing\n * behind them. Neither takes code out of the bundle; see `sections`.\n */\n enabled: boolean;\n roles?: readonly R[];\n /** The role the server enforces now. Named `currentRole`, not `role`, because `role` on\n * a JSX element is the ARIA role (as `RoleChip`'s `value`). */\n currentRole?: R;\n /** Apply a role — the app calls server-kit's `POST /dev/switch {role}` and re-reads\n * `/auth/me` (§2.7, §6.2). */\n onRole?: (role: R) => void;\n plans?: readonly P[];\n /** The plan the server enforces now. Left out (not known yet — kastlan's overview is a\n * 404 while billing is off), the plan group still renders, with no row checked; a\n * `GET /dev/switch` answers it. */\n currentPlan?: P;\n /** Apply a plan — `POST /dev/switch {plan}`, then the overview (§6.3). */\n onPlan?: (plan: P) => void;\n /**\n * The role to offer \"Back to {role}\" for. Left out, the kit keeps it itself: the role\n * before the first switch of this browser session, in `sessionStorage` under\n * `storageKey` — the server answers with the NEW role after a switch, so only the\n * browser still knows the old one.\n */\n originalRole?: R;\n /** The `sessionStorage` key for the kept role. Default {@link DEV_ORIGINAL_ROLE_KEY};\n * an app with several accounts on one browser may scope it per user. */\n storageKey?: string;\n /** Billing is off locally: the plan group says plans change nothing, and stays usable\n * (§6.3). */\n billingOff?: boolean;\n /** A role's or a plan's words in the menu. Default: the value itself. */\n roleLabel?: (role: R) => ReactNode;\n planLabel?: (plan: P) => ReactNode;\n /** Prop > `<UiKitProvider labels={{ topBarParts: { dev } }}>` > English. */\n labels?: LabelOverride<DevSwitchersLabels>;\n /** 0.51: the app's own dev groups, after the kit's role and plan, in this order. Their\n * DEFINITIONS belong in a module only a dev build imports (§2.7.1): `enabled={false}`\n * hides the menu, but the code of a section built inline stays in the bundle. */\n sections?: readonly DevMenuSection[];\n /**\n * 0.51: an override is on that the developer could forget — a \"today\" that is not\n * today, a simulated slow server. The flask wears a dot, and its name says so (\"Dev\n * tools · Role: ADMIN · Plan: free Overrides on\"), since a dot alone tells a screen\n * reader nothing. The app decides what counts; the kit cannot see into its sections.\n */\n active?: boolean;\n}\n\nconst flask = <FlaskConical className=\"size-5 text-warning\" />;\n\n/** A label's text for a sentence, or the raw value when the label is not text. */\nconst textOf = (label: ReactNode, value: string) =>\n typeof label === \"string\" || typeof label === \"number\" ? String(label) : value;\n\n/** A row someone can pick — what makes a menu worth drawing. */\nconst isRow = (entry: TopBarMenuEntry) => entry.kind !== \"heading\" && entry.kind !== \"divider\";\n\n/**\n * The top bar's local-dev menu (docs/top-bar-harmonization.md §2.7, §2.7.1, §6.2, §6.3):\n * ONE amber flask, `RoleSwitcher`'s, over the kit's Account section and the app's own.\n *\n * 0.42's `DevSwitchers` drew a flask per switcher and had no place for anything else,\n * and an app has more dev controls than a role and a plan — keksdose's budget role, a\n * \"today\" override, resets (agreed with keksdose for 0.51). So the kit's part is now the\n * menu, and the app's rows go in it.\n *\n * - **The Account section** comes first: the role group, ending in \"Back to {role}\" once\n * the role differs from the one the session started with (the dev route needs only a\n * signed-in user, so a switch to a lesser role can always switch back); then the plan\n * group, which with `billingOff` notes that plans change nothing. Each renders only\n * with its list and handler.\n * - **The app's `sections`** follow, each a group under its own heading.\n * - **`active`** puts a dot on the flask for an override that is easy to forget.\n *\n * Nothing renders unless `enabled`, and nothing with no row to show. The panel scrolls\n * (`TopBarActionMenu`'s `scrollable`): some 25 rows ran off a 390×844 phone.\n *\n * From `md` up the groups stand side by side, one column each, in that order (0.51.4,\n * `TopBarActionMenu`'s `columns`; keksdose dev #640, Marcel: \"Each group gets a column\").\n * \"Back to {role}\" stays under the roles. A desktop too narrow for all of them wraps\n * the columns onto a second row; a phone keeps the one scrolling column.\n */\nexport function DevMenu<R extends string, P extends string>({\n enabled,\n roles,\n currentRole: role,\n onRole,\n plans,\n currentPlan: plan,\n onPlan,\n originalRole,\n storageKey = DEV_ORIGINAL_ROLE_KEY,\n billingOff = false,\n roleLabel = (r) => r,\n planLabel = (p) => p,\n labels: labelsProp,\n sections = [],\n active = false,\n}: DevMenuProps<R, P>) {\n const bar = useKitLabels(\"topBar\", DEFAULT_TOP_BAR_LABELS);\n const words = useTopBarPartsLabels(labelsProp ? { dev: labelsProp } : undefined).dev;\n const [kept, setKept] = useState<string | null>(() => (enabled ? readSessionStored(storageKey) : null));\n // 0.43 (keksdose): `enabled` may start false and turn true — an app's GET probe of the\n // dev route — so the kept role is read again then, or \"Back to {role}\" is lost after a\n // reload. Adjusted during render, React's pattern for state that follows a prop.\n const [wasEnabled, setWasEnabled] = useState(enabled);\n if (wasEnabled !== enabled) {\n setWasEnabled(enabled);\n if (enabled) setKept(readSessionStored(storageKey));\n }\n if (!enabled) return null;\n\n const original = (originalRole ?? kept ?? undefined) as R | undefined;\n\n const pickRole = (next: R) => {\n if (originalRole === undefined) {\n if (next === original) {\n // Back where the session began: nothing left to go back to.\n writeSessionStored(storageKey, null);\n setKept(null);\n } else if (kept === null && role !== undefined && next !== role) {\n writeSessionStored(storageKey, role);\n setKept(role);\n }\n }\n onRole?.(next);\n };\n\n const roleGroup: TopBarMenuEntry[] =\n roles && roles.length > 0 && role !== undefined && onRole\n ? [\n { kind: \"heading\", key: \"head-role\", label: words.roleHeading },\n ...roles.map((r): TopBarMenuEntry => ({\n key: `role-${r}`,\n label: roleLabel(r),\n checked: r === role,\n onSelect: () => pickRole(r),\n })),\n // Behind a rule, which ends the role group: \"Back to\" is a way out, not a role.\n ...(original !== undefined && original !== role\n ? ([\n { kind: \"divider\", key: \"sep-back\" },\n {\n key: \"back\",\n icon: <Undo2 className=\"size-4\" />,\n label: words.backTo(textOf(roleLabel(original), original)),\n onSelect: () => pickRole(original),\n },\n ] satisfies TopBarMenuEntry[])\n : []),\n ]\n : [];\n\n const planGroup: TopBarMenuEntry[] =\n plans && plans.length > 0 && onPlan\n ? [\n {\n kind: \"heading\",\n key: \"head-plan\",\n // The billing-off note is part of the group's NAME, under the heading. In 0.42's\n // own plan menu it was a trailing `<li>`: not a row, so the arrow keys passed\n // over it and a screen reader moving through the menu never reached it. Named,\n // it is read on the way into the plans. And in one menu a trailing note would\n // sit under the app's sections, not under the plans.\n label: billingOff ? (\n <>\n {words.planHeading}{\" \"}\n <span\n data-dev-billing-off=\"\"\n className=\"mt-0.5 block font-normal normal-case tracking-normal text-xs text-muted\"\n >\n {words.billingOff}\n </span>\n </>\n ) : (\n words.planHeading\n ),\n },\n ...plans.map((p): TopBarMenuEntry => ({\n key: `plan-${p}`,\n label: planLabel(p),\n checked: p === plan,\n onSelect: () => onPlan(p),\n })),\n ]\n : [];\n\n // The app's rows keyed under their section: two sections may well both have a \"reset\".\n const appGroups = sections.flatMap((section): TopBarMenuEntry[] => [\n { kind: \"heading\", key: `section:${section.key}`, label: section.title },\n ...section.entries.map((entry): TopBarMenuEntry => ({ ...entry, key: `${section.key}:${entry.key}` })),\n ]);\n\n const entries = [...roleGroup, ...planGroup, ...appGroups];\n if (!entries.some(isRow)) return null;\n\n // The menu, then the role and the plan, as 0.42's two triggers named them: the bar\n // shows the flask only, so its name (and tooltip) is where they are read.\n const name = [\n words.menu,\n roleGroup.length > 0 && role !== undefined ? bar.role(role) : null,\n planGroup.length > 0 && plan !== undefined ? words.plan(plan) : null,\n ]\n .filter((part): part is string => part !== null)\n .join(\" · \");\n\n return (\n <TopBarActionMenu\n icon={flask}\n // The badge's words join the trigger's name, as the tours compass's NEW dot does.\n // `danger`, the badge's default: an amber dot would vanish into the amber flask.\n iconBadge={active ? { label: words.overridesOn } : null}\n aria-label={name}\n entries={entries}\n scrollable\n columns\n />\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,3 +1,4 @@
1
+ /** @deprecated 0.52 — `DevMenuProps` (`roles`, `currentRole`, `onRole`) (MOD-5); removed in 0.53. */
1
2
  export interface RoleSwitcherProps<R extends string> {
2
3
  roles: readonly R[];
3
4
  value: R;
@@ -17,5 +18,11 @@ export interface RoleSwitcherProps<R extends string> {
17
18
  * The flask wears `--warning` rather than a fixed `amber-500`: it is a caution
18
19
  * marker — the app is not showing you your own role — and the token carries that
19
20
  * amber across both themes instead of pinning one hue onto every palette.
21
+ *
22
+ * Deprecated in 0.52, removed in 0.53 (decision 4 of the refactor audit 2026-10-30,
23
+ * MOD-5): the role switch every app draws is `DevMenu`'s Account section (0.51), and no
24
+ * app renders this one.
25
+ *
26
+ * @deprecated 0.52 — `DevMenu` with `roles`, `currentRole` and `onRole` (MOD-5); removed in 0.53.
20
27
  */
21
28
  export declare function RoleSwitcher<R extends string>({ roles, value, onChange, "aria-label": ariaLabel, heading, title, }: RoleSwitcherProps<R>): import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/shell/role-switcher.tsx"],"sourcesContent":["import { FlaskConical } from \"lucide-react\";\nimport { OptionSwitcherMenu } from \"./option-switcher-menu\";\nimport { DEFAULT_TOP_BAR_LABELS, useKitLabels } from \"../i18n/kit-labels\";\n\nexport interface RoleSwitcherProps<R extends string> {\n roles: readonly R[];\n value: R;\n onChange: (role: R) => void;\n /** Default: `topBar.switchRole` from the {@link UiKitProvider}, else English. */\n \"aria-label\"?: string;\n heading?: string;\n /** The trigger's tooltip. Default: `topBar.role(value)`. */\n title?: string;\n}\n\n/**\n * A reusable user-role switcher (feedback #337): a thin wrapper over\n * {@link OptionSwitcherMenu} with the standard flask icon, so an app drops it in\n * the top bar with just the role list + current value + a handler. Typically\n * dev-only / UI-only, but the app decides where and whether to render it.\n *\n * The flask wears `--warning` rather than a fixed `amber-500`: it is a caution\n * marker — the app is not showing you your own role — and the token carries that\n * amber across both themes instead of pinning one hue onto every palette.\n */\nexport function RoleSwitcher<R extends string>({\n roles,\n value,\n onChange,\n \"aria-label\": ariaLabel,\n heading,\n title,\n}: RoleSwitcherProps<R>) {\n const labels = useKitLabels(\"topBar\", DEFAULT_TOP_BAR_LABELS, { switchRole: ariaLabel });\n return (\n <OptionSwitcherMenu<R>\n aria-label={labels.switchRole}\n title={title ?? labels.role(value)}\n heading={heading}\n icon={<FlaskConical className=\"size-5 text-warning\" />}\n options={roles.map((r) => ({ value: r, label: r }))}\n value={value}\n onSelect={onChange}\n />\n );\n}\n"],"mappings":";AAuCY;AAvCZ,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,wBAAwB,oBAAoB;AAuB9C,SAAS,aAA+B;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAAyB;AACvB,QAAM,SAAS,aAAa,UAAU,wBAAwB,EAAE,YAAY,UAAU,CAAC;AACvF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,cAAY,OAAO;AAAA,MACnB,OAAO,SAAS,OAAO,KAAK,KAAK;AAAA,MACjC;AAAA,MACA,MAAM,oBAAC,gBAAa,WAAU,uBAAsB;AAAA,MACpD,SAAS,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,EAAE;AAAA,MAClD;AAAA,MACA,UAAU;AAAA;AAAA,EACZ;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/shell/role-switcher.tsx"],"sourcesContent":["import { FlaskConical } from \"lucide-react\";\nimport { OptionSwitcherMenu } from \"./option-switcher-menu\";\nimport { DEFAULT_TOP_BAR_LABELS, useKitLabels } from \"../i18n/kit-labels\";\n\n/** @deprecated 0.52 — `DevMenuProps` (`roles`, `currentRole`, `onRole`) (MOD-5); removed in 0.53. */\nexport interface RoleSwitcherProps<R extends string> {\n roles: readonly R[];\n value: R;\n onChange: (role: R) => void;\n /** Default: `topBar.switchRole` from the {@link UiKitProvider}, else English. */\n \"aria-label\"?: string;\n heading?: string;\n /** The trigger's tooltip. Default: `topBar.role(value)`. */\n title?: string;\n}\n\n/**\n * A reusable user-role switcher (feedback #337): a thin wrapper over\n * {@link OptionSwitcherMenu} with the standard flask icon, so an app drops it in\n * the top bar with just the role list + current value + a handler. Typically\n * dev-only / UI-only, but the app decides where and whether to render it.\n *\n * The flask wears `--warning` rather than a fixed `amber-500`: it is a caution\n * marker — the app is not showing you your own role — and the token carries that\n * amber across both themes instead of pinning one hue onto every palette.\n *\n * Deprecated in 0.52, removed in 0.53 (decision 4 of the refactor audit 2026-10-30,\n * MOD-5): the role switch every app draws is `DevMenu`'s Account section (0.51), and no\n * app renders this one.\n *\n * @deprecated 0.52 — `DevMenu` with `roles`, `currentRole` and `onRole` (MOD-5); removed in 0.53.\n */\nexport function RoleSwitcher<R extends string>({\n roles,\n value,\n onChange,\n \"aria-label\": ariaLabel,\n heading,\n title,\n}: RoleSwitcherProps<R>) {\n const labels = useKitLabels(\"topBar\", DEFAULT_TOP_BAR_LABELS, { switchRole: ariaLabel });\n return (\n <OptionSwitcherMenu<R>\n aria-label={labels.switchRole}\n title={title ?? labels.role(value)}\n heading={heading}\n icon={<FlaskConical className=\"size-5 text-warning\" />}\n options={roles.map((r) => ({ value: r, label: r }))}\n value={value}\n onSelect={onChange}\n />\n );\n}\n"],"mappings":";AA8CY;AA9CZ,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,wBAAwB,oBAAoB;AA8B9C,SAAS,aAA+B;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAAyB;AACvB,QAAM,SAAS,aAAa,UAAU,wBAAwB,EAAE,YAAY,UAAU,CAAC;AACvF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,cAAY,OAAO;AAAA,MACnB,OAAO,SAAS,OAAO,KAAK,KAAK;AAAA,MACjC;AAAA,MACA,MAAM,oBAAC,gBAAa,WAAU,uBAAsB;AAAA,MACpD,SAAS,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,EAAE;AAAA,MAClD;AAAA,MACA,UAAU;AAAA;AAAA,EACZ;AAEJ;","names":[]}
@@ -21,7 +21,7 @@ export interface TopBarActionsProps {
21
21
  /** `DevMenu` (0.51, docs/top-bar-harmonization.md §2.7.1): the one flask — the role,
22
22
  * the plan, then the app's own dev sections. Fill it only behind
23
23
  * `import.meta.env.DEV`, so a production build drops the branch. (0.42's
24
- * `DevSwitchers`, deprecated, is a DevMenu with no sections.) */
24
+ * `DevSwitchers` was a DevMenu with no sections; removed in 0.52.) */
25
25
  dev?: ReactNode;
26
26
  /** kastlan's platform button. */
27
27
  platform?: ReactNode;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/shell/top-bar-actions.tsx"],"sourcesContent":["import { Fragment } from \"react\";\nimport type { ReactNode } from \"react\";\n\n/**\n * The top bar's items by name (docs/top-bar-harmonization.md §2.1, §6.6). Each is the\n * app's own node — a kit part or its own — and any may be left out.\n */\nexport interface TopBarActionsProps {\n /** kastlan's `CompanySwitcher`: the context, first. */\n companySwitcher?: ReactNode;\n /** `GlobalSearch` (⌘K). */\n search?: ReactNode;\n /** `ThemeToggle`. */\n theme?: ReactNode;\n /** `FeedbackMenu`. */\n feedback?: ReactNode;\n /** `TourMenu`. */\n tours?: ReactNode;\n /** kastlan's assistant, beside the tours while it is on. */\n assistant?: ReactNode;\n /** `SyncStatusIndicator`. */\n sync?: ReactNode;\n /** `DevMenu` (0.51, docs/top-bar-harmonization.md §2.7.1): the one flask — the role,\n * the plan, then the app's own dev sections. Fill it only behind\n * `import.meta.env.DEV`, so a production build drops the branch. (0.42's\n * `DevSwitchers`, deprecated, is a DevMenu with no sections.) */\n dev?: ReactNode;\n /** kastlan's platform button. */\n platform?: ReactNode;\n /** 0.46 (docs/notifications-harmonization.md §10.1): `NotificationBell`, right before the\n * account menu. Optional per app: an app shows the bell or an unread dot on the avatar,\n * never both (keksdose keeps its dot and leaves this empty). */\n notifications?: ReactNode;\n /** The account menu. When it is set the signed-out slots are not drawn. */\n account?: ReactNode;\n /** Signed out (§6.6): the bar's `LanguageMenu`, since there is no account menu to hold\n * the language. Drawn only without `account`. */\n language?: ReactNode;\n /** Signed out (§6.6): the \"Sign in\" button, where the account menu would be. Drawn only\n * without `account`. */\n signIn?: ReactNode;\n}\n\n/** §2.1's order, then the signed-out pair in the account menu's place. */\nexport const TOP_BAR_ACTION_ORDER = [\n \"companySwitcher\",\n \"search\",\n \"theme\",\n \"feedback\",\n \"tours\",\n \"assistant\",\n \"sync\",\n \"dev\",\n \"platform\",\n \"notifications\",\n \"account\",\n \"language\",\n \"signIn\",\n] as const satisfies readonly (keyof TopBarActionsProps)[];\n\nconst present = (node: ReactNode) => node !== undefined && node !== null && node !== false && node !== \"\";\n\n/**\n * The top bar's actions in the one order every app shares (§2.1): company switcher ·\n * Search · Theme · Feedback · Tours (· Assistant) · Sync · dev role · dev plan · platform ·\n * notifications (the bell, 0.46) · account menu — and, signed out, Language · Sign in where the account menu goes (§6.6).\n * The app fills the slots it has; an empty slot is skipped, so it leaves no gap.\n *\n * It draws a fragment, no box of its own: hand it to `TopBar`'s `actions`, whose row\n * spaces the items.\n *\n * ```tsx\n * <TopBar brand={…} actions={<TopBarActions search={…} theme={…} tours={…} account={…} />} />\n * ```\n */\nexport function TopBarActions(props: TopBarActionsProps) {\n const signedOut = !present(props.account);\n return (\n <>\n {TOP_BAR_ACTION_ORDER.map((slot) => {\n if ((slot === \"language\" || slot === \"signIn\") && !signedOut) return null;\n const node = props[slot];\n return present(node) ? <Fragment key={slot}>{node}</Fragment> : null;\n })}\n </>\n );\n}\n"],"mappings":";AA8EI,mBAI2B,WAJ3B;AA9EJ,SAAS,YAAAA,iBAAgB;AA4ClB,MAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,UAAU,CAAC,SAAoB,SAAS,UAAa,SAAS,QAAQ,SAAS,SAAS,SAAS;AAehG,SAAS,cAAc,OAA2B;AACvD,QAAM,YAAY,CAAC,QAAQ,MAAM,OAAO;AACxC,SACE,gCACG,+BAAqB,IAAI,CAAC,SAAS;AAClC,SAAK,SAAS,cAAc,SAAS,aAAa,CAAC,UAAW,QAAO;AACrE,UAAM,OAAO,MAAM,IAAI;AACvB,WAAO,QAAQ,IAAI,IAAI,oBAACA,WAAA,EAAqB,kBAAP,IAAY,IAAc;AAAA,EAClE,CAAC,GACH;AAEJ;","names":["Fragment"]}
1
+ {"version":3,"sources":["../../src/shell/top-bar-actions.tsx"],"sourcesContent":["import { Fragment } from \"react\";\nimport type { ReactNode } from \"react\";\n\n/**\n * The top bar's items by name (docs/top-bar-harmonization.md §2.1, §6.6). Each is the\n * app's own node — a kit part or its own — and any may be left out.\n */\nexport interface TopBarActionsProps {\n /** kastlan's `CompanySwitcher`: the context, first. */\n companySwitcher?: ReactNode;\n /** `GlobalSearch` (⌘K). */\n search?: ReactNode;\n /** `ThemeToggle`. */\n theme?: ReactNode;\n /** `FeedbackMenu`. */\n feedback?: ReactNode;\n /** `TourMenu`. */\n tours?: ReactNode;\n /** kastlan's assistant, beside the tours while it is on. */\n assistant?: ReactNode;\n /** `SyncStatusIndicator`. */\n sync?: ReactNode;\n /** `DevMenu` (0.51, docs/top-bar-harmonization.md §2.7.1): the one flask — the role,\n * the plan, then the app's own dev sections. Fill it only behind\n * `import.meta.env.DEV`, so a production build drops the branch. (0.42's\n * `DevSwitchers` was a DevMenu with no sections; removed in 0.52.) */\n dev?: ReactNode;\n /** kastlan's platform button. */\n platform?: ReactNode;\n /** 0.46 (docs/notifications-harmonization.md §10.1): `NotificationBell`, right before the\n * account menu. Optional per app: an app shows the bell or an unread dot on the avatar,\n * never both (keksdose keeps its dot and leaves this empty). */\n notifications?: ReactNode;\n /** The account menu. When it is set the signed-out slots are not drawn. */\n account?: ReactNode;\n /** Signed out (§6.6): the bar's `LanguageMenu`, since there is no account menu to hold\n * the language. Drawn only without `account`. */\n language?: ReactNode;\n /** Signed out (§6.6): the \"Sign in\" button, where the account menu would be. Drawn only\n * without `account`. */\n signIn?: ReactNode;\n}\n\n/** §2.1's order, then the signed-out pair in the account menu's place. */\nexport const TOP_BAR_ACTION_ORDER = [\n \"companySwitcher\",\n \"search\",\n \"theme\",\n \"feedback\",\n \"tours\",\n \"assistant\",\n \"sync\",\n \"dev\",\n \"platform\",\n \"notifications\",\n \"account\",\n \"language\",\n \"signIn\",\n] as const satisfies readonly (keyof TopBarActionsProps)[];\n\nconst present = (node: ReactNode) => node !== undefined && node !== null && node !== false && node !== \"\";\n\n/**\n * The top bar's actions in the one order every app shares (§2.1): company switcher ·\n * Search · Theme · Feedback · Tours (· Assistant) · Sync · dev role · dev plan · platform ·\n * notifications (the bell, 0.46) · account menu — and, signed out, Language · Sign in where the account menu goes (§6.6).\n * The app fills the slots it has; an empty slot is skipped, so it leaves no gap.\n *\n * It draws a fragment, no box of its own: hand it to `TopBar`'s `actions`, whose row\n * spaces the items.\n *\n * ```tsx\n * <TopBar brand={…} actions={<TopBarActions search={…} theme={…} tours={…} account={…} />} />\n * ```\n */\nexport function TopBarActions(props: TopBarActionsProps) {\n const signedOut = !present(props.account);\n return (\n <>\n {TOP_BAR_ACTION_ORDER.map((slot) => {\n if ((slot === \"language\" || slot === \"signIn\") && !signedOut) return null;\n const node = props[slot];\n return present(node) ? <Fragment key={slot}>{node}</Fragment> : null;\n })}\n </>\n );\n}\n"],"mappings":";AA8EI,mBAI2B,WAJ3B;AA9EJ,SAAS,YAAAA,iBAAgB;AA4ClB,MAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,UAAU,CAAC,SAAoB,SAAS,UAAa,SAAS,QAAQ,SAAS,SAAS,SAAS;AAehG,SAAS,cAAc,OAA2B;AACvD,QAAM,YAAY,CAAC,QAAQ,MAAM,OAAO;AACxC,SACE,gCACG,+BAAqB,IAAI,CAAC,SAAS;AAClC,SAAK,SAAS,cAAc,SAAS,aAAa,CAAC,UAAW,QAAO;AACrE,UAAM,OAAO,MAAM,IAAI;AACvB,WAAO,QAAQ,IAAI,IAAI,oBAACA,WAAA,EAAqB,kBAAP,IAAY,IAAc;AAAA,EAClE,CAAC,GACH;AAEJ;","names":["Fragment"]}
@@ -78,8 +78,6 @@ export interface DevSwitchersLabels {
78
78
  overridesOn: string;
79
79
  /** The heading of the role group. */
80
80
  roleHeading: string;
81
- /** @deprecated 0.51 — DevMenu's one flask is named by `menu`; removed in 0.52. */
82
- switchPlan: string;
83
81
  /** The plan in the flask's name, given the active plan. */
84
82
  plan: (value: string) => string;
85
83
  /** The heading of the plan group. */
@@ -36,7 +36,6 @@ const DEFAULT_TOP_BAR_PARTS_LABELS = {
36
36
  menu: "Dev tools",
37
37
  overridesOn: "Overrides on",
38
38
  roleHeading: "Dev \xB7 role",
39
- switchPlan: "Switch plan",
40
39
  plan: (value) => `Plan: ${value}`,
41
40
  planHeading: "Dev \xB7 plan",
42
41
  backTo: (role) => `Back to ${role}`,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/shell/top-bar-parts-labels.ts"],"sourcesContent":["import { useKitLabels, type LabelOverride } from \"../i18n/kit-labels\";\n\n/**\n * The `topBarParts` namespace (0.42, docs/top-bar-harmonization.md §3.1): the words of the\n * top bar's shared parts — `TourMenu`, `SyncStatusIndicator` and `DevMenu` (0.42's\n * `DevSwitchers`, whose words these still are, §2.7.1). A module\n * of words with no component code, like every `*-labels.ts` (0.34, KS U8). The language\n * sub-list (`AccountMenuLanguage`) names itself with `topBar.language`, and the role in the\n * dev flask's name is `topBar.role`, as `RoleSwitcher`'s tooltip.\n */\n\n/** `TourMenu`'s words (§2.4). */\nexport interface TourMenuLabels {\n /** The compass's name, and the menu's. */\n menu: string;\n /** The NEW dot on the compass, for a reader: it joins the trigger's name. */\n newDot: string;\n /** The heading over the tours that start on the open page. */\n thisPage: string;\n /** The heading over the untaken new tours. */\n newTours: string;\n /** The last row, the way to the app's tours page (only with `href`). */\n allTours: string;\n /** The chip on a new tour's row. */\n badgeNew: string;\n /** What the ✓ on a taken tour's row says to a reader. */\n completed: string;\n /** The chip on a tour reset by an update (0.43, docs/tours-harmonization.md §8). */\n badgeUpdated: string;\n /** The dot on the compass while only updated tours light it, for a reader. */\n updatedDot: string;\n /** The heading over the untaken new tours when updated ones are among them. */\n newAndUpdated: string;\n}\n\n/** `SyncStatusIndicator`'s words (§2.6). The \"waiting for a plan\" state is\n * `billing.waitingChanges`, the kit's words for it since billing §12.5. */\nexport interface SyncStatusLabels {\n /** Writes this device cannot send (keksdose: no key for the budget). Ranked first. */\n blocked: (count: number) => string;\n offline: string;\n /** The server refused the last round. */\n refused: string;\n syncing: string;\n pending: (count: number) => string;\n /** Settled, with the time of the last good round (already formatted). */\n syncedAt: (time: string) => string;\n /** Settled, before the first round. */\n idle: string;\n /** Joined to the state when a tap syncs: what the tap does. */\n syncHint: string;\n /** Joined to the state while offline, when a tap can do nothing. */\n offlineHint: string;\n /** The state and what a tap does, as one tooltip: \"Offline — nothing to sync…\". */\n withHint: (state: string, hint: string) => string;\n /** The state with the app's `scope` words before it: \"Handovers on this device: …\". */\n scoped: (scope: string, state: string) => string;\n /** The short words beside the cloud (`showLabel`): offline. */\n offlineShort: string;\n /** The short words while syncing. */\n syncingShort: string;\n /** The short words while changes wait (pending, held for a plan, or blocked). */\n waitingShort: (count: number) => string;\n /** The short words after a refused round. */\n refusedShort: string;\n /** Offline in an online-only app (`storage=\"none\"`): nothing is kept on the device. */\n offlineUnsaved: string;\n /** A round under way in an online-only app — it saves, it doesn't sync. Also its short\n * words beside the cloud. */\n saving: string;\n}\n\n/**\n * `DevMenu`'s words (§2.7, §2.7.1, §6.2, §6.3). Still named for 0.42's `DevSwitchers`: the\n * namespace is the same `topBarParts.dev`, and an app's label tree keeps compiling.\n */\nexport interface DevSwitchersLabels {\n /** 0.51: the flask's name, and the menu's — the role and the plan follow it. */\n menu: string;\n /** 0.51: what the dot on the flask means while `active`, joined to its name — an\n * override the developer could forget is on (a \"today\", a slow server). */\n overridesOn: string;\n /** The heading of the role group. */\n roleHeading: string;\n /** @deprecated 0.51 — DevMenu's one flask is named by `menu`; removed in 0.52. */\n switchPlan: string;\n /** The plan in the flask's name, given the active plan. */\n plan: (value: string) => string;\n /** The heading of the plan group. */\n planHeading: string;\n /** The row back to the role the session started with. */\n backTo: (role: string) => string;\n /** The plan group's note while billing is off locally. */\n billingOff: string;\n}\n\nexport interface TopBarPartsLabels {\n tours: TourMenuLabels;\n sync: SyncStatusLabels;\n dev: DevSwitchersLabels;\n}\n\nexport const DEFAULT_TOP_BAR_PARTS_LABELS: TopBarPartsLabels = {\n tours: {\n menu: \"Guided tours\",\n newDot: \"New tours\",\n thisPage: \"On this page\",\n newTours: \"New tours\",\n allTours: \"All tours…\",\n badgeNew: \"New\",\n completed: \"Completed\",\n badgeUpdated: \"Updated\",\n updatedDot: \"Updated tours\",\n newAndUpdated: \"New and updated\",\n },\n sync: {\n blocked: (count) =>\n count === 1 ? \"1 change cannot be sent from this device\" : `${count} changes cannot be sent from this device`,\n offline: \"Offline — changes are saved on this device and will sync when you reconnect\",\n refused: \"The server refused the last sync\",\n syncing: \"Syncing…\",\n pending: (count) => (count === 1 ? \"1 change waiting to sync\" : `${count} changes waiting to sync`),\n syncedAt: (time) => `Synced at ${time}`,\n idle: \"Up to date\",\n syncHint: \"Tap to sync now\",\n offlineHint: \"nothing to sync while offline\",\n withHint: (state, hint) => `${state} — ${hint}`,\n scoped: (scope, state) => `${scope}: ${state}`,\n offlineShort: \"Offline\",\n syncingShort: \"Syncing…\",\n waitingShort: (count) => `${count} waiting`,\n refusedShort: \"Not synced\",\n offlineUnsaved: \"Offline — changes can't be saved until you reconnect\",\n saving: \"Saving…\",\n },\n dev: {\n menu: \"Dev tools\",\n overridesOn: \"Overrides on\",\n roleHeading: \"Dev · role\",\n switchPlan: \"Switch plan\",\n plan: (value) => `Plan: ${value}`,\n planHeading: \"Dev · plan\",\n backTo: (role) => `Back to ${role}`,\n billingOff: \"Billing is off locally: plans change nothing\",\n },\n};\n\n/** The `topBarParts` namespace, resolved — English, then the provider, then `labels`. */\nexport function useTopBarPartsLabels(labels?: LabelOverride<TopBarPartsLabels>): TopBarPartsLabels {\n return useKitLabels(\"topBarParts\", DEFAULT_TOP_BAR_PARTS_LABELS, labels);\n}\n"],"mappings":";AAAA,SAAS,oBAAwC;AAsG1C,MAAM,+BAAkD;AAAA,EAC7D,OAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,WAAW;AAAA,IACX,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,MAAM;AAAA,IACJ,SAAS,CAAC,UACR,UAAU,IAAI,6CAA6C,GAAG,KAAK;AAAA,IACrE,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS,CAAC,UAAW,UAAU,IAAI,6BAA6B,GAAG,KAAK;AAAA,IACxE,UAAU,CAAC,SAAS,aAAa,IAAI;AAAA,IACrC,MAAM;AAAA,IACN,UAAU;AAAA,IACV,aAAa;AAAA,IACb,UAAU,CAAC,OAAO,SAAS,GAAG,KAAK,WAAM,IAAI;AAAA,IAC7C,QAAQ,CAAC,OAAO,UAAU,GAAG,KAAK,KAAK,KAAK;AAAA,IAC5C,cAAc;AAAA,IACd,cAAc;AAAA,IACd,cAAc,CAAC,UAAU,GAAG,KAAK;AAAA,IACjC,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,QAAQ;AAAA,EACV;AAAA,EACA,KAAK;AAAA,IACH,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,MAAM,CAAC,UAAU,SAAS,KAAK;AAAA,IAC/B,aAAa;AAAA,IACb,QAAQ,CAAC,SAAS,WAAW,IAAI;AAAA,IACjC,YAAY;AAAA,EACd;AACF;AAGO,SAAS,qBAAqB,QAA8D;AACjG,SAAO,aAAa,eAAe,8BAA8B,MAAM;AACzE;","names":[]}
1
+ {"version":3,"sources":["../../src/shell/top-bar-parts-labels.ts"],"sourcesContent":["import { useKitLabels, type LabelOverride } from \"../i18n/kit-labels\";\n\n/**\n * The `topBarParts` namespace (0.42, docs/top-bar-harmonization.md §3.1): the words of the\n * top bar's shared parts — `TourMenu`, `SyncStatusIndicator` and `DevMenu` (0.42's\n * `DevSwitchers`, whose words these still are, §2.7.1). A module\n * of words with no component code, like every `*-labels.ts` (0.34, KS U8). The language\n * sub-list (`AccountMenuLanguage`) names itself with `topBar.language`, and the role in the\n * dev flask's name is `topBar.role`, as `RoleSwitcher`'s tooltip.\n */\n\n/** `TourMenu`'s words (§2.4). */\nexport interface TourMenuLabels {\n /** The compass's name, and the menu's. */\n menu: string;\n /** The NEW dot on the compass, for a reader: it joins the trigger's name. */\n newDot: string;\n /** The heading over the tours that start on the open page. */\n thisPage: string;\n /** The heading over the untaken new tours. */\n newTours: string;\n /** The last row, the way to the app's tours page (only with `href`). */\n allTours: string;\n /** The chip on a new tour's row. */\n badgeNew: string;\n /** What the ✓ on a taken tour's row says to a reader. */\n completed: string;\n /** The chip on a tour reset by an update (0.43, docs/tours-harmonization.md §8). */\n badgeUpdated: string;\n /** The dot on the compass while only updated tours light it, for a reader. */\n updatedDot: string;\n /** The heading over the untaken new tours when updated ones are among them. */\n newAndUpdated: string;\n}\n\n/** `SyncStatusIndicator`'s words (§2.6). The \"waiting for a plan\" state is\n * `billing.waitingChanges`, the kit's words for it since billing §12.5. */\nexport interface SyncStatusLabels {\n /** Writes this device cannot send (keksdose: no key for the budget). Ranked first. */\n blocked: (count: number) => string;\n offline: string;\n /** The server refused the last round. */\n refused: string;\n syncing: string;\n pending: (count: number) => string;\n /** Settled, with the time of the last good round (already formatted). */\n syncedAt: (time: string) => string;\n /** Settled, before the first round. */\n idle: string;\n /** Joined to the state when a tap syncs: what the tap does. */\n syncHint: string;\n /** Joined to the state while offline, when a tap can do nothing. */\n offlineHint: string;\n /** The state and what a tap does, as one tooltip: \"Offline — nothing to sync…\". */\n withHint: (state: string, hint: string) => string;\n /** The state with the app's `scope` words before it: \"Handovers on this device: …\". */\n scoped: (scope: string, state: string) => string;\n /** The short words beside the cloud (`showLabel`): offline. */\n offlineShort: string;\n /** The short words while syncing. */\n syncingShort: string;\n /** The short words while changes wait (pending, held for a plan, or blocked). */\n waitingShort: (count: number) => string;\n /** The short words after a refused round. */\n refusedShort: string;\n /** Offline in an online-only app (`storage=\"none\"`): nothing is kept on the device. */\n offlineUnsaved: string;\n /** A round under way in an online-only app — it saves, it doesn't sync. Also its short\n * words beside the cloud. */\n saving: string;\n}\n\n/**\n * `DevMenu`'s words (§2.7, §2.7.1, §6.2, §6.3). Still named for 0.42's `DevSwitchers`: the\n * namespace is the same `topBarParts.dev`, and an app's label tree keeps compiling.\n */\nexport interface DevSwitchersLabels {\n /** 0.51: the flask's name, and the menu's — the role and the plan follow it. */\n menu: string;\n /** 0.51: what the dot on the flask means while `active`, joined to its name — an\n * override the developer could forget is on (a \"today\", a slow server). */\n overridesOn: string;\n /** The heading of the role group. */\n roleHeading: string;\n /** The plan in the flask's name, given the active plan. */\n plan: (value: string) => string;\n /** The heading of the plan group. */\n planHeading: string;\n /** The row back to the role the session started with. */\n backTo: (role: string) => string;\n /** The plan group's note while billing is off locally. */\n billingOff: string;\n}\n\nexport interface TopBarPartsLabels {\n tours: TourMenuLabels;\n sync: SyncStatusLabels;\n dev: DevSwitchersLabels;\n}\n\nexport const DEFAULT_TOP_BAR_PARTS_LABELS: TopBarPartsLabels = {\n tours: {\n menu: \"Guided tours\",\n newDot: \"New tours\",\n thisPage: \"On this page\",\n newTours: \"New tours\",\n allTours: \"All tours…\",\n badgeNew: \"New\",\n completed: \"Completed\",\n badgeUpdated: \"Updated\",\n updatedDot: \"Updated tours\",\n newAndUpdated: \"New and updated\",\n },\n sync: {\n blocked: (count) =>\n count === 1 ? \"1 change cannot be sent from this device\" : `${count} changes cannot be sent from this device`,\n offline: \"Offline — changes are saved on this device and will sync when you reconnect\",\n refused: \"The server refused the last sync\",\n syncing: \"Syncing…\",\n pending: (count) => (count === 1 ? \"1 change waiting to sync\" : `${count} changes waiting to sync`),\n syncedAt: (time) => `Synced at ${time}`,\n idle: \"Up to date\",\n syncHint: \"Tap to sync now\",\n offlineHint: \"nothing to sync while offline\",\n withHint: (state, hint) => `${state} — ${hint}`,\n scoped: (scope, state) => `${scope}: ${state}`,\n offlineShort: \"Offline\",\n syncingShort: \"Syncing…\",\n waitingShort: (count) => `${count} waiting`,\n refusedShort: \"Not synced\",\n offlineUnsaved: \"Offline — changes can't be saved until you reconnect\",\n saving: \"Saving…\",\n },\n dev: {\n menu: \"Dev tools\",\n overridesOn: \"Overrides on\",\n roleHeading: \"Dev · role\",\n plan: (value) => `Plan: ${value}`,\n planHeading: \"Dev · plan\",\n backTo: (role) => `Back to ${role}`,\n billingOff: \"Billing is off locally: plans change nothing\",\n },\n};\n\n/** The `topBarParts` namespace, resolved — English, then the provider, then `labels`. */\nexport function useTopBarPartsLabels(labels?: LabelOverride<TopBarPartsLabels>): TopBarPartsLabels {\n return useKitLabels(\"topBarParts\", DEFAULT_TOP_BAR_PARTS_LABELS, labels);\n}\n"],"mappings":";AAAA,SAAS,oBAAwC;AAoG1C,MAAM,+BAAkD;AAAA,EAC7D,OAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,WAAW;AAAA,IACX,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB;AAAA,EACA,MAAM;AAAA,IACJ,SAAS,CAAC,UACR,UAAU,IAAI,6CAA6C,GAAG,KAAK;AAAA,IACrE,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS,CAAC,UAAW,UAAU,IAAI,6BAA6B,GAAG,KAAK;AAAA,IACxE,UAAU,CAAC,SAAS,aAAa,IAAI;AAAA,IACrC,MAAM;AAAA,IACN,UAAU;AAAA,IACV,aAAa;AAAA,IACb,UAAU,CAAC,OAAO,SAAS,GAAG,KAAK,WAAM,IAAI;AAAA,IAC7C,QAAQ,CAAC,OAAO,UAAU,GAAG,KAAK,KAAK,KAAK;AAAA,IAC5C,cAAc;AAAA,IACd,cAAc;AAAA,IACd,cAAc,CAAC,UAAU,GAAG,KAAK;AAAA,IACjC,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,QAAQ;AAAA,EACV;AAAA,EACA,KAAK;AAAA,IACH,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,IACb,MAAM,CAAC,UAAU,SAAS,KAAK;AAAA,IAC/B,aAAa;AAAA,IACb,QAAQ,CAAC,SAAS,WAAW,IAAI;AAAA,IACjC,YAAY;AAAA,EACd;AACF;AAGO,SAAS,qBAAqB,QAA8D;AACjG,SAAO,aAAa,eAAe,8BAA8B,MAAM;AACzE;","names":[]}
package/dist/shell.d.ts CHANGED
@@ -1,6 +1,11 @@
1
1
  export * from "./shell/topbar-controls.js";
2
2
  export * from "./shell/top-bar.js";
3
3
  export * from "./shell/app-shell.js";
4
+ export {
5
+ /** @deprecated 0.52 — `AppShell`, which picks its phone bar with it (API-4); removed in 0.53 */
6
+ pickMobileBar,
7
+ /** @deprecated 0.52 — `AppShell`, which splits its phone bar with it (API-4); removed in 0.53 */
8
+ splitMobileBar, } from "./shell/app-shell.js";
4
9
  export * from "./shell/option-switcher-menu.js";
5
10
  export * from "./shell/role-switcher.js";
6
11
  export * from "./shell/topbar-action-menu.js";
@@ -14,11 +19,21 @@ export { useAdminMenuEntry } from "./shell/admin-menu.js";
14
19
  export type { UseAdminMenuEntryOptions } from "./shell/admin-menu.js";
15
20
  export { AdminWaitingBadge } from "./shell/admin-menu.js";
16
21
  export type { AdminWaitingBadgeProps } from "./shell/admin-menu.js";
17
- export { SettingsLayout, SETTINGS_SEARCH_THRESHOLD } from "./settings/settings-layout.js";
22
+ export { SettingsLayout,
23
+ /** @deprecated 0.52 — `SettingsLayout`, which shows its search past that many entries (API-4); removed in 0.53 */
24
+ SETTINGS_SEARCH_THRESHOLD, } from "./settings/settings-layout.js";
18
25
  export type { SettingsLayoutProps, SettingsLayoutWidth, SettingsDocumentTitleParts } from "./settings/settings-layout.js";
19
- export { useSettingsRoute, resolveSettingsLocation, settingsFromListState, SETTINGS_FROM_LIST_STATE, } from "./settings/use-settings-route.js";
26
+ export { useSettingsRoute,
27
+ /** @deprecated 0.52 — `useSettingsRoute`, which resolves the location with it (API-4); removed in 0.53 */
28
+ resolveSettingsLocation, settingsFromListState,
29
+ /** @deprecated 0.52 — `settingsFromListState` and `useSettingsRoute`, which write and read it (API-4); removed in 0.53 */
30
+ SETTINGS_FROM_LIST_STATE, } from "./settings/use-settings-route.js";
20
31
  export type { UseSettingsRouteOptions, SettingsRoute, SettingsLayoutMode, SettingsLocation, SettingsLocationRules, SettingsLocationResult, } from "./settings/use-settings-route.js";
21
- export { useSettingsFocus, useFocusParam, SETTINGS_FOCUS_RING, SETTINGS_FOCUS_MS } from "./settings/use-settings-focus.js";
32
+ export { useSettingsFocus, useFocusParam,
33
+ /** @deprecated 0.52 — `useSettingsFocus` / `useFocusParam`, which ring the card with it (API-4); removed in 0.53 */
34
+ SETTINGS_FOCUS_RING,
35
+ /** @deprecated 0.52 — `useSettingsFocus` / `useFocusParam`, which hold the ring that long (API-4); removed in 0.53 */
36
+ SETTINGS_FOCUS_MS, } from "./settings/use-settings-focus.js";
22
37
  export { SettingsSection } from "./settings/settings-section.js";
23
38
  export type { SettingsSectionProps } from "./settings/settings-section.js";
24
39
  export { useSettingsLayout } from "./settings/settings-context.js";
@@ -31,7 +46,9 @@ export { RootEntry, RedirectIfAuthed, useLastVisitedPage, readLastVisitedPage, c
31
46
  export type { RootEntryProps, RedirectIfAuthedProps, RoutingSession, LastVisitedPageOptions, PathPattern, } from "./landing/routing.js";
32
47
  export { PublicHeader } from "./landing/public-header.js";
33
48
  export type { PublicHeaderProps, PublicHeaderBrand } from "./landing/public-header.js";
34
- export { TopBarActions, TOP_BAR_ACTION_ORDER } from "./shell/top-bar-actions.js";
49
+ export { TopBarActions,
50
+ /** @deprecated 0.52 — `TopBarActions`, which puts its slots in that order (API-4); removed in 0.53 */
51
+ TOP_BAR_ACTION_ORDER, } from "./shell/top-bar-actions.js";
35
52
  export type { TopBarActionsProps } from "./shell/top-bar-actions.js";
36
53
  export { AccountMenuLanguage } from "./shell/account-menu-language.js";
37
54
  export type { AccountMenuLanguageProps, AccountMenuLanguageOption } from "./shell/account-menu-language.js";
@@ -39,11 +56,13 @@ export { AccountMenuTextSize } from "./shell/account-menu-text-size.js";
39
56
  export type { AccountMenuTextSizeProps } from "./shell/account-menu-text-size.js";
40
57
  export { TourMenu } from "./shell/tour-menu.js";
41
58
  export type { TourMenuProps, TourMenuTour } from "./shell/tour-menu.js";
42
- export { SyncStatusIndicator, syncState } from "./shell/sync-status-indicator.js";
59
+ export { SyncStatusIndicator,
60
+ /** @deprecated 0.52 — `SyncStatusIndicator`, which derives its state with it (API-4); removed in 0.53 */
61
+ syncState, } from "./shell/sync-status-indicator.js";
43
62
  export type { SyncStatus, SyncState, SyncStatusScope, SyncStatusIndicatorProps } from "./shell/sync-status-indicator.js";
44
- export { DevMenu, DEV_ORIGINAL_ROLE_KEY } from "./shell/dev-menu.js";
63
+ export { DevMenu,
64
+ /** @deprecated 0.52 — `DevMenu`, which keeps the role there unless `storageKey` names another key (API-4); removed in 0.53 */
65
+ DEV_ORIGINAL_ROLE_KEY, } from "./shell/dev-menu.js";
45
66
  export type { DevMenuProps, DevMenuSection } from "./shell/dev-menu.js";
46
- export { DevSwitchers } from "./shell/dev-switchers.js";
47
- export type { DevSwitchersProps } from "./shell/dev-switchers.js";
48
67
  export { DEFAULT_TOP_BAR_PARTS_LABELS, useTopBarPartsLabels } from "./shell/top-bar-parts-labels.js";
49
68
  export type { TopBarPartsLabels, TourMenuLabels, SyncStatusLabels, DevSwitchersLabels, } from "./shell/top-bar-parts-labels.js";
package/dist/shell.js CHANGED
@@ -2,6 +2,10 @@
2
2
  export * from "./shell/topbar-controls.js";
3
3
  export * from "./shell/top-bar.js";
4
4
  export * from "./shell/app-shell.js";
5
+ import {
6
+ pickMobileBar,
7
+ splitMobileBar
8
+ } from "./shell/app-shell.js";
5
9
  export * from "./shell/option-switcher-menu.js";
6
10
  export * from "./shell/role-switcher.js";
7
11
  export * from "./shell/topbar-action-menu.js";
@@ -11,14 +15,22 @@ import { FillHeight, FILL_HEIGHT_CLASS } from "./shell/fill-height.js";
11
15
  import { adminMenuEntry, AdminMenuRow } from "./shell/admin-menu.js";
12
16
  import { useAdminMenuEntry } from "./shell/admin-menu.js";
13
17
  import { AdminWaitingBadge } from "./shell/admin-menu.js";
14
- import { SettingsLayout, SETTINGS_SEARCH_THRESHOLD } from "./settings/settings-layout.js";
18
+ import {
19
+ SettingsLayout,
20
+ SETTINGS_SEARCH_THRESHOLD
21
+ } from "./settings/settings-layout.js";
15
22
  import {
16
23
  useSettingsRoute,
17
24
  resolveSettingsLocation,
18
25
  settingsFromListState,
19
26
  SETTINGS_FROM_LIST_STATE
20
27
  } from "./settings/use-settings-route.js";
21
- import { useSettingsFocus, useFocusParam, SETTINGS_FOCUS_RING, SETTINGS_FOCUS_MS } from "./settings/use-settings-focus.js";
28
+ import {
29
+ useSettingsFocus,
30
+ useFocusParam,
31
+ SETTINGS_FOCUS_RING,
32
+ SETTINGS_FOCUS_MS
33
+ } from "./settings/use-settings-focus.js";
22
34
  import { SettingsSection } from "./settings/settings-section.js";
23
35
  import { useSettingsLayout } from "./settings/settings-context.js";
24
36
  import { SettingsHeadingLevel, useSettingsHeadingLevel } from "./settings/settings-heading.js";
@@ -39,13 +51,21 @@ import {
39
51
  DEFAULT_LAST_VISITED_EXCLUDES
40
52
  } from "./landing/routing.js";
41
53
  import { PublicHeader } from "./landing/public-header.js";
42
- import { TopBarActions, TOP_BAR_ACTION_ORDER } from "./shell/top-bar-actions.js";
54
+ import {
55
+ TopBarActions,
56
+ TOP_BAR_ACTION_ORDER
57
+ } from "./shell/top-bar-actions.js";
43
58
  import { AccountMenuLanguage } from "./shell/account-menu-language.js";
44
59
  import { AccountMenuTextSize } from "./shell/account-menu-text-size.js";
45
60
  import { TourMenu } from "./shell/tour-menu.js";
46
- import { SyncStatusIndicator, syncState } from "./shell/sync-status-indicator.js";
47
- import { DevMenu, DEV_ORIGINAL_ROLE_KEY } from "./shell/dev-menu.js";
48
- import { DevSwitchers } from "./shell/dev-switchers.js";
61
+ import {
62
+ SyncStatusIndicator,
63
+ syncState
64
+ } from "./shell/sync-status-indicator.js";
65
+ import {
66
+ DevMenu,
67
+ DEV_ORIGINAL_ROLE_KEY
68
+ } from "./shell/dev-menu.js";
49
69
  import { DEFAULT_TOP_BAR_PARTS_LABELS, useTopBarPartsLabels } from "./shell/top-bar-parts-labels.js";
50
70
  export {
51
71
  AccountMenuLanguage,
@@ -56,7 +76,6 @@ export {
56
76
  DEFAULT_TOP_BAR_PARTS_LABELS,
57
77
  DEV_ORIGINAL_ROLE_KEY,
58
78
  DevMenu,
59
- DevSwitchers,
60
79
  FILL_HEIGHT_CLASS,
61
80
  FillHeight,
62
81
  NEXT_PARAM,
@@ -76,12 +95,14 @@ export {
76
95
  TourMenu,
77
96
  adminMenuEntry,
78
97
  clearLastVisitedPage,
98
+ pickMobileBar,
79
99
  readLastVisitedPage,
80
100
  resolveSettingsLocation,
81
101
  safeNextPath,
82
102
  settingsFromListState,
83
103
  settingsHref,
84
104
  settingsSearchEntries,
105
+ splitMobileBar,
85
106
  syncState,
86
107
  useAdminMenuEntry,
87
108
  useFocusParam,