@eifi1/ui-kit 0.54.0 → 0.55.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 (847) hide show
  1. package/README.md +90 -76
  2. package/dist/admin/plan-change.js +2 -2
  3. package/dist/admin/plan-change.js.map +1 -1
  4. package/dist/admin/user-roster.d.ts +6 -0
  5. package/dist/admin/user-roster.js +4 -0
  6. package/dist/admin/user-roster.js.map +1 -1
  7. package/dist/billing/billing-labels.d.ts +26 -0
  8. package/dist/billing/billing-labels.js +9 -0
  9. package/dist/billing/billing-labels.js.map +1 -1
  10. package/dist/billing/subscription-standing.d.ts +61 -0
  11. package/dist/billing/subscription-standing.js +51 -0
  12. package/dist/billing/subscription-standing.js.map +1 -0
  13. package/dist/billing/usage-meter.d.ts +52 -0
  14. package/dist/billing/usage-meter.js +52 -0
  15. package/dist/billing/usage-meter.js.map +1 -0
  16. package/dist/chart.d.ts +1 -0
  17. package/dist/chart.js +4 -0
  18. package/dist/chart.js.map +1 -1
  19. package/dist/components/alert-banner.js +2 -3
  20. package/dist/components/alert-banner.js.map +1 -1
  21. package/dist/components/amount-input.js +3 -15
  22. package/dist/components/amount-input.js.map +1 -1
  23. package/dist/components/autocomplete.js +2 -2
  24. package/dist/components/autocomplete.js.map +1 -1
  25. package/dist/components/bulk-action-bar.js +2 -1
  26. package/dist/components/bulk-action-bar.js.map +1 -1
  27. package/dist/components/button.d.ts +35 -1
  28. package/dist/components/button.js +5 -9
  29. package/dist/components/button.js.map +1 -1
  30. package/dist/components/calendar-heatmap.js +2 -2
  31. package/dist/components/calendar-heatmap.js.map +1 -1
  32. package/dist/components/camera-button.d.ts +89 -0
  33. package/dist/components/camera-button.js +122 -0
  34. package/dist/components/camera-button.js.map +1 -0
  35. package/dist/components/camera-capture.d.ts +66 -0
  36. package/dist/components/camera-capture.js +190 -0
  37. package/dist/components/camera-capture.js.map +1 -0
  38. package/dist/components/camera-labels.d.ts +20 -0
  39. package/dist/components/camera-labels.js +15 -0
  40. package/dist/components/camera-labels.js.map +1 -0
  41. package/dist/components/chart-edge.d.ts +9 -0
  42. package/dist/components/chart-edge.js +14 -3
  43. package/dist/components/chart-edge.js.map +1 -1
  44. package/dist/components/chart-zoom-core.js +34 -29
  45. package/dist/components/chart-zoom-core.js.map +1 -1
  46. package/dist/components/checkbox-group.js +1 -1
  47. package/dist/components/checkbox-group.js.map +1 -1
  48. package/dist/components/combobox-core.js +3 -2
  49. package/dist/components/combobox-core.js.map +1 -1
  50. package/dist/components/combobox.js +2 -2
  51. package/dist/components/combobox.js.map +1 -1
  52. package/dist/components/consent-again-notice-labels.d.ts +25 -0
  53. package/dist/components/consent-again-notice-labels.js +15 -0
  54. package/dist/components/consent-again-notice-labels.js.map +1 -0
  55. package/dist/components/consent-again-notice.d.ts +85 -0
  56. package/dist/components/consent-again-notice.js +94 -0
  57. package/dist/components/consent-again-notice.js.map +1 -0
  58. package/dist/components/country-select.js +2 -7
  59. package/dist/components/country-select.js.map +1 -1
  60. package/dist/components/currency-select.js +2 -2
  61. package/dist/components/currency-select.js.map +1 -1
  62. package/dist/components/danger-confirm.js +2 -2
  63. package/dist/components/danger-confirm.js.map +1 -1
  64. package/dist/components/data-table-column-settings.js +2 -2
  65. package/dist/components/data-table-column-settings.js.map +1 -1
  66. package/dist/components/data-table-fit.js.map +1 -1
  67. package/dist/components/data-table-virtual.js +13 -3
  68. package/dist/components/data-table-virtual.js.map +1 -1
  69. package/dist/components/date-field.js +2 -2
  70. package/dist/components/date-field.js.map +1 -1
  71. package/dist/components/date-picker.js +2 -2
  72. package/dist/components/date-picker.js.map +1 -1
  73. package/dist/components/date-range-picker.js +2 -6
  74. package/dist/components/date-range-picker.js.map +1 -1
  75. package/dist/components/dialog-frame.d.ts +3 -1
  76. package/dist/components/dialog-frame.js.map +1 -1
  77. package/dist/components/dropdown.js +7 -3
  78. package/dist/components/dropdown.js.map +1 -1
  79. package/dist/components/entity-combobox.js +2 -2
  80. package/dist/components/entity-combobox.js.map +1 -1
  81. package/dist/components/field-parts.d.ts +108 -6
  82. package/dist/components/field-parts.js +59 -6
  83. package/dist/components/field-parts.js.map +1 -1
  84. package/dist/components/field-suggestion-labels.d.ts +2 -0
  85. package/dist/components/field-suggestion-labels.js +10 -0
  86. package/dist/components/field-suggestion-labels.js.map +1 -0
  87. package/dist/components/field.js +1 -1
  88. package/dist/components/field.js.map +1 -1
  89. package/dist/components/file-button.d.ts +1 -1
  90. package/dist/components/file-button.js.map +1 -1
  91. package/dist/components/floating-panel.d.ts +7 -6
  92. package/dist/components/floating-panel.js +3 -17
  93. package/dist/components/floating-panel.js.map +1 -1
  94. package/dist/components/form-actions.d.ts +3 -2
  95. package/dist/components/form-actions.js.map +1 -1
  96. package/dist/components/hover-menu.js +3 -2
  97. package/dist/components/hover-menu.js.map +1 -1
  98. package/dist/components/icon-button.d.ts +23 -5
  99. package/dist/components/icon-button.js +6 -8
  100. package/dist/components/icon-button.js.map +1 -1
  101. package/dist/components/inline-confirm.js +2 -1
  102. package/dist/components/inline-confirm.js.map +1 -1
  103. package/dist/components/inline-entity-combobox.js +2 -2
  104. package/dist/components/inline-entity-combobox.js.map +1 -1
  105. package/dist/components/input.js +2 -2
  106. package/dist/components/input.js.map +1 -1
  107. package/dist/components/jump-calendar.js +3 -3
  108. package/dist/components/jump-calendar.js.map +1 -1
  109. package/dist/components/legal.d.ts +13 -1
  110. package/dist/components/legal.js +12 -0
  111. package/dist/components/legal.js.map +1 -1
  112. package/dist/components/legended-series-chart.d.ts +80 -0
  113. package/dist/components/legended-series-chart.js +70 -0
  114. package/dist/components/legended-series-chart.js.map +1 -0
  115. package/dist/components/lightbox.js +2 -1
  116. package/dist/components/lightbox.js.map +1 -1
  117. package/dist/components/mini-calendar.js +13 -5
  118. package/dist/components/mini-calendar.js.map +1 -1
  119. package/dist/components/modal.d.ts +23 -2
  120. package/dist/components/modal.js +24 -6
  121. package/dist/components/modal.js.map +1 -1
  122. package/dist/components/month-picker.d.ts +1 -1
  123. package/dist/components/month-picker.js +6 -6
  124. package/dist/components/month-picker.js.map +1 -1
  125. package/dist/components/multi-entity-combobox.js +2 -2
  126. package/dist/components/multi-entity-combobox.js.map +1 -1
  127. package/dist/components/multi-select.js +2 -6
  128. package/dist/components/multi-select.js.map +1 -1
  129. package/dist/components/number-input.js +2 -2
  130. package/dist/components/number-input.js.map +1 -1
  131. package/dist/components/page-header-layout.d.ts +18 -0
  132. package/dist/components/page-header-layout.js +23 -0
  133. package/dist/components/page-header-layout.js.map +1 -0
  134. package/dist/components/page-header-skeleton.d.ts +41 -0
  135. package/dist/components/page-header-skeleton.js +52 -0
  136. package/dist/components/page-header-skeleton.js.map +1 -0
  137. package/dist/components/page-header.js +4 -17
  138. package/dist/components/page-header.js.map +1 -1
  139. package/dist/components/popover.js +7 -2
  140. package/dist/components/popover.js.map +1 -1
  141. package/dist/components/release-notes-labels.d.ts +16 -0
  142. package/dist/components/release-notes-labels.js +18 -0
  143. package/dist/components/release-notes-labels.js.map +1 -0
  144. package/dist/components/release-notes.d.ts +65 -0
  145. package/dist/components/release-notes.js +65 -0
  146. package/dist/components/release-notes.js.map +1 -0
  147. package/dist/components/select.js +2 -2
  148. package/dist/components/select.js.map +1 -1
  149. package/dist/components/series-chart-labels.d.ts +9 -0
  150. package/dist/components/series-chart-labels.js +3 -1
  151. package/dist/components/series-chart-labels.js.map +1 -1
  152. package/dist/components/series-chart.d.ts +5 -0
  153. package/dist/components/series-chart.js +89 -36
  154. package/dist/components/series-chart.js.map +1 -1
  155. package/dist/components/toggle-group.js +3 -2
  156. package/dist/components/toggle-group.js.map +1 -1
  157. package/dist/components/treemap-layout.js.map +1 -1
  158. package/dist/components/treemap.d.ts +17 -15
  159. package/dist/components/treemap.js +167 -85
  160. package/dist/components/treemap.js.map +1 -1
  161. package/dist/eslint/index.js +1 -1
  162. package/dist/eslint/role-utilities.d.ts +2 -2
  163. package/dist/eslint/role-utilities.js.map +1 -1
  164. package/dist/feedback/feedback-inbox-page.d.ts +260 -0
  165. package/dist/feedback/feedback-inbox-page.js +207 -0
  166. package/dist/feedback/feedback-inbox-page.js.map +1 -0
  167. package/dist/feedback/feedback-vocabulary.js +2 -2
  168. package/dist/feedback/feedback-vocabulary.js.map +1 -1
  169. package/dist/feedback.d.ts +1 -0
  170. package/dist/feedback.js +6 -0
  171. package/dist/feedback.js.map +1 -1
  172. package/dist/hooks/use-debounce.d.ts +32 -5
  173. package/dist/hooks/use-debounce.js +6 -5
  174. package/dist/hooks/use-debounce.js.map +1 -1
  175. package/dist/hooks/use-file-picker.d.ts +3 -1
  176. package/dist/hooks/use-file-picker.js.map +1 -1
  177. package/dist/hooks/use-focus-trap.d.ts +19 -3
  178. package/dist/hooks/use-focus-trap.js +15 -5
  179. package/dist/hooks/use-focus-trap.js.map +1 -1
  180. package/dist/hooks/use-has-camera.d.ts +36 -0
  181. package/dist/hooks/use-has-camera.js +53 -0
  182. package/dist/hooks/use-has-camera.js.map +1 -0
  183. package/dist/hooks/use-hotkey.js +1 -10
  184. package/dist/hooks/use-hotkey.js.map +1 -1
  185. package/dist/hooks/use-overlay-history.d.ts +6 -1
  186. package/dist/hooks/use-overlay-history.js +10 -2
  187. package/dist/hooks/use-overlay-history.js.map +1 -1
  188. package/dist/i18n/defaults.js +11 -1
  189. package/dist/i18n/defaults.js.map +1 -1
  190. package/dist/i18n/german.js +75 -3
  191. package/dist/i18n/german.js.map +1 -1
  192. package/dist/i18n/kit-labels.d.ts +20 -0
  193. package/dist/i18n/kit-labels.js.map +1 -1
  194. package/dist/i18n/locales/en.js +92 -4
  195. package/dist/i18n/locales/en.js.map +3 -3
  196. package/dist/i18n/locales/es.js +71 -3
  197. package/dist/i18n/locales/es.js.map +1 -1
  198. package/dist/i18n/locales/fr.js +72 -2
  199. package/dist/i18n/locales/fr.js.map +1 -1
  200. package/dist/i18n/locales/hu.js +74 -3
  201. package/dist/i18n/locales/hu.js.map +1 -1
  202. package/dist/i18n/locales/it.js +74 -3
  203. package/dist/i18n/locales/it.js.map +1 -1
  204. package/dist/i18n/locales/zh.js +71 -3
  205. package/dist/i18n/locales/zh.js.map +1 -1
  206. package/dist/i18n/review.js +22 -1
  207. package/dist/i18n/review.js.map +1 -1
  208. package/dist/index.d.ts +24 -5
  209. package/dist/index.js +35 -1
  210. package/dist/index.js.map +1 -1
  211. package/dist/landing/landing-labels.d.ts +8 -0
  212. package/dist/landing/landing-labels.js +2 -1
  213. package/dist/landing/landing-labels.js.map +1 -1
  214. package/dist/lib/changelog.d.ts +130 -0
  215. package/dist/lib/changelog.js +137 -0
  216. package/dist/lib/changelog.js.map +1 -0
  217. package/dist/lib/clipboard-minus.js +2 -2
  218. package/dist/lib/clipboard-minus.js.map +1 -1
  219. package/dist/lib/dates.d.ts +29 -3
  220. package/dist/lib/dates.js +41 -12
  221. package/dist/lib/dates.js.map +1 -1
  222. package/dist/lib/editable-content.d.ts +33 -0
  223. package/dist/lib/editable-content.js +15 -0
  224. package/dist/lib/editable-content.js.map +1 -0
  225. package/dist/lib/focus-left.d.ts +47 -1
  226. package/dist/lib/focus-left.js +11 -2
  227. package/dist/lib/focus-left.js.map +1 -1
  228. package/dist/lib/server-wake.d.ts +49 -9
  229. package/dist/lib/server-wake.js +25 -14
  230. package/dist/lib/server-wake.js.map +1 -1
  231. package/dist/lib/session-refresh.d.ts +53 -0
  232. package/dist/lib/session-refresh.js +27 -1
  233. package/dist/lib/session-refresh.js.map +1 -1
  234. package/dist/rhf/fields.js +3 -3
  235. package/dist/rhf/fields.js.map +1 -1
  236. package/dist/shell/app-shell.d.ts +25 -1
  237. package/dist/shell/app-shell.js +3 -1
  238. package/dist/shell/app-shell.js.map +1 -1
  239. package/dist/shell/dev-menu.d.ts +3 -0
  240. package/dist/shell/dev-menu.js +4 -2
  241. package/dist/shell/dev-menu.js.map +1 -1
  242. package/dist/shell/held-changes-banner-labels.d.ts +23 -0
  243. package/dist/shell/held-changes-banner-labels.js +14 -0
  244. package/dist/shell/held-changes-banner-labels.js.map +1 -0
  245. package/dist/shell/held-changes-banner.d.ts +75 -0
  246. package/dist/shell/held-changes-banner.js +106 -0
  247. package/dist/shell/held-changes-banner.js.map +1 -0
  248. package/dist/shell/sync-status-indicator.d.ts +27 -12
  249. package/dist/shell/sync-status-indicator.js +13 -4
  250. package/dist/shell/sync-status-indicator.js.map +1 -1
  251. package/dist/shell/top-bar-parts-labels.d.ts +5 -0
  252. package/dist/shell/top-bar-parts-labels.js +3 -1
  253. package/dist/shell/top-bar-parts-labels.js.map +1 -1
  254. package/dist/shell.d.ts +2 -0
  255. package/dist/shell.js +3 -0
  256. package/dist/shell.js.map +1 -1
  257. package/dist/sync/engine.d.ts +11 -2
  258. package/dist/sync/engine.js +13 -5
  259. package/dist/sync/engine.js.map +1 -1
  260. package/dist/sync/hooks.d.ts +3 -2
  261. package/dist/sync/hooks.js +4 -2
  262. package/dist/sync/hooks.js.map +1 -1
  263. package/dist/testing/css-variables.generated.d.ts +2 -2
  264. package/dist/testing/css-variables.generated.js +1 -1
  265. package/dist/testing/css-variables.generated.js.map +1 -1
  266. package/dist/theme/chart-palette.d.ts +18 -0
  267. package/dist/theme/chart-palette.js +17 -1
  268. package/dist/theme/chart-palette.js.map +1 -1
  269. package/dist/theme/contrast-tokens.d.ts +3 -3
  270. package/dist/theme/contrast-tokens.js.map +1 -1
  271. package/dist/theme/contrast.d.ts +4 -4
  272. package/dist/theme/contrast.js.map +1 -1
  273. package/dist/tour/tour-overlay.js +2 -1
  274. package/dist/tour/tour-overlay.js.map +1 -1
  275. package/package.json +5 -9
  276. package/tokens.css +19 -54
  277. package/src/account/account-parts.ts +0 -47
  278. package/src/account/account-settings-labels.ts +0 -240
  279. package/src/account/account-settings.tsx +0 -698
  280. package/src/account/data-export-setting-labels.ts +0 -20
  281. package/src/account/data-export-setting.tsx +0 -200
  282. package/src/account/delete-account-setting-labels.ts +0 -33
  283. package/src/account/delete-account-setting.tsx +0 -342
  284. package/src/account/email-change-setting-labels.ts +0 -31
  285. package/src/account/email-change-setting.tsx +0 -443
  286. package/src/account/passkeys-setting.tsx +0 -445
  287. package/src/account/sessions-setting-labels.ts +0 -24
  288. package/src/account/sessions-setting.tsx +0 -283
  289. package/src/admin/admin-action-confirm-labels.ts +0 -19
  290. package/src/admin/admin-action-confirm.tsx +0 -509
  291. package/src/admin/admin-action-log-labels.ts +0 -83
  292. package/src/admin/admin-action-log.tsx +0 -464
  293. package/src/admin/admin-area-labels.ts +0 -114
  294. package/src/admin/admin-forbidden.tsx +0 -75
  295. package/src/admin/admin-overview.tsx +0 -258
  296. package/src/admin/admin-parts.ts +0 -68
  297. package/src/admin/admin-sections.tsx +0 -208
  298. package/src/admin/admin-tool-links.tsx +0 -90
  299. package/src/admin/invitations-panel-labels.ts +0 -31
  300. package/src/admin/invitations-panel.tsx +0 -516
  301. package/src/admin/mail-test-card-labels.ts +0 -19
  302. package/src/admin/mail-test-card.tsx +0 -189
  303. package/src/admin/plan-change-labels.ts +0 -5
  304. package/src/admin/plan-change.tsx +0 -474
  305. package/src/admin/reviewer-scope-editor-labels.ts +0 -16
  306. package/src/admin/reviewer-scope-editor.tsx +0 -224
  307. package/src/admin/role-select-labels.ts +0 -16
  308. package/src/admin/role-select.tsx +0 -282
  309. package/src/admin/transfer-ownership-dialog-labels.ts +0 -20
  310. package/src/admin/transfer-ownership-dialog.tsx +0 -162
  311. package/src/admin/user-roster-labels.ts +0 -17
  312. package/src/admin/user-roster.tsx +0 -559
  313. package/src/auth/accept-invitation-labels.ts +0 -21
  314. package/src/auth/accept-invitation.tsx +0 -210
  315. package/src/auth/auth-errors-labels.ts +0 -23
  316. package/src/auth/auth-errors.ts +0 -439
  317. package/src/auth/complete-name-dialog-labels.ts +0 -16
  318. package/src/auth/complete-name-dialog.tsx +0 -253
  319. package/src/auth/email-tag.ts +0 -75
  320. package/src/auth/forgot-password-form-labels.ts +0 -20
  321. package/src/auth/forgot-password-form.tsx +0 -221
  322. package/src/auth/form-rules.ts +0 -40
  323. package/src/auth/new-password-fields.tsx +0 -85
  324. package/src/auth/not-found-page-labels.ts +0 -12
  325. package/src/auth/not-found-page.tsx +0 -95
  326. package/src/auth/register-form-labels.ts +0 -31
  327. package/src/auth/register-form.tsx +0 -456
  328. package/src/auth/reset-password-form-labels.ts +0 -27
  329. package/src/auth/reset-password-form.tsx +0 -341
  330. package/src/auth/sign-in-form-labels.ts +0 -44
  331. package/src/auth/sign-in-form.tsx +0 -858
  332. package/src/auth/status-parts.tsx +0 -132
  333. package/src/auth/verify-email-labels.ts +0 -26
  334. package/src/auth/verify-email.tsx +0 -445
  335. package/src/billing/billing-banner.tsx +0 -258
  336. package/src/billing/billing-labels.ts +0 -381
  337. package/src/billing/billing-lock.ts +0 -108
  338. package/src/billing/billing-overview.ts +0 -157
  339. package/src/billing/billing-standing.ts +0 -80
  340. package/src/billing/cancel-request.ts +0 -97
  341. package/src/billing/cancel-subscription.tsx +0 -98
  342. package/src/billing/checkout-processing.ts +0 -394
  343. package/src/billing/checkout-return.ts +0 -90
  344. package/src/billing/pay-page.ts +0 -330
  345. package/src/billing/plan-card.tsx +0 -562
  346. package/src/billing/plan-change-labels.ts +0 -66
  347. package/src/billing/plan-limit-notice.tsx +0 -148
  348. package/src/billing/plan-limit-toast.tsx +0 -90
  349. package/src/billing/plan-limit.ts +0 -52
  350. package/src/billing/plan-price.ts +0 -98
  351. package/src/billing/plan-switch.tsx +0 -216
  352. package/src/billing/provider-page.ts +0 -84
  353. package/src/billing/subscription-actions.tsx +0 -247
  354. package/src/billing/subscription-status-chip.tsx +0 -95
  355. package/src/chart.ts +0 -103
  356. package/src/components/account-chips-labels.ts +0 -16
  357. package/src/components/account-chips.tsx +0 -474
  358. package/src/components/alert-banner.tsx +0 -670
  359. package/src/components/amount-input.tsx +0 -816
  360. package/src/components/appearance-labels.ts +0 -63
  361. package/src/components/authed-image-labels.ts +0 -11
  362. package/src/components/authed-image.tsx +0 -209
  363. package/src/components/autocomplete.tsx +0 -645
  364. package/src/components/breadcrumbs-labels.ts +0 -10
  365. package/src/components/breadcrumbs.tsx +0 -205
  366. package/src/components/bulk-action-bar-labels.ts +0 -11
  367. package/src/components/bulk-action-bar.tsx +0 -443
  368. package/src/components/button-group.tsx +0 -223
  369. package/src/components/button-look.ts +0 -256
  370. package/src/components/button.tsx +0 -339
  371. package/src/components/calculator.tsx +0 -341
  372. package/src/components/calendar-heatmap-labels.ts +0 -15
  373. package/src/components/calendar-heatmap.tsx +0 -600
  374. package/src/components/card.tsx +0 -377
  375. package/src/components/chart-edge.ts +0 -106
  376. package/src/components/chart-figure.tsx +0 -35
  377. package/src/components/chart-height.ts +0 -30
  378. package/src/components/chart-zoom-core.tsx +0 -627
  379. package/src/components/chart-zoom.tsx +0 -22
  380. package/src/components/chart.tsx +0 -554
  381. package/src/components/checkbox-group.tsx +0 -247
  382. package/src/components/checkbox.tsx +0 -346
  383. package/src/components/chip-input.tsx +0 -370
  384. package/src/components/chip-labels.ts +0 -13
  385. package/src/components/chip.tsx +0 -843
  386. package/src/components/choice-card.tsx +0 -544
  387. package/src/components/column-mapper-labels.ts +0 -38
  388. package/src/components/column-mapper.tsx +0 -655
  389. package/src/components/combobox-core.tsx +0 -1321
  390. package/src/components/combobox-suggestions.tsx +0 -131
  391. package/src/components/combobox.tsx +0 -716
  392. package/src/components/confirm-context.ts +0 -7
  393. package/src/components/confirm-dialog-labels.ts +0 -13
  394. package/src/components/confirm-dialog.tsx +0 -341
  395. package/src/components/copy-button-labels.ts +0 -13
  396. package/src/components/copy-button.tsx +0 -192
  397. package/src/components/country-select-labels.ts +0 -11
  398. package/src/components/country-select.tsx +0 -539
  399. package/src/components/currency-option-list.tsx +0 -188
  400. package/src/components/currency-select.tsx +0 -343
  401. package/src/components/danger-confirm-labels.ts +0 -20
  402. package/src/components/danger-confirm.tsx +0 -987
  403. package/src/components/data-table-cells.tsx +0 -118
  404. package/src/components/data-table-column-settings.tsx +0 -198
  405. package/src/components/data-table-filter-popover.tsx +0 -289
  406. package/src/components/data-table-filters.ts +0 -315
  407. package/src/components/data-table-fit.ts +0 -301
  408. package/src/components/data-table-groups.tsx +0 -288
  409. package/src/components/data-table-head.tsx +0 -280
  410. package/src/components/data-table-labels.ts +0 -198
  411. package/src/components/data-table-leading-row.tsx +0 -58
  412. package/src/components/data-table-mobile.tsx +0 -1117
  413. package/src/components/data-table-pagination.tsx +0 -202
  414. package/src/components/data-table-resize.ts +0 -188
  415. package/src/components/data-table-row-actions.tsx +0 -302
  416. package/src/components/data-table-row.tsx +0 -496
  417. package/src/components/data-table-selection.ts +0 -71
  418. package/src/components/data-table-shared.tsx +0 -287
  419. package/src/components/data-table-sort.ts +0 -163
  420. package/src/components/data-table-virtual.ts +0 -576
  421. package/src/components/data-table.tsx +0 -2598
  422. package/src/components/date-field.tsx +0 -684
  423. package/src/components/date-format-setting.tsx +0 -64
  424. package/src/components/date-picker.tsx +0 -404
  425. package/src/components/date-range-picker.tsx +0 -518
  426. package/src/components/description-list-labels.ts +0 -9
  427. package/src/components/description-list.tsx +0 -386
  428. package/src/components/dialog-frame-labels.ts +0 -7
  429. package/src/components/dialog-frame.tsx +0 -284
  430. package/src/components/disclosure.tsx +0 -476
  431. package/src/components/dropdown.tsx +0 -461
  432. package/src/components/empty-state.tsx +0 -136
  433. package/src/components/entity-combobox.tsx +0 -422
  434. package/src/components/error-boundary-labels.ts +0 -20
  435. package/src/components/error-boundary.tsx +0 -675
  436. package/src/components/facing-pair.ts +0 -93
  437. package/src/components/field-base-labels.ts +0 -20
  438. package/src/components/field-base.tsx +0 -656
  439. package/src/components/field-parts.tsx +0 -825
  440. package/src/components/field-strip.tsx +0 -129
  441. package/src/components/field.tsx +0 -206
  442. package/src/components/file-button.tsx +0 -295
  443. package/src/components/file-dropzone.tsx +0 -559
  444. package/src/components/floating-panel-labels.ts +0 -10
  445. package/src/components/floating-panel.tsx +0 -828
  446. package/src/components/focus-ring.ts +0 -16
  447. package/src/components/form-actions-labels.ts +0 -11
  448. package/src/components/form-actions.tsx +0 -578
  449. package/src/components/full-bleed-dialog.tsx +0 -294
  450. package/src/components/grouped-picker.tsx +0 -184
  451. package/src/components/help-popover.tsx +0 -117
  452. package/src/components/hover-menu.tsx +0 -343
  453. package/src/components/iban-input-labels.ts +0 -14
  454. package/src/components/iban-input.tsx +0 -236
  455. package/src/components/icon-button.tsx +0 -959
  456. package/src/components/icon-picker-labels.ts +0 -13
  457. package/src/components/icon-picker.tsx +0 -232
  458. package/src/components/image-grid-labels.ts +0 -11
  459. package/src/components/image-grid.tsx +0 -202
  460. package/src/components/inline-confirm.tsx +0 -116
  461. package/src/components/inline-edit-field-labels.ts +0 -11
  462. package/src/components/inline-edit-field.tsx +0 -552
  463. package/src/components/inline-entity-combobox.tsx +0 -849
  464. package/src/components/input.tsx +0 -394
  465. package/src/components/jump-calendar.tsx +0 -265
  466. package/src/components/language-select.tsx +0 -93
  467. package/src/components/legal-labels.ts +0 -105
  468. package/src/components/legal-page.tsx +0 -711
  469. package/src/components/legal.tsx +0 -668
  470. package/src/components/lightbox-labels.ts +0 -18
  471. package/src/components/lightbox.tsx +0 -399
  472. package/src/components/line-items-labels.ts +0 -14
  473. package/src/components/line-items.tsx +0 -602
  474. package/src/components/list-labels.ts +0 -12
  475. package/src/components/list.tsx +0 -870
  476. package/src/components/loading-state.tsx +0 -78
  477. package/src/components/measured-grid-labels.ts +0 -25
  478. package/src/components/measured-grid.tsx +0 -837
  479. package/src/components/menu-item.tsx +0 -241
  480. package/src/components/mini-calendar-labels.ts +0 -17
  481. package/src/components/mini-calendar.tsx +0 -792
  482. package/src/components/modal.tsx +0 -534
  483. package/src/components/money-draft.ts +0 -83
  484. package/src/components/money-field.tsx +0 -76
  485. package/src/components/month-grid.tsx +0 -229
  486. package/src/components/month-picker-labels.ts +0 -22
  487. package/src/components/month-picker.tsx +0 -1087
  488. package/src/components/multi-entity-combobox.tsx +0 -369
  489. package/src/components/multi-select.tsx +0 -376
  490. package/src/components/nav-pills.tsx +0 -198
  491. package/src/components/number-field.tsx +0 -327
  492. package/src/components/number-input.tsx +0 -559
  493. package/src/components/numeric-field.ts +0 -169
  494. package/src/components/numpad-sheet.tsx +0 -285
  495. package/src/components/one-time-code-input.tsx +0 -270
  496. package/src/components/page-contents-labels.ts +0 -9
  497. package/src/components/page-contents.tsx +0 -282
  498. package/src/components/page-header-context.ts +0 -8
  499. package/src/components/page-header.tsx +0 -298
  500. package/src/components/password-strength-labels.ts +0 -22
  501. package/src/components/password-strength.tsx +0 -241
  502. package/src/components/phone-input-labels.ts +0 -10
  503. package/src/components/phone-input.tsx +0 -282
  504. package/src/components/picker-sheet.tsx +0 -330
  505. package/src/components/pie-chart-labels.ts +0 -40
  506. package/src/components/pie-chart.tsx +0 -480
  507. package/src/components/popover-labels.ts +0 -14
  508. package/src/components/popover.tsx +0 -268
  509. package/src/components/progress-bar-labels.ts +0 -10
  510. package/src/components/progress-bar.tsx +0 -479
  511. package/src/components/qr-code.tsx +0 -76
  512. package/src/components/reauth-dialog-labels.ts +0 -13
  513. package/src/components/reauth-dialog.tsx +0 -265
  514. package/src/components/row-actions-labels.ts +0 -12
  515. package/src/components/row-actions.tsx +0 -795
  516. package/src/components/scroll-area.tsx +0 -123
  517. package/src/components/search-field.tsx +0 -192
  518. package/src/components/select.tsx +0 -294
  519. package/src/components/separator.tsx +0 -33
  520. package/src/components/series-chart-axes.ts +0 -342
  521. package/src/components/series-chart-budget.ts +0 -150
  522. package/src/components/series-chart-labels.ts +0 -33
  523. package/src/components/series-chart-thin.ts +0 -180
  524. package/src/components/series-chart-ticks.ts +0 -194
  525. package/src/components/series-chart.tsx +0 -1906
  526. package/src/components/server-wake-labels.ts +0 -11
  527. package/src/components/server-wake.tsx +0 -129
  528. package/src/components/settings-fields.tsx +0 -237
  529. package/src/components/share-card-labels.ts +0 -30
  530. package/src/components/share-card.tsx +0 -675
  531. package/src/components/signature-pad-labels.ts +0 -24
  532. package/src/components/signature-pad.tsx +0 -747
  533. package/src/components/signed-amount-labels.ts +0 -10
  534. package/src/components/signed-amount.tsx +0 -336
  535. package/src/components/skeleton.tsx +0 -80
  536. package/src/components/slider.tsx +0 -338
  537. package/src/components/sparkline-labels.ts +0 -14
  538. package/src/components/sparkline.tsx +0 -322
  539. package/src/components/spinner.tsx +0 -81
  540. package/src/components/stat-tile-labels.ts +0 -15
  541. package/src/components/stat-tile.tsx +0 -754
  542. package/src/components/status-dot.tsx +0 -170
  543. package/src/components/swatch-picker-labels.ts +0 -10
  544. package/src/components/swatch-picker.tsx +0 -283
  545. package/src/components/swipeable-row.tsx +0 -386
  546. package/src/components/switch.tsx +0 -273
  547. package/src/components/table-skeleton.tsx +0 -136
  548. package/src/components/table.tsx +0 -647
  549. package/src/components/tabs-labels.ts +0 -13
  550. package/src/components/tabs.tsx +0 -693
  551. package/src/components/text-link.tsx +0 -359
  552. package/src/components/text.tsx +0 -150
  553. package/src/components/textarea.tsx +0 -330
  554. package/src/components/tile-radio.tsx +0 -332
  555. package/src/components/time-input.tsx +0 -121
  556. package/src/components/toast-labels.ts +0 -12
  557. package/src/components/toast.tsx +0 -519
  558. package/src/components/toggle-group.tsx +0 -752
  559. package/src/components/toggle-legend.tsx +0 -394
  560. package/src/components/tooltip.tsx +0 -1149
  561. package/src/components/translation-review-editor.tsx +0 -290
  562. package/src/components/translation-review-labels.ts +0 -181
  563. package/src/components/translation-review-parts.tsx +0 -272
  564. package/src/components/translation-review.tsx +0 -1240
  565. package/src/components/tree-view.tsx +0 -589
  566. package/src/components/treemap-labels.ts +0 -47
  567. package/src/components/treemap-layout.ts +0 -210
  568. package/src/components/treemap.tsx +0 -1184
  569. package/src/components/trigger-aria.ts +0 -44
  570. package/src/components/use-anchor-dir.ts +0 -20
  571. package/src/components/use-mobile-reveal.ts +0 -62
  572. package/src/components/use-table-state.ts +0 -753
  573. package/src/components/user-avatar.tsx +0 -116
  574. package/src/components/wizard-stepper.tsx +0 -42
  575. package/src/components/write-lock-labels.ts +0 -10
  576. package/src/components/write-lock.tsx +0 -253
  577. package/src/currencies.ts +0 -90
  578. package/src/data-table.ts +0 -42
  579. package/src/demo/demo-banner.tsx +0 -153
  580. package/src/demo/demo-countdown.ts +0 -136
  581. package/src/demo/demo-ended.tsx +0 -90
  582. package/src/demo/demo-labels.ts +0 -78
  583. package/src/demo/demo-session.ts +0 -32
  584. package/src/demo/demo-start.tsx +0 -156
  585. package/src/eslint/index.ts +0 -161
  586. package/src/eslint/role-utilities.generated.ts +0 -146
  587. package/src/eslint/role-utilities.ts +0 -233
  588. package/src/feedback/feedback-attachment-download.tsx +0 -77
  589. package/src/feedback/feedback-attachment-labels.ts +0 -37
  590. package/src/feedback/feedback-attachment.tsx +0 -1239
  591. package/src/feedback/feedback-capture.ts +0 -287
  592. package/src/feedback/feedback-comment-thread.tsx +0 -353
  593. package/src/feedback/feedback-context-labels.ts +0 -11
  594. package/src/feedback/feedback-context.tsx +0 -245
  595. package/src/feedback/feedback-crash.ts +0 -547
  596. package/src/feedback/feedback-diagnostics.tsx +0 -41
  597. package/src/feedback/feedback-dialog-labels.ts +0 -29
  598. package/src/feedback/feedback-dialog.tsx +0 -452
  599. package/src/feedback/feedback-entry-file.tsx +0 -150
  600. package/src/feedback/feedback-inbox.tsx +0 -552
  601. package/src/feedback/feedback-labels.ts +0 -144
  602. package/src/feedback/feedback-menu-labels.ts +0 -12
  603. package/src/feedback/feedback-menu.tsx +0 -177
  604. package/src/feedback/feedback-mutation.ts +0 -20
  605. package/src/feedback/feedback-page-link.ts +0 -90
  606. package/src/feedback/feedback-public-labels.ts +0 -81
  607. package/src/feedback/feedback-public-list.tsx +0 -524
  608. package/src/feedback/feedback-public-switch.tsx +0 -102
  609. package/src/feedback/feedback-public-types.ts +0 -101
  610. package/src/feedback/feedback-record.ts +0 -428
  611. package/src/feedback/feedback-replies-context.ts +0 -9
  612. package/src/feedback/feedback-replies.tsx +0 -343
  613. package/src/feedback/feedback-rework-entry-chip.tsx +0 -18
  614. package/src/feedback/feedback-row-detail-labels.ts +0 -31
  615. package/src/feedback/feedback-row-detail.tsx +0 -871
  616. package/src/feedback/feedback-status-undo.ts +0 -109
  617. package/src/feedback/feedback-submit-dialog.tsx +0 -131
  618. package/src/feedback/feedback-submit.tsx +0 -270
  619. package/src/feedback/feedback-swipe.tsx +0 -192
  620. package/src/feedback/feedback-table-labels.ts +0 -27
  621. package/src/feedback/feedback-table.tsx +0 -912
  622. package/src/feedback/feedback-thread-labels.ts +0 -22
  623. package/src/feedback/feedback-thread-parts-labels.ts +0 -41
  624. package/src/feedback/feedback-thread.tsx +0 -905
  625. package/src/feedback/feedback-vocabulary.ts +0 -263
  626. package/src/feedback/feedback-vote-button.tsx +0 -124
  627. package/src/feedback.ts +0 -116
  628. package/src/hooks/use-anchored-panel.ts +0 -396
  629. package/src/hooks/use-anchored-rect.ts +0 -77
  630. package/src/hooks/use-announce.ts +0 -85
  631. package/src/hooks/use-authed-src.ts +0 -167
  632. package/src/hooks/use-body-scroll-lock.ts +0 -119
  633. package/src/hooks/use-breakpoint.ts +0 -133
  634. package/src/hooks/use-close-transition.ts +0 -107
  635. package/src/hooks/use-copy-to-clipboard.ts +0 -122
  636. package/src/hooks/use-debounce.ts +0 -114
  637. package/src/hooks/use-dismiss.ts +0 -371
  638. package/src/hooks/use-document-title.ts +0 -33
  639. package/src/hooks/use-file-drop.ts +0 -121
  640. package/src/hooks/use-file-picker-labels.ts +0 -28
  641. package/src/hooks/use-file-picker.tsx +0 -359
  642. package/src/hooks/use-focus-trap.ts +0 -199
  643. package/src/hooks/use-hotkey.ts +0 -212
  644. package/src/hooks/use-large-text.ts +0 -41
  645. package/src/hooks/use-long-press.ts +0 -140
  646. package/src/hooks/use-media-query.ts +0 -39
  647. package/src/hooks/use-mounted.ts +0 -39
  648. package/src/hooks/use-noindex.ts +0 -37
  649. package/src/hooks/use-overlay-history.ts +0 -714
  650. package/src/hooks/use-row-swipe.ts +0 -207
  651. package/src/hooks/use-search-param-state.ts +0 -434
  652. package/src/hooks/use-windowed-rows.ts +0 -225
  653. package/src/i18n/defaults.ts +0 -267
  654. package/src/i18n/german.ts +0 -2059
  655. package/src/i18n/kit-labels.tsx +0 -1003
  656. package/src/i18n/languages.ts +0 -349
  657. package/src/i18n/locales/de-CH.ts +0 -24
  658. package/src/i18n/locales/en.ts +0 -267
  659. package/src/i18n/locales/es.ts +0 -1999
  660. package/src/i18n/locales/fr.ts +0 -2037
  661. package/src/i18n/locales/hu.ts +0 -2004
  662. package/src/i18n/locales/it.ts +0 -2014
  663. package/src/i18n/locales/zh.ts +0 -1912
  664. package/src/i18n/plurals.ts +0 -86
  665. package/src/i18n/review.ts +0 -475
  666. package/src/i18n/shared-labels.ts +0 -138
  667. package/src/i18n/swiss.ts +0 -29
  668. package/src/index.ts +0 -1191
  669. package/src/landing/access.ts +0 -93
  670. package/src/landing/landing-actions.tsx +0 -97
  671. package/src/landing/landing-labels.ts +0 -59
  672. package/src/landing/landing-sections.tsx +0 -341
  673. package/src/landing/page-seo.ts +0 -261
  674. package/src/landing/public-header.tsx +0 -121
  675. package/src/landing/public-page.tsx +0 -106
  676. package/src/landing/routing.tsx +0 -225
  677. package/src/lib/broadcast.ts +0 -52
  678. package/src/lib/calc.ts +0 -323
  679. package/src/lib/chip-edge-snap.ts +0 -212
  680. package/src/lib/clipboard-minus.ts +0 -107
  681. package/src/lib/clipping.ts +0 -34
  682. package/src/lib/cn.ts +0 -28
  683. package/src/lib/column-mapping.ts +0 -234
  684. package/src/lib/countries.ts +0 -91
  685. package/src/lib/data-attributes.ts +0 -14
  686. package/src/lib/date-format.ts +0 -227
  687. package/src/lib/dates.ts +0 -288
  688. package/src/lib/day-format.ts +0 -96
  689. package/src/lib/decimal-marks.ts +0 -108
  690. package/src/lib/describe-failure.ts +0 -18
  691. package/src/lib/device-settings.ts +0 -147
  692. package/src/lib/direction.ts +0 -74
  693. package/src/lib/document-navigation.ts +0 -17
  694. package/src/lib/document-title.ts +0 -41
  695. package/src/lib/download.ts +0 -172
  696. package/src/lib/float-clearance.ts +0 -70
  697. package/src/lib/floating-stack.ts +0 -70
  698. package/src/lib/focus-left.ts +0 -156
  699. package/src/lib/format.ts +0 -585
  700. package/src/lib/http-status.ts +0 -38
  701. package/src/lib/iban.ts +0 -251
  702. package/src/lib/ime.ts +0 -24
  703. package/src/lib/intl-cache.ts +0 -27
  704. package/src/lib/iso-day.ts +0 -13
  705. package/src/lib/lazy-with-fallback.ts +0 -82
  706. package/src/lib/logger.ts +0 -69
  707. package/src/lib/minus.ts +0 -50
  708. package/src/lib/path-pattern.ts +0 -55
  709. package/src/lib/person-name.ts +0 -155
  710. package/src/lib/phone.ts +0 -208
  711. package/src/lib/plain-text.ts +0 -22
  712. package/src/lib/presence.ts +0 -18
  713. package/src/lib/qr-encode.ts +0 -444
  714. package/src/lib/quiet-focus.ts +0 -32
  715. package/src/lib/reduced-motion.ts +0 -22
  716. package/src/lib/refs.ts +0 -22
  717. package/src/lib/round.ts +0 -43
  718. package/src/lib/safe-storage.ts +0 -119
  719. package/src/lib/server-wake.ts +0 -315
  720. package/src/lib/session-refresh.ts +0 -472
  721. package/src/lib/share-format.ts +0 -18
  722. package/src/lib/status-tone.ts +0 -43
  723. package/src/lib/strip-fade.ts +0 -287
  724. package/src/lib/table-text.ts +0 -554
  725. package/src/lib/text-case.ts +0 -19
  726. package/src/lib/text-match.ts +0 -169
  727. package/src/lib/thenable.ts +0 -19
  728. package/src/lib/translation-review.ts +0 -769
  729. package/src/notifications/device-zone-report.ts +0 -67
  730. package/src/notifications/feedback-notification-types-labels.ts +0 -33
  731. package/src/notifications/feedback-notification-types.ts +0 -71
  732. package/src/notifications/notification-bell.tsx +0 -119
  733. package/src/notifications/notification-inbox.tsx +0 -309
  734. package/src/notifications/notification-parts.tsx +0 -81
  735. package/src/notifications/notification-types-setting.tsx +0 -406
  736. package/src/notifications/notification-types.ts +0 -89
  737. package/src/notifications/notifications-labels.ts +0 -287
  738. package/src/notifications/push-device-setting.tsx +0 -230
  739. package/src/notifications/push-devices-setting.tsx +0 -374
  740. package/src/notifications/push-worker.ts +0 -168
  741. package/src/notifications/quiet-hours-setting.tsx +0 -238
  742. package/src/notifications/unsubscribe-panel.tsx +0 -200
  743. package/src/notifications/use-push-device.ts +0 -448
  744. package/src/offline/local-first.ts +0 -100
  745. package/src/offline/pwa-update-prompt-labels.ts +0 -9
  746. package/src/offline/pwa-update-prompt.tsx +0 -78
  747. package/src/offline/query-persistence.ts +0 -391
  748. package/src/offline/service-worker-updates.ts +0 -81
  749. package/src/offline/shared-computer-labels.ts +0 -8
  750. package/src/offline/shared-computer.tsx +0 -87
  751. package/src/offline/sign-out-pending-dialog-labels.ts +0 -21
  752. package/src/offline/sign-out-pending-dialog.tsx +0 -135
  753. package/src/offline.ts +0 -37
  754. package/src/push-worker.ts +0 -25
  755. package/src/rhf/fields.tsx +0 -2187
  756. package/src/rhf/form-core.tsx +0 -324
  757. package/src/rhf/form.tsx +0 -12
  758. package/src/rhf/line-items.tsx +0 -135
  759. package/src/rhf/use-rhf-wizard-step.ts +0 -104
  760. package/src/rhf.ts +0 -21
  761. package/src/search/command-palette-labels.ts +0 -16
  762. package/src/search/command-palette.tsx +0 -624
  763. package/src/search/global-search-labels.ts +0 -13
  764. package/src/search/global-search.tsx +0 -660
  765. package/src/search/search-index.ts +0 -283
  766. package/src/search/use-command-key.ts +0 -23
  767. package/src/search.ts +0 -14
  768. package/src/settings/device-reset-setting-labels.ts +0 -20
  769. package/src/settings/device-reset-setting.tsx +0 -116
  770. package/src/settings/settings-card-classes.ts +0 -11
  771. package/src/settings/settings-catalogue.ts +0 -150
  772. package/src/settings/settings-context.ts +0 -33
  773. package/src/settings/settings-heading.tsx +0 -67
  774. package/src/settings/settings-labels.ts +0 -87
  775. package/src/settings/settings-layout.tsx +0 -471
  776. package/src/settings/settings-section.tsx +0 -108
  777. package/src/settings/use-account-appearance.ts +0 -148
  778. package/src/settings/use-account-language.ts +0 -146
  779. package/src/settings/use-settings-focus.ts +0 -128
  780. package/src/settings/use-settings-route.ts +0 -258
  781. package/src/shell/account-menu-language.tsx +0 -130
  782. package/src/shell/account-menu-text-size.tsx +0 -80
  783. package/src/shell/admin-menu.tsx +0 -183
  784. package/src/shell/app-shell-labels.ts +0 -11
  785. package/src/shell/app-shell.tsx +0 -1560
  786. package/src/shell/auth-layout.tsx +0 -186
  787. package/src/shell/company-switcher-labels.ts +0 -13
  788. package/src/shell/company-switcher.tsx +0 -136
  789. package/src/shell/dev-menu.tsx +0 -257
  790. package/src/shell/fill-height.tsx +0 -45
  791. package/src/shell/language-code.ts +0 -5
  792. package/src/shell/option-switcher-menu.tsx +0 -84
  793. package/src/shell/sync-status-indicator.tsx +0 -303
  794. package/src/shell/top-bar-actions.tsx +0 -87
  795. package/src/shell/top-bar-brand.tsx +0 -78
  796. package/src/shell/top-bar-parts-labels.ts +0 -148
  797. package/src/shell/top-bar.tsx +0 -40
  798. package/src/shell/topbar-action-menu.tsx +0 -567
  799. package/src/shell/topbar-controls.tsx +0 -269
  800. package/src/shell/tour-menu.tsx +0 -187
  801. package/src/shell.ts +0 -108
  802. package/src/sync/db.ts +0 -129
  803. package/src/sync/engine.ts +0 -1011
  804. package/src/sync/hooks.ts +0 -98
  805. package/src/sync/testing.ts +0 -73
  806. package/src/sync/wire.ts +0 -61
  807. package/src/sync.ts +0 -37
  808. package/src/table-text.ts +0 -8
  809. package/src/testing/css-variables.generated.ts +0 -112
  810. package/src/testing/css-variables.ts +0 -189
  811. package/src/testing/index.ts +0 -29
  812. package/src/testing/react.ts +0 -58
  813. package/src/testing/tour.ts +0 -41
  814. package/src/testing/viewport.ts +0 -357
  815. package/src/theme/chart-palette.ts +0 -232
  816. package/src/theme/color.ts +0 -272
  817. package/src/theme/contrast-tokens.ts +0 -268
  818. package/src/theme/contrast.ts +0 -250
  819. package/src/theme/palette-derive.ts +0 -825
  820. package/src/theme/palette-presets.ts +0 -544
  821. package/src/theme/palette-store.ts +0 -108
  822. package/src/theme/text-size.ts +0 -289
  823. package/src/theme/theme-store.ts +0 -157
  824. package/src/tour/tour-catalogue-labels.ts +0 -75
  825. package/src/tour/tour-catalogue.tsx +0 -335
  826. package/src/tour/tour-dock.ts +0 -134
  827. package/src/tour/tour-engine.ts +0 -37
  828. package/src/tour/tour-gates.ts +0 -218
  829. package/src/tour/tour-guide-button.tsx +0 -64
  830. package/src/tour/tour-guide-labels.ts +0 -15
  831. package/src/tour/tour-info.ts +0 -144
  832. package/src/tour/tour-labels.ts +0 -23
  833. package/src/tour/tour-overlay.tsx +0 -1170
  834. package/src/tour/tour.tsx +0 -750
  835. package/src/tour/use-tour-progress.ts +0 -671
  836. package/src/tour/use-tour-url-sync.ts +0 -266
  837. package/src/tour.ts +0 -21
  838. package/src/vite-env.d.ts +0 -23
  839. package/src/wizard/stepper-nav.tsx +0 -360
  840. package/src/wizard/types.ts +0 -275
  841. package/src/wizard/use-wizard.ts +0 -560
  842. package/src/wizard/validation.ts +0 -39
  843. package/src/wizard/wizard-context.tsx +0 -74
  844. package/src/wizard/wizard-labels.ts +0 -29
  845. package/src/wizard/wizard-step.tsx +0 -76
  846. package/src/wizard/wizard-summary.tsx +0 -84
  847. package/src/wizard.ts +0 -15
