@eifi1/ui-kit 0.51.3 → 0.51.5

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 (780) hide show
  1. package/README.md +6 -6
  2. package/dist/account/account-settings-labels.js.map +1 -1
  3. package/dist/account/account-settings.js +11 -9
  4. package/dist/account/account-settings.js.map +1 -1
  5. package/dist/account/delete-account-setting.js +56 -65
  6. package/dist/account/delete-account-setting.js.map +1 -1
  7. package/dist/account/email-change-setting-labels.js.map +1 -1
  8. package/dist/account/email-change-setting.js.map +1 -1
  9. package/dist/account/passkeys-setting.js.map +1 -1
  10. package/dist/account/sessions-setting.js.map +1 -1
  11. package/dist/admin/admin-action-confirm.js +1 -3
  12. package/dist/admin/admin-action-confirm.js.map +1 -1
  13. package/dist/admin/admin-action-log.js.map +1 -1
  14. package/dist/admin/admin-area-labels.js +4 -1
  15. package/dist/admin/admin-area-labels.js.map +1 -1
  16. package/dist/admin/admin-overview.js +19 -11
  17. package/dist/admin/admin-overview.js.map +1 -1
  18. package/dist/admin/admin-sections.js.map +1 -1
  19. package/dist/admin/admin-tool-links.d.ts +1 -1
  20. package/dist/admin/admin-tool-links.js +7 -1
  21. package/dist/admin/admin-tool-links.js.map +1 -1
  22. package/dist/admin/invitations-panel.js +2 -13
  23. package/dist/admin/invitations-panel.js.map +1 -1
  24. package/dist/admin/mail-test-card.js.map +1 -1
  25. package/dist/admin/reviewer-scope-editor.js +4 -11
  26. package/dist/admin/reviewer-scope-editor.js.map +1 -1
  27. package/dist/admin/role-select.js.map +1 -1
  28. package/dist/admin/user-roster.js +1 -9
  29. package/dist/admin/user-roster.js.map +1 -1
  30. package/dist/auth/accept-invitation.js.map +1 -1
  31. package/dist/auth/auth-errors.js.map +1 -1
  32. package/dist/auth/forgot-password-form.js +23 -31
  33. package/dist/auth/forgot-password-form.js.map +1 -1
  34. package/dist/auth/register-form.js.map +1 -1
  35. package/dist/auth/reset-password-form.js.map +1 -1
  36. package/dist/auth/sign-in-form.js +13 -5
  37. package/dist/auth/sign-in-form.js.map +1 -1
  38. package/dist/auth/verify-email.js +1 -8
  39. package/dist/auth/verify-email.js.map +1 -1
  40. package/dist/billing/billing-banner.js.map +1 -1
  41. package/dist/billing/billing-labels.js.map +1 -1
  42. package/dist/billing/checkout-processing.js.map +1 -1
  43. package/dist/billing/plan-card.js +91 -85
  44. package/dist/billing/plan-card.js.map +1 -1
  45. package/dist/billing/plan-limit-toast.js.map +1 -1
  46. package/dist/billing/plan-limit.js.map +1 -1
  47. package/dist/billing/plan-price.js.map +1 -1
  48. package/dist/billing/plan-switch.js.map +1 -1
  49. package/dist/billing/subscription-actions.js.map +1 -1
  50. package/dist/bin/eifi1-pay-page.mjs +6 -1
  51. package/dist/components/account-chips.js.map +1 -1
  52. package/dist/components/alert-banner.js +1 -5
  53. package/dist/components/alert-banner.js.map +1 -1
  54. package/dist/components/amount-input.js +29 -12
  55. package/dist/components/amount-input.js.map +1 -1
  56. package/dist/components/authed-image.js.map +1 -1
  57. package/dist/components/autocomplete.js.map +1 -1
  58. package/dist/components/bulk-action-bar.js +1 -4
  59. package/dist/components/bulk-action-bar.js.map +1 -1
  60. package/dist/components/button-group.js.map +1 -1
  61. package/dist/components/button-look.js.map +1 -1
  62. package/dist/components/button.js +1 -7
  63. package/dist/components/button.js.map +1 -1
  64. package/dist/components/calculator.js +5 -5
  65. package/dist/components/calculator.js.map +1 -1
  66. package/dist/components/calendar-heatmap.js +4 -10
  67. package/dist/components/calendar-heatmap.js.map +1 -1
  68. package/dist/components/card.js +1 -8
  69. package/dist/components/card.js.map +1 -1
  70. package/dist/components/chart-zoom-core.js +3 -17
  71. package/dist/components/chart-zoom-core.js.map +1 -1
  72. package/dist/components/chart.d.ts +1 -1
  73. package/dist/components/chart.js +4 -22
  74. package/dist/components/chart.js.map +1 -1
  75. package/dist/components/checkbox-group.js +1 -4
  76. package/dist/components/checkbox-group.js.map +1 -1
  77. package/dist/components/chip-input.js +4 -1
  78. package/dist/components/chip-input.js.map +1 -1
  79. package/dist/components/chip.js +10 -5
  80. package/dist/components/chip.js.map +1 -1
  81. package/dist/components/choice-card.js +58 -74
  82. package/dist/components/choice-card.js.map +1 -1
  83. package/dist/components/column-mapper-labels.js.map +1 -1
  84. package/dist/components/column-mapper.js +167 -227
  85. package/dist/components/column-mapper.js.map +1 -1
  86. package/dist/components/combobox-core.js +5 -9
  87. package/dist/components/combobox-core.js.map +1 -1
  88. package/dist/components/combobox.js +1 -4
  89. package/dist/components/combobox.js.map +1 -1
  90. package/dist/components/confirm-dialog.js.map +1 -1
  91. package/dist/components/copy-button.js.map +1 -1
  92. package/dist/components/country-select.d.ts +5 -4
  93. package/dist/components/country-select.js +3 -19
  94. package/dist/components/country-select.js.map +1 -1
  95. package/dist/components/currency-option-list.js +13 -11
  96. package/dist/components/currency-option-list.js.map +1 -1
  97. package/dist/components/currency-select.js +1 -6
  98. package/dist/components/currency-select.js.map +1 -1
  99. package/dist/components/danger-confirm.js.map +1 -1
  100. package/dist/components/data-table-cells.js.map +1 -1
  101. package/dist/components/data-table-column-settings.js.map +1 -1
  102. package/dist/components/data-table-filter-popover.js +2 -18
  103. package/dist/components/data-table-filter-popover.js.map +1 -1
  104. package/dist/components/data-table-filters.js.map +1 -1
  105. package/dist/components/data-table-fit.js +7 -5
  106. package/dist/components/data-table-fit.js.map +1 -1
  107. package/dist/components/data-table-groups.js +3 -1
  108. package/dist/components/data-table-groups.js.map +1 -1
  109. package/dist/components/data-table-head.js +49 -57
  110. package/dist/components/data-table-head.js.map +1 -1
  111. package/dist/components/data-table-mobile.js +31 -44
  112. package/dist/components/data-table-mobile.js.map +1 -1
  113. package/dist/components/data-table-pagination.js.map +1 -1
  114. package/dist/components/data-table-row-actions.js +19 -16
  115. package/dist/components/data-table-row-actions.js.map +1 -1
  116. package/dist/components/data-table-row.js.map +1 -1
  117. package/dist/components/data-table-shared.js.map +1 -1
  118. package/dist/components/data-table-sort.js.map +1 -1
  119. package/dist/components/data-table-virtual.js +4 -1
  120. package/dist/components/data-table-virtual.js.map +1 -1
  121. package/dist/components/data-table.d.ts +8 -0
  122. package/dist/components/data-table.js +30 -39
  123. package/dist/components/data-table.js.map +1 -1
  124. package/dist/components/date-picker.js +1 -6
  125. package/dist/components/date-picker.js.map +1 -1
  126. package/dist/components/date-range-picker.js.map +1 -1
  127. package/dist/components/description-list.js +10 -10
  128. package/dist/components/description-list.js.map +1 -1
  129. package/dist/components/dialog-frame.js +9 -2
  130. package/dist/components/dialog-frame.js.map +1 -1
  131. package/dist/components/disclosure.js +17 -27
  132. package/dist/components/disclosure.js.map +1 -1
  133. package/dist/components/dropdown.js +25 -35
  134. package/dist/components/dropdown.js.map +1 -1
  135. package/dist/components/empty-state.js.map +1 -1
  136. package/dist/components/entity-combobox.js.map +1 -1
  137. package/dist/components/error-boundary.js.map +1 -1
  138. package/dist/components/field-base.js +5 -5
  139. package/dist/components/field-base.js.map +1 -1
  140. package/dist/components/field-parts.d.ts +1 -1
  141. package/dist/components/field-parts.js +10 -14
  142. package/dist/components/field-parts.js.map +1 -1
  143. package/dist/components/field-sync.js +8 -10
  144. package/dist/components/field-sync.js.map +1 -1
  145. package/dist/components/file-button.js.map +1 -1
  146. package/dist/components/file-dropzone.js.map +1 -1
  147. package/dist/components/floating-panel.js +4 -1
  148. package/dist/components/floating-panel.js.map +1 -1
  149. package/dist/components/focus-ring.js.map +1 -1
  150. package/dist/components/form-actions.js.map +1 -1
  151. package/dist/components/grouped-picker.js +11 -12
  152. package/dist/components/grouped-picker.js.map +1 -1
  153. package/dist/components/hover-menu.js +1 -4
  154. package/dist/components/hover-menu.js.map +1 -1
  155. package/dist/components/iban-input-labels.js.map +1 -1
  156. package/dist/components/icon-button.js +4 -1
  157. package/dist/components/icon-button.js.map +1 -1
  158. package/dist/components/icon-picker.js +6 -10
  159. package/dist/components/icon-picker.js.map +1 -1
  160. package/dist/components/image-grid.js +41 -50
  161. package/dist/components/image-grid.js.map +1 -1
  162. package/dist/components/inline-edit-field.js.map +1 -1
  163. package/dist/components/inline-entity-combobox.js +6 -12
  164. package/dist/components/inline-entity-combobox.js.map +1 -1
  165. package/dist/components/input.js +14 -2
  166. package/dist/components/input.js.map +1 -1
  167. package/dist/components/jump-calendar.js +1 -7
  168. package/dist/components/jump-calendar.js.map +1 -1
  169. package/dist/components/legal-labels.js +8 -2
  170. package/dist/components/legal-labels.js.map +1 -1
  171. package/dist/components/legal-page.d.ts +18 -1
  172. package/dist/components/legal-page.js +27 -2
  173. package/dist/components/legal-page.js.map +1 -1
  174. package/dist/components/legal.d.ts +40 -5
  175. package/dist/components/legal.js +41 -5
  176. package/dist/components/legal.js.map +1 -1
  177. package/dist/components/lightbox.js.map +1 -1
  178. package/dist/components/line-items.js +26 -36
  179. package/dist/components/line-items.js.map +1 -1
  180. package/dist/components/list-labels.js +3 -1
  181. package/dist/components/list-labels.js.map +1 -1
  182. package/dist/components/list.d.ts +18 -1
  183. package/dist/components/list.js +54 -13
  184. package/dist/components/list.js.map +1 -1
  185. package/dist/components/measured-grid.js +29 -53
  186. package/dist/components/measured-grid.js.map +1 -1
  187. package/dist/components/menu-item.js.map +1 -1
  188. package/dist/components/mini-calendar.js +13 -31
  189. package/dist/components/mini-calendar.js.map +1 -1
  190. package/dist/components/money-field.js.map +1 -1
  191. package/dist/components/month-picker.js +10 -21
  192. package/dist/components/month-picker.js.map +1 -1
  193. package/dist/components/multi-entity-combobox.js +3 -16
  194. package/dist/components/multi-entity-combobox.js.map +1 -1
  195. package/dist/components/multi-select.js.map +1 -1
  196. package/dist/components/nav-pills.js +10 -1
  197. package/dist/components/nav-pills.js.map +1 -1
  198. package/dist/components/number-field.js.map +1 -1
  199. package/dist/components/number-input.js +1 -7
  200. package/dist/components/number-input.js.map +1 -1
  201. package/dist/components/numpad-sheet.js +1 -4
  202. package/dist/components/numpad-sheet.js.map +1 -1
  203. package/dist/components/one-time-code-input.js +1 -7
  204. package/dist/components/one-time-code-input.js.map +1 -1
  205. package/dist/components/page-contents.js +13 -22
  206. package/dist/components/page-contents.js.map +1 -1
  207. package/dist/components/page-header.js +1 -11
  208. package/dist/components/page-header.js.map +1 -1
  209. package/dist/components/password-strength-labels.js.map +1 -1
  210. package/dist/components/password-strength.js +2 -8
  211. package/dist/components/password-strength.js.map +1 -1
  212. package/dist/components/phone-input.js +42 -57
  213. package/dist/components/phone-input.js.map +1 -1
  214. package/dist/components/picker-sheet.js.map +1 -1
  215. package/dist/components/pie-chart.js +1 -8
  216. package/dist/components/pie-chart.js.map +1 -1
  217. package/dist/components/popover.js.map +1 -1
  218. package/dist/components/progress-bar.js +16 -9
  219. package/dist/components/progress-bar.js.map +1 -1
  220. package/dist/components/qr-code.js +1 -8
  221. package/dist/components/qr-code.js.map +1 -1
  222. package/dist/components/row-actions.js +5 -1
  223. package/dist/components/row-actions.js.map +1 -1
  224. package/dist/components/search-field.js.map +1 -1
  225. package/dist/components/select.js +28 -38
  226. package/dist/components/select.js.map +1 -1
  227. package/dist/components/separator.js +1 -5
  228. package/dist/components/separator.js.map +1 -1
  229. package/dist/components/series-chart-axes.js +4 -1
  230. package/dist/components/series-chart-axes.js.map +1 -1
  231. package/dist/components/series-chart-budget.js.map +1 -1
  232. package/dist/components/series-chart-ticks.js.map +1 -1
  233. package/dist/components/series-chart.js +29 -45
  234. package/dist/components/series-chart.js.map +1 -1
  235. package/dist/components/settings-fields.js +21 -17
  236. package/dist/components/settings-fields.js.map +1 -1
  237. package/dist/components/share-card.js +4 -9
  238. package/dist/components/share-card.js.map +1 -1
  239. package/dist/components/sign-chip.js.map +1 -1
  240. package/dist/components/signature-pad.js +4 -13
  241. package/dist/components/signature-pad.js.map +1 -1
  242. package/dist/components/signed-amount.js +12 -5
  243. package/dist/components/signed-amount.js.map +1 -1
  244. package/dist/components/skeleton.js +2 -17
  245. package/dist/components/skeleton.js.map +1 -1
  246. package/dist/components/slider.js +13 -36
  247. package/dist/components/slider.js.map +1 -1
  248. package/dist/components/sparkline.js.map +1 -1
  249. package/dist/components/stat-tile.js +14 -10
  250. package/dist/components/stat-tile.js.map +1 -1
  251. package/dist/components/swatch-picker.js +14 -4
  252. package/dist/components/swatch-picker.js.map +1 -1
  253. package/dist/components/swipeable-row.d.ts +1 -1
  254. package/dist/components/swipeable-row.js +1 -8
  255. package/dist/components/swipeable-row.js.map +1 -1
  256. package/dist/components/table-skeleton.js +4 -1
  257. package/dist/components/table-skeleton.js.map +1 -1
  258. package/dist/components/table.js +12 -9
  259. package/dist/components/table.js.map +1 -1
  260. package/dist/components/tabs.js +5 -24
  261. package/dist/components/tabs.js.map +1 -1
  262. package/dist/components/text-link.js.map +1 -1
  263. package/dist/components/text.js.map +1 -1
  264. package/dist/components/tile-radio.js +1 -7
  265. package/dist/components/tile-radio.js.map +1 -1
  266. package/dist/components/time-input.js.map +1 -1
  267. package/dist/components/toast.js.map +1 -1
  268. package/dist/components/toggle-group.js +6 -1
  269. package/dist/components/toggle-group.js.map +1 -1
  270. package/dist/components/toggle-legend.js +2 -11
  271. package/dist/components/toggle-legend.js.map +1 -1
  272. package/dist/components/tooltip.js +2 -22
  273. package/dist/components/tooltip.js.map +1 -1
  274. package/dist/components/translation-review-editor.js +1 -4
  275. package/dist/components/translation-review-editor.js.map +1 -1
  276. package/dist/components/translation-review-parts.d.ts +1 -1
  277. package/dist/components/translation-review-parts.js +7 -1
  278. package/dist/components/translation-review-parts.js.map +1 -1
  279. package/dist/components/translation-review.js +18 -7
  280. package/dist/components/translation-review.js.map +1 -1
  281. package/dist/components/tree-view.js +14 -10
  282. package/dist/components/tree-view.js.map +1 -1
  283. package/dist/components/treemap.js +1 -13
  284. package/dist/components/treemap.js.map +1 -1
  285. package/dist/components/trigger-aria.js.map +1 -1
  286. package/dist/components/use-table-state.js +14 -11
  287. package/dist/components/use-table-state.js.map +1 -1
  288. package/dist/components/user-avatar.js +3 -26
  289. package/dist/components/user-avatar.js.map +1 -1
  290. package/dist/demo/demo-start.js +8 -4
  291. package/dist/demo/demo-start.js.map +1 -1
  292. package/dist/eslint/index.js +1 -1
  293. package/dist/feedback/feedback-attachment-labels.js.map +1 -1
  294. package/dist/feedback/feedback-attachment.js +1 -8
  295. package/dist/feedback/feedback-attachment.js.map +1 -1
  296. package/dist/feedback/feedback-capture.d.ts +1 -1
  297. package/dist/feedback/feedback-capture.js +3 -1
  298. package/dist/feedback/feedback-capture.js.map +1 -1
  299. package/dist/feedback/feedback-comment-thread.js +27 -13
  300. package/dist/feedback/feedback-comment-thread.js.map +1 -1
  301. package/dist/feedback/feedback-context.js +1 -4
  302. package/dist/feedback/feedback-context.js.map +1 -1
  303. package/dist/feedback/feedback-dialog.js.map +1 -1
  304. package/dist/feedback/feedback-inbox.js.map +1 -1
  305. package/dist/feedback/feedback-public-list.js +7 -1
  306. package/dist/feedback/feedback-public-list.js.map +1 -1
  307. package/dist/feedback/feedback-record.js +1 -5
  308. package/dist/feedback/feedback-record.js.map +1 -1
  309. package/dist/feedback/feedback-replies.js +25 -10
  310. package/dist/feedback/feedback-replies.js.map +1 -1
  311. package/dist/feedback/feedback-row-detail.js.map +1 -1
  312. package/dist/feedback/feedback-status-undo.js.map +1 -1
  313. package/dist/feedback/feedback-submit-dialog.js.map +1 -1
  314. package/dist/feedback/feedback-table.d.ts +3 -1
  315. package/dist/feedback/feedback-table.js +22 -5
  316. package/dist/feedback/feedback-table.js.map +1 -1
  317. package/dist/feedback/feedback-thread.js +2 -13
  318. package/dist/feedback/feedback-thread.js.map +1 -1
  319. package/dist/feedback/feedback-vocabulary.js.map +1 -1
  320. package/dist/feedback/feedback-vote-button.js.map +1 -1
  321. package/dist/hooks/use-anchored-rect.js.map +1 -1
  322. package/dist/hooks/use-document-title.js.map +1 -1
  323. package/dist/hooks/use-file-drop.js.map +1 -1
  324. package/dist/hooks/use-file-picker-labels.js.map +1 -1
  325. package/dist/hooks/use-file-picker.js.map +1 -1
  326. package/dist/hooks/use-focus-trap.js.map +1 -1
  327. package/dist/hooks/use-overlay-history.js +10 -5
  328. package/dist/hooks/use-overlay-history.js.map +1 -1
  329. package/dist/hooks/use-row-swipe.d.ts +1 -1
  330. package/dist/hooks/use-row-swipe.js +1 -6
  331. package/dist/hooks/use-row-swipe.js.map +1 -1
  332. package/dist/i18n/defaults.js +1 -4
  333. package/dist/i18n/defaults.js.map +1 -1
  334. package/dist/i18n/german.js +15 -4
  335. package/dist/i18n/german.js.map +1 -1
  336. package/dist/i18n/kit-labels.js +2 -8
  337. package/dist/i18n/kit-labels.js.map +1 -1
  338. package/dist/i18n/languages.js.map +1 -1
  339. package/dist/i18n/locales/en.js +19 -4
  340. package/dist/i18n/locales/en.js.map +2 -2
  341. package/dist/i18n/locales/es.js +15 -4
  342. package/dist/i18n/locales/es.js.map +1 -1
  343. package/dist/i18n/locales/fr.js +15 -4
  344. package/dist/i18n/locales/fr.js.map +1 -1
  345. package/dist/i18n/locales/hu.js +15 -4
  346. package/dist/i18n/locales/hu.js.map +1 -1
  347. package/dist/i18n/locales/it.js +15 -4
  348. package/dist/i18n/locales/it.js.map +1 -1
  349. package/dist/i18n/locales/zh.js +11 -3
  350. package/dist/i18n/locales/zh.js.map +1 -1
  351. package/dist/i18n/plurals.js.map +1 -1
  352. package/dist/i18n/review.js +15 -7
  353. package/dist/i18n/review.js.map +1 -1
  354. package/dist/i18n/shared-labels.js.map +1 -1
  355. package/dist/index.d.ts +17 -17
  356. package/dist/index.js +40 -23
  357. package/dist/index.js.map +1 -1
  358. package/dist/landing/access.js +1 -4
  359. package/dist/landing/access.js.map +1 -1
  360. package/dist/landing/landing-sections.js +35 -38
  361. package/dist/landing/landing-sections.js.map +1 -1
  362. package/dist/landing/page-seo.js.map +1 -1
  363. package/dist/lib/calc.js.map +1 -1
  364. package/dist/lib/clipboard-minus.js.map +1 -1
  365. package/dist/lib/dates.js.map +1 -1
  366. package/dist/lib/decimal-marks.js.map +1 -1
  367. package/dist/lib/device-settings.js +2 -1
  368. package/dist/lib/device-settings.js.map +1 -1
  369. package/dist/lib/direction.js.map +1 -1
  370. package/dist/lib/iban.js.map +1 -1
  371. package/dist/lib/logger.js +1 -5
  372. package/dist/lib/logger.js.map +1 -1
  373. package/dist/lib/person-name.js.map +1 -1
  374. package/dist/lib/phone.js.map +1 -1
  375. package/dist/lib/qr-encode.js +344 -8
  376. package/dist/lib/qr-encode.js.map +1 -1
  377. package/dist/lib/session-refresh.js.map +1 -1
  378. package/dist/lib/table-text.js +15 -3
  379. package/dist/lib/table-text.js.map +1 -1
  380. package/dist/lib/text-match.d.ts +20 -0
  381. package/dist/lib/text-match.js +11 -1
  382. package/dist/lib/text-match.js.map +1 -1
  383. package/dist/lib/translation-review.js.map +1 -1
  384. package/dist/notifications/notification-inbox.js +63 -44
  385. package/dist/notifications/notification-inbox.js.map +1 -1
  386. package/dist/notifications/notification-parts.js.map +1 -1
  387. package/dist/notifications/notification-types-setting.js.map +1 -1
  388. package/dist/notifications/notifications-labels.js.map +1 -1
  389. package/dist/notifications/push-device-setting.js +6 -1
  390. package/dist/notifications/push-device-setting.js.map +1 -1
  391. package/dist/notifications/push-devices-setting.js.map +1 -1
  392. package/dist/notifications/push-worker.js.map +1 -1
  393. package/dist/notifications/quiet-hours-setting.js.map +1 -1
  394. package/dist/notifications/use-push-device.js +4 -1
  395. package/dist/notifications/use-push-device.js.map +1 -1
  396. package/dist/offline/pwa-update-prompt.d.ts +1 -1
  397. package/dist/offline/pwa-update-prompt.js +7 -1
  398. package/dist/offline/pwa-update-prompt.js.map +1 -1
  399. package/dist/offline/query-persistence.js.map +1 -1
  400. package/dist/offline.d.ts +1 -1
  401. package/dist/offline.js +6 -1
  402. package/dist/offline.js.map +1 -1
  403. package/dist/pay/pay.css +8 -1
  404. package/dist/rhf/fields.d.ts +1 -2
  405. package/dist/rhf/fields.js +1 -10
  406. package/dist/rhf/fields.js.map +1 -1
  407. package/dist/rhf/form-core.js +1 -4
  408. package/dist/rhf/form-core.js.map +1 -1
  409. package/dist/rhf/line-items.js.map +1 -1
  410. package/dist/rhf/use-rhf-wizard-step.js.map +1 -1
  411. package/dist/search/command-palette.js +71 -62
  412. package/dist/search/command-palette.js.map +1 -1
  413. package/dist/search/global-search.js +34 -5
  414. package/dist/search/global-search.js.map +1 -1
  415. package/dist/search/search-index.js.map +1 -1
  416. package/dist/settings/device-reset-setting.js +1 -6
  417. package/dist/settings/device-reset-setting.js.map +1 -1
  418. package/dist/settings/settings-heading.js.map +1 -1
  419. package/dist/settings/settings-layout.js +9 -20
  420. package/dist/settings/settings-layout.js.map +1 -1
  421. package/dist/settings/use-settings-focus.d.ts +7 -0
  422. package/dist/settings/use-settings-focus.js +2 -0
  423. package/dist/settings/use-settings-focus.js.map +1 -1
  424. package/dist/settings/use-settings-route.js.map +1 -1
  425. package/dist/shell/app-shell.js +62 -31
  426. package/dist/shell/app-shell.js.map +1 -1
  427. package/dist/shell/auth-layout.js +1 -10
  428. package/dist/shell/auth-layout.js.map +1 -1
  429. package/dist/shell/dev-menu.d.ts +5 -0
  430. package/dist/shell/dev-menu.js +14 -7
  431. package/dist/shell/dev-menu.js.map +1 -1
  432. package/dist/shell/option-switcher-menu.js.map +1 -1
  433. package/dist/shell/sync-status-indicator.js +7 -6
  434. package/dist/shell/sync-status-indicator.js.map +1 -1
  435. package/dist/shell/top-bar-parts-labels.js.map +1 -1
  436. package/dist/shell/topbar-action-menu.d.ts +14 -1
  437. package/dist/shell/topbar-action-menu.js +85 -34
  438. package/dist/shell/topbar-action-menu.js.map +1 -1
  439. package/dist/shell/topbar-controls.js +1 -10
  440. package/dist/shell/topbar-controls.js.map +1 -1
  441. package/dist/shell/tour-menu.js +9 -1
  442. package/dist/shell/tour-menu.js.map +1 -1
  443. package/dist/shell.d.ts +1 -1
  444. package/dist/shell.js +2 -1
  445. package/dist/shell.js.map +1 -1
  446. package/dist/sync/db.js.map +1 -1
  447. package/dist/sync/engine.js +24 -6
  448. package/dist/sync/engine.js.map +1 -1
  449. package/dist/sync.d.ts +2 -2
  450. package/dist/sync.js +7 -1
  451. package/dist/sync.js.map +1 -1
  452. package/dist/testing/css-variables.js.map +1 -1
  453. package/dist/testing/index.d.ts +1 -1
  454. package/dist/testing/index.js +1 -3
  455. package/dist/testing/index.js.map +1 -1
  456. package/dist/testing/react.js.map +1 -1
  457. package/dist/testing/viewport.js +7 -4
  458. package/dist/testing/viewport.js.map +1 -1
  459. package/dist/theme/contrast-tokens.js +13 -2
  460. package/dist/theme/contrast-tokens.js.map +1 -1
  461. package/dist/theme/palette-derive.d.ts +1 -1
  462. package/dist/theme/palette-derive.js +18 -29
  463. package/dist/theme/palette-derive.js.map +1 -1
  464. package/dist/theme/palette-presets.js.map +1 -1
  465. package/dist/theme/palette-store.js.map +1 -1
  466. package/dist/theme/text-size.js.map +1 -1
  467. package/dist/theme/theme-store.js +1 -3
  468. package/dist/theme/theme-store.js.map +1 -1
  469. package/dist/tour/tour-catalogue.js.map +1 -1
  470. package/dist/tour/tour-dock.js +5 -1
  471. package/dist/tour/tour-dock.js.map +1 -1
  472. package/dist/tour/tour-engine.js +1 -4
  473. package/dist/tour/tour-engine.js.map +1 -1
  474. package/dist/tour/tour.js +21 -12
  475. package/dist/tour/tour.js.map +1 -1
  476. package/dist/tour/use-tour-progress.js.map +1 -1
  477. package/dist/tour/use-tour-url-sync.js.map +1 -1
  478. package/dist/wizard/stepper-nav.js +3 -24
  479. package/dist/wizard/stepper-nav.js.map +1 -1
  480. package/dist/wizard/types.js.map +1 -1
  481. package/dist/wizard/use-wizard.js +24 -28
  482. package/dist/wizard/use-wizard.js.map +1 -1
  483. package/dist/wizard/validation.js.map +1 -1
  484. package/dist/wizard/wizard-context.js.map +1 -1
  485. package/dist/wizard/wizard-step.d.ts +1 -1
  486. package/dist/wizard/wizard-step.js +1 -8
  487. package/dist/wizard/wizard-step.js.map +1 -1
  488. package/dist/wizard/wizard-summary.js.map +1 -1
  489. package/package.json +5 -2
  490. package/src/account/account-settings-labels.ts +1 -2
  491. package/src/account/account-settings.tsx +11 -17
  492. package/src/account/delete-account-setting.tsx +1 -6
  493. package/src/account/email-change-setting-labels.ts +1 -2
  494. package/src/account/email-change-setting.tsx +3 -1
  495. package/src/account/passkeys-setting.tsx +1 -3
  496. package/src/account/sessions-setting.tsx +4 -2
  497. package/src/admin/admin-action-confirm.tsx +4 -7
  498. package/src/admin/admin-action-log.tsx +29 -29
  499. package/src/admin/admin-area-labels.ts +4 -1
  500. package/src/admin/admin-overview.tsx +8 -2
  501. package/src/admin/admin-sections.tsx +3 -1
  502. package/src/admin/admin-tool-links.tsx +7 -1
  503. package/src/admin/invitations-panel.tsx +5 -11
  504. package/src/admin/mail-test-card.tsx +1 -2
  505. package/src/admin/reviewer-scope-editor.tsx +4 -9
  506. package/src/admin/role-select.tsx +4 -2
  507. package/src/admin/user-roster.tsx +2 -11
  508. package/src/auth/accept-invitation.tsx +1 -7
  509. package/src/auth/auth-errors.ts +1 -6
  510. package/src/auth/forgot-password-form.tsx +2 -7
  511. package/src/auth/register-form.tsx +7 -8
  512. package/src/auth/reset-password-form.tsx +2 -5
  513. package/src/auth/sign-in-form.tsx +15 -14
  514. package/src/auth/verify-email.tsx +2 -7
  515. package/src/billing/billing-banner.tsx +3 -7
  516. package/src/billing/billing-labels.ts +6 -4
  517. package/src/billing/checkout-processing.ts +0 -1
  518. package/src/billing/plan-card.tsx +9 -8
  519. package/src/billing/plan-limit-toast.tsx +1 -2
  520. package/src/billing/plan-limit.ts +1 -2
  521. package/src/billing/plan-price.ts +1 -4
  522. package/src/billing/plan-switch.tsx +1 -2
  523. package/src/billing/subscription-actions.tsx +5 -2
  524. package/src/components/account-chips.tsx +1 -7
  525. package/src/components/alert-banner.tsx +2 -8
  526. package/src/components/amount-input.tsx +206 -178
  527. package/src/components/authed-image.tsx +7 -4
  528. package/src/components/autocomplete.tsx +7 -9
  529. package/src/components/bulk-action-bar.tsx +2 -7
  530. package/src/components/button-group.tsx +1 -2
  531. package/src/components/button-look.ts +6 -17
  532. package/src/components/button.tsx +1 -4
  533. package/src/components/calculator.tsx +6 -9
  534. package/src/components/calendar-heatmap.tsx +5 -10
  535. package/src/components/card.tsx +9 -13
  536. package/src/components/chart-zoom-core.tsx +6 -33
  537. package/src/components/chart.tsx +8 -31
  538. package/src/components/checkbox-group.tsx +1 -4
  539. package/src/components/chip-input.tsx +6 -6
  540. package/src/components/chip.tsx +14 -26
  541. package/src/components/choice-card.tsx +4 -18
  542. package/src/components/column-mapper-labels.ts +3 -10
  543. package/src/components/column-mapper.tsx +33 -122
  544. package/src/components/combobox-core.tsx +17 -47
  545. package/src/components/combobox.tsx +2 -6
  546. package/src/components/confirm-dialog.tsx +1 -3
  547. package/src/components/copy-button.tsx +2 -4
  548. package/src/components/country-select.tsx +9 -21
  549. package/src/components/currency-option-list.tsx +16 -18
  550. package/src/components/currency-select.tsx +2 -7
  551. package/src/components/danger-confirm.tsx +8 -9
  552. package/src/components/data-table-cells.tsx +1 -2
  553. package/src/components/data-table-column-settings.tsx +1 -3
  554. package/src/components/data-table-filter-popover.tsx +5 -19
  555. package/src/components/data-table-filters.ts +1 -6
  556. package/src/components/data-table-fit.ts +7 -7
  557. package/src/components/data-table-groups.tsx +3 -1
  558. package/src/components/data-table-head.tsx +32 -46
  559. package/src/components/data-table-mobile.tsx +99 -108
  560. package/src/components/data-table-pagination.tsx +2 -6
  561. package/src/components/data-table-row-actions.tsx +25 -24
  562. package/src/components/data-table-row.tsx +16 -17
  563. package/src/components/data-table-shared.tsx +10 -16
  564. package/src/components/data-table-sort.ts +1 -2
  565. package/src/components/data-table-virtual.ts +9 -4
  566. package/src/components/data-table.tsx +497 -501
  567. package/src/components/date-picker.tsx +1 -7
  568. package/src/components/date-range-picker.tsx +3 -13
  569. package/src/components/description-list.tsx +7 -13
  570. package/src/components/dialog-frame.tsx +12 -3
  571. package/src/components/disclosure.tsx +8 -12
  572. package/src/components/dropdown.tsx +3 -11
  573. package/src/components/empty-state.tsx +1 -3
  574. package/src/components/entity-combobox.tsx +2 -6
  575. package/src/components/error-boundary.tsx +7 -7
  576. package/src/components/field-base.tsx +8 -14
  577. package/src/components/field-parts.tsx +12 -23
  578. package/src/components/field-sync.tsx +7 -11
  579. package/src/components/file-button.tsx +7 -3
  580. package/src/components/file-dropzone.tsx +7 -12
  581. package/src/components/floating-panel.tsx +44 -51
  582. package/src/components/focus-ring.ts +1 -2
  583. package/src/components/form-actions.tsx +1 -4
  584. package/src/components/grouped-picker.tsx +21 -16
  585. package/src/components/hover-menu.tsx +1 -4
  586. package/src/components/iban-input-labels.ts +1 -2
  587. package/src/components/icon-button.tsx +46 -48
  588. package/src/components/icon-picker.tsx +9 -20
  589. package/src/components/image-grid.tsx +1 -6
  590. package/src/components/inline-edit-field.tsx +1 -5
  591. package/src/components/inline-entity-combobox.tsx +11 -25
  592. package/src/components/input.tsx +14 -2
  593. package/src/components/jump-calendar.tsx +2 -6
  594. package/src/components/legal-labels.ts +8 -3
  595. package/src/components/legal-page.tsx +56 -6
  596. package/src/components/legal.tsx +83 -10
  597. package/src/components/lightbox.tsx +1 -3
  598. package/src/components/line-items.tsx +7 -15
  599. package/src/components/list-labels.ts +2 -0
  600. package/src/components/list.tsx +81 -27
  601. package/src/components/measured-grid.tsx +8 -30
  602. package/src/components/menu-item.tsx +1 -3
  603. package/src/components/mini-calendar.tsx +129 -159
  604. package/src/components/money-field.tsx +4 -2
  605. package/src/components/month-picker.tsx +14 -21
  606. package/src/components/multi-entity-combobox.tsx +6 -26
  607. package/src/components/multi-select.tsx +5 -9
  608. package/src/components/nav-pills.tsx +10 -2
  609. package/src/components/number-field.tsx +18 -15
  610. package/src/components/number-input.tsx +3 -19
  611. package/src/components/numpad-sheet.tsx +9 -13
  612. package/src/components/one-time-code-input.tsx +6 -11
  613. package/src/components/page-contents.tsx +2 -9
  614. package/src/components/page-header.tsx +5 -10
  615. package/src/components/password-strength-labels.ts +1 -2
  616. package/src/components/password-strength.tsx +6 -9
  617. package/src/components/phone-input.tsx +2 -13
  618. package/src/components/picker-sheet.tsx +2 -5
  619. package/src/components/pie-chart.tsx +6 -12
  620. package/src/components/popover.tsx +2 -1
  621. package/src/components/progress-bar.tsx +16 -25
  622. package/src/components/qr-code.tsx +2 -9
  623. package/src/components/row-actions.tsx +9 -1
  624. package/src/components/search-field.tsx +4 -5
  625. package/src/components/select.tsx +2 -10
  626. package/src/components/separator.tsx +1 -5
  627. package/src/components/series-chart-axes.ts +5 -5
  628. package/src/components/series-chart-budget.ts +1 -4
  629. package/src/components/series-chart-ticks.ts +1 -4
  630. package/src/components/series-chart.tsx +43 -83
  631. package/src/components/settings-fields.tsx +20 -15
  632. package/src/components/share-card.tsx +6 -14
  633. package/src/components/sign-chip.tsx +16 -16
  634. package/src/components/signature-pad.tsx +21 -13
  635. package/src/components/signed-amount.tsx +6 -14
  636. package/src/components/skeleton.tsx +2 -13
  637. package/src/components/slider.tsx +9 -20
  638. package/src/components/sparkline.tsx +2 -13
  639. package/src/components/stat-tile.tsx +13 -24
  640. package/src/components/swatch-picker.tsx +8 -3
  641. package/src/components/swipeable-row.tsx +2 -11
  642. package/src/components/table-skeleton.tsx +4 -1
  643. package/src/components/table.tsx +12 -8
  644. package/src/components/tabs.tsx +24 -39
  645. package/src/components/text-link.tsx +6 -6
  646. package/src/components/text.tsx +1 -2
  647. package/src/components/tile-radio.tsx +6 -19
  648. package/src/components/time-input.tsx +4 -5
  649. package/src/components/toast.tsx +3 -12
  650. package/src/components/toggle-group.tsx +9 -9
  651. package/src/components/toggle-legend.tsx +4 -16
  652. package/src/components/tooltip.tsx +9 -48
  653. package/src/components/translation-review-editor.tsx +4 -4
  654. package/src/components/translation-review-parts.tsx +7 -1
  655. package/src/components/translation-review.tsx +15 -16
  656. package/src/components/tree-view.tsx +17 -20
  657. package/src/components/treemap.tsx +3 -15
  658. package/src/components/trigger-aria.ts +1 -4
  659. package/src/components/use-table-state.ts +16 -17
  660. package/src/components/user-avatar.tsx +4 -21
  661. package/src/demo/demo-start.tsx +8 -4
  662. package/src/feedback/feedback-attachment-labels.ts +2 -1
  663. package/src/feedback/feedback-attachment.tsx +16 -29
  664. package/src/feedback/feedback-capture.ts +3 -1
  665. package/src/feedback/feedback-comment-thread.tsx +9 -6
  666. package/src/feedback/feedback-context.tsx +1 -4
  667. package/src/feedback/feedback-dialog.tsx +3 -4
  668. package/src/feedback/feedback-inbox.tsx +3 -9
  669. package/src/feedback/feedback-public-list.tsx +7 -1
  670. package/src/feedback/feedback-record.ts +6 -14
  671. package/src/feedback/feedback-replies.tsx +10 -5
  672. package/src/feedback/feedback-row-detail.tsx +2 -5
  673. package/src/feedback/feedback-status-undo.ts +1 -4
  674. package/src/feedback/feedback-submit-dialog.tsx +4 -4
  675. package/src/feedback/feedback-table.tsx +29 -9
  676. package/src/feedback/feedback-thread.tsx +4 -16
  677. package/src/feedback/feedback-vocabulary.ts +72 -82
  678. package/src/feedback/feedback-vote-button.tsx +9 -8
  679. package/src/hooks/use-anchored-rect.ts +1 -4
  680. package/src/hooks/use-document-title.ts +3 -1
  681. package/src/hooks/use-file-drop.ts +1 -3
  682. package/src/hooks/use-file-picker-labels.ts +1 -2
  683. package/src/hooks/use-file-picker.tsx +1 -5
  684. package/src/hooks/use-focus-trap.ts +1 -2
  685. package/src/hooks/use-overlay-history.ts +10 -5
  686. package/src/hooks/use-row-swipe.ts +1 -6
  687. package/src/i18n/defaults.ts +1 -4
  688. package/src/i18n/german.ts +42 -50
  689. package/src/i18n/kit-labels.tsx +5 -20
  690. package/src/i18n/languages.ts +2 -8
  691. package/src/i18n/locales/en.ts +15 -31
  692. package/src/i18n/locales/es.ts +44 -50
  693. package/src/i18n/locales/fr.ts +43 -52
  694. package/src/i18n/locales/hu.ts +35 -38
  695. package/src/i18n/locales/it.ts +44 -53
  696. package/src/i18n/locales/zh.ts +23 -33
  697. package/src/i18n/plurals.ts +4 -1
  698. package/src/i18n/review.ts +20 -7
  699. package/src/i18n/shared-labels.ts +1 -2
  700. package/src/index.ts +107 -32
  701. package/src/landing/access.ts +2 -7
  702. package/src/landing/landing-sections.tsx +14 -15
  703. package/src/landing/page-seo.ts +1 -3
  704. package/src/lib/calc.ts +4 -1
  705. package/src/lib/clipboard-minus.ts +4 -1
  706. package/src/lib/dates.ts +2 -10
  707. package/src/lib/decimal-marks.ts +1 -3
  708. package/src/lib/device-settings.ts +2 -1
  709. package/src/lib/direction.ts +1 -3
  710. package/src/lib/iban.ts +89 -9
  711. package/src/lib/logger.ts +1 -5
  712. package/src/lib/person-name.ts +1 -3
  713. package/src/lib/phone.ts +5 -8
  714. package/src/lib/qr-encode.ts +32 -8
  715. package/src/lib/session-refresh.ts +5 -6
  716. package/src/lib/table-text.ts +24 -6
  717. package/src/lib/text-match.ts +43 -1
  718. package/src/lib/translation-review.ts +1 -3
  719. package/src/notifications/notification-inbox.tsx +17 -4
  720. package/src/notifications/notification-parts.tsx +1 -2
  721. package/src/notifications/notification-types-setting.tsx +19 -18
  722. package/src/notifications/notifications-labels.ts +1 -2
  723. package/src/notifications/push-device-setting.tsx +7 -1
  724. package/src/notifications/push-devices-setting.tsx +7 -3
  725. package/src/notifications/push-worker.ts +10 -2
  726. package/src/notifications/quiet-hours-setting.tsx +4 -1
  727. package/src/notifications/use-push-device.ts +4 -1
  728. package/src/offline/pwa-update-prompt.tsx +7 -1
  729. package/src/offline/query-persistence.ts +9 -6
  730. package/src/offline.ts +6 -1
  731. package/src/rhf/fields.tsx +50 -19
  732. package/src/rhf/form-core.tsx +2 -6
  733. package/src/rhf/line-items.tsx +5 -7
  734. package/src/rhf/use-rhf-wizard-step.ts +3 -12
  735. package/src/search/command-palette.tsx +15 -23
  736. package/src/search/global-search.tsx +38 -8
  737. package/src/search/search-index.ts +5 -1
  738. package/src/settings/device-reset-setting.tsx +5 -8
  739. package/src/settings/settings-heading.tsx +3 -1
  740. package/src/settings/settings-layout.tsx +6 -13
  741. package/src/settings/use-settings-focus.ts +8 -0
  742. package/src/settings/use-settings-route.ts +4 -3
  743. package/src/shell/app-shell.tsx +48 -24
  744. package/src/shell/auth-layout.tsx +1 -6
  745. package/src/shell/dev-menu.tsx +18 -6
  746. package/src/shell/option-switcher-menu.tsx +1 -3
  747. package/src/shell/sync-status-indicator.tsx +14 -12
  748. package/src/shell/top-bar-parts-labels.ts +1 -3
  749. package/src/shell/topbar-action-menu.tsx +130 -45
  750. package/src/shell/topbar-controls.tsx +5 -19
  751. package/src/shell/tour-menu.tsx +9 -1
  752. package/src/shell.ts +1 -1
  753. package/src/sync/db.ts +5 -1
  754. package/src/sync/engine.ts +44 -12
  755. package/src/sync.ts +16 -2
  756. package/src/testing/css-variables.ts +1 -2
  757. package/src/testing/index.ts +1 -6
  758. package/src/testing/react.ts +1 -2
  759. package/src/testing/viewport.ts +9 -9
  760. package/src/theme/contrast-tokens.ts +13 -2
  761. package/src/theme/palette-derive.ts +24 -50
  762. package/src/theme/palette-presets.ts +0 -1
  763. package/src/theme/palette-store.ts +1 -4
  764. package/src/theme/text-size.ts +1 -1
  765. package/src/theme/theme-store.ts +2 -6
  766. package/src/tour/tour-catalogue.tsx +4 -2
  767. package/src/tour/tour-dock.ts +5 -1
  768. package/src/tour/tour-engine.ts +2 -6
  769. package/src/tour/tour.tsx +28 -12
  770. package/src/tour/use-tour-progress.ts +8 -2
  771. package/src/tour/use-tour-url-sync.ts +3 -1
  772. package/src/vite-env.d.ts +1 -4
  773. package/src/wizard/stepper-nav.tsx +10 -35
  774. package/src/wizard/types.ts +1 -4
  775. package/src/wizard/use-wizard.ts +28 -43
  776. package/src/wizard/validation.ts +1 -5
  777. package/src/wizard/wizard-context.tsx +2 -6
  778. package/src/wizard/wizard-step.tsx +1 -8
  779. package/src/wizard/wizard-summary.tsx +2 -6
  780. package/tokens.css +393 -152