@@ -0,0 +1,260 @@
1
+ import type { ReactNode } from "react";
2
+ import { type DataTableColumn, type DataTableProps } from "../components/data-table.js";
3
+ import type { CommitScope } from "../components/write-lock.js";
4
+ import type { AuthedFetcher } from "../hooks/use-authed-src.js";
5
+ import type { LabelOverride } from "../i18n/kit-labels.js";
6
+ import type { PathPattern } from "../landing/routing.js";
7
+ import type { FeedbackRecord } from "./feedback-record.js";
8
+ import { type FeedbackDetailPatch, type FeedbackRowDetailProps, type FeedbackUpload } from "./feedback-row-detail.js";
9
+ import { type FeedbackStatusChange } from "./feedback-status-undo.js";
10
+ import { type FeedbackSwipeBinding } from "./feedback-swipe.js";
11
+ import { type FeedbackPageLabels, type FeedbackRenderDate } from "./feedback-table.js";
12
+ import type { FeedbackStatus } from "./feedback-vocabulary.js";
13
+ /**
14
+ * The feedback inbox, ASSEMBLED ONCE (0.55; kastlan reuse audit 2026-11-02, proposal 2;
15
+ * docs/feedback-harmonization.md §13).
16
+ *
17
+ * Since 0.27 every part of `/feedback` and `/my-feedback` has been the kit's — the columns,
18
+ * the phone card and its day headers, the detail, the Undo, the swipes, the awaiting toggle
19
+ * (feedback-table.tsx, feedback-row-detail.tsx, feedback-swipe.tsx). What was not the kit's
20
+ * was the WIRING between them, and each app wrote the same ~150 lines of it:
21
+ * kastlan `frontend/src/features/feedback/pages/feedback-page.tsx:40-205`, keksdose
22
+ * `frontend/src/features/feedback/feedback-page.tsx:51-303`, Kurvenschmiede
23
+ * `frontend/src/features/feedback/feedback-page.tsx:88-245`. The open row in `?row=` with
24
+ * its numeric parse and its `rowHref`, `useFeedbackStatusUndo` over the page's PATCH, the
25
+ * `DataTable` with a dozen props, `FeedbackRowDetail` with a dozen more, the phone's
26
+ * grouping, card and swipe plan, the awaiting filter and its toggle. So every rename the
27
+ * parts took (0.52's `mutateAsync`, 0.53's removals) was made three times, and three
28
+ * times reviewed.
29
+ *
30
+ * Here that wiring is the kit's: {@link useFeedbackInbox} holds it and returns what the
31
+ * table, the detail and the phone cards need; {@link FeedbackInbox} draws the page from
32
+ * it. What stays the app's is what differs between the three, each a slot: where the rows
33
+ * come from and the three mutations (its API client, TanStack Query in all three — the kit
34
+ * sends no request), who may triage, the votes, the public switch, the comments (the app's
35
+ * `FeedbackCommentThread` over its own queries), its own columns, its swipe binding, its
36
+ * date writer, the page's header and frame, and whatever else `DataTable` takes.
37
+ *
38
+ * Additive: every part it is built from stays exported and unchanged, for a page that
39
+ * wants its own layout — call the hook and spread `inbox.table` into a `DataTable`.
40
+ */
41
+ /**
42
+ * One of the page's mutations, as the inbox calls it: **TanStack Query's `useMutation`
43
+ * result, passed as it is** — `update={update}`. The inbox reads `mutateAsync` (whose
44
+ * promise settles for every call, refactor audit 2026-10-30 FLW-3) and `isPending`, and
45
+ * nothing else. Any object with those two fits, so a page on another data layer hands
46
+ * `{ mutateAsync: api.update, isPending }`.
47
+ *
48
+ * Taking the mutation rather than a callback per control is the point of the round: how
49
+ * the parts call it (0.52 moved them from `mutate` to `mutateAsync`) is then the kit's to
50
+ * change, once. Failure is the mutation's own: its `onError` toasts the server's sentence
51
+ * (§4.4), and the inbox catches the rejection.
52
+ */
53
+ export interface FeedbackInboxMutation<V> {
54
+ mutateAsync: (variables: V) => Promise<unknown>;
55
+ /** In flight: the editors' and the composer's buttons wait for it. */
56
+ isPending?: boolean;
57
+ }
58
+ /** What the reply mutation is sent: `POST /feedback/{id}/replies` (§9.7, §12) — the
59
+ * body, the status picked (absent: "No change") and the uploaded file's URL (absent:
60
+ * none). Keys that carry nothing are left out, so a `mutationFn` may spread them onto
61
+ * the wire. kastlan's `useFeedbackReply` takes exactly this. */
62
+ export interface FeedbackReplyPost {
63
+ id: number;
64
+ body: string;
65
+ status?: FeedbackStatus;
66
+ attachmentUrl?: string;
67
+ }
68
+ /** What the rework mutation is sent: `POST /feedback/{id}/rework` (§10.3) — the author's
69
+ * trimmed note and the uploaded file's URL (absent: none). kastlan's `useFeedbackRework`
70
+ * takes exactly this. */
71
+ export interface FeedbackReworkPost {
72
+ id: number;
73
+ note: string;
74
+ attachmentUrl?: string;
75
+ }
76
+ export interface UseFeedbackInboxOptions<T extends FeedbackRecord> {
77
+ /** The list as the app's query answered it (`GET /feedback`, `GET /feedback/my`) —
78
+ * `list.data ?? []`. Shown newest first and, behind the awaiting toggle, narrowed. */
79
+ rows: readonly T[];
80
+ /** `/my-feedback`: the viewer's own reports — no triage there, for an admin too (§4.3). */
81
+ mine?: boolean;
82
+ /** The viewer may triage: the admin. Only on the inbox — `mine` wins — so `isAdmin`
83
+ * is enough. The status cell, the pills, the reply composer, the swipes, the submitter
84
+ * on the card and the awaiting toggle. */
85
+ canEdit: boolean;
86
+ /** The signed-in user's id: who the AUTHOR is (the description editor, Rework, the
87
+ * public switch's window). */
88
+ viewerId?: number | null;
89
+ /**
90
+ * `PATCH /feedback/{id}` (§3.4): every edit of the report itself — a status change from
91
+ * the cell, the pills or a swipe (with the Undo, `useFeedbackStatusUndo`), the
92
+ * description, the legacy rework append and, with {@link publicSwitch}, the flip. ONE
93
+ * mutation for all of them, the page's, so its observer outlives a row a status filter
94
+ * removes (§4.5).
95
+ */
96
+ update: FeedbackInboxMutation<FeedbackDetailPatch>;
97
+ /** `POST /feedback/{id}/replies` — the admin's answer (§9.7) with its one file (§12).
98
+ * Without it no composer is drawn. */
99
+ reply?: FeedbackInboxMutation<FeedbackReplyPost>;
100
+ /** `POST /feedback/{id}/rework` — the author's rework entry (§10.3). Without it a rework
101
+ * goes through {@link update} as the legacy body append (§3.4). */
102
+ rework?: FeedbackInboxMutation<FeedbackReworkPost>;
103
+ /**
104
+ * The **Visible to others** switch in the detail (§9.3), its flip sent through
105
+ * {@link update} as `{ id, public }` — as keksdose and Kurvenschmiede send it. Off by
106
+ * default: an app without public parts (kastlan) has no switch.
107
+ */
108
+ publicSwitch?: boolean;
109
+ /** The **Votes** column and the card's count (§9.6). Off by default (kastlan); keksdose
110
+ * always, Kurvenschmiede for a reader of the public parts. */
111
+ votes?: boolean;
112
+ /**
113
+ * The report's comments, in a section of their own under the replies (§9.8): the app's
114
+ * `FeedbackCommentThread` over its own queries — a component of its own, since its
115
+ * queries are hooks. Return `null` for a row without a thread (a CRASH, a reader who
116
+ * does not see the public parts; `false` is read as `null`). Called only for the open
117
+ * row.
118
+ *
119
+ * ```tsx
120
+ * comments={(row) => <RowComments id={row.id} isAdmin={isAdmin} canComment={!canEdit} />}
121
+ * ```
122
+ */
123
+ comments?: (row: T) => ReactNode;
124
+ /** The detail as drawn, to wrap or extend — kastlan's tour anchor:
125
+ * `(row, detail) => <div data-tour="feedback-row-detail">{detail}</div>`. */
126
+ renderDetail?: (row: T, detail: ReactNode) => ReactNode;
127
+ /**
128
+ * The app's own columns over the kit's (§4.3's nine, and Votes): add, drop, reorder —
129
+ * the keys are stable (`columns.filter((c) => c.key !== "email")`). A column brings its
130
+ * filter with it. Keep it stable (module scope or `useCallback`): it is a memo's
131
+ * dependency.
132
+ */
133
+ columns?: (columns: readonly DataTableColumn<T>[]) => readonly DataTableColumn<T>[];
134
+ /** Which swipe does what on the phone (§4.5) — keksdose's Settings → Interaction binding,
135
+ * `{ end: prefs.right, start: prefs.left }`. Default `DEFAULT_FEEDBACK_SWIPE`. */
136
+ swipe?: FeedbackSwipeBinding;
137
+ /** The status writes the TABLE offers — the status cell and the desktop's actions
138
+ * column — commit: under a locked `WriteLockProvider` they stay and say why
139
+ * (`FeedbackStatusTransitions`' `commit`). Off by default. The detail's own saves:
140
+ * `detail={{ commit }}`. */
141
+ commit?: CommitScope;
142
+ /** `POST /feedback/attachments` (§3.3): the rework's file and the reply's. */
143
+ onUpload?: FeedbackUpload;
144
+ /** The app's authenticated GET for the pictures and the downloads (§3.5). */
145
+ fetcher?: AuthedFetcher | null;
146
+ /** "Capture screenshot" beside the rework's and the reply's file field. Default: the
147
+ * kit's `captureAppScreenshot()`; `null` for no button. */
148
+ onCaptureScreenshot?: (() => Promise<File | null>) | null;
149
+ /**
150
+ * The app's date writer (keksdose's `useDateCell()`, the date-format setting): the date
151
+ * and resolved columns, the card, the phone's day headers AND the detail's "Resolved:",
152
+ * so all five say the same. Left out, the kit's date with the weekday in the table and
153
+ * on the phone, and in the detail its sentence date — as the parts draw them alone.
154
+ */
155
+ renderDate?: FeedbackRenderDate;
156
+ /** The app's one-shot routes, on top of the kit's (0.52, FLW-7) — for the URL column and
157
+ * the detail's URL section alike. Keep it stable (module scope). */
158
+ pageLinkExclude?: readonly PathPattern[];
159
+ /** The list is still loading (`list.isPending`): the table says "Loading…" where its
160
+ * rows will be, not "None". */
161
+ loading?: boolean;
162
+ /** Over the detail's props the inbox sets — `commit`, `showSubject`,
163
+ * `reworkAttachment`, `replyAttachments` (on here), `labels`, `className`. Merged last,
164
+ * so it wins. */
165
+ detail?: Partial<Omit<FeedbackRowDetailProps, "row">>;
166
+ /** Over the `feedbackPage` namespace: the columns, the card, the empty state, the toggle
167
+ * and the title. Keep it stable: it is a memo's dependency. */
168
+ labels?: LabelOverride<FeedbackPageLabels>;
169
+ }
170
+ /** What {@link useFeedbackInbox} returns: the state, and the props of the parts. */
171
+ export interface FeedbackInboxState<T extends FeedbackRecord> {
172
+ /** `canEdit && !mine`: the admin on the inbox. */
173
+ editable: boolean;
174
+ /** The page's title, `feedbackPage.title` — or `.myTitle` on `/my-feedback`. */
175
+ title: string;
176
+ /** The open row's id, from `?row=`; `null` when none is open or the param named no
177
+ * id (`?row=abc`, `?row=1.5`, `?row=0`). */
178
+ openId: number | null;
179
+ /** Open a row by its id, or close it with `null`: rewrites `?row=`, replacing the
180
+ * history entry rather than stacking one per report looked at. */
181
+ setOpenId: (id: number | null) => void;
182
+ /** A row's own address: this view — the table's page, sort and filters — with the row
183
+ * open. The row's link (a new tab, a copied address); a plain click opens it in place. */
184
+ rowHref: (row: T) => string;
185
+ /** The undoable status change (§4.5): the status cell's, the pills', the swipes'. */
186
+ changeStatus: FeedbackStatusChange;
187
+ /** The phone's "Only what is waiting for you" — page state, not the URL (§4.3). */
188
+ awaiting: boolean;
189
+ setAwaiting: (next: boolean) => void;
190
+ /** The one date writer the columns, the card and the day headers use. */
191
+ renderDate: FeedbackRenderDate;
192
+ /** `FeedbackRowDetail`'s props for a row, slots included. */
193
+ detailProps: (row: T) => FeedbackRowDetailProps;
194
+ /** `DataTable`'s props, ready to spread: the rows (newest first, narrowed by
195
+ * `awaiting`), the columns, the open row, the detail, the phone's card, day headers and
196
+ * swipes, the desktop's actions column, the empty state, `urlSync`,
197
+ * `storageKey="feedback"`, `fillHeight`. */
198
+ table: DataTableProps<T>;
199
+ }
200
+ /**
201
+ * The inbox's wiring, once (§13): from the app's rows and mutations to what the table,
202
+ * the detail and the phone cards take.
203
+ *
204
+ * ```tsx
205
+ * const list = useQuery({ queryKey: keys.feedback.all, queryFn: api.listFeedback });
206
+ * const update = useMutation({ mutationFn: ({ id, ...patch }: FeedbackDetailPatch) => api.update(id, patch), … });
207
+ * const inbox = useFeedbackInbox({ rows: list.data ?? [], canEdit: isAdmin, viewerId: user?.id, update });
208
+ * <DataTable {...inbox.table} edgeFade />
209
+ * ```
210
+ *
211
+ * {@link FeedbackInbox} is this hook drawn — use the hook alone for a layout of your own.
212
+ * Needs a react-router Router (`?row=`, `urlSync`).
213
+ */
214
+ export declare function useFeedbackInbox<T extends FeedbackRecord>({ rows, mine, canEdit, viewerId, update, reply, rework, publicSwitch, votes, comments, renderDetail, columns: ownColumns, swipe, commit, onUpload, fetcher, onCaptureScreenshot, renderDate: renderDateProp, pageLinkExclude, loading, detail, labels, }: UseFeedbackInboxOptions<T>): FeedbackInboxState<T>;
215
+ export interface FeedbackInboxProps<T extends FeedbackRecord> extends UseFeedbackInboxOptions<T> {
216
+ /**
217
+ * Above the table. Default: `<PageHeader title={title} className="mb-4 md:shrink-0" />`.
218
+ * A function gets the page's title (`feedbackPage.title` / `.myTitle`) — the app's own
219
+ * header: `(title) => <PageHeader size="compact" title={title} data-tour="feedback-header" />`.
220
+ * `null` for none.
221
+ */
222
+ header?: ReactNode | ((title: string) => ReactNode);
223
+ /** Over the inbox's `DataTable` props — `edgeFade`, `locale`, `mobileExpandAsDialog`,
224
+ * `className`, another `storageKey`. Merged last, so it wins. */
225
+ table?: Partial<DataTableProps<T>>;
226
+ /** Further `FloatingAction`s on the phone: after the awaiting toggle on the inbox, in a
227
+ * group of their own on `/my-feedback`. */
228
+ phoneActions?: ReactNode;
229
+ /** On the page's frame — the fill-height column (`FILL_HEIGHT_CLASS`); the app's page
230
+ * padding goes here. */
231
+ className?: string;
232
+ }
233
+ /**
234
+ * The feedback inbox (§13): `/feedback` and `/my-feedback` drawn whole from
235
+ * {@link useFeedbackInbox} — the header, the table with its detail, phone cards and swipes,
236
+ * and the phone's awaiting toggle, in the fill-height frame (page layout §1.3) — so a page
237
+ * is its queries and this:
238
+ *
239
+ * ```tsx
240
+ * export function FeedbackPage({ mine = false }: { mine?: boolean }) {
241
+ * const { user, isAdmin } = useAuth();
242
+ * const list = useQuery({ queryKey: mine ? keys.mine : keys.all, queryFn: mine ? api.mine : api.all });
243
+ * const update = useFeedbackUpdate();
244
+ * const reply = useFeedbackReply();
245
+ * const rework = useFeedbackRework();
246
+ * if (!mine && !isAdmin) return <Navigate to="/my-feedback" replace />;
247
+ * return (
248
+ * <FeedbackInbox
249
+ * rows={list.data ?? []} loading={list.isPending} mine={mine} canEdit={isAdmin} viewerId={user?.id}
250
+ * update={update} reply={reply} rework={rework}
251
+ * onUpload={api.upload} fetcher={api.file}
252
+ * />
253
+ * );
254
+ * }
255
+ * ```
256
+ *
257
+ * Every slot is {@link UseFeedbackInboxOptions}' or one of the four below. The redirect of
258
+ * a non-admin, the routes and the queries stay the app's.
259
+ */
260
+ export declare function FeedbackInbox<T extends FeedbackRecord>({ header, table, phoneActions, className, ...options }: FeedbackInboxProps<T>): import("react").JSX.Element;
@@ -0,0 +1,207 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useMemo, useState } from "react";
4
+ import { useHref, useLocation } from "react-router";
5
+ import { cn } from "../lib/cn.js";
6
+ import { DataTable } from "../components/data-table.js";
7
+ import { FloatingActionGroup } from "../components/floating-panel.js";
8
+ import { LoadingState } from "../components/loading-state.js";
9
+ import { PageHeader } from "../components/page-header.js";
10
+ import { useSearchParamState } from "../hooks/use-search-param-state.js";
11
+ import { FILL_HEIGHT_CLASS } from "../shell/fill-height.js";
12
+ import { captureAppScreenshot } from "./feedback-capture.js";
13
+ import { useFeedbackStatusLabels } from "./feedback-labels.js";
14
+ import { runMutation } from "./feedback-mutation.js";
15
+ import {
16
+ FeedbackRowDetail
17
+ } from "./feedback-row-detail.js";
18
+ import { useFeedbackStatusUndo } from "./feedback-status-undo.js";
19
+ import {
20
+ DEFAULT_FEEDBACK_SWIPE,
21
+ feedbackSwipeOmitShown,
22
+ feedbackSwipePlan
23
+ } from "./feedback-swipe.js";
24
+ import {
25
+ FeedbackAwaitingToggle,
26
+ FeedbackEmptyState,
27
+ FeedbackMobileCard,
28
+ feedbackMobileGroupBy,
29
+ isFeedbackAwaiting,
30
+ useFeedbackColumns,
31
+ useFeedbackPageLabels,
32
+ useFeedbackRenderDate
33
+ } from "./feedback-table.js";
34
+ function parseRowId(raw) {
35
+ if (!/^[1-9]\d*$/.test(raw)) return void 0;
36
+ const id = Number(raw);
37
+ return Number.isSafeInteger(id) ? id : void 0;
38
+ }
39
+ const ROW_PARAM = { parse: parseRowId, history: "replace" };
40
+ const newestFirst = (a, b) => a.created_at < b.created_at ? 1 : a.created_at > b.created_at ? -1 : 0;
41
+ const rowId = (row) => row.id;
42
+ const rowTitle = (row) => row.title;
43
+ const captureScreenshot = () => captureAppScreenshot();
44
+ const ignore = () => {
45
+ };
46
+ const threadOf = (node) => node === false || node === "" ? void 0 : node;
47
+ function useFeedbackInbox({
48
+ rows,
49
+ mine = false,
50
+ canEdit,
51
+ viewerId,
52
+ update,
53
+ reply,
54
+ rework,
55
+ publicSwitch = false,
56
+ votes = false,
57
+ comments,
58
+ renderDetail,
59
+ columns: ownColumns,
60
+ swipe = DEFAULT_FEEDBACK_SWIPE,
61
+ commit,
62
+ onUpload,
63
+ fetcher,
64
+ onCaptureScreenshot = captureScreenshot,
65
+ renderDate: renderDateProp,
66
+ pageLinkExclude,
67
+ loading = false,
68
+ detail,
69
+ labels
70
+ }) {
71
+ const editable = canEdit && !mine;
72
+ const pageLabels = useFeedbackPageLabels(labels);
73
+ const statusLabels = useFeedbackStatusLabels();
74
+ const renderDate = useFeedbackRenderDate(renderDateProp);
75
+ const updateAsync = update.mutateAsync;
76
+ const changeStatus = useFeedbackStatusUndo(updateAsync);
77
+ const [openId, setOpenId] = useSearchParamState("row", null, ROW_PARAM);
78
+ const { pathname, search } = useLocation();
79
+ const here = useHref({ pathname });
80
+ const rowHref = useCallback(
81
+ (row) => {
82
+ const params = new URLSearchParams(search);
83
+ params.set("row", String(row.id));
84
+ return `${here}?${params.toString()}`;
85
+ },
86
+ [here, search]
87
+ );
88
+ const [awaiting, setAwaiting] = useState(false);
89
+ const shown = useMemo(
90
+ () => (editable && awaiting ? rows.filter((row) => isFeedbackAwaiting(row.status)) : [...rows]).sort(newestFirst),
91
+ [rows, editable, awaiting]
92
+ );
93
+ const kitColumns = useFeedbackColumns({
94
+ mine,
95
+ canEdit,
96
+ onStatus: changeStatus,
97
+ renderDate,
98
+ commit,
99
+ votes,
100
+ pageLinkExclude,
101
+ labels
102
+ });
103
+ const columns = useMemo(() => ownColumns ? ownColumns(kitColumns) : kitColumns, [ownColumns, kitColumns]);
104
+ const mobileGroupBy = useMemo(() => feedbackMobileGroupBy(renderDate), [renderDate]);
105
+ const pending = Boolean(update.isPending || rework?.isPending);
106
+ const capture = onCaptureScreenshot ?? void 0;
107
+ const detailProps = (row) => ({
108
+ row,
109
+ canEdit: editable,
110
+ viewerId,
111
+ onUpdate: updateAsync,
112
+ pending,
113
+ // The page's change, not one the detail would build: the same Undo as the cell's.
114
+ statusChange: changeStatus,
115
+ onUpload,
116
+ fetcher,
117
+ onCaptureScreenshot: capture,
118
+ // Only the app's own: left out, the detail's "Resolved:" is the kit's sentence date,
119
+ // no weekday — as kastlan's has always been.
120
+ renderDate: renderDateProp,
121
+ pageLinkExclude,
122
+ onReply: reply ? (body, status, attachmentUrl) => reply.mutateAsync({
123
+ id: row.id,
124
+ body,
125
+ ...status ? { status } : {},
126
+ ...attachmentUrl ? { attachmentUrl } : {}
127
+ }) : void 0,
128
+ // The reply's one file (§12): all three apps are on server-kit 0.18, and the reply
129
+ // mutation's `attachmentUrl` is in its type from the start (the B1 risk the detail's
130
+ // default guards against — an `onReply` that drops the file — cannot arise here).
131
+ replyAttachments: true,
132
+ replying: reply?.isPending ?? false,
133
+ onRework: rework ? (note, attachmentUrl) => rework.mutateAsync({ id: row.id, note, ...attachmentUrl ? { attachmentUrl } : {} }) : void 0,
134
+ comments: threadOf(comments?.(row)),
135
+ onPublicChange: publicSwitch ? (next) => runMutation(updateAsync, { id: row.id, public: next }, ignore) : void 0,
136
+ ...detail
137
+ });
138
+ const table = {
139
+ rows: shown,
140
+ columns,
141
+ rowKey: rowId,
142
+ storageKey: "feedback",
143
+ urlSync: true,
144
+ fillHeight: true,
145
+ rowHref,
146
+ // The link covers the row's first cell; a click anywhere on the row opens it — or,
147
+ // on the open one, closes it.
148
+ onRowClick: (row) => setOpenId((id) => id === row.id ? null : row.id),
149
+ isExpanded: (row) => row.id === openId,
150
+ expandedRow: (row) => {
151
+ const node = /* @__PURE__ */ jsx(FeedbackRowDetail, { ...detailProps(row) });
152
+ return renderDetail ? renderDetail(row, node) : node;
153
+ },
154
+ // §7.13: one word, also when a filter or the toggle leaves nothing; and while the
155
+ // first answer is out, what is happening instead.
156
+ empty: loading ? /* @__PURE__ */ jsx(LoadingState, { size: "sm", inline: true }) : /* @__PURE__ */ jsx(FeedbackEmptyState, { labels }),
157
+ mobileGroupBy,
158
+ mobileCard: (row) => /* @__PURE__ */ jsx(FeedbackMobileCard, { row, showSubmitter: editable, renderDate, votes, labels }),
159
+ // The admin inbox only — /my-feedback is read-only by design (keksdose #331) — and
160
+ // every swipe through the same Undo as a tap (§4.5, §7.10).
161
+ mobileSwipeActions: editable ? (row) => feedbackSwipePlan(swipe, row, { change: changeStatus, labels: statusLabels }) : void 0,
162
+ // The swipes as the desktop's last column (0.46, keksdose dev#598), less what the
163
+ // status cell already offers.
164
+ desktopSwipeActions: { omit: feedbackSwipeOmitShown, name: rowTitle, ...commit === void 0 ? {} : { commit } }
165
+ };
166
+ return {
167
+ editable,
168
+ title: mine ? pageLabels.myTitle : pageLabels.title,
169
+ openId,
170
+ setOpenId,
171
+ rowHref,
172
+ changeStatus,
173
+ awaiting,
174
+ setAwaiting,
175
+ renderDate,
176
+ detailProps,
177
+ table
178
+ };
179
+ }
180
+ function FeedbackInbox({
181
+ header,
182
+ table,
183
+ phoneActions,
184
+ className,
185
+ ...options
186
+ }) {
187
+ const inbox = useFeedbackInbox(options);
188
+ const pageLabels = useFeedbackPageLabels(options.labels);
189
+ const head = header === void 0 ? /* @__PURE__ */ jsx(PageHeader, { title: inbox.title, className: "mb-4 md:shrink-0" }) : typeof header === "function" ? header(inbox.title) : header;
190
+ return (
191
+ // A plain element on the way to the table carries the fill (page layout §1.3).
192
+ /* @__PURE__ */ jsxs("div", { className: cn(FILL_HEIGHT_CLASS, className), "aria-busy": options.loading || void 0, "data-feedback-inbox": "", children: [
193
+ head,
194
+ /* @__PURE__ */ jsx(DataTable, { ...inbox.table, ...table }),
195
+ inbox.editable ? (
196
+ // The phone's floating action (keksdose feedback #58): only on the inbox — on
197
+ // /my-feedback the author is not waiting on their own verdict.
198
+ /* @__PURE__ */ jsx(FeedbackAwaitingToggle, { pressed: inbox.awaiting, onPressedChange: inbox.setAwaiting, labels: options.labels, children: phoneActions })
199
+ ) : phoneActions && /* @__PURE__ */ jsx(FloatingActionGroup, { "aria-label": pageLabels.phoneActions, className: "md:hidden", children: phoneActions })
200
+ ] })
201
+ );
202
+ }
203
+ export {
204
+ FeedbackInbox,
205
+ useFeedbackInbox
206
+ };
207
+ //# sourceMappingURL=feedback-inbox-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/feedback/feedback-inbox-page.tsx"],"sourcesContent":["import { useCallback, useMemo, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useHref, useLocation } from \"react-router\";\nimport { cn } from \"../lib/cn\";\nimport { DataTable, type DataTableColumn, type DataTableProps } from \"../components/data-table\";\nimport { FloatingActionGroup } from \"../components/floating-panel\";\nimport { LoadingState } from \"../components/loading-state\";\nimport { PageHeader } from \"../components/page-header\";\nimport type { CommitScope } from \"../components/write-lock\";\nimport type { AuthedFetcher } from \"../hooks/use-authed-src\";\nimport { useSearchParamState } from \"../hooks/use-search-param-state\";\nimport type { LabelOverride } from \"../i18n/kit-labels\";\nimport type { PathPattern } from \"../landing/routing\";\nimport { FILL_HEIGHT_CLASS } from \"../shell/fill-height\";\nimport { captureAppScreenshot } from \"./feedback-capture\";\nimport { useFeedbackStatusLabels } from \"./feedback-labels\";\nimport { runMutation } from \"./feedback-mutation\";\nimport type { FeedbackRecord } from \"./feedback-record\";\nimport {\n FeedbackRowDetail,\n type FeedbackDetailPatch,\n type FeedbackRowDetailProps,\n type FeedbackUpload,\n} from \"./feedback-row-detail\";\nimport { useFeedbackStatusUndo, type FeedbackStatusChange } from \"./feedback-status-undo\";\nimport {\n DEFAULT_FEEDBACK_SWIPE,\n feedbackSwipeOmitShown,\n feedbackSwipePlan,\n type FeedbackSwipeBinding,\n} from \"./feedback-swipe\";\nimport {\n FeedbackAwaitingToggle,\n FeedbackEmptyState,\n FeedbackMobileCard,\n feedbackMobileGroupBy,\n isFeedbackAwaiting,\n useFeedbackColumns,\n useFeedbackPageLabels,\n useFeedbackRenderDate,\n type FeedbackPageLabels,\n type FeedbackRenderDate,\n} from \"./feedback-table\";\nimport type { FeedbackStatus } from \"./feedback-vocabulary\";\n\n/**\n * The feedback inbox, ASSEMBLED ONCE (0.55; kastlan reuse audit 2026-11-02, proposal 2;\n * docs/feedback-harmonization.md §13).\n *\n * Since 0.27 every part of `/feedback` and `/my-feedback` has been the kit's — the columns,\n * the phone card and its day headers, the detail, the Undo, the swipes, the awaiting toggle\n * (feedback-table.tsx, feedback-row-detail.tsx, feedback-swipe.tsx). What was not the kit's\n * was the WIRING between them, and each app wrote the same ~150 lines of it:\n * kastlan `frontend/src/features/feedback/pages/feedback-page.tsx:40-205`, keksdose\n * `frontend/src/features/feedback/feedback-page.tsx:51-303`, Kurvenschmiede\n * `frontend/src/features/feedback/feedback-page.tsx:88-245`. The open row in `?row=` with\n * its numeric parse and its `rowHref`, `useFeedbackStatusUndo` over the page's PATCH, the\n * `DataTable` with a dozen props, `FeedbackRowDetail` with a dozen more, the phone's\n * grouping, card and swipe plan, the awaiting filter and its toggle. So every rename the\n * parts took (0.52's `mutateAsync`, 0.53's removals) was made three times, and three\n * times reviewed.\n *\n * Here that wiring is the kit's: {@link useFeedbackInbox} holds it and returns what the\n * table, the detail and the phone cards need; {@link FeedbackInbox} draws the page from\n * it. What stays the app's is what differs between the three, each a slot: where the rows\n * come from and the three mutations (its API client, TanStack Query in all three — the kit\n * sends no request), who may triage, the votes, the public switch, the comments (the app's\n * `FeedbackCommentThread` over its own queries), its own columns, its swipe binding, its\n * date writer, the page's header and frame, and whatever else `DataTable` takes.\n *\n * Additive: every part it is built from stays exported and unchanged, for a page that\n * wants its own layout — call the hook and spread `inbox.table` into a `DataTable`.\n */\n\n/* ── The mutations ──────────────────────────────────────────────────────────── */\n\n/**\n * One of the page's mutations, as the inbox calls it: **TanStack Query's `useMutation`\n * result, passed as it is** — `update={update}`. The inbox reads `mutateAsync` (whose\n * promise settles for every call, refactor audit 2026-10-30 FLW-3) and `isPending`, and\n * nothing else. Any object with those two fits, so a page on another data layer hands\n * `{ mutateAsync: api.update, isPending }`.\n *\n * Taking the mutation rather than a callback per control is the point of the round: how\n * the parts call it (0.52 moved them from `mutate` to `mutateAsync`) is then the kit's to\n * change, once. Failure is the mutation's own: its `onError` toasts the server's sentence\n * (§4.4), and the inbox catches the rejection.\n */\nexport interface FeedbackInboxMutation<V> {\n mutateAsync: (variables: V) => Promise<unknown>;\n /** In flight: the editors' and the composer's buttons wait for it. */\n isPending?: boolean;\n}\n\n/** What the reply mutation is sent: `POST /feedback/{id}/replies` (§9.7, §12) — the\n * body, the status picked (absent: \"No change\") and the uploaded file's URL (absent:\n * none). Keys that carry nothing are left out, so a `mutationFn` may spread them onto\n * the wire. kastlan's `useFeedbackReply` takes exactly this. */\nexport interface FeedbackReplyPost {\n id: number;\n body: string;\n status?: FeedbackStatus;\n attachmentUrl?: string;\n}\n\n/** What the rework mutation is sent: `POST /feedback/{id}/rework` (§10.3) — the author's\n * trimmed note and the uploaded file's URL (absent: none). kastlan's `useFeedbackRework`\n * takes exactly this. */\nexport interface FeedbackReworkPost {\n id: number;\n note: string;\n attachmentUrl?: string;\n}\n\n/* ── The hook ───────────────────────────────────────────────────────────────── */\n\nexport interface UseFeedbackInboxOptions<T extends FeedbackRecord> {\n /** The list as the app's query answered it (`GET /feedback`, `GET /feedback/my`) —\n * `list.data ?? []`. Shown newest first and, behind the awaiting toggle, narrowed. */\n rows: readonly T[];\n /** `/my-feedback`: the viewer's own reports — no triage there, for an admin too (§4.3). */\n mine?: boolean;\n /** The viewer may triage: the admin. Only on the inbox — `mine` wins — so `isAdmin`\n * is enough. The status cell, the pills, the reply composer, the swipes, the submitter\n * on the card and the awaiting toggle. */\n canEdit: boolean;\n /** The signed-in user's id: who the AUTHOR is (the description editor, Rework, the\n * public switch's window). */\n viewerId?: number | null;\n /**\n * `PATCH /feedback/{id}` (§3.4): every edit of the report itself — a status change from\n * the cell, the pills or a swipe (with the Undo, `useFeedbackStatusUndo`), the\n * description, the legacy rework append and, with {@link publicSwitch}, the flip. ONE\n * mutation for all of them, the page's, so its observer outlives a row a status filter\n * removes (§4.5).\n */\n update: FeedbackInboxMutation<FeedbackDetailPatch>;\n /** `POST /feedback/{id}/replies` — the admin's answer (§9.7) with its one file (§12).\n * Without it no composer is drawn. */\n reply?: FeedbackInboxMutation<FeedbackReplyPost>;\n /** `POST /feedback/{id}/rework` — the author's rework entry (§10.3). Without it a rework\n * goes through {@link update} as the legacy body append (§3.4). */\n rework?: FeedbackInboxMutation<FeedbackReworkPost>;\n /**\n * The **Visible to others** switch in the detail (§9.3), its flip sent through\n * {@link update} as `{ id, public }` — as keksdose and Kurvenschmiede send it. Off by\n * default: an app without public parts (kastlan) has no switch.\n */\n publicSwitch?: boolean;\n /** The **Votes** column and the card's count (§9.6). Off by default (kastlan); keksdose\n * always, Kurvenschmiede for a reader of the public parts. */\n votes?: boolean;\n /**\n * The report's comments, in a section of their own under the replies (§9.8): the app's\n * `FeedbackCommentThread` over its own queries — a component of its own, since its\n * queries are hooks. Return `null` for a row without a thread (a CRASH, a reader who\n * does not see the public parts; `false` is read as `null`). Called only for the open\n * row.\n *\n * ```tsx\n * comments={(row) => <RowComments id={row.id} isAdmin={isAdmin} canComment={!canEdit} />}\n * ```\n */\n comments?: (row: T) => ReactNode;\n /** The detail as drawn, to wrap or extend — kastlan's tour anchor:\n * `(row, detail) => <div data-tour=\"feedback-row-detail\">{detail}</div>`. */\n renderDetail?: (row: T, detail: ReactNode) => ReactNode;\n /**\n * The app's own columns over the kit's (§4.3's nine, and Votes): add, drop, reorder —\n * the keys are stable (`columns.filter((c) => c.key !== \"email\")`). A column brings its\n * filter with it. Keep it stable (module scope or `useCallback`): it is a memo's\n * dependency.\n */\n columns?: (columns: readonly DataTableColumn<T>[]) => readonly DataTableColumn<T>[];\n /** Which swipe does what on the phone (§4.5) — keksdose's Settings → Interaction binding,\n * `{ end: prefs.right, start: prefs.left }`. Default `DEFAULT_FEEDBACK_SWIPE`. */\n swipe?: FeedbackSwipeBinding;\n /** The status writes the TABLE offers — the status cell and the desktop's actions\n * column — commit: under a locked `WriteLockProvider` they stay and say why\n * (`FeedbackStatusTransitions`' `commit`). Off by default. The detail's own saves:\n * `detail={{ commit }}`. */\n commit?: CommitScope;\n /** `POST /feedback/attachments` (§3.3): the rework's file and the reply's. */\n onUpload?: FeedbackUpload;\n /** The app's authenticated GET for the pictures and the downloads (§3.5). */\n fetcher?: AuthedFetcher | null;\n /** \"Capture screenshot\" beside the rework's and the reply's file field. Default: the\n * kit's `captureAppScreenshot()`; `null` for no button. */\n onCaptureScreenshot?: (() => Promise<File | null>) | null;\n /**\n * The app's date writer (keksdose's `useDateCell()`, the date-format setting): the date\n * and resolved columns, the card, the phone's day headers AND the detail's \"Resolved:\",\n * so all five say the same. Left out, the kit's date with the weekday in the table and\n * on the phone, and in the detail its sentence date — as the parts draw them alone.\n */\n renderDate?: FeedbackRenderDate;\n /** The app's one-shot routes, on top of the kit's (0.52, FLW-7) — for the URL column and\n * the detail's URL section alike. Keep it stable (module scope). */\n pageLinkExclude?: readonly PathPattern[];\n /** The list is still loading (`list.isPending`): the table says \"Loading…\" where its\n * rows will be, not \"None\". */\n loading?: boolean;\n /** Over the detail's props the inbox sets — `commit`, `showSubject`,\n * `reworkAttachment`, `replyAttachments` (on here), `labels`, `className`. Merged last,\n * so it wins. */\n detail?: Partial<Omit<FeedbackRowDetailProps, \"row\">>;\n /** Over the `feedbackPage` namespace: the columns, the card, the empty state, the toggle\n * and the title. Keep it stable: it is a memo's dependency. */\n labels?: LabelOverride<FeedbackPageLabels>;\n}\n\n/** What {@link useFeedbackInbox} returns: the state, and the props of the parts. */\nexport interface FeedbackInboxState<T extends FeedbackRecord> {\n /** `canEdit && !mine`: the admin on the inbox. */\n editable: boolean;\n /** The page's title, `feedbackPage.title` — or `.myTitle` on `/my-feedback`. */\n title: string;\n /** The open row's id, from `?row=`; `null` when none is open or the param named no\n * id (`?row=abc`, `?row=1.5`, `?row=0`). */\n openId: number | null;\n /** Open a row by its id, or close it with `null`: rewrites `?row=`, replacing the\n * history entry rather than stacking one per report looked at. */\n setOpenId: (id: number | null) => void;\n /** A row's own address: this view — the table's page, sort and filters — with the row\n * open. The row's link (a new tab, a copied address); a plain click opens it in place. */\n rowHref: (row: T) => string;\n /** The undoable status change (§4.5): the status cell's, the pills', the swipes'. */\n changeStatus: FeedbackStatusChange;\n /** The phone's \"Only what is waiting for you\" — page state, not the URL (§4.3). */\n awaiting: boolean;\n setAwaiting: (next: boolean) => void;\n /** The one date writer the columns, the card and the day headers use. */\n renderDate: FeedbackRenderDate;\n /** `FeedbackRowDetail`'s props for a row, slots included. */\n detailProps: (row: T) => FeedbackRowDetailProps;\n /** `DataTable`'s props, ready to spread: the rows (newest first, narrowed by\n * `awaiting`), the columns, the open row, the detail, the phone's card, day headers and\n * swipes, the desktop's actions column, the empty state, `urlSync`,\n * `storageKey=\"feedback\"`, `fillHeight`. */\n table: DataTableProps<T>;\n}\n\n/** `?row=`'s value: a report's id is a positive integer, written in digits. Anything\n * else — a hand-edited link, `1e2`, `0x10`, `-3`, `1.5` — opens no row (and the URL\n * keeps it until a row is opened or closed). The three apps parsed with `Number()`, so\n * `?row=1e2` opened #100 in all three. */\nfunction parseRowId(raw: string): number | undefined {\n if (!/^[1-9]\\d*$/.test(raw)) return undefined;\n const id = Number(raw);\n return Number.isSafeInteger(id) ? id : undefined;\n}\n\nconst ROW_PARAM = { parse: parseRowId, history: \"replace\" } as const;\n\n/** Newest first, as `GET /feedback` sends it (§3.3) — the phone's day headers group runs\n * of equal days, so an older row between two of today's would split the day in two.\n * ISO strings from one server sort as their instants; the sort is stable. */\nconst newestFirst = (a: FeedbackRecord, b: FeedbackRecord) =>\n a.created_at < b.created_at ? 1 : a.created_at > b.created_at ? -1 : 0;\n\nconst rowId = (row: FeedbackRecord) => row.id;\nconst rowTitle = (row: FeedbackRecord) => row.title;\nconst captureScreenshot = () => captureAppScreenshot();\nconst ignore = () => {};\n/** A slot's \"nothing\": `cond && <Thread />` answers `false`, which the detail would draw\n * as an empty Comments section (it draws one for anything but `null`). */\nconst threadOf = (node: ReactNode): ReactNode => (node === false || node === \"\" ? undefined : node);\n\n/**\n * The inbox's wiring, once (§13): from the app's rows and mutations to what the table,\n * the detail and the phone cards take.\n *\n * ```tsx\n * const list = useQuery({ queryKey: keys.feedback.all, queryFn: api.listFeedback });\n * const update = useMutation({ mutationFn: ({ id, ...patch }: FeedbackDetailPatch) => api.update(id, patch), … });\n * const inbox = useFeedbackInbox({ rows: list.data ?? [], canEdit: isAdmin, viewerId: user?.id, update });\n * <DataTable {...inbox.table} edgeFade />\n * ```\n *\n * {@link FeedbackInbox} is this hook drawn — use the hook alone for a layout of your own.\n * Needs a react-router Router (`?row=`, `urlSync`).\n */\nexport function useFeedbackInbox<T extends FeedbackRecord>({\n rows,\n mine = false,\n canEdit,\n viewerId,\n update,\n reply,\n rework,\n publicSwitch = false,\n votes = false,\n comments,\n renderDetail,\n columns: ownColumns,\n swipe = DEFAULT_FEEDBACK_SWIPE,\n commit,\n onUpload,\n fetcher,\n onCaptureScreenshot = captureScreenshot,\n renderDate: renderDateProp,\n pageLinkExclude,\n loading = false,\n detail,\n labels,\n}: UseFeedbackInboxOptions<T>): FeedbackInboxState<T> {\n // An admin on /my-feedback reads as any author does (§4.3), as `feedbackColumns` has it.\n const editable = canEdit && !mine;\n const pageLabels = useFeedbackPageLabels(labels);\n const statusLabels = useFeedbackStatusLabels();\n const renderDate = useFeedbackRenderDate(renderDateProp);\n\n // TanStack's `mutateAsync` is stable, so the Undo and the columns' memo hold across\n // renders; the mutation object around it is not.\n const updateAsync = update.mutateAsync;\n const changeStatus = useFeedbackStatusUndo(updateAsync);\n\n // The open row IS the URL (§4.3: `?row=<id>`, every app) — which is what makes a row a\n // real link at all (keksdose feedback #451). Replace, not push: looking through ten\n // reports is not ten steps for Back.\n const [openId, setOpenId] = useSearchParamState<number | null>(\"row\", null, ROW_PARAM);\n const { pathname, search } = useLocation();\n // Through the router, so a basename (and a hash router's `#`) is in the address.\n const here = useHref({ pathname });\n // Built from the CURRENT query, not a bare `?row=`: the table keeps its `f.*`, `sort`\n // and `p` in the URL, and dropping them would open the new tab on an unfiltered list\n // where the row may not be on the first page (keksdose feedback-page.tsx:145).\n const rowHref = useCallback(\n (row: T) => {\n const params = new URLSearchParams(search);\n params.set(\"row\", String(row.id));\n return `${here}?${params.toString()}`;\n },\n [here, search],\n );\n\n // A thumb gesture on one screen, not a view worth linking to (§4.3; keksdose live #330).\n const [awaiting, setAwaiting] = useState(false);\n const shown = useMemo(\n () => (editable && awaiting ? rows.filter((row) => isFeedbackAwaiting(row.status)) : [...rows]).sort(newestFirst),\n [rows, editable, awaiting],\n );\n\n const kitColumns = useFeedbackColumns<T>({\n mine,\n canEdit,\n onStatus: changeStatus,\n renderDate,\n commit,\n votes,\n pageLinkExclude,\n labels,\n });\n const columns = useMemo(() => (ownColumns ? ownColumns(kitColumns) : kitColumns), [ownColumns, kitColumns]);\n const mobileGroupBy = useMemo(() => feedbackMobileGroupBy(renderDate), [renderDate]);\n\n // The rework's sending is the detail's too (keksdose, Kurvenschmiede): its editors and\n // the public switch wait for whichever write is out.\n const pending = Boolean(update.isPending || rework?.isPending);\n const capture = onCaptureScreenshot ?? undefined;\n\n const detailProps = (row: T): FeedbackRowDetailProps => ({\n row,\n canEdit: editable,\n viewerId,\n onUpdate: updateAsync,\n pending,\n // The page's change, not one the detail would build: the same Undo as the cell's.\n statusChange: changeStatus,\n onUpload,\n fetcher,\n onCaptureScreenshot: capture,\n // Only the app's own: left out, the detail's \"Resolved:\" is the kit's sentence date,\n // no weekday — as kastlan's has always been.\n renderDate: renderDateProp,\n pageLinkExclude,\n onReply: reply\n ? (body, status, attachmentUrl) =>\n reply.mutateAsync({\n id: row.id,\n body,\n ...(status ? { status } : {}),\n ...(attachmentUrl ? { attachmentUrl } : {}),\n })\n : undefined,\n // The reply's one file (§12): all three apps are on server-kit 0.18, and the reply\n // mutation's `attachmentUrl` is in its type from the start (the B1 risk the detail's\n // default guards against — an `onReply` that drops the file — cannot arise here).\n replyAttachments: true,\n replying: reply?.isPending ?? false,\n onRework: rework\n ? (note, attachmentUrl) => rework.mutateAsync({ id: row.id, note, ...(attachmentUrl ? { attachmentUrl } : {}) })\n : undefined,\n comments: threadOf(comments?.(row)),\n onPublicChange: publicSwitch ? (next) => runMutation(updateAsync, { id: row.id, public: next }, ignore) : undefined,\n ...detail,\n });\n\n const table: DataTableProps<T> = {\n rows: shown,\n columns,\n rowKey: rowId,\n storageKey: \"feedback\",\n urlSync: true,\n fillHeight: true,\n rowHref,\n // The link covers the row's first cell; a click anywhere on the row opens it — or,\n // on the open one, closes it.\n onRowClick: (row) => setOpenId((id) => (id === row.id ? null : row.id)),\n isExpanded: (row) => row.id === openId,\n expandedRow: (row) => {\n const node = <FeedbackRowDetail {...detailProps(row)} />;\n return renderDetail ? renderDetail(row, node) : node;\n },\n // §7.13: one word, also when a filter or the toggle leaves nothing; and while the\n // first answer is out, what is happening instead.\n empty: loading ? <LoadingState size=\"sm\" inline /> : <FeedbackEmptyState labels={labels} />,\n mobileGroupBy,\n mobileCard: (row) => (\n <FeedbackMobileCard row={row} showSubmitter={editable} renderDate={renderDate} votes={votes} labels={labels} />\n ),\n // The admin inbox only — /my-feedback is read-only by design (keksdose #331) — and\n // every swipe through the same Undo as a tap (§4.5, §7.10).\n mobileSwipeActions: editable\n ? (row) => feedbackSwipePlan(swipe, row, { change: changeStatus, labels: statusLabels })\n : undefined,\n // The swipes as the desktop's last column (0.46, keksdose dev#598), less what the\n // status cell already offers.\n desktopSwipeActions: { omit: feedbackSwipeOmitShown, name: rowTitle, ...(commit === undefined ? {} : { commit }) },\n };\n\n return {\n editable,\n title: mine ? pageLabels.myTitle : pageLabels.title,\n openId,\n setOpenId,\n rowHref,\n changeStatus,\n awaiting,\n setAwaiting,\n renderDate,\n detailProps,\n table,\n };\n}\n\n/* ── The component ──────────────────────────────────────────────────────────── */\n\nexport interface FeedbackInboxProps<T extends FeedbackRecord> extends UseFeedbackInboxOptions<T> {\n /**\n * Above the table. Default: `<PageHeader title={title} className=\"mb-4 md:shrink-0\" />`.\n * A function gets the page's title (`feedbackPage.title` / `.myTitle`) — the app's own\n * header: `(title) => <PageHeader size=\"compact\" title={title} data-tour=\"feedback-header\" />`.\n * `null` for none.\n */\n header?: ReactNode | ((title: string) => ReactNode);\n /** Over the inbox's `DataTable` props — `edgeFade`, `locale`, `mobileExpandAsDialog`,\n * `className`, another `storageKey`. Merged last, so it wins. */\n table?: Partial<DataTableProps<T>>;\n /** Further `FloatingAction`s on the phone: after the awaiting toggle on the inbox, in a\n * group of their own on `/my-feedback`. */\n phoneActions?: ReactNode;\n /** On the page's frame — the fill-height column (`FILL_HEIGHT_CLASS`); the app's page\n * padding goes here. */\n className?: string;\n}\n\n/**\n * The feedback inbox (§13): `/feedback` and `/my-feedback` drawn whole from\n * {@link useFeedbackInbox} — the header, the table with its detail, phone cards and swipes,\n * and the phone's awaiting toggle, in the fill-height frame (page layout §1.3) — so a page\n * is its queries and this:\n *\n * ```tsx\n * export function FeedbackPage({ mine = false }: { mine?: boolean }) {\n * const { user, isAdmin } = useAuth();\n * const list = useQuery({ queryKey: mine ? keys.mine : keys.all, queryFn: mine ? api.mine : api.all });\n * const update = useFeedbackUpdate();\n * const reply = useFeedbackReply();\n * const rework = useFeedbackRework();\n * if (!mine && !isAdmin) return <Navigate to=\"/my-feedback\" replace />;\n * return (\n * <FeedbackInbox\n * rows={list.data ?? []} loading={list.isPending} mine={mine} canEdit={isAdmin} viewerId={user?.id}\n * update={update} reply={reply} rework={rework}\n * onUpload={api.upload} fetcher={api.file}\n * />\n * );\n * }\n * ```\n *\n * Every slot is {@link UseFeedbackInboxOptions}' or one of the four below. The redirect of\n * a non-admin, the routes and the queries stay the app's.\n */\nexport function FeedbackInbox<T extends FeedbackRecord>({\n header,\n table,\n phoneActions,\n className,\n ...options\n}: FeedbackInboxProps<T>) {\n const inbox = useFeedbackInbox<T>(options);\n const pageLabels = useFeedbackPageLabels(options.labels);\n const head =\n header === undefined ? (\n <PageHeader title={inbox.title} className=\"mb-4 md:shrink-0\" />\n ) : typeof header === \"function\" ? (\n header(inbox.title)\n ) : (\n header\n );\n return (\n // A plain element on the way to the table carries the fill (page layout §1.3).\n <div className={cn(FILL_HEIGHT_CLASS, className)} aria-busy={options.loading || undefined} data-feedback-inbox=\"\">\n {head}\n <DataTable {...inbox.table} {...table} />\n {inbox.editable ? (\n // The phone's floating action (keksdose feedback #58): only on the inbox — on\n // /my-feedback the author is not waiting on their own verdict.\n <FeedbackAwaitingToggle pressed={inbox.awaiting} onPressedChange={inbox.setAwaiting} labels={options.labels}>\n {phoneActions}\n </FeedbackAwaitingToggle>\n ) : (\n phoneActions && (\n <FloatingActionGroup aria-label={pageLabels.phoneActions} className=\"md:hidden\">\n {phoneActions}\n </FloatingActionGroup>\n )\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -70,8 +70,8 @@ const FEEDBACK_STATUS_META = {
70
70
  },