@@ -126,6 +126,11 @@ const isRow = (entry: TopBarMenuEntry) => entry.kind !== "heading" && entry.kind
126
126
  *
127
127
  * Nothing renders unless `enabled`, and nothing with no row to show. The panel scrolls
128
128
  * (`TopBarActionMenu`'s `scrollable`): some 25 rows ran off a 390×844 phone.
129
+ *
130
+ * From `md` up the groups stand side by side, one column each, in that order (0.51.4,
131
+ * `TopBarActionMenu`'s `columns`; keksdose dev #640, Marcel: "Each group gets a column").
132
+ * "Back to {role}" stays under the roles. A desktop too narrow for all of them wraps
133
+ * the columns onto a second row; a phone keeps the one scrolling column.
129
134
  */
130
135
  export function DevMenu<R extends string, P extends string>({
131
136
  enabled,
@@ -177,9 +182,12 @@ export function DevMenu<R extends string, P extends string>({
177
182
  roles && roles.length > 0 && role !== undefined && onRole
178
183
  ? [
179
184
  { kind: "heading", key: "head-role", label: words.roleHeading },
180
- ...roles.map(
181
- (r): TopBarMenuEntry => ({ key: `role-${r}`, label: roleLabel(r), checked: r === role, onSelect: () => pickRole(r) }),
182
- ),
185
+ ...roles.map((r): TopBarMenuEntry => ({
186
+ key: `role-${r}`,
187
+ label: roleLabel(r),
188
+ checked: r === role,
189
+ onSelect: () => pickRole(r),
190
+ })),
183
191
  // Behind a rule, which ends the role group: "Back to" is a way out, not a role.
184
192
  ...(original !== undefined && original !== role
185
193
  ? ([
@@ -220,9 +228,12 @@ export function DevMenu<R extends string, P extends string>({
220
228
  words.planHeading
221
229
  ),
222
230
  },
223
- ...plans.map(
224
- (p): TopBarMenuEntry => ({ key: `plan-${p}`, label: planLabel(p), checked: p === plan, onSelect: () => onPlan(p) }),
225
- ),
231
+ ...plans.map((p): TopBarMenuEntry => ({
232
+ key: `plan-${p}`,
233
+ label: planLabel(p),
234
+ checked: p === plan,
235
+ onSelect: () => onPlan(p),
236
+ })),
226
237
  ]
227
238
  : [];
228
239
 
@@ -254,6 +265,7 @@ export function DevMenu<R extends string, P extends string>({
254
265
  aria-label={name}
255
266
  entries={entries}
256
267
  scrollable
268
+ columns
257
269
  />
258
270
  );
259
271
  }
@@ -60,9 +60,7 @@ export function OptionSwitcherMenu<T extends string>({
60
60
  {(close) => (
61
61
  <ul className="py-1">
62
62
  {heading && (
63
- <li className="px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder">
64
- {heading}
65
- </li>
63
+ <li className="px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder">{heading}</li>
66
64
  )}
67
65
  {options.map((opt) => (
68
66
  <li key={opt.value}>
@@ -160,10 +160,7 @@ export function SyncStatusIndicator({
160
160
 
161
161
  const onlineOnly = storage === "none";
162
162
  // Online-only: nothing waits on the device, so only offline, error, saving and settled.
163
- const state = syncState(
164
- onlineOnly ? { ...status, pending: 0, blocked: 0, waitingForPlan: 0 } : status,
165
- refreshing,
166
- );
163
+ const state = syncState(onlineOnly ? { ...status, pending: 0, blocked: 0, waitingForPlan: 0 } : status, refreshing);
167
164
  const data = dataAttributes(rest);
168
165
  if (hideWhenIdle && state === "synced") return null;
169
166
 
@@ -190,12 +187,13 @@ export function SyncStatusIndicator({
190
187
  text = words.pending(status.pending);
191
188
  break;
192
189
  default:
193
- text = !onlineOnly && status.lastSyncedAt
194
- ? words.syncedAt(
195
- // A clock time in the UI's language, never the browser's (keksdose live #246).
196
- new Date(status.lastSyncedAt).toLocaleTimeString(locale, { hour: "2-digit", minute: "2-digit" }),
197
- )
198
- : words.idle;
190
+ text =
191
+ !onlineOnly && status.lastSyncedAt
192
+ ? words.syncedAt(
193
+ // A clock time in the UI's language, never the browser's (keksdose live #246).
194
+ new Date(status.lastSyncedAt).toLocaleTimeString(locale, { hour: "2-digit", minute: "2-digit" }),
195
+ )
196
+ : words.idle;
199
197
  }
200
198
  if (scope) {
201
199
  text = state === "offline" && scope.offline ? scope.offline : words.scoped(scope.name, text);
@@ -272,7 +270,10 @@ export function SyncStatusIndicator({
272
270
  {...data}
273
271
  role="status"
274
272
  data-sync-state={state}
275
- className={cn("relative inline-flex size-9 shrink-0 items-center justify-center [&>svg]:size-5", TEXT_TONE[tone])}
273
+ className={cn(
274
+ "relative inline-flex size-9 shrink-0 items-center justify-center [&>svg]:size-5",
275
+ TEXT_TONE[tone],
276
+ )}
276
277
  >
277
278
  {glyph}
278
279
  <span className="sr-only">{name}</span>
@@ -288,7 +289,8 @@ export function SyncStatusIndicator({
288
289
  </Tooltip>
289
290
  );
290
291
 
291
- if (!showLabel || !short) return className ? <span className={cn("inline-flex", className)}>{control}</span> : control;
292
+ if (!showLabel || !short)
293
+ return className ? <span className={cn("inline-flex", className)}>{control}</span> : control;
292
294
  return (
293
295
  <span className={cn("inline-flex items-center gap-1", className)}>
294
296
  {control}
@@ -115,9 +115,7 @@ export const DEFAULT_TOP_BAR_PARTS_LABELS: TopBarPartsLabels = {
115
115
  },
116
116
  sync: {
117
117
  blocked: (count) =>
118
- count === 1
119
- ? "1 change cannot be sent from this device"
120
- : `${count} changes cannot be sent from this device`,
118
+ count === 1 ? "1 change cannot be sent from this device" : `${count} changes cannot be sent from this device`,
121
119
  offline: "Offline — changes are saved on this device and will sync when you reconnect",
122
120
  refused: "The server refused the last sync",
123
121
  syncing: "Syncing…",
@@ -1,5 +1,5 @@
1
1
  import { useId, useLayoutEffect, useRef } from "react";
2
- import type { KeyboardEvent as ReactKeyboardEvent, ReactNode } from "react";
2
+ import type { CSSProperties, KeyboardEvent as ReactKeyboardEvent, ReactNode } from "react";
3
3
  import { Link } from "react-router";
4
4
  import { cn } from "../lib/cn";
5
5
  import { HoverMenu, type HoverMenuProps } from "../components/hover-menu";
@@ -83,7 +83,8 @@ type DividerEntry = Extract<TopBarMenuEntry, { kind: "divider" }>;
83
83
  type RowEntry = Exclude<TopBarMenuEntry, HeadingEntry | DividerEntry>;
84
84
 
85
85
  /** What the panel draws from `entries`: loose rows and rules, and headed groups. */
86
- type Block = { kind: "loose"; entry: RowEntry | DividerEntry } | { kind: "group"; heading: HeadingEntry; rows: RowEntry[] };
86
+ type Block =
87
+ { kind: "loose"; entry: RowEntry | DividerEntry } | { kind: "group"; heading: HeadingEntry; rows: RowEntry[] };
87
88
 
88
89
  /**
89
90
  * Cut `entries` into blocks: a heading opens a group that takes the rows after it until
@@ -109,6 +110,40 @@ function toBlocks(entries: readonly TopBarMenuEntry[]): Block[] {
109
110
  return blocks.filter((block) => block.kind === "loose" || block.rows.length > 0);
110
111
  }
111
112
 
113
+ /** One column of `columns` (0.51.4): a group and the loose entries after it, up to the
114
+ * next group — so a group's own way out behind a rule (DevMenu's "Back to {role}") stays
115
+ * under it instead of running across the panel. */
116
+ type LooseBlock = Extract<Block, { kind: "loose" }>;
117
+ type Column = { group: Extract<Block, { kind: "group" }>; after: Array<RowEntry | DividerEntry>; index: number };
118
+
119
+ /** `blocks` as the columns layout draws them: what comes before the first group, then a
120
+ * column per group. A rule that would end a column is dropped: the column's edge is the
121
+ * separation there. */
122
+ function toColumns(blocks: readonly Block[]): { lead: LooseBlock[]; columns: Column[] } {
123
+ const lead: LooseBlock[] = [];
124
+ const columns: Column[] = [];
125
+ blocks.forEach((block, index) => {
126
+ if (block.kind === "group") columns.push({ group: block, after: [], index });
127
+ else if (columns.length === 0) lead.push(block);
128
+ else columns[columns.length - 1]!.after.push(block.entry);
129
+ });
130
+ for (const column of columns) {
131
+ while (column.after.at(-1)?.kind === "divider") column.after.pop();
132
+ }
133
+ return { lead, columns };
134
+ }
135
+
136
+ /**
137
+ * `columns`' panel: each column 14rem, the panel as wide as its columns (a CSS variable
138
+ * the list sets) but never wider than the glass, and from `md` up only. The grid places
139
+ * as many 14rem columns as that width holds, so a narrow desktop wraps the groups onto a
140
+ * second row instead of scrolling sideways. The header, the title and the footer span
141
+ * the row.
142
+ */
143
+ const COLUMNS_PANEL =
144
+ "md:grid md:grid-cols-[repeat(auto-fill,minmax(14rem,1fr))] md:items-start md:gap-y-2 md:w-[min(calc(100vw-2rem),var(--menu-columns-width))]";
145
+ const SPAN_ALL = "md:col-span-full";
146
+
112
147
  /**
113
148
  * The non-interactive identity block at the top of an account menu — kastlan's name +
114
149
  * role, keksdose's display name + email + role chip. It is text, not a `menuitem`: the
@@ -133,7 +168,8 @@ export interface TopBarMenuHeader {
133
168
  /** What a control is, as far as `HoverMenu` is concerned, when it lives in the header
134
169
  * or the footer: not a menu row. */
135
170
  const SECTION_CONTROLS = "a[href]:not([role]),button:not([role])";
136
- const TABBABLE = 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]';
171
+ const TABBABLE =
172
+ "a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]";
137
173
 
138
174
  /**
139
175
  * `scrollable`'s cap (0.51, DevMenu): the glass under the bar. Under `TopBar` the panel
@@ -225,6 +261,7 @@ export function TopBarActionMenu({
225
261
  align,
226
262
  panelClassName,
227
263
  scrollable = false,
264
+ columns = false,
228
265
  triggerAttributes,
229
266
  }: {
230
267
  /** The trigger's face for the usual icon button. Ignored when `trigger` is given. */
@@ -308,6 +345,19 @@ export function TopBarActionMenu({
308
345
  * header and the footer are inside the list and scroll with the rows.
309
346
  */
310
347
  scrollable?: boolean;
348
+ /**
349
+ * From `md` up, lay the heading groups side by side, one column per group (0.51.4,
350
+ * `DevMenu`; keksdose dev #640, Marcel: "Each group gets a column. That way it would be
351
+ * much better visible for desktop users"). Below `md`, the one column as before.
352
+ *
353
+ * A column is a group and the loose rows after it up to the next heading, so a row
354
+ * behind a rule at the end of a group (DevMenu's "Back to {role}") stays in that
355
+ * group's column. Loose rows before the first heading, the header, the menu-wide
356
+ * `heading` and the footer span the panel. The DOM order is unchanged, so ↓/↑ walk the
357
+ * rows down one column and on into the next, as a reader reads them. `leading` and
358
+ * `children` rows take a cell each; add `md:col-span-full` to one that should span.
359
+ */
360
+ columns?: boolean;
311
361
  /** `data-*` attributes for the trigger itself — a tour's anchor (`data-tour`), a test
312
362
  * hook. The parts built on this menu (`TourMenu`) pass theirs through here. */
313
363
  triggerAttributes?: { [key: `data-${string}`]: string | number | boolean | undefined };
@@ -316,6 +366,10 @@ export function TopBarActionMenu({
316
366
  // entry's `key`, which is the caller's text and may hold a space — and a space in
317
367
  // `aria-labelledby` is a list separator.
318
368
  const uid = useId();
369
+ const blocks = toBlocks(entries);
370
+ const grouped = columns ? toColumns(blocks) : null;
371
+ // A menu with no group has nothing to put side by side: the list as always.
372
+ const laidOut = grouped && grouped.columns.length > 0 ? grouped : null;
319
373
  return (
320
374
  <HoverMenu
321
375
  aria-label={ariaLabel}
@@ -350,8 +404,7 @@ export function TopBarActionMenu({
350
404
  <>
351
405
  <span className="sr-only">{ariaLabel}</span>
352
406
  {/* The space keeps the name from running into the face's text ("Account
353
- menu3 unread"); as a flex item it takes no room. */}
354
- {" "}
407
+ menu3 unread"); as a flex item it takes no room. */}{" "}
355
408
  {trigger({ open })}
356
409
  </>,
357
410
  );
@@ -380,8 +433,8 @@ export function TopBarActionMenu({
380
433
  const footerClass =
381
434
  "flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted [&_a:hover]:text-primary [&_a]:rounded-sm [&_a:focus-visible]:outline-none [&_a:focus-visible]:ring-focus [&_a:focus-visible]:ring-brand";
382
435
  /** One action or link row — loose, or inside a heading's group. */
383
- const row = (entry: RowEntry) => (
384
- <li key={entry.key}>
436
+ const row = (entry: RowEntry, className?: string) => (
437
+ <li key={entry.key} className={className}>
385
438
  {entry.kind === "link" ? (
386
439
  <MenuItem
387
440
  href={entry.to}
@@ -413,58 +466,90 @@ export function TopBarActionMenu({
413
466
  )}
414
467
  </li>
415
468
  );
469
+ /** A rule or a row outside any group; `span` stretches it across the columns. */
470
+ const loose = (block: LooseBlock, span: boolean) => {
471
+ const entry = block.entry;
472
+ if (entry.kind === "divider") {
473
+ return <li key={entry.key} className={cn("my-1 border-t border-subtle", span && SPAN_ALL)} />;
474
+ }
475
+ return row(entry, span ? SPAN_ALL : undefined);
476
+ };
477
+ /** A heading's group: its name, then its rows in a named `role="group"`. */
478
+ const group = (block: Extract<Block, { kind: "group" }>, i: number, tight: boolean, inColumn = false) => {
479
+ const headingId = `${uid}-group-${i}`;
480
+ return (
481
+ <li key={block.heading.key} role="none">
482
+ <div
483
+ id={headingId}
484
+ role="presentation"
485
+ className={cn(
486
+ "px-3 pb-0.5 text-caption font-semibold uppercase tracking-wide text-muted [overflow-wrap:anywhere]",
487
+ // A column's heading lines up with its neighbours' at the top of the
488
+ // grid row; under `md` the columns stack, and it spaces like the list's.
489
+ tight ? "pt-1" : cn("pt-2.5", inColumn && "md:pt-1"),
490
+ )}
491
+ >
492
+ {block.heading.label}
493
+ </div>
494
+ <ul role="group" aria-labelledby={headingId}>
495
+ {block.rows.map((entry) => row(entry))}
496
+ </ul>
497
+ </li>
498
+ );
499
+ };
416
500
  return (
417
501
  // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- a Tab bubbling up from a row or footer link, see keepTabInsidePanel
418
- <ul className={cn("py-1", scrollable && SCROLLABLE_PANEL, panelClassName)} onKeyDown={keepTabInsidePanel}>
502
+ <ul
503
+ className={cn("py-1", scrollable && SCROLLABLE_PANEL, laidOut && COLUMNS_PANEL, panelClassName)}
504
+ style={
505
+ laidOut ? ({ "--menu-columns-width": `${laidOut.columns.length * 14}rem` } as CSSProperties) : undefined
506
+ }
507
+ onKeyDown={keepTabInsidePanel}
508
+ >
419
509
  {header && (
420
- <MenuSection className="mb-1 border-b border-subtle px-3 py-2">
510
+ <MenuSection className={cn("mb-1 border-b border-subtle px-3 py-2", laidOut && SPAN_ALL)}>
421
511
  <div className="truncate text-sm font-medium text-primary">{header.title}</div>
422
- {header.subtitle != null && (
423
- <div className="truncate text-xs text-muted">{header.subtitle}</div>
424
- )}
512
+ {header.subtitle != null && <div className="truncate text-xs text-muted">{header.subtitle}</div>}
425
513
  {headerExtra != null && headerExtra !== false && <div className="mt-1">{headerExtra}</div>}
426
514
  </MenuSection>
427
515
  )}
428
516
  {heading && (
429
- <li className="px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder">
517
+ <li
518
+ className={cn(
519
+ "px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder",
520
+ laidOut && SPAN_ALL,
521
+ )}
522
+ >
430
523
  {heading}
431
524
  </li>
432
525
  )}
433
526
  {leading?.(close)}
434
- {toBlocks(entries).map((block, i, blocks) => {
435
- if (block.kind === "loose") {
436
- const entry = block.entry;
437
- if (entry.kind === "divider") {
438
- return <li key={entry.key} className="my-1 border-t border-subtle" />;
439
- }
440
- return row(entry);
441
- }
442
- const headingId = `${uid}-group-${i}`;
443
- const before = blocks[i - 1];
444
- // Under a rule (or at the top of the rows) the rule's margin is the gap;
445
- // straight under another group's last row the heading makes its own.
446
- const tight = !before || (before.kind === "loose" && before.entry.kind === "divider");
447
- return (
448
- <li key={block.heading.key} role="none">
449
- <div
450
- id={headingId}
451
- role="presentation"
452
- className={cn(
453
- "px-3 pb-0.5 text-caption font-semibold uppercase tracking-wide text-muted [overflow-wrap:anywhere]",
454
- tight ? "pt-1" : "pt-2.5",
455
- )}
456
- >
457
- {block.heading.label}
458
- </div>
459
- <ul role="group" aria-labelledby={headingId}>
460
- {block.rows.map(row)}
461
- </ul>
462
- </li>
463
- );
464
- })}
527
+ {laidOut ? (
528
+ <>
529
+ {laidOut.lead.map((block) => loose(block, true))}
530
+ {laidOut.columns.map((column, c) => (
531
+ // A column of the grid; under `md` a group as in the list, its rows
532
+ // following.
533
+ <li key={column.group.heading.key} role="none" data-menu-column="" className="min-w-0">
534
+ <ul role="none">
535
+ {group(column.group, column.index, c === 0 && laidOut.lead.length === 0, true)}
536
+ {column.after.map((entry) => loose({ kind: "loose", entry }, false))}
537
+ </ul>
538
+ </li>
539
+ ))}
540
+ </>
541
+ ) : (
542
+ blocks.map((block, i) => {
543
+ if (block.kind === "loose") return loose(block, false);
544
+ const before = blocks[i - 1];
545
+ // Under a rule (or at the top of the rows) the rule's margin is the gap;
546
+ // straight under another group's last row the heading makes its own.
547
+ return group(block, i, !before || (before.kind === "loose" && before.entry.kind === "divider"));
548
+ })
549
+ )}
465
550
  {children?.(close)}
466
551
  {footerBody != null && footerBody !== false && (
467
- <MenuSection className="mt-1 border-t border-subtle px-3 py-2">
552
+ <MenuSection className={cn("mt-1 border-t border-subtle px-3 py-2", laidOut && SPAN_ALL)}>
468
553
  {footerLabel ? (
469
554
  <nav aria-label={footerLabel} className={footerClass}>
470
555
  {footerBody}
@@ -19,11 +19,7 @@ export const TOPBAR_MENU_ITEM_CLASS =
19
19
 
20
20
  /** The small uppercase heading row the top-bar menus share (`heading`). */
21
21
  function MenuHeading({ children }: { children: string }) {
22
- return (
23
- <li className="px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder">
24
- {children}
25
- </li>
26
- );
22
+ return <li className="px-3 py-1 text-micro font-semibold uppercase tracking-wide text-placeholder">{children}</li>;
27
23
  }
28
24
 
29
25
  /**
@@ -108,12 +104,7 @@ export function PaletteMenu({
108
104
  aria-label={labels.palette}
109
105
  trigger={({ toggle }) => (
110
106
  <Tooltip label={activeName} portal>
111
- <button
112
- type="button"
113
- onClick={toggle}
114
- aria-label={labels.palette}
115
- className={TOPBAR_TRIGGER_CLASS}
116
- >
107
+ <button type="button" onClick={toggle} aria-label={labels.palette} className={TOPBAR_TRIGGER_CLASS}>
117
108
  {/* A DATA colour, not a semantic one: the palette mark is the
118
109
  "colour" control, so it carries a colour, and which hue is
119
110
  arbitrary. `--chart-1` is the violet end of the CVD-safe
@@ -155,14 +146,10 @@ export function PaletteMenu({
155
146
  </span>
156
147
  <span className="flex min-w-0 flex-col text-start">
157
148
  <span className="truncate">{p.name}</span>
158
- <span className="truncate text-caption text-placeholder">
159
- {p.blurb}
160
- </span>
149
+ <span className="truncate text-caption text-placeholder">{p.blurb}</span>
161
150
  </span>
162
151
  </span>
163
- {activeId === p.id && (
164
- <Check className="size-4 shrink-0 text-secondary" />
165
- )}
152
+ {activeId === p.id && <Check className="size-4 shrink-0 text-secondary" />}
166
153
  </button>
167
154
  </li>
168
155
  );
@@ -186,8 +173,7 @@ export type LanguageMenuTrigger = "flag+code" | "code" | "flag";
186
173
  /** The trigger with a code: as tall as the others, as wide as flag and code need. */
187
174
  const LANGUAGE_TRIGGER_WIDE_CLASS = TOPBAR_TRIGGER_CLASS.replace("size-9", "h-9 min-w-9 gap-1.5 px-2");
188
175
 
189
- const FLAG_CLASS =
190
- "inline-block h-[0.9375rem] w-5 shrink-0 rounded-sm shadow-[0_0_0_1px_rgba(0,0,0,0.08)]";
176
+ const FLAG_CLASS = "inline-block h-[0.9375rem] w-5 shrink-0 rounded-sm shadow-[0_0_0_1px_rgba(0,0,0,0.08)]";
191
177
 
192
178
  /** Language switcher: a hover menu of options with flags and a check on the
193
179
  * active one. Controlled — the app owns the current code and change handler.
@@ -148,7 +148,15 @@ export function TourMenu({
148
148
  const tail: TopBarMenuEntry[] = [
149
149
  ...rest.map(entryFor),
150
150
  ...(href
151
- ? [{ kind: "link" as const, key: "all-tours", icon: <Compass className="size-4" />, label: words.allTours, to: href }]
151
+ ? [
152
+ {
153
+ kind: "link" as const,
154
+ key: "all-tours",
155
+ icon: <Compass className="size-4" />,
156
+ label: words.allTours,
157
+ to: href,
158
+ },
159
+ ]
152
160
  : []),
153
161
  ];
154
162
 
package/src/shell.ts CHANGED
@@ -41,7 +41,7 @@ export type {
41
41
  SettingsLocationRules,
42
42
  SettingsLocationResult,
43
43
  } from "./settings/use-settings-route";
44
- export { useSettingsFocus, SETTINGS_FOCUS_RING, SETTINGS_FOCUS_MS } from "./settings/use-settings-focus";
44
+ export { useSettingsFocus, useFocusParam, SETTINGS_FOCUS_RING, SETTINGS_FOCUS_MS } from "./settings/use-settings-focus";
45
45
  export { SettingsSection } from "./settings/settings-section";
46
46
  export type { SettingsSectionProps } from "./settings/settings-section";
47
47
  export { useSettingsLayout } from "./settings/settings-context";
package/src/sync/db.ts CHANGED
@@ -98,7 +98,11 @@ export const SYNC_DB_PK_INDEX = {
98
98
  */
99
99
  export async function rowByPk(db: SyncDb, entity: string, pk: number): Promise<SyncedRow | undefined> {
100
100
  if (db.rows.schema.idxByName["[entity+pk]"]) return db.rows.where("[entity+pk]").equals([entity, pk]).first();
101
- return db.rows.where("entity").equals(entity).filter((row) => row.pk === pk).first();
101
+ return db.rows
102
+ .where("entity")
103
+ .equals(entity)
104
+ .filter((row) => row.pk === pk)
105
+ .first();
102
106
  }
103
107
 
104
108
  /**
@@ -103,7 +103,13 @@ export interface SyncEngine {
103
103
  /** Into the copy at once and into the queue, in the scope the caller names (D11). An edit
104
104
  * merges into the row's last `pending` upsert; deleting a row that never reached the
105
105
  * server forgets its queue; stamped with `stampAfter`. */
106
- write(scope: string, entity: string, id: string, op: "upsert" | "delete", data?: Record<string, unknown>): Promise<void>;
106
+ write(
107
+ scope: string,
108
+ entity: string,
109
+ id: string,
110
+ op: "upsert" | "delete",
111
+ data?: Record<string, unknown>,
112
+ ): Promise<void>;
107
113
  start(): void;
108
114
  /** Stops the poll and the timers, aborts the round in flight and drops its answer (the
109
115
  * queue is laid back). A new engine's round on the same database waits for it. */
@@ -164,9 +170,9 @@ function defaultPlanCode(err: unknown): string | null {
164
170
  * `{detail: {code, detail}}`. */
165
171
  function refusalOf(err: unknown): { code?: string; detail?: string } {
166
172
  const body = (err as { response?: { data?: unknown } }).response?.data as
167
- | { code?: unknown; detail?: unknown }
168
- | undefined;
169
- const inner = body?.detail && typeof body.detail === "object" ? (body.detail as { code?: unknown; detail?: unknown }) : body;
173
+ { code?: unknown; detail?: unknown } | undefined;
174
+ const inner =
175
+ body?.detail && typeof body.detail === "object" ? (body.detail as { code?: unknown; detail?: unknown }) : body;
170
176
  const text = (v: unknown) => (typeof v === "string" && v ? v : undefined);
171
177
  return { code: text(inner?.code), detail: text(inner?.detail) };
172
178
  }
@@ -200,7 +206,13 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
200
206
  const sharedComputer = options.sharedComputer ?? isSharedComputer;
201
207
 
202
208
  let generation = 0;
203
- let state: SyncEngineState = { phase: "idle", online: browserOnline(), counts: ZERO, lastSyncedAt: null, nextRetryAt: null };
209
+ let state: SyncEngineState = {
210
+ phase: "idle",
211
+ online: browserOnline(),
212
+ counts: ZERO,
213
+ lastSyncedAt: null,
214
+ nextRetryAt: null,
215
+ };
204
216
  const listeners = new Set<() => void>();
205
217
  let started = false;
206
218
  let poll: ReturnType<typeof setInterval> | null = null;
@@ -281,7 +293,8 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
281
293
  const rejected = sent.filter((c) => !refusedIds.has(c.id) && rejections.has(c.id));
282
294
  await db.outbox.bulkDelete(sent.filter((c) => !refusedIds.has(c.id) && !rejections.has(c.id)).map((c) => c.seq!));
283
295
  const hold = refused != null && holdCodes.has(refused.code);
284
- if (refused) await mark(kept, { status: hold ? "waiting" : "blocked", code: refused.code, reason: refused.detail });
296
+ if (refused)
297
+ await mark(kept, { status: hold ? "waiting" : "blocked", code: refused.code, reason: refused.detail });
285
298
  for (const change of rejected) {
286
299
  const why = rejections.get(change.id)!;
287
300
  await db.outbox.update(change.seq!, { status: "rejected", code: why.code, reason: why.detail });
@@ -313,7 +326,13 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
313
326
  continue;
314
327
  }
315
328
  const row = (await db.rows.get([change.entity, change.id])) as CopyRow | undefined;
316
- await db.rows.put({ ...row, entity: change.entity, id: change.id, pk: row?.pk ?? null, data: { ...row?.data, ...change.data } });
329
+ await db.rows.put({
330
+ ...row,
331
+ entity: change.entity,
332
+ id: change.id,
333
+ pk: row?.pk ?? null,
334
+ data: { ...row?.data, ...change.data },
335
+ });
317
336
  }
318
337
  if (lastPage) {
319
338
  await db.meta.put({ key: lastKnowledgeKey(scope), value: answer.server_knowledge });
@@ -345,7 +364,12 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
345
364
 
346
365
  type ScopeResult = { offline: true } | { offline: false; waiting: number; blocked: number; rejected: number };
347
366
 
348
- async function syncScope(scope: string, gen: number, signal: AbortSignal, withBlocked: boolean): Promise<ScopeResult> {
367
+ async function syncScope(
368
+ scope: string,
369
+ gen: number,
370
+ signal: AbortSignal,
371
+ withBlocked: boolean,
372
+ ): Promise<ScopeResult> {
349
373
  const sent = await takeQueue(scope, withBlocked);
350
374
  const last = Number((await db.meta.get(lastKnowledgeKey(scope)))?.value ?? 0) || 0;
351
375
  const body = (changes: SyncWireChange[], page_cursor: SyncRequestBody["page_cursor"]): SyncRequestBody => ({
@@ -369,7 +393,8 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
369
393
  await mark(sent, { status: "waiting", code: plan, reason: plan });
370
394
  return { offline: false, waiting: sent.length, blocked: 0, rejected: 0 };
371
395
  }
372
- if (httpStatusOf(err) === 403) return { offline: false, waiting: 0, blocked: 0, rejected: await loseScope(scope, err) };
396
+ if (httpStatusOf(err) === 403)
397
+ return { offline: false, waiting: 0, blocked: 0, rejected: await loseScope(scope, err) };
373
398
  throw err;
374
399
  }
375
400
  let cursor = options.paged ? (answer.page_cursor ?? null) : null;
@@ -545,7 +570,9 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
545
570
  const row = (await db.rows.get([entity, id])) as CopyRow | undefined;
546
571
  const ofRow = await db.outbox.where("[entity+id]").equals([entity, id]).toArray();
547
572
  ofRow.sort((a, b) => a.seq! - b.seq!);
548
- const updated_at = stampAfter(latest([row?.updated_at, row?.data.updated_at, ...ofRow.map((c) => c.updated_at)]));
573
+ const updated_at = stampAfter(
574
+ latest([row?.updated_at, row?.data.updated_at, ...ofRow.map((c) => c.updated_at)]),
575
+ );
549
576
  // A new edit to the row moves a rejected change out of the way (D13).
550
577
  const rejected = ofRow.filter((c) => c.scope === scope && c.status === "rejected");
551
578
  if (op === "delete") {
@@ -564,7 +591,10 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
564
591
  const next: CopyRow = { ...row, entity, id, pk: row?.pk ?? null, data: { ...row?.data, ...data } };
565
592
  if (!row) next.local = true;
566
593
  await db.rows.put(next);
567
- const carried = Object.assign({}, ...rejected.filter((c) => c.op === "upsert").map((c) => c.data)) as Record<string, unknown>;
594
+ const carried = Object.assign({}, ...rejected.filter((c) => c.op === "upsert").map((c) => c.data)) as Record<
595
+ string,
596
+ unknown
597
+ >;
568
598
  await db.outbox.bulkDelete(rejected.map((c) => c.seq!));
569
599
  const last = ofRow.filter((c) => c.scope === scope && c.status === "pending").at(-1);
570
600
  if (last && last.op === "upsert") {
@@ -628,7 +658,9 @@ export function createSyncEngine<D extends SyncDb = SyncDb>(options: SyncEngineO
628
658
  },
629
659
 
630
660
  async discardRejected(scope) {
631
- const gone = (await db.outbox.where("status").equals("rejected").toArray()).filter((c) => !scope || c.scope === scope);
661
+ const gone = (await db.outbox.where("status").equals("rejected").toArray()).filter(
662
+ (c) => !scope || c.scope === scope,
663
+ );
632
664
  if (gone.length === 0) return;
633
665
  await db.transaction("rw", db.rows, db.outbox, db.meta, async () => {
634
666
  await db.outbox.bulkDelete(gone.map((c) => c.seq!));
package/src/sync.ts CHANGED
@@ -5,8 +5,22 @@
5
5
  // `/offline`'s TanStack and idb-keyval peers: the leaf utilities both entries export live in
6
6
  // one module of their own (src/offline/local-first.ts). NOT re-exported from the main barrel.
7
7
  export { createSyncDb, rowByPk, SYNC_DB_PK_INDEX, SYNC_DB_STORES } from "./sync/db";
8
- export type { CreateSyncDbOptions, OutboxChange, OutboxStatus, SyncDb, SyncDbUpgrade, SyncedRow, SyncMetaEntry } from "./sync/db";
9
- export { createSyncEngine, DEFAULT_HOLD_CODES, DEFAULT_SYNC_BACKOFF_MS, releaseSyncEngine, syncEngineFor } from "./sync/engine";
8
+ export type {
9
+ CreateSyncDbOptions,
10
+ OutboxChange,
11
+ OutboxStatus,
12
+ SyncDb,
13
+ SyncDbUpgrade,
14
+ SyncedRow,
15
+ SyncMetaEntry,
16
+ } from "./sync/db";
17
+ export {
18
+ createSyncEngine,
19
+ DEFAULT_HOLD_CODES,
20
+ DEFAULT_SYNC_BACKOFF_MS,
21
+ releaseSyncEngine,
22
+ syncEngineFor,
23
+ } from "./sync/engine";
10
24
  export type {
11
25
  SyncCounts,
12
26
  SyncEngine,
@@ -158,8 +158,7 @@ export function undeclaredCssVariables(
158
158
  if (isCssPath(path)) for (const name of declaredCustomProperties(text)) declared.add(name);
159
159
  for (const name of runtimeWrites(text)) declared.add(name);
160
160
  }
161
- const listed = (name: string) =>
162
- runtime.some((r) => (typeof r === "string" ? r === name : r.test(name)));
161
+ const listed = (name: string) => runtime.some((r) => (typeof r === "string" ? r === name : r.test(name)));
163
162
 
164
163
  const out: string[] = [];
165
164
  for (const [path, text] of code) {
@@ -26,9 +26,4 @@ export {
26
26
  } from "./viewport";
27
27
  // 0.50.1 (keksdose N4): a valid `TourStepContext` for a test that calls a step's
28
28
  // `beforeStep` or `when` itself — `beforeStep!(tourStepContext())`.
29
- export {
30
- tourStepContext,
31
- type TestTourStepContext,
32
- type TourStepContextOptions,
33
- type TourStepVia,
34
- } from "./tour";
29
+ export { tourStepContext, type TestTourStepContext, type TourStepContextOptions, type TourStepVia } from "./tour";