71
71
  // The one status with nowhere to move to: the vocabulary has a brand, an info, a
72
72
  // warning and a danger, and nothing that means "succeeded". Deliberately NOT
73
- // borrowed from a family that means something else — `--status-synced` is a
74
- // FIELD's trip to the database rather than an outcome, and tokens.css says so in
73
+ // borrowed from a colour that means something else — a field's "saved" is a trip
74
+ // to the database rather than an outcome, and tokens.css's `--success` says so in
75
75
  // as many words. Green beside WONT_DO's red is the classic CVD-unsafe pair, which
76
76
  // is why both carry a glyph and neither leans on colour alone.
77
77
  DONE: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feedback/feedback-vocabulary.ts"],"sourcesContent":["import {\n Ban,\n Bug,\n CheckCircle2,\n ClipboardCheck,\n CloudUpload,\n Eye,\n HelpCircle,\n Inbox,\n Lightbulb,\n MoreHorizontal,\n OctagonAlert,\n PauseCircle,\n RotateCcw,\n Wrench,\n} from \"lucide-react\";\nimport type { LucideIcon } from \"lucide-react\";\n\n/**\n * The feedback **vocabulary**: the nine statuses and five categories, the glyph and tone\n * of each, their orders, and the policy for how a report moves from status to status.\n *\n * Data and plain functions, no components. Until 0.34 this lived at the top of\n * feedback-inbox.tsx, so the feedback menu every app mounts in its top bar imported the\n * inbox — its components and the attachment field they render — for one constant (a\n * category's glyph), and only tree-shaking kept the rest out of every app's entry chunk.\n * From here the top bar's imports reach none of it (MOD-1, refactor audit 2026-10).\n * feedback-inbox.tsx re-exports every name here, so nothing an app imports has moved.\n */\n\n/** The nine states a report can be in.\n *\n * Shared value for value across the apps on purpose: it is what lets one habit,\n * and one agent prompt, work on any repo. Five are a chain and three sit off\n * it — see {@link visibleFeedbackStatuses} for what that buys. `READY` joined in 0.31\n * (feedback contract §8.2): OPEN is \"filed, not yet triaged\", READY \"released for\n * implementation\", and nobody works an OPEN row. `REWORK` joined in 0.40 (§10.2\n * decisions 2, 4): \"sent back, released for work again\" — a READY that came back. */\nexport type FeedbackStatus =\n \"OPEN\" | \"READY\" | \"REWORK\" | \"IN_PROGRESS\" | \"IN_EVALUATION\" | \"NEEDS_LIVE_TEST\" | \"POSTPONED\" | \"DONE\" | \"WONT_DO\";\n\n/** What a report is about. `CRASH` is filed by an error boundary and never\n * chosen, which is exactly why it is loud below and absent from every picker. */\nexport type FeedbackCategory = \"CRASH\" | \"BUG\" | \"IDEA\" | \"QUESTION\" | \"OTHER\";\n\n/**\n * A glyph and a tone per status.\n *\n * Colour alone is not a label — two of these sit a hue apart, and a consumer who\n * moves `--brand` can park it beside any of the others — so every status carries\n * its own shape as well. Declaration order is chain order, and\n * {@link FEEDBACK_STATUS_ORDER} is derived from it rather than restated, because\n * a restated list cannot be checked for exhaustiveness: an eighth status would\n * break the build here and leave a literal eight long (as READY did in 0.31).\n */\nexport const FEEDBACK_STATUS_META: Record<FeedbackStatus, { icon: LucideIcon; activeBg: string; activeText: string }> =\n {\n OPEN: {\n icon: Inbox,\n activeBg: \"bg-active\",\n activeText: \"text-primary\",\n },\n // Triaged and released for implementation (feedback contract §8.2, keksdose live\n // #396): OPEN is \"filed, nobody has looked yet\", READY is \"go\". The brand tint at full\n // strength, so it reads as the go-ahead beside OPEN's neutral fill and\n // NEEDS_LIVE_TEST's muted brand.\n READY: {\n icon: ClipboardCheck,\n activeBg: \"bg-brand-soft\",\n activeText: \"text-brand\",\n },\n // Sent back by its author or an admin and released for work again (0.40, feedback\n // contract §10.2 decision 4): the Rework button's `RotateCcw`, in the danger tint so the\n // queue shows reworks apart from new reports. Not IN_PROGRESS's warning tint — that is\n // where a REWORK row moves next — and WONT_DO, the only other red, sits at the far end\n // with `Ban`.\n REWORK: {\n icon: RotateCcw,\n activeBg: \"bg-danger-soft\",\n activeText: \"text-danger\",\n },\n IN_PROGRESS: {\n icon: Wrench,\n activeBg: \"bg-warning-soft\",\n activeText: \"text-warning\",\n },\n // Where solved work is parked, waiting on the person who reported it. Its own\n // colour, because \"somebody has to check this\" is a state you want to find by\n // scanning rather than by reading.\n IN_EVALUATION: {\n icon: Eye,\n activeBg: \"bg-info-soft\",\n activeText: \"text-info\",\n },\n // Resolved but only checkable on a deployed build — the SOFT brand tint, so it\n // reads as \"waiting on something\" rather than as a done or a refusal, and it\n // follows whatever the consumer's brand is instead of pinning an indigo island\n // beside it.\n NEEDS_LIVE_TEST: {\n icon: CloudUpload,\n activeBg: \"bg-brand-soft\",\n activeText: \"text-brand-muted\",\n },\n // Parked on purpose. Muted, not `--danger`: it is not a refusal.\n POSTPONED: {\n icon: PauseCircle,\n activeBg: \"bg-active\",\n activeText: \"text-secondary\",\n },\n // The one status with nowhere to move to: the vocabulary has a brand, an info, a\n // warning and a danger, and nothing that means \"succeeded\". Deliberately NOT\n // borrowed from a family that means something else — `--status-synced` is a\n // FIELD's trip to the database rather than an outcome, and tokens.css says so in\n // as many words. Green beside WONT_DO's red is the classic CVD-unsafe pair, which\n // is why both carry a glyph and neither leans on colour alone.\n DONE: {\n icon: CheckCircle2,\n activeBg: \"bg-success-soft\",\n activeText: \"text-success\",\n },\n WONT_DO: {\n icon: Ban,\n activeBg: \"bg-danger-soft\",\n activeText: \"text-danger\",\n },\n };\n\n/** Chain order, then the three off it. The order a picker offers, and the rank a\n * status column sorts by — so a list sorted by status reads as a queue rather\n * than as an alphabet. */\nexport const FEEDBACK_STATUS_ORDER = Object.keys(FEEDBACK_STATUS_META) as FeedbackStatus[];\n\n/** States that sit OFF the linear chain: reachable from anywhere, leading\n * nowhere by themselves. `WONT_DO` has always worked this way; `POSTPONED`\n * (\"not now\") and `NEEDS_LIVE_TEST` (\"resolved, but only provable on a deployed\n * build\") are the same shape — a row can be parked or handed to the next deploy\n * from any point, and comes back to the chain when somebody picks a real state\n * for it.\n *\n * Kept out of the forward chain deliberately: putting them in it would mean an\n * \"advance\" gesture could park an item, and every row would have to pass\n * through them to reach `DONE`. */\nconst OFF_CHAIN: FeedbackStatus[] = [\"NEEDS_LIVE_TEST\", \"POSTPONED\", \"WONT_DO\"];\n\nconst FORWARD_CHAIN: FeedbackStatus[] = [\"OPEN\", \"READY\", \"IN_PROGRESS\", \"IN_EVALUATION\", \"DONE\"];\n\n/** The next status along the chain, or null at the end (or off it, as `WONT_DO`\n * is). What a swipe-to-advance gesture commits. `REWORK` (0.40) is not in the chain —\n * \"advance\" from READY still goes to IN_PROGRESS — but it leads there too: a reworked\n * row is READY's twin. */\nexport function nextFeedbackStatus(current: FeedbackStatus): FeedbackStatus | null {\n if (current === \"REWORK\") return \"IN_PROGRESS\";\n const at = FORWARD_CHAIN.indexOf(current);\n return at !== -1 && at < FORWARD_CHAIN.length - 1 ? FORWARD_CHAIN[at + 1] : null;\n}\n\n/**\n * The steps that make sense from where a row currently stands.\n *\n * For the compact control in a table cell: it is a glanceable triage affordance,\n * and a row of nine icons in a cell is noise. One step forward, one step back\n * (so an item can be sent back for rework), and any of the three off-chain\n * verdicts — which is what makes those usable as verdicts at all.\n *\n * The two parking states are not dead ends: each offers the step that resumes\n * work and the ones that close it, but deliberately **not each other** —\n * \"postponed\" and \"waiting on a deploy\" are different answers to different\n * questions, and a row moving between them directly is a re-triage, which starts\n * by picking the work back up.\n */\nexport function visibleFeedbackStatuses(current: FeedbackStatus): FeedbackStatus[] {\n const set = new Set<FeedbackStatus>([current]);\n const at = FORWARD_CHAIN.indexOf(current);\n if (current === \"REWORK\") {\n // READY's twin (0.40, §10.2 decision 4): the step that picks the work up, and the\n // verdicts a released row can still get.\n set.add(\"IN_PROGRESS\");\n for (const off of OFF_CHAIN) set.add(off);\n } else if (at !== -1) {\n if (at < FORWARD_CHAIN.length - 1) set.add(FORWARD_CHAIN[at + 1]);\n if (at > 0) set.add(FORWARD_CHAIN[at - 1]);\n for (const off of OFF_CHAIN) set.add(off);\n } else if (current !== \"WONT_DO\") {\n set.add(\"IN_PROGRESS\");\n set.add(\"DONE\");\n set.add(\"WONT_DO\");\n }\n // WONT_DO falls through with nothing added: it stays terminal, reopened by a\n // note from its author rather than by a status pill.\n return FEEDBACK_STATUS_ORDER.filter((status) => set.has(status));\n}\n\n/**\n * Every status, in chain order — what an EXPANDED row offers.\n *\n * {@link visibleFeedbackStatuses} narrows the choice to the steps that make\n * sense from where a row is, which is right for a table cell. Once the row is\n * open in front of you, that same narrowing turns every non-adjacent move into a\n * walk: OPEN to DONE meant three round trips, and WONT_DO could not be left at\n * all except through a rework note.\n *\n * Takes a `current` it does not use, so the two policies read as one pair at the\n * call sites and a future rule (\"terminal rows still cannot jump to X\") has a\n * place to live.\n */\nexport function selectableFeedbackStatuses(_current: FeedbackStatus): FeedbackStatus[] {\n return [...FEEDBACK_STATUS_ORDER];\n}\n\n/**\n * Per-category badge treatment, the counterpart to the status meta above.\n *\n * A category cell that is one grey pill holding the raw enum makes a CRASH —\n * filed automatically, by somebody staring at a broken page right now — read\n * exactly like a QUESTION, and sit unnoticed in the queue. `--danger` plus its own\n * glyph is what makes that impossible; the hand-filed categories stay\n * deliberately quiet so that the loud one means something.\n *\n * Declaration order is triage order, CRASH first.\n */\nexport const FEEDBACK_CATEGORY_META: Record<\n FeedbackCategory,\n { icon: LucideIcon; badgeBg: string; badgeText: string }\n> = {\n CRASH: {\n icon: OctagonAlert,\n badgeBg: \"bg-danger-soft\",\n badgeText: \"text-danger\",\n },\n BUG: {\n icon: Bug,\n badgeBg: \"bg-warning-soft\",\n badgeText: \"text-warning\",\n },\n IDEA: {\n icon: Lightbulb,\n badgeBg: \"bg-surface-2\",\n badgeText: \"text-secondary\",\n },\n QUESTION: {\n icon: HelpCircle,\n badgeBg: \"bg-surface-2\",\n badgeText: \"text-secondary\",\n },\n OTHER: {\n icon: MoreHorizontal,\n badgeBg: \"bg-surface-2\",\n badgeText: \"text-secondary\",\n },\n};\n\n/** Triage order, CRASH first — also a category column's sort key and the option\n * order in its filter. Sorting by the raw enum is alphabetical, which parks\n * CRASH between BUG and IDEA. */\nexport const FEEDBACK_CATEGORY_ORDER = Object.keys(FEEDBACK_CATEGORY_META) as FeedbackCategory[];\n\n/** A category's rank for a column sort. Anything this build has never heard of —\n * an older client against a newer API — sorts LAST rather than to `indexOf`'s\n * −1, which would rank it above CRASH. */\nexport function feedbackCategoryRank(category: FeedbackCategory): number {\n const at = FEEDBACK_CATEGORY_ORDER.indexOf(category);\n return at === -1 ? FEEDBACK_CATEGORY_ORDER.length : at;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/feedback/feedback-vocabulary.ts"],"sourcesContent":["import {\n Ban,\n Bug,\n CheckCircle2,\n ClipboardCheck,\n CloudUpload,\n Eye,\n HelpCircle,\n Inbox,\n Lightbulb,\n MoreHorizontal,\n OctagonAlert,\n PauseCircle,\n RotateCcw,\n Wrench,\n} from \"lucide-react\";\nimport type { LucideIcon } from \"lucide-react\";\n\n/**\n * The feedback **vocabulary**: the nine statuses and five categories, the glyph and tone\n * of each, their orders, and the policy for how a report moves from status to status.\n *\n * Data and plain functions, no components. Until 0.34 this lived at the top of\n * feedback-inbox.tsx, so the feedback menu every app mounts in its top bar imported the\n * inbox — its components and the attachment field they render — for one constant (a\n * category's glyph), and only tree-shaking kept the rest out of every app's entry chunk.\n * From here the top bar's imports reach none of it (MOD-1, refactor audit 2026-10).\n * feedback-inbox.tsx re-exports every name here, so nothing an app imports has moved.\n */\n\n/** The nine states a report can be in.\n *\n * Shared value for value across the apps on purpose: it is what lets one habit,\n * and one agent prompt, work on any repo. Five are a chain and three sit off\n * it — see {@link visibleFeedbackStatuses} for what that buys. `READY` joined in 0.31\n * (feedback contract §8.2): OPEN is \"filed, not yet triaged\", READY \"released for\n * implementation\", and nobody works an OPEN row. `REWORK` joined in 0.40 (§10.2\n * decisions 2, 4): \"sent back, released for work again\" — a READY that came back. */\nexport type FeedbackStatus =\n \"OPEN\" | \"READY\" | \"REWORK\" | \"IN_PROGRESS\" | \"IN_EVALUATION\" | \"NEEDS_LIVE_TEST\" | \"POSTPONED\" | \"DONE\" | \"WONT_DO\";\n\n/** What a report is about. `CRASH` is filed by an error boundary and never\n * chosen, which is exactly why it is loud below and absent from every picker. */\nexport type FeedbackCategory = \"CRASH\" | \"BUG\" | \"IDEA\" | \"QUESTION\" | \"OTHER\";\n\n/**\n * A glyph and a tone per status.\n *\n * Colour alone is not a label — two of these sit a hue apart, and a consumer who\n * moves `--brand` can park it beside any of the others — so every status carries\n * its own shape as well. Declaration order is chain order, and\n * {@link FEEDBACK_STATUS_ORDER} is derived from it rather than restated, because\n * a restated list cannot be checked for exhaustiveness: an eighth status would\n * break the build here and leave a literal eight long (as READY did in 0.31).\n */\nexport const FEEDBACK_STATUS_META: Record<FeedbackStatus, { icon: LucideIcon; activeBg: string; activeText: string }> =\n {\n OPEN: {\n icon: Inbox,\n activeBg: \"bg-active\",\n activeText: \"text-primary\",\n },\n // Triaged and released for implementation (feedback contract §8.2, keksdose live\n // #396): OPEN is \"filed, nobody has looked yet\", READY is \"go\". The brand tint at full\n // strength, so it reads as the go-ahead beside OPEN's neutral fill and\n // NEEDS_LIVE_TEST's muted brand.\n READY: {\n icon: ClipboardCheck,\n activeBg: \"bg-brand-soft\",\n activeText: \"text-brand\",\n },\n // Sent back by its author or an admin and released for work again (0.40, feedback\n // contract §10.2 decision 4): the Rework button's `RotateCcw`, in the danger tint so the\n // queue shows reworks apart from new reports. Not IN_PROGRESS's warning tint — that is\n // where a REWORK row moves next — and WONT_DO, the only other red, sits at the far end\n // with `Ban`.\n REWORK: {\n icon: RotateCcw,\n activeBg: \"bg-danger-soft\",\n activeText: \"text-danger\",\n },\n IN_PROGRESS: {\n icon: Wrench,\n activeBg: \"bg-warning-soft\",\n activeText: \"text-warning\",\n },\n // Where solved work is parked, waiting on the person who reported it. Its own\n // colour, because \"somebody has to check this\" is a state you want to find by\n // scanning rather than by reading.\n IN_EVALUATION: {\n icon: Eye,\n activeBg: \"bg-info-soft\",\n activeText: \"text-info\",\n },\n // Resolved but only checkable on a deployed build — the SOFT brand tint, so it\n // reads as \"waiting on something\" rather than as a done or a refusal, and it\n // follows whatever the consumer's brand is instead of pinning an indigo island\n // beside it.\n NEEDS_LIVE_TEST: {\n icon: CloudUpload,\n activeBg: \"bg-brand-soft\",\n activeText: \"text-brand-muted\",\n },\n // Parked on purpose. Muted, not `--danger`: it is not a refusal.\n POSTPONED: {\n icon: PauseCircle,\n activeBg: \"bg-active\",\n activeText: \"text-secondary\",\n },\n // The one status with nowhere to move to: the vocabulary has a brand, an info, a\n // warning and a danger, and nothing that means \"succeeded\". Deliberately NOT\n // borrowed from a colour that means something else — a field's \"saved\" is a trip\n // to the database rather than an outcome, and tokens.css's `--success` says so in\n // as many words. Green beside WONT_DO's red is the classic CVD-unsafe pair, which\n // is why both carry a glyph and neither leans on colour alone.\n DONE: {\n icon: CheckCircle2,\n activeBg: \"bg-success-soft\",\n activeText: \"text-success\",\n },\n WONT_DO: {\n icon: Ban,\n activeBg: \"bg-danger-soft\",\n activeText: \"text-danger\",\n },\n };\n\n/** Chain order, then the three off it. The order a picker offers, and the rank a\n * status column sorts by — so a list sorted by status reads as a queue rather\n * than as an alphabet. */\nexport const FEEDBACK_STATUS_ORDER = Object.keys(FEEDBACK_STATUS_META) as FeedbackStatus[];\n\n/** States that sit OFF the linear chain: reachable from anywhere, leading\n * nowhere by themselves. `WONT_DO` has always worked this way; `POSTPONED`\n * (\"not now\") and `NEEDS_LIVE_TEST` (\"resolved, but only provable on a deployed\n * build\") are the same shape — a row can be parked or handed to the next deploy\n * from any point, and comes back to the chain when somebody picks a real state\n * for it.\n *\n * Kept out of the forward chain deliberately: putting them in it would mean an\n * \"advance\" gesture could park an item, and every row would have to pass\n * through them to reach `DONE`. */\nconst OFF_CHAIN: FeedbackStatus[] = [\"NEEDS_LIVE_TEST\", \"POSTPONED\", \"WONT_DO\"];\n\nconst FORWARD_CHAIN: FeedbackStatus[] = [\"OPEN\", \"READY\", \"IN_PROGRESS\", \"IN_EVALUATION\", \"DONE\"];\n\n/** The next status along the chain, or null at the end (or off it, as `WONT_DO`\n * is). What a swipe-to-advance gesture commits. `REWORK` (0.40) is not in the chain —\n * \"advance\" from READY still goes to IN_PROGRESS — but it leads there too: a reworked\n * row is READY's twin. */\nexport function nextFeedbackStatus(current: FeedbackStatus): FeedbackStatus | null {\n if (current === \"REWORK\") return \"IN_PROGRESS\";\n const at = FORWARD_CHAIN.indexOf(current);\n return at !== -1 && at < FORWARD_CHAIN.length - 1 ? FORWARD_CHAIN[at + 1] : null;\n}\n\n/**\n * The steps that make sense from where a row currently stands.\n *\n * For the compact control in a table cell: it is a glanceable triage affordance,\n * and a row of nine icons in a cell is noise. One step forward, one step back\n * (so an item can be sent back for rework), and any of the three off-chain\n * verdicts — which is what makes those usable as verdicts at all.\n *\n * The two parking states are not dead ends: each offers the step that resumes\n * work and the ones that close it, but deliberately **not each other** —\n * \"postponed\" and \"waiting on a deploy\" are different answers to different\n * questions, and a row moving between them directly is a re-triage, which starts\n * by picking the work back up.\n */\nexport function visibleFeedbackStatuses(current: FeedbackStatus): FeedbackStatus[] {\n const set = new Set<FeedbackStatus>([current]);\n const at = FORWARD_CHAIN.indexOf(current);\n if (current === \"REWORK\") {\n // READY's twin (0.40, §10.2 decision 4): the step that picks the work up, and the\n // verdicts a released row can still get.\n set.add(\"IN_PROGRESS\");\n for (const off of OFF_CHAIN) set.add(off);\n } else if (at !== -1) {\n if (at < FORWARD_CHAIN.length - 1) set.add(FORWARD_CHAIN[at + 1]);\n if (at > 0) set.add(FORWARD_CHAIN[at - 1]);\n for (const off of OFF_CHAIN) set.add(off);\n } else if (current !== \"WONT_DO\") {\n set.add(\"IN_PROGRESS\");\n set.add(\"DONE\");\n set.add(\"WONT_DO\");\n }\n // WONT_DO falls through with nothing added: it stays terminal, reopened by a\n // note from its author rather than by a status pill.\n return FEEDBACK_STATUS_ORDER.filter((status) => set.has(status));\n}\n\n/**\n * Every status, in chain order — what an EXPANDED row offers.\n *\n * {@link visibleFeedbackStatuses} narrows the choice to the steps that make\n * sense from where a row is, which is right for a table cell. Once the row is\n * open in front of you, that same narrowing turns every non-adjacent move into a\n * walk: OPEN to DONE meant three round trips, and WONT_DO could not be left at\n * all except through a rework note.\n *\n * Takes a `current` it does not use, so the two policies read as one pair at the\n * call sites and a future rule (\"terminal rows still cannot jump to X\") has a\n * place to live.\n */\nexport function selectableFeedbackStatuses(_current: FeedbackStatus): FeedbackStatus[] {\n return [...FEEDBACK_STATUS_ORDER];\n}\n\n/**\n * Per-category badge treatment, the counterpart to the status meta above.\n *\n * A category cell that is one grey pill holding the raw enum makes a CRASH —\n * filed automatically, by somebody staring at a broken page right now — read\n * exactly like a QUESTION, and sit unnoticed in the queue. `--danger` plus its own\n * glyph is what makes that impossible; the hand-filed categories stay\n * deliberately quiet so that the loud one means something.\n *\n * Declaration order is triage order, CRASH first.\n */\nexport const FEEDBACK_CATEGORY_META: Record<\n FeedbackCategory,\n { icon: LucideIcon; badgeBg: string; badgeText: string }\n> = {\n CRASH: {\n icon: OctagonAlert,\n badgeBg: \"bg-danger-soft\",\n badgeText: \"text-danger\",\n },\n BUG: {\n icon: Bug,\n badgeBg: \"bg-warning-soft\",\n badgeText: \"text-warning\",\n },\n IDEA: {\n icon: Lightbulb,\n badgeBg: \"bg-surface-2\",\n badgeText: \"text-secondary\",\n },\n QUESTION: {\n icon: HelpCircle,\n badgeBg: \"bg-surface-2\",\n badgeText: \"text-secondary\",\n },\n OTHER: {\n icon: MoreHorizontal,\n badgeBg: \"bg-surface-2\",\n badgeText: \"text-secondary\",\n },\n};\n\n/** Triage order, CRASH first — also a category column's sort key and the option\n * order in its filter. Sorting by the raw enum is alphabetical, which parks\n * CRASH between BUG and IDEA. */\nexport const FEEDBACK_CATEGORY_ORDER = Object.keys(FEEDBACK_CATEGORY_META) as FeedbackCategory[];\n\n/** A category's rank for a column sort. Anything this build has never heard of —\n * an older client against a newer API — sorts LAST rather than to `indexOf`'s\n * −1, which would rank it above CRASH. */\nexport function feedbackCategoryRank(category: FeedbackCategory): number {\n const at = FEEDBACK_CATEGORY_ORDER.indexOf(category);\n return at === -1 ? FEEDBACK_CATEGORY_ORDER.length : at;\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAwCA,MAAM,uBACX;AAAA,EACE,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAIA,eAAe;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB;AAAA,IACf,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA;AAAA,EAEA,WAAW;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AACF;AAKK,MAAM,wBAAwB,OAAO,KAAK,oBAAoB;AAYrE,MAAM,YAA8B,CAAC,mBAAmB,aAAa,SAAS;AAE9E,MAAM,gBAAkC,CAAC,QAAQ,SAAS,eAAe,iBAAiB,MAAM;AAMzF,SAAS,mBAAmB,SAAgD;AACjF,MAAI,YAAY,SAAU,QAAO;AACjC,QAAM,KAAK,cAAc,QAAQ,OAAO;AACxC,SAAO,OAAO,MAAM,KAAK,cAAc,SAAS,IAAI,cAAc,KAAK,CAAC,IAAI;AAC9E;AAgBO,SAAS,wBAAwB,SAA2C;AACjF,QAAM,MAAM,oBAAI,IAAoB,CAAC,OAAO,CAAC;AAC7C,QAAM,KAAK,cAAc,QAAQ,OAAO;AACxC,MAAI,YAAY,UAAU;AAGxB,QAAI,IAAI,aAAa;AACrB,eAAW,OAAO,UAAW,KAAI,IAAI,GAAG;AAAA,EAC1C,WAAW,OAAO,IAAI;AACpB,QAAI,KAAK,cAAc,SAAS,EAAG,KAAI,IAAI,cAAc,KAAK,CAAC,CAAC;AAChE,QAAI,KAAK,EAAG,KAAI,IAAI,cAAc,KAAK,CAAC,CAAC;AACzC,eAAW,OAAO,UAAW,KAAI,IAAI,GAAG;AAAA,EAC1C,WAAW,YAAY,WAAW;AAChC,QAAI,IAAI,aAAa;AACrB,QAAI,IAAI,MAAM;AACd,QAAI,IAAI,SAAS;AAAA,EACnB;AAGA,SAAO,sBAAsB,OAAO,CAAC,WAAW,IAAI,IAAI,MAAM,CAAC;AACjE;AAeO,SAAS,2BAA2B,UAA4C;AACrF,SAAO,CAAC,GAAG,qBAAqB;AAClC;AAaO,MAAM,yBAGT;AAAA,EACF,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,KAAK;AAAA,IACH,MAAM;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AACF;AAKO,MAAM,0BAA0B,OAAO,KAAK,sBAAsB;AAKlE,SAAS,qBAAqB,UAAoC;AACvE,QAAM,KAAK,wBAAwB,QAAQ,QAAQ;AACnD,SAAO,OAAO,KAAK,wBAAwB,SAAS;AACtD;","names":[]}
@@ -20,3 +20,4 @@ export * from "./feedback/feedback-vote-button.js";
20
20
  export * from "./feedback/feedback-comment-thread.js";
21
21
  export * from "./feedback/feedback-replies.js";
22
22
  export * from "./feedback/feedback-entry-file.js";
23
+ export { useFeedbackInbox, FeedbackInbox, type FeedbackInboxMutation, type FeedbackReplyPost, type FeedbackReworkPost, type UseFeedbackInboxOptions, type FeedbackInboxState, type FeedbackInboxProps, } from "./feedback/feedback-inbox-page.js";