@eifi1/ui-kit 0.53.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 (902) hide show
  1. package/README.md +96 -82
  2. package/dist/account/delete-account-setting.d.ts +3 -2
  3. package/dist/account/delete-account-setting.js.map +1 -1
  4. package/dist/admin/plan-change.js +2 -2
  5. package/dist/admin/plan-change.js.map +1 -1
  6. package/dist/admin/user-roster.d.ts +6 -0
  7. package/dist/admin/user-roster.js +4 -0
  8. package/dist/admin/user-roster.js.map +1 -1
  9. package/dist/auth/auth-errors.d.ts +36 -0
  10. package/dist/auth/auth-errors.js +20 -0
  11. package/dist/auth/auth-errors.js.map +1 -1
  12. package/dist/billing/billing-labels.d.ts +26 -0
  13. package/dist/billing/billing-labels.js +9 -0
  14. package/dist/billing/billing-labels.js.map +1 -1
  15. package/dist/billing/subscription-standing.d.ts +61 -0
  16. package/dist/billing/subscription-standing.js +51 -0
  17. package/dist/billing/subscription-standing.js.map +1 -0
  18. package/dist/billing/usage-meter.d.ts +52 -0
  19. package/dist/billing/usage-meter.js +52 -0
  20. package/dist/billing/usage-meter.js.map +1 -0
  21. package/dist/chart.d.ts +1 -0
  22. package/dist/chart.js +4 -0
  23. package/dist/chart.js.map +1 -1
  24. package/dist/components/alert-banner.js +2 -3
  25. package/dist/components/alert-banner.js.map +1 -1
  26. package/dist/components/amount-input.d.ts +2 -1
  27. package/dist/components/amount-input.js +3 -15
  28. package/dist/components/amount-input.js.map +1 -1
  29. package/dist/components/autocomplete.js +2 -2
  30. package/dist/components/autocomplete.js.map +1 -1
  31. package/dist/components/bulk-action-bar.js +2 -1
  32. package/dist/components/bulk-action-bar.js.map +1 -1
  33. package/dist/components/button.d.ts +35 -1
  34. package/dist/components/button.js +5 -9
  35. package/dist/components/button.js.map +1 -1
  36. package/dist/components/calendar-heatmap.js +6 -4
  37. package/dist/components/calendar-heatmap.js.map +1 -1
  38. package/dist/components/camera-button.d.ts +89 -0
  39. package/dist/components/camera-button.js +122 -0
  40. package/dist/components/camera-button.js.map +1 -0
  41. package/dist/components/camera-capture.d.ts +66 -0
  42. package/dist/components/camera-capture.js +190 -0
  43. package/dist/components/camera-capture.js.map +1 -0
  44. package/dist/components/camera-labels.d.ts +20 -0
  45. package/dist/components/camera-labels.js +15 -0
  46. package/dist/components/camera-labels.js.map +1 -0
  47. package/dist/components/chart-edge.d.ts +9 -0
  48. package/dist/components/chart-edge.js +14 -3
  49. package/dist/components/chart-edge.js.map +1 -1
  50. package/dist/components/chart-zoom-core.js +34 -29
  51. package/dist/components/chart-zoom-core.js.map +1 -1
  52. package/dist/components/checkbox-group.js +1 -1
  53. package/dist/components/checkbox-group.js.map +1 -1
  54. package/dist/components/combobox-core.js +3 -2
  55. package/dist/components/combobox-core.js.map +1 -1
  56. package/dist/components/combobox.js +2 -2
  57. package/dist/components/combobox.js.map +1 -1
  58. package/dist/components/consent-again-notice-labels.d.ts +25 -0
  59. package/dist/components/consent-again-notice-labels.js +15 -0
  60. package/dist/components/consent-again-notice-labels.js.map +1 -0
  61. package/dist/components/consent-again-notice.d.ts +85 -0
  62. package/dist/components/consent-again-notice.js +94 -0
  63. package/dist/components/consent-again-notice.js.map +1 -0
  64. package/dist/components/country-select.js +2 -7
  65. package/dist/components/country-select.js.map +1 -1
  66. package/dist/components/currency-option-list.d.ts +2 -1
  67. package/dist/components/currency-option-list.js +10 -3
  68. package/dist/components/currency-option-list.js.map +1 -1
  69. package/dist/components/currency-select.d.ts +3 -1
  70. package/dist/components/currency-select.js +2 -2
  71. package/dist/components/currency-select.js.map +1 -1
  72. package/dist/components/danger-confirm.d.ts +22 -1
  73. package/dist/components/danger-confirm.js +52 -30
  74. package/dist/components/danger-confirm.js.map +1 -1
  75. package/dist/components/data-table-column-settings.js +2 -2
  76. package/dist/components/data-table-column-settings.js.map +1 -1
  77. package/dist/components/data-table-filter-popover.d.ts +2 -1
  78. package/dist/components/data-table-filter-popover.js +3 -2
  79. package/dist/components/data-table-filter-popover.js.map +1 -1
  80. package/dist/components/data-table-filters.d.ts +33 -3
  81. package/dist/components/data-table-filters.js +6 -4
  82. package/dist/components/data-table-filters.js.map +1 -1
  83. package/dist/components/data-table-fit.js.map +1 -1
  84. package/dist/components/data-table-virtual.js +13 -3
  85. package/dist/components/data-table-virtual.js.map +1 -1
  86. package/dist/components/date-field.js +2 -2
  87. package/dist/components/date-field.js.map +1 -1
  88. package/dist/components/date-picker.js +2 -2
  89. package/dist/components/date-picker.js.map +1 -1
  90. package/dist/components/date-range-picker.js +2 -6
  91. package/dist/components/date-range-picker.js.map +1 -1
  92. package/dist/components/dialog-frame.d.ts +5 -1
  93. package/dist/components/dialog-frame.js +6 -2
  94. package/dist/components/dialog-frame.js.map +1 -1
  95. package/dist/components/dropdown.js +7 -3
  96. package/dist/components/dropdown.js.map +1 -1
  97. package/dist/components/entity-combobox.js +2 -2
  98. package/dist/components/entity-combobox.js.map +1 -1
  99. package/dist/components/field-parts.d.ts +108 -6
  100. package/dist/components/field-parts.js +59 -6
  101. package/dist/components/field-parts.js.map +1 -1
  102. package/dist/components/field-suggestion-labels.d.ts +2 -0
  103. package/dist/components/field-suggestion-labels.js +10 -0
  104. package/dist/components/field-suggestion-labels.js.map +1 -0
  105. package/dist/components/field.js +1 -1
  106. package/dist/components/field.js.map +1 -1
  107. package/dist/components/file-button.d.ts +1 -1
  108. package/dist/components/file-button.js.map +1 -1
  109. package/dist/components/floating-panel.d.ts +7 -6
  110. package/dist/components/floating-panel.js +3 -17
  111. package/dist/components/floating-panel.js.map +1 -1
  112. package/dist/components/form-actions.d.ts +3 -2
  113. package/dist/components/form-actions.js.map +1 -1
  114. package/dist/components/hover-menu.js +3 -2
  115. package/dist/components/hover-menu.js.map +1 -1
  116. package/dist/components/icon-button.d.ts +23 -5
  117. package/dist/components/icon-button.js +6 -8
  118. package/dist/components/icon-button.js.map +1 -1
  119. package/dist/components/inline-confirm.js +2 -1
  120. package/dist/components/inline-confirm.js.map +1 -1
  121. package/dist/components/inline-entity-combobox.js +2 -2
  122. package/dist/components/inline-entity-combobox.js.map +1 -1
  123. package/dist/components/input.js +2 -2
  124. package/dist/components/input.js.map +1 -1
  125. package/dist/components/jump-calendar.js +3 -3
  126. package/dist/components/jump-calendar.js.map +1 -1
  127. package/dist/components/legal.d.ts +13 -1
  128. package/dist/components/legal.js +12 -0
  129. package/dist/components/legal.js.map +1 -1
  130. package/dist/components/legended-series-chart.d.ts +80 -0
  131. package/dist/components/legended-series-chart.js +70 -0
  132. package/dist/components/legended-series-chart.js.map +1 -0
  133. package/dist/components/lightbox.js +2 -1
  134. package/dist/components/lightbox.js.map +1 -1
  135. package/dist/components/mini-calendar.js +16 -7
  136. package/dist/components/mini-calendar.js.map +1 -1
  137. package/dist/components/modal.d.ts +48 -0
  138. package/dist/components/modal.js +26 -6
  139. package/dist/components/modal.js.map +1 -1
  140. package/dist/components/month-picker.d.ts +1 -1
  141. package/dist/components/month-picker.js +6 -6
  142. package/dist/components/month-picker.js.map +1 -1
  143. package/dist/components/multi-entity-combobox.js +2 -2
  144. package/dist/components/multi-entity-combobox.js.map +1 -1
  145. package/dist/components/multi-select.js +2 -6
  146. package/dist/components/multi-select.js.map +1 -1
  147. package/dist/components/number-input.js +2 -2
  148. package/dist/components/number-input.js.map +1 -1
  149. package/dist/components/page-header-layout.d.ts +18 -0
  150. package/dist/components/page-header-layout.js +23 -0
  151. package/dist/components/page-header-layout.js.map +1 -0
  152. package/dist/components/page-header-skeleton.d.ts +41 -0
  153. package/dist/components/page-header-skeleton.js +52 -0
  154. package/dist/components/page-header-skeleton.js.map +1 -0
  155. package/dist/components/page-header.js +4 -17
  156. package/dist/components/page-header.js.map +1 -1
  157. package/dist/components/popover.js +7 -2
  158. package/dist/components/popover.js.map +1 -1
  159. package/dist/components/release-notes-labels.d.ts +16 -0
  160. package/dist/components/release-notes-labels.js +18 -0
  161. package/dist/components/release-notes-labels.js.map +1 -0
  162. package/dist/components/release-notes.d.ts +65 -0
  163. package/dist/components/release-notes.js +65 -0
  164. package/dist/components/release-notes.js.map +1 -0
  165. package/dist/components/select.js +2 -2
  166. package/dist/components/select.js.map +1 -1
  167. package/dist/components/series-chart-labels.d.ts +9 -0
  168. package/dist/components/series-chart-labels.js +3 -1
  169. package/dist/components/series-chart-labels.js.map +1 -1
  170. package/dist/components/series-chart.d.ts +5 -0
  171. package/dist/components/series-chart.js +89 -36
  172. package/dist/components/series-chart.js.map +1 -1
  173. package/dist/components/stat-tile.d.ts +21 -2
  174. package/dist/components/stat-tile.js +4 -2
  175. package/dist/components/stat-tile.js.map +1 -1
  176. package/dist/components/toggle-group.js +3 -2
  177. package/dist/components/toggle-group.js.map +1 -1
  178. package/dist/components/treemap-layout.js.map +1 -1
  179. package/dist/components/treemap.d.ts +17 -15
  180. package/dist/components/treemap.js +167 -85
  181. package/dist/components/treemap.js.map +1 -1
  182. package/dist/currencies.d.ts +16 -2
  183. package/dist/currencies.js +2 -1
  184. package/dist/currencies.js.map +1 -1
  185. package/dist/eslint/index.js +1 -1
  186. package/dist/eslint/role-utilities.d.ts +2 -2
  187. package/dist/eslint/role-utilities.js.map +1 -1
  188. package/dist/feedback/feedback-context-labels.js +2 -1
  189. package/dist/feedback/feedback-context-labels.js.map +1 -1
  190. package/dist/feedback/feedback-context.d.ts +19 -3
  191. package/dist/feedback/feedback-context.js +12 -1
  192. package/dist/feedback/feedback-context.js.map +1 -1
  193. package/dist/feedback/feedback-diagnostics.d.ts +17 -0
  194. package/dist/feedback/feedback-diagnostics.js +27 -0
  195. package/dist/feedback/feedback-diagnostics.js.map +1 -0
  196. package/dist/feedback/feedback-dialog.d.ts +10 -0
  197. package/dist/feedback/feedback-dialog.js +6 -4
  198. package/dist/feedback/feedback-dialog.js.map +1 -1
  199. package/dist/feedback/feedback-inbox-page.d.ts +260 -0
  200. package/dist/feedback/feedback-inbox-page.js +207 -0
  201. package/dist/feedback/feedback-inbox-page.js.map +1 -0
  202. package/dist/feedback/feedback-record.d.ts +5 -0
  203. package/dist/feedback/feedback-record.js.map +1 -1
  204. package/dist/feedback/feedback-row-detail-labels.js +1 -0
  205. package/dist/feedback/feedback-row-detail-labels.js.map +1 -1
  206. package/dist/feedback/feedback-row-detail.d.ts +3 -0
  207. package/dist/feedback/feedback-row-detail.js +3 -0
  208. package/dist/feedback/feedback-row-detail.js.map +1 -1
  209. package/dist/feedback/feedback-submit-dialog.d.ts +5 -1
  210. package/dist/feedback/feedback-submit-dialog.js +15 -3
  211. package/dist/feedback/feedback-submit-dialog.js.map +1 -1
  212. package/dist/feedback/feedback-submit.d.ts +30 -2
  213. package/dist/feedback/feedback-submit.js +5 -2
  214. package/dist/feedback/feedback-submit.js.map +1 -1
  215. package/dist/feedback/feedback-vocabulary.js +2 -2
  216. package/dist/feedback/feedback-vocabulary.js.map +1 -1
  217. package/dist/feedback.d.ts +1 -0
  218. package/dist/feedback.js +6 -0
  219. package/dist/feedback.js.map +1 -1
  220. package/dist/hooks/use-debounce.d.ts +32 -5
  221. package/dist/hooks/use-debounce.js +6 -5
  222. package/dist/hooks/use-debounce.js.map +1 -1
  223. package/dist/hooks/use-file-picker.d.ts +3 -1
  224. package/dist/hooks/use-file-picker.js.map +1 -1
  225. package/dist/hooks/use-focus-trap.d.ts +19 -3
  226. package/dist/hooks/use-focus-trap.js +15 -5
  227. package/dist/hooks/use-focus-trap.js.map +1 -1
  228. package/dist/hooks/use-has-camera.d.ts +36 -0
  229. package/dist/hooks/use-has-camera.js +53 -0
  230. package/dist/hooks/use-has-camera.js.map +1 -0
  231. package/dist/hooks/use-hotkey.js +2 -1
  232. package/dist/hooks/use-hotkey.js.map +1 -1
  233. package/dist/hooks/use-overlay-history.d.ts +6 -1
  234. package/dist/hooks/use-overlay-history.js +10 -2
  235. package/dist/hooks/use-overlay-history.js.map +1 -1
  236. package/dist/i18n/defaults.js +11 -1
  237. package/dist/i18n/defaults.js.map +1 -1
  238. package/dist/i18n/german.js +78 -4
  239. package/dist/i18n/german.js.map +1 -1
  240. package/dist/i18n/kit-labels.d.ts +20 -0
  241. package/dist/i18n/kit-labels.js.map +1 -1
  242. package/dist/i18n/locales/en.js +95 -5
  243. package/dist/i18n/locales/en.js.map +3 -3
  244. package/dist/i18n/locales/es.js +74 -4
  245. package/dist/i18n/locales/es.js.map +1 -1
  246. package/dist/i18n/locales/fr.js +75 -3
  247. package/dist/i18n/locales/fr.js.map +1 -1
  248. package/dist/i18n/locales/hu.js +77 -4
  249. package/dist/i18n/locales/hu.js.map +1 -1
  250. package/dist/i18n/locales/it.js +77 -4
  251. package/dist/i18n/locales/it.js.map +1 -1
  252. package/dist/i18n/locales/zh.js +74 -4
  253. package/dist/i18n/locales/zh.js.map +1 -1
  254. package/dist/i18n/review.js +22 -1
  255. package/dist/i18n/review.js.map +1 -1
  256. package/dist/index.d.ts +27 -8
  257. package/dist/index.js +41 -2
  258. package/dist/index.js.map +1 -1
  259. package/dist/landing/landing-labels.d.ts +8 -0
  260. package/dist/landing/landing-labels.js +2 -1
  261. package/dist/landing/landing-labels.js.map +1 -1
  262. package/dist/lib/changelog.d.ts +130 -0
  263. package/dist/lib/changelog.js +137 -0
  264. package/dist/lib/changelog.js.map +1 -0
  265. package/dist/lib/clipboard-minus.js +2 -2
  266. package/dist/lib/clipboard-minus.js.map +1 -1
  267. package/dist/lib/dates.d.ts +36 -4
  268. package/dist/lib/dates.js +49 -13
  269. package/dist/lib/dates.js.map +1 -1
  270. package/dist/lib/editable-content.d.ts +33 -0
  271. package/dist/lib/editable-content.js +15 -0
  272. package/dist/lib/editable-content.js.map +1 -0
  273. package/dist/lib/focus-left.d.ts +47 -1
  274. package/dist/lib/focus-left.js +11 -2
  275. package/dist/lib/focus-left.js.map +1 -1
  276. package/dist/lib/format.d.ts +37 -2
  277. package/dist/lib/format.js +25 -1
  278. package/dist/lib/format.js.map +1 -1
  279. package/dist/lib/intl-cache.d.ts +4 -2
  280. package/dist/lib/intl-cache.js.map +1 -1
  281. package/dist/lib/server-wake.d.ts +49 -9
  282. package/dist/lib/server-wake.js +25 -14
  283. package/dist/lib/server-wake.js.map +1 -1
  284. package/dist/lib/session-refresh.d.ts +53 -0
  285. package/dist/lib/session-refresh.js +27 -1
  286. package/dist/lib/session-refresh.js.map +1 -1
  287. package/dist/lib/translation-review.d.ts +26 -0
  288. package/dist/lib/translation-review.js +14 -0
  289. package/dist/lib/translation-review.js.map +1 -1
  290. package/dist/rhf/fields.js +3 -3
  291. package/dist/rhf/fields.js.map +1 -1
  292. package/dist/shell/app-shell.d.ts +25 -1
  293. package/dist/shell/app-shell.js +3 -1
  294. package/dist/shell/app-shell.js.map +1 -1
  295. package/dist/shell/dev-menu.d.ts +3 -0
  296. package/dist/shell/dev-menu.js +4 -2
  297. package/dist/shell/dev-menu.js.map +1 -1
  298. package/dist/shell/held-changes-banner-labels.d.ts +23 -0
  299. package/dist/shell/held-changes-banner-labels.js +14 -0
  300. package/dist/shell/held-changes-banner-labels.js.map +1 -0
  301. package/dist/shell/held-changes-banner.d.ts +75 -0
  302. package/dist/shell/held-changes-banner.js +106 -0
  303. package/dist/shell/held-changes-banner.js.map +1 -0
  304. package/dist/shell/sync-status-indicator.d.ts +27 -12
  305. package/dist/shell/sync-status-indicator.js +13 -4
  306. package/dist/shell/sync-status-indicator.js.map +1 -1
  307. package/dist/shell/top-bar-parts-labels.d.ts +5 -0
  308. package/dist/shell/top-bar-parts-labels.js +3 -1
  309. package/dist/shell/top-bar-parts-labels.js.map +1 -1
  310. package/dist/shell.d.ts +2 -0
  311. package/dist/shell.js +3 -0
  312. package/dist/shell.js.map +1 -1
  313. package/dist/sync/engine.d.ts +11 -2
  314. package/dist/sync/engine.js +13 -5
  315. package/dist/sync/engine.js.map +1 -1
  316. package/dist/sync/hooks.d.ts +3 -2
  317. package/dist/sync/hooks.js +4 -2
  318. package/dist/sync/hooks.js.map +1 -1
  319. package/dist/testing/css-variables.generated.d.ts +2 -2
  320. package/dist/testing/css-variables.generated.js +1 -1
  321. package/dist/testing/css-variables.generated.js.map +1 -1
  322. package/dist/theme/chart-palette.d.ts +18 -0
  323. package/dist/theme/chart-palette.js +17 -1
  324. package/dist/theme/chart-palette.js.map +1 -1
  325. package/dist/theme/contrast-tokens.d.ts +3 -3
  326. package/dist/theme/contrast-tokens.js.map +1 -1
  327. package/dist/theme/contrast.d.ts +4 -4
  328. package/dist/theme/contrast.js.map +1 -1
  329. package/dist/tour/tour-overlay.js +2 -1
  330. package/dist/tour/tour-overlay.js.map +1 -1
  331. package/package.json +5 -9
  332. package/tokens.css +19 -54
  333. package/src/account/account-parts.ts +0 -47
  334. package/src/account/account-settings-labels.ts +0 -240
  335. package/src/account/account-settings.tsx +0 -698
  336. package/src/account/data-export-setting-labels.ts +0 -20
  337. package/src/account/data-export-setting.tsx +0 -200
  338. package/src/account/delete-account-setting-labels.ts +0 -33
  339. package/src/account/delete-account-setting.tsx +0 -341
  340. package/src/account/email-change-setting-labels.ts +0 -31
  341. package/src/account/email-change-setting.tsx +0 -443
  342. package/src/account/passkeys-setting.tsx +0 -445
  343. package/src/account/sessions-setting-labels.ts +0 -24
  344. package/src/account/sessions-setting.tsx +0 -283
  345. package/src/admin/admin-action-confirm-labels.ts +0 -19
  346. package/src/admin/admin-action-confirm.tsx +0 -509
  347. package/src/admin/admin-action-log-labels.ts +0 -83
  348. package/src/admin/admin-action-log.tsx +0 -464
  349. package/src/admin/admin-area-labels.ts +0 -114
  350. package/src/admin/admin-forbidden.tsx +0 -75
  351. package/src/admin/admin-overview.tsx +0 -258
  352. package/src/admin/admin-parts.ts +0 -68
  353. package/src/admin/admin-sections.tsx +0 -208
  354. package/src/admin/admin-tool-links.tsx +0 -90
  355. package/src/admin/invitations-panel-labels.ts +0 -31
  356. package/src/admin/invitations-panel.tsx +0 -516
  357. package/src/admin/mail-test-card-labels.ts +0 -19
  358. package/src/admin/mail-test-card.tsx +0 -189
  359. package/src/admin/plan-change-labels.ts +0 -5
  360. package/src/admin/plan-change.tsx +0 -474
  361. package/src/admin/reviewer-scope-editor-labels.ts +0 -16
  362. package/src/admin/reviewer-scope-editor.tsx +0 -224
  363. package/src/admin/role-select-labels.ts +0 -16
  364. package/src/admin/role-select.tsx +0 -282
  365. package/src/admin/transfer-ownership-dialog-labels.ts +0 -20
  366. package/src/admin/transfer-ownership-dialog.tsx +0 -162
  367. package/src/admin/user-roster-labels.ts +0 -17
  368. package/src/admin/user-roster.tsx +0 -559
  369. package/src/auth/accept-invitation-labels.ts +0 -21
  370. package/src/auth/accept-invitation.tsx +0 -210
  371. package/src/auth/auth-errors-labels.ts +0 -23
  372. package/src/auth/auth-errors.ts +0 -370
  373. package/src/auth/complete-name-dialog-labels.ts +0 -16
  374. package/src/auth/complete-name-dialog.tsx +0 -253
  375. package/src/auth/email-tag.ts +0 -75
  376. package/src/auth/forgot-password-form-labels.ts +0 -20
  377. package/src/auth/forgot-password-form.tsx +0 -221
  378. package/src/auth/form-rules.ts +0 -40
  379. package/src/auth/new-password-fields.tsx +0 -85
  380. package/src/auth/not-found-page-labels.ts +0 -12
  381. package/src/auth/not-found-page.tsx +0 -95
  382. package/src/auth/register-form-labels.ts +0 -31
  383. package/src/auth/register-form.tsx +0 -456
  384. package/src/auth/reset-password-form-labels.ts +0 -27
  385. package/src/auth/reset-password-form.tsx +0 -341
  386. package/src/auth/sign-in-form-labels.ts +0 -44
  387. package/src/auth/sign-in-form.tsx +0 -858
  388. package/src/auth/status-parts.tsx +0 -132
  389. package/src/auth/verify-email-labels.ts +0 -26
  390. package/src/auth/verify-email.tsx +0 -445
  391. package/src/billing/billing-banner.tsx +0 -258
  392. package/src/billing/billing-labels.ts +0 -381
  393. package/src/billing/billing-lock.ts +0 -108
  394. package/src/billing/billing-overview.ts +0 -157
  395. package/src/billing/billing-standing.ts +0 -80
  396. package/src/billing/cancel-request.ts +0 -97
  397. package/src/billing/cancel-subscription.tsx +0 -98
  398. package/src/billing/checkout-processing.ts +0 -394
  399. package/src/billing/checkout-return.ts +0 -90
  400. package/src/billing/pay-page.ts +0 -330
  401. package/src/billing/plan-card.tsx +0 -562
  402. package/src/billing/plan-change-labels.ts +0 -66
  403. package/src/billing/plan-limit-notice.tsx +0 -148
  404. package/src/billing/plan-limit-toast.tsx +0 -90
  405. package/src/billing/plan-limit.ts +0 -52
  406. package/src/billing/plan-price.ts +0 -98
  407. package/src/billing/plan-switch.tsx +0 -216
  408. package/src/billing/provider-page.ts +0 -84
  409. package/src/billing/subscription-actions.tsx +0 -247
  410. package/src/billing/subscription-status-chip.tsx +0 -95
  411. package/src/chart.ts +0 -103
  412. package/src/components/account-chips-labels.ts +0 -16
  413. package/src/components/account-chips.tsx +0 -474
  414. package/src/components/alert-banner.tsx +0 -670
  415. package/src/components/amount-input.tsx +0 -815
  416. package/src/components/appearance-labels.ts +0 -63
  417. package/src/components/authed-image-labels.ts +0 -11
  418. package/src/components/authed-image.tsx +0 -209
  419. package/src/components/autocomplete.tsx +0 -645
  420. package/src/components/breadcrumbs-labels.ts +0 -10
  421. package/src/components/breadcrumbs.tsx +0 -205
  422. package/src/components/bulk-action-bar-labels.ts +0 -11
  423. package/src/components/bulk-action-bar.tsx +0 -443
  424. package/src/components/button-group.tsx +0 -223
  425. package/src/components/button-look.ts +0 -256
  426. package/src/components/button.tsx +0 -339
  427. package/src/components/calculator.tsx +0 -341
  428. package/src/components/calendar-heatmap-labels.ts +0 -15
  429. package/src/components/calendar-heatmap.tsx +0 -594
  430. package/src/components/card.tsx +0 -377
  431. package/src/components/chart-edge.ts +0 -106
  432. package/src/components/chart-figure.tsx +0 -35
  433. package/src/components/chart-height.ts +0 -30
  434. package/src/components/chart-zoom-core.tsx +0 -627
  435. package/src/components/chart-zoom.tsx +0 -22
  436. package/src/components/chart.tsx +0 -554
  437. package/src/components/checkbox-group.tsx +0 -247
  438. package/src/components/checkbox.tsx +0 -346
  439. package/src/components/chip-input.tsx +0 -370
  440. package/src/components/chip-labels.ts +0 -13
  441. package/src/components/chip.tsx +0 -843
  442. package/src/components/choice-card.tsx +0 -544
  443. package/src/components/column-mapper-labels.ts +0 -38
  444. package/src/components/column-mapper.tsx +0 -655
  445. package/src/components/combobox-core.tsx +0 -1321
  446. package/src/components/combobox-suggestions.tsx +0 -131
  447. package/src/components/combobox.tsx +0 -716
  448. package/src/components/confirm-context.ts +0 -7
  449. package/src/components/confirm-dialog-labels.ts +0 -13
  450. package/src/components/confirm-dialog.tsx +0 -341
  451. package/src/components/copy-button-labels.ts +0 -13
  452. package/src/components/copy-button.tsx +0 -192
  453. package/src/components/country-select-labels.ts +0 -11
  454. package/src/components/country-select.tsx +0 -539
  455. package/src/components/currency-option-list.tsx +0 -180
  456. package/src/components/currency-select.tsx +0 -341
  457. package/src/components/danger-confirm-labels.ts +0 -20
  458. package/src/components/danger-confirm.tsx +0 -934
  459. package/src/components/data-table-cells.tsx +0 -118
  460. package/src/components/data-table-column-settings.tsx +0 -198
  461. package/src/components/data-table-filter-popover.tsx +0 -281
  462. package/src/components/data-table-filters.ts +0 -287
  463. package/src/components/data-table-fit.ts +0 -301
  464. package/src/components/data-table-groups.tsx +0 -288
  465. package/src/components/data-table-head.tsx +0 -280
  466. package/src/components/data-table-labels.ts +0 -198
  467. package/src/components/data-table-leading-row.tsx +0 -58
  468. package/src/components/data-table-mobile.tsx +0 -1117
  469. package/src/components/data-table-pagination.tsx +0 -202
  470. package/src/components/data-table-resize.ts +0 -188
  471. package/src/components/data-table-row-actions.tsx +0 -302
  472. package/src/components/data-table-row.tsx +0 -496
  473. package/src/components/data-table-selection.ts +0 -71
  474. package/src/components/data-table-shared.tsx +0 -287
  475. package/src/components/data-table-sort.ts +0 -163
  476. package/src/components/data-table-virtual.ts +0 -576
  477. package/src/components/data-table.tsx +0 -2598
  478. package/src/components/date-field.tsx +0 -684
  479. package/src/components/date-format-setting.tsx +0 -64
  480. package/src/components/date-picker.tsx +0 -404
  481. package/src/components/date-range-picker.tsx +0 -518
  482. package/src/components/description-list-labels.ts +0 -9
  483. package/src/components/description-list.tsx +0 -386
  484. package/src/components/dialog-frame-labels.ts +0 -7
  485. package/src/components/dialog-frame.tsx +0 -276
  486. package/src/components/disclosure.tsx +0 -476
  487. package/src/components/dropdown.tsx +0 -461
  488. package/src/components/empty-state.tsx +0 -136
  489. package/src/components/entity-combobox.tsx +0 -422
  490. package/src/components/error-boundary-labels.ts +0 -20
  491. package/src/components/error-boundary.tsx +0 -675
  492. package/src/components/facing-pair.ts +0 -93
  493. package/src/components/field-base-labels.ts +0 -20
  494. package/src/components/field-base.tsx +0 -656
  495. package/src/components/field-parts.tsx +0 -825
  496. package/src/components/field-strip.tsx +0 -129
  497. package/src/components/field.tsx +0 -206
  498. package/src/components/file-button.tsx +0 -295
  499. package/src/components/file-dropzone.tsx +0 -559
  500. package/src/components/floating-panel-labels.ts +0 -10
  501. package/src/components/floating-panel.tsx +0 -828
  502. package/src/components/focus-ring.ts +0 -16
  503. package/src/components/form-actions-labels.ts +0 -11
  504. package/src/components/form-actions.tsx +0 -578
  505. package/src/components/full-bleed-dialog.tsx +0 -294
  506. package/src/components/grouped-picker.tsx +0 -184
  507. package/src/components/help-popover.tsx +0 -117
  508. package/src/components/hover-menu.tsx +0 -343
  509. package/src/components/iban-input-labels.ts +0 -14
  510. package/src/components/iban-input.tsx +0 -236
  511. package/src/components/icon-button.tsx +0 -959
  512. package/src/components/icon-picker-labels.ts +0 -13
  513. package/src/components/icon-picker.tsx +0 -232
  514. package/src/components/image-grid-labels.ts +0 -11
  515. package/src/components/image-grid.tsx +0 -202
  516. package/src/components/inline-confirm.tsx +0 -116
  517. package/src/components/inline-edit-field-labels.ts +0 -11
  518. package/src/components/inline-edit-field.tsx +0 -552
  519. package/src/components/inline-entity-combobox.tsx +0 -849
  520. package/src/components/input.tsx +0 -394
  521. package/src/components/jump-calendar.tsx +0 -265
  522. package/src/components/language-select.tsx +0 -93
  523. package/src/components/legal-labels.ts +0 -105
  524. package/src/components/legal-page.tsx +0 -711
  525. package/src/components/legal.tsx +0 -668
  526. package/src/components/lightbox-labels.ts +0 -18
  527. package/src/components/lightbox.tsx +0 -399
  528. package/src/components/line-items-labels.ts +0 -14
  529. package/src/components/line-items.tsx +0 -602
  530. package/src/components/list-labels.ts +0 -12
  531. package/src/components/list.tsx +0 -870
  532. package/src/components/loading-state.tsx +0 -78
  533. package/src/components/measured-grid-labels.ts +0 -25
  534. package/src/components/measured-grid.tsx +0 -837
  535. package/src/components/menu-item.tsx +0 -241
  536. package/src/components/mini-calendar-labels.ts +0 -17
  537. package/src/components/mini-calendar.tsx +0 -789
  538. package/src/components/modal.tsx +0 -505
  539. package/src/components/money-draft.ts +0 -83
  540. package/src/components/money-field.tsx +0 -76
  541. package/src/components/month-grid.tsx +0 -229
  542. package/src/components/month-picker-labels.ts +0 -22
  543. package/src/components/month-picker.tsx +0 -1087
  544. package/src/components/multi-entity-combobox.tsx +0 -369
  545. package/src/components/multi-select.tsx +0 -376
  546. package/src/components/nav-pills.tsx +0 -198
  547. package/src/components/number-field.tsx +0 -327
  548. package/src/components/number-input.tsx +0 -558
  549. package/src/components/numeric-field.ts +0 -169
  550. package/src/components/numpad-sheet.tsx +0 -285
  551. package/src/components/one-time-code-input.tsx +0 -270
  552. package/src/components/page-contents-labels.ts +0 -9
  553. package/src/components/page-contents.tsx +0 -282
  554. package/src/components/page-header-context.ts +0 -8
  555. package/src/components/page-header.tsx +0 -298
  556. package/src/components/password-strength-labels.ts +0 -22
  557. package/src/components/password-strength.tsx +0 -241
  558. package/src/components/phone-input-labels.ts +0 -10
  559. package/src/components/phone-input.tsx +0 -282
  560. package/src/components/picker-sheet.tsx +0 -330
  561. package/src/components/pie-chart-labels.ts +0 -40
  562. package/src/components/pie-chart.tsx +0 -480
  563. package/src/components/popover-labels.ts +0 -14
  564. package/src/components/popover.tsx +0 -268
  565. package/src/components/progress-bar-labels.ts +0 -10
  566. package/src/components/progress-bar.tsx +0 -479
  567. package/src/components/qr-code.tsx +0 -76
  568. package/src/components/reauth-dialog-labels.ts +0 -13
  569. package/src/components/reauth-dialog.tsx +0 -265
  570. package/src/components/row-actions-labels.ts +0 -12
  571. package/src/components/row-actions.tsx +0 -795
  572. package/src/components/scroll-area.tsx +0 -123
  573. package/src/components/search-field.tsx +0 -192
  574. package/src/components/select.tsx +0 -294
  575. package/src/components/separator.tsx +0 -33
  576. package/src/components/series-chart-axes.ts +0 -342
  577. package/src/components/series-chart-budget.ts +0 -150
  578. package/src/components/series-chart-labels.ts +0 -33
  579. package/src/components/series-chart-thin.ts +0 -180
  580. package/src/components/series-chart-ticks.ts +0 -194
  581. package/src/components/series-chart.tsx +0 -1906
  582. package/src/components/server-wake-labels.ts +0 -11
  583. package/src/components/server-wake.tsx +0 -129
  584. package/src/components/settings-fields.tsx +0 -237
  585. package/src/components/share-card-labels.ts +0 -30
  586. package/src/components/share-card.tsx +0 -675
  587. package/src/components/signature-pad-labels.ts +0 -24
  588. package/src/components/signature-pad.tsx +0 -747
  589. package/src/components/signed-amount-labels.ts +0 -10
  590. package/src/components/signed-amount.tsx +0 -336
  591. package/src/components/skeleton.tsx +0 -80
  592. package/src/components/slider.tsx +0 -338
  593. package/src/components/sparkline-labels.ts +0 -14
  594. package/src/components/sparkline.tsx +0 -322
  595. package/src/components/spinner.tsx +0 -81
  596. package/src/components/stat-tile-labels.ts +0 -15
  597. package/src/components/stat-tile.tsx +0 -725
  598. package/src/components/status-dot.tsx +0 -170
  599. package/src/components/swatch-picker-labels.ts +0 -10
  600. package/src/components/swatch-picker.tsx +0 -283
  601. package/src/components/swipeable-row.tsx +0 -386
  602. package/src/components/switch.tsx +0 -273
  603. package/src/components/table-skeleton.tsx +0 -136
  604. package/src/components/table.tsx +0 -647
  605. package/src/components/tabs-labels.ts +0 -13
  606. package/src/components/tabs.tsx +0 -693
  607. package/src/components/text-link.tsx +0 -359
  608. package/src/components/text.tsx +0 -150
  609. package/src/components/textarea.tsx +0 -330
  610. package/src/components/tile-radio.tsx +0 -332
  611. package/src/components/time-input.tsx +0 -121
  612. package/src/components/toast-labels.ts +0 -12
  613. package/src/components/toast.tsx +0 -519
  614. package/src/components/toggle-group.tsx +0 -752
  615. package/src/components/toggle-legend.tsx +0 -394
  616. package/src/components/tooltip.tsx +0 -1149
  617. package/src/components/translation-review-editor.tsx +0 -290
  618. package/src/components/translation-review-labels.ts +0 -181
  619. package/src/components/translation-review-parts.tsx +0 -272
  620. package/src/components/translation-review.tsx +0 -1240
  621. package/src/components/tree-view.tsx +0 -589
  622. package/src/components/treemap-labels.ts +0 -47
  623. package/src/components/treemap-layout.ts +0 -210
  624. package/src/components/treemap.tsx +0 -1184
  625. package/src/components/trigger-aria.ts +0 -44
  626. package/src/components/use-anchor-dir.ts +0 -20
  627. package/src/components/use-mobile-reveal.ts +0 -62
  628. package/src/components/use-table-state.ts +0 -753
  629. package/src/components/user-avatar.tsx +0 -116
  630. package/src/components/wizard-stepper.tsx +0 -42
  631. package/src/components/write-lock-labels.ts +0 -10
  632. package/src/components/write-lock.tsx +0 -253
  633. package/src/currencies.ts +0 -70
  634. package/src/data-table.ts +0 -42
  635. package/src/demo/demo-banner.tsx +0 -153
  636. package/src/demo/demo-countdown.ts +0 -136
  637. package/src/demo/demo-ended.tsx +0 -90
  638. package/src/demo/demo-labels.ts +0 -78
  639. package/src/demo/demo-session.ts +0 -32
  640. package/src/demo/demo-start.tsx +0 -156
  641. package/src/eslint/index.ts +0 -161
  642. package/src/eslint/role-utilities.generated.ts +0 -146
  643. package/src/eslint/role-utilities.ts +0 -233
  644. package/src/feedback/feedback-attachment-download.tsx +0 -77
  645. package/src/feedback/feedback-attachment-labels.ts +0 -37
  646. package/src/feedback/feedback-attachment.tsx +0 -1239
  647. package/src/feedback/feedback-capture.ts +0 -287
  648. package/src/feedback/feedback-comment-thread.tsx +0 -353
  649. package/src/feedback/feedback-context-labels.ts +0 -10
  650. package/src/feedback/feedback-context.tsx +0 -213
  651. package/src/feedback/feedback-crash.ts +0 -547
  652. package/src/feedback/feedback-dialog-labels.ts +0 -29
  653. package/src/feedback/feedback-dialog.tsx +0 -440
  654. package/src/feedback/feedback-entry-file.tsx +0 -150
  655. package/src/feedback/feedback-inbox.tsx +0 -552
  656. package/src/feedback/feedback-labels.ts +0 -144
  657. package/src/feedback/feedback-menu-labels.ts +0 -12
  658. package/src/feedback/feedback-menu.tsx +0 -177
  659. package/src/feedback/feedback-mutation.ts +0 -20
  660. package/src/feedback/feedback-page-link.ts +0 -90
  661. package/src/feedback/feedback-public-labels.ts +0 -81
  662. package/src/feedback/feedback-public-list.tsx +0 -524
  663. package/src/feedback/feedback-public-switch.tsx +0 -102
  664. package/src/feedback/feedback-public-types.ts +0 -101
  665. package/src/feedback/feedback-record.ts +0 -423
  666. package/src/feedback/feedback-replies-context.ts +0 -9
  667. package/src/feedback/feedback-replies.tsx +0 -343
  668. package/src/feedback/feedback-rework-entry-chip.tsx +0 -18
  669. package/src/feedback/feedback-row-detail-labels.ts +0 -30
  670. package/src/feedback/feedback-row-detail.tsx +0 -858
  671. package/src/feedback/feedback-status-undo.ts +0 -109
  672. package/src/feedback/feedback-submit-dialog.tsx +0 -118
  673. package/src/feedback/feedback-submit.tsx +0 -237
  674. package/src/feedback/feedback-swipe.tsx +0 -192
  675. package/src/feedback/feedback-table-labels.ts +0 -27
  676. package/src/feedback/feedback-table.tsx +0 -912
  677. package/src/feedback/feedback-thread-labels.ts +0 -22
  678. package/src/feedback/feedback-thread-parts-labels.ts +0 -41
  679. package/src/feedback/feedback-thread.tsx +0 -905
  680. package/src/feedback/feedback-vocabulary.ts +0 -263
  681. package/src/feedback/feedback-vote-button.tsx +0 -124
  682. package/src/feedback.ts +0 -116
  683. package/src/hooks/use-anchored-panel.ts +0 -396
  684. package/src/hooks/use-anchored-rect.ts +0 -77
  685. package/src/hooks/use-announce.ts +0 -85
  686. package/src/hooks/use-authed-src.ts +0 -167
  687. package/src/hooks/use-body-scroll-lock.ts +0 -119
  688. package/src/hooks/use-breakpoint.ts +0 -133
  689. package/src/hooks/use-close-transition.ts +0 -107
  690. package/src/hooks/use-copy-to-clipboard.ts +0 -122
  691. package/src/hooks/use-debounce.ts +0 -114
  692. package/src/hooks/use-dismiss.ts +0 -371
  693. package/src/hooks/use-document-title.ts +0 -33
  694. package/src/hooks/use-file-drop.ts +0 -121
  695. package/src/hooks/use-file-picker-labels.ts +0 -28
  696. package/src/hooks/use-file-picker.tsx +0 -359
  697. package/src/hooks/use-focus-trap.ts +0 -199
  698. package/src/hooks/use-hotkey.ts +0 -189
  699. package/src/hooks/use-large-text.ts +0 -41
  700. package/src/hooks/use-long-press.ts +0 -140
  701. package/src/hooks/use-media-query.ts +0 -39
  702. package/src/hooks/use-mounted.ts +0 -39
  703. package/src/hooks/use-noindex.ts +0 -37
  704. package/src/hooks/use-overlay-history.ts +0 -714
  705. package/src/hooks/use-row-swipe.ts +0 -207
  706. package/src/hooks/use-search-param-state.ts +0 -434
  707. package/src/hooks/use-windowed-rows.ts +0 -225
  708. package/src/i18n/defaults.ts +0 -267
  709. package/src/i18n/german.ts +0 -2057
  710. package/src/i18n/kit-labels.tsx +0 -1003
  711. package/src/i18n/languages.ts +0 -349
  712. package/src/i18n/locales/de-CH.ts +0 -24
  713. package/src/i18n/locales/en.ts +0 -267
  714. package/src/i18n/locales/es.ts +0 -1997
  715. package/src/i18n/locales/fr.ts +0 -2035
  716. package/src/i18n/locales/hu.ts +0 -2002
  717. package/src/i18n/locales/it.ts +0 -2012
  718. package/src/i18n/locales/zh.ts +0 -1910
  719. package/src/i18n/plurals.ts +0 -86
  720. package/src/i18n/review.ts +0 -475
  721. package/src/i18n/shared-labels.ts +0 -138
  722. package/src/i18n/swiss.ts +0 -29
  723. package/src/index.ts +0 -1179
  724. package/src/landing/access.ts +0 -93
  725. package/src/landing/landing-actions.tsx +0 -97
  726. package/src/landing/landing-labels.ts +0 -59
  727. package/src/landing/landing-sections.tsx +0 -341
  728. package/src/landing/page-seo.ts +0 -261
  729. package/src/landing/public-header.tsx +0 -121
  730. package/src/landing/public-page.tsx +0 -106
  731. package/src/landing/routing.tsx +0 -225
  732. package/src/lib/broadcast.ts +0 -52
  733. package/src/lib/calc.ts +0 -323
  734. package/src/lib/chip-edge-snap.ts +0 -212
  735. package/src/lib/clipboard-minus.ts +0 -107
  736. package/src/lib/clipping.ts +0 -34
  737. package/src/lib/cn.ts +0 -28
  738. package/src/lib/column-mapping.ts +0 -234
  739. package/src/lib/countries.ts +0 -91
  740. package/src/lib/data-attributes.ts +0 -14
  741. package/src/lib/date-format.ts +0 -227
  742. package/src/lib/dates.ts +0 -266
  743. package/src/lib/day-format.ts +0 -96
  744. package/src/lib/decimal-marks.ts +0 -108
  745. package/src/lib/describe-failure.ts +0 -18
  746. package/src/lib/device-settings.ts +0 -147
  747. package/src/lib/direction.ts +0 -74
  748. package/src/lib/document-navigation.ts +0 -17
  749. package/src/lib/document-title.ts +0 -41
  750. package/src/lib/download.ts +0 -172
  751. package/src/lib/float-clearance.ts +0 -70
  752. package/src/lib/floating-stack.ts +0 -70
  753. package/src/lib/focus-left.ts +0 -156
  754. package/src/lib/format.ts +0 -522
  755. package/src/lib/http-status.ts +0 -38
  756. package/src/lib/iban.ts +0 -251
  757. package/src/lib/ime.ts +0 -24
  758. package/src/lib/intl-cache.ts +0 -25
  759. package/src/lib/iso-day.ts +0 -13
  760. package/src/lib/lazy-with-fallback.ts +0 -82
  761. package/src/lib/logger.ts +0 -69
  762. package/src/lib/minus.ts +0 -50
  763. package/src/lib/path-pattern.ts +0 -55
  764. package/src/lib/person-name.ts +0 -155
  765. package/src/lib/phone.ts +0 -208
  766. package/src/lib/plain-text.ts +0 -22
  767. package/src/lib/presence.ts +0 -18
  768. package/src/lib/qr-encode.ts +0 -444
  769. package/src/lib/quiet-focus.ts +0 -32
  770. package/src/lib/reduced-motion.ts +0 -22
  771. package/src/lib/refs.ts +0 -22
  772. package/src/lib/round.ts +0 -43
  773. package/src/lib/safe-storage.ts +0 -119
  774. package/src/lib/server-wake.ts +0 -315
  775. package/src/lib/session-refresh.ts +0 -472
  776. package/src/lib/share-format.ts +0 -18
  777. package/src/lib/status-tone.ts +0 -43
  778. package/src/lib/strip-fade.ts +0 -287
  779. package/src/lib/table-text.ts +0 -554
  780. package/src/lib/text-case.ts +0 -19
  781. package/src/lib/text-match.ts +0 -169
  782. package/src/lib/thenable.ts +0 -19
  783. package/src/lib/translation-review.ts +0 -717
  784. package/src/notifications/device-zone-report.ts +0 -67
  785. package/src/notifications/feedback-notification-types-labels.ts +0 -33
  786. package/src/notifications/feedback-notification-types.ts +0 -71
  787. package/src/notifications/notification-bell.tsx +0 -119
  788. package/src/notifications/notification-inbox.tsx +0 -309
  789. package/src/notifications/notification-parts.tsx +0 -81
  790. package/src/notifications/notification-types-setting.tsx +0 -406
  791. package/src/notifications/notification-types.ts +0 -89
  792. package/src/notifications/notifications-labels.ts +0 -287
  793. package/src/notifications/push-device-setting.tsx +0 -230
  794. package/src/notifications/push-devices-setting.tsx +0 -374
  795. package/src/notifications/push-worker.ts +0 -168
  796. package/src/notifications/quiet-hours-setting.tsx +0 -238
  797. package/src/notifications/unsubscribe-panel.tsx +0 -200
  798. package/src/notifications/use-push-device.ts +0 -448
  799. package/src/offline/local-first.ts +0 -100
  800. package/src/offline/pwa-update-prompt-labels.ts +0 -9
  801. package/src/offline/pwa-update-prompt.tsx +0 -78
  802. package/src/offline/query-persistence.ts +0 -391
  803. package/src/offline/service-worker-updates.ts +0 -81
  804. package/src/offline/shared-computer-labels.ts +0 -8
  805. package/src/offline/shared-computer.tsx +0 -87
  806. package/src/offline/sign-out-pending-dialog-labels.ts +0 -21
  807. package/src/offline/sign-out-pending-dialog.tsx +0 -135
  808. package/src/offline.ts +0 -37
  809. package/src/push-worker.ts +0 -25
  810. package/src/rhf/fields.tsx +0 -2187
  811. package/src/rhf/form-core.tsx +0 -324
  812. package/src/rhf/form.tsx +0 -12
  813. package/src/rhf/line-items.tsx +0 -135
  814. package/src/rhf/use-rhf-wizard-step.ts +0 -104
  815. package/src/rhf.ts +0 -21
  816. package/src/search/command-palette-labels.ts +0 -16
  817. package/src/search/command-palette.tsx +0 -624
  818. package/src/search/global-search-labels.ts +0 -13
  819. package/src/search/global-search.tsx +0 -660
  820. package/src/search/search-index.ts +0 -283
  821. package/src/search/use-command-key.ts +0 -23
  822. package/src/search.ts +0 -14
  823. package/src/settings/device-reset-setting-labels.ts +0 -20
  824. package/src/settings/device-reset-setting.tsx +0 -116
  825. package/src/settings/settings-card-classes.ts +0 -11
  826. package/src/settings/settings-catalogue.ts +0 -150
  827. package/src/settings/settings-context.ts +0 -33
  828. package/src/settings/settings-heading.tsx +0 -67
  829. package/src/settings/settings-labels.ts +0 -87
  830. package/src/settings/settings-layout.tsx +0 -471
  831. package/src/settings/settings-section.tsx +0 -108
  832. package/src/settings/use-account-appearance.ts +0 -148
  833. package/src/settings/use-account-language.ts +0 -146
  834. package/src/settings/use-settings-focus.ts +0 -128
  835. package/src/settings/use-settings-route.ts +0 -258
  836. package/src/shell/account-menu-language.tsx +0 -130
  837. package/src/shell/account-menu-text-size.tsx +0 -80
  838. package/src/shell/admin-menu.tsx +0 -183
  839. package/src/shell/app-shell-labels.ts +0 -11
  840. package/src/shell/app-shell.tsx +0 -1560
  841. package/src/shell/auth-layout.tsx +0 -186
  842. package/src/shell/company-switcher-labels.ts +0 -13
  843. package/src/shell/company-switcher.tsx +0 -136
  844. package/src/shell/dev-menu.tsx +0 -257
  845. package/src/shell/fill-height.tsx +0 -45
  846. package/src/shell/language-code.ts +0 -5
  847. package/src/shell/option-switcher-menu.tsx +0 -84
  848. package/src/shell/sync-status-indicator.tsx +0 -303
  849. package/src/shell/top-bar-actions.tsx +0 -87
  850. package/src/shell/top-bar-brand.tsx +0 -78
  851. package/src/shell/top-bar-parts-labels.ts +0 -148
  852. package/src/shell/top-bar.tsx +0 -40
  853. package/src/shell/topbar-action-menu.tsx +0 -567
  854. package/src/shell/topbar-controls.tsx +0 -269
  855. package/src/shell/tour-menu.tsx +0 -187
  856. package/src/shell.ts +0 -108
  857. package/src/sync/db.ts +0 -129
  858. package/src/sync/engine.ts +0 -1011
  859. package/src/sync/hooks.ts +0 -98
  860. package/src/sync/testing.ts +0 -73
  861. package/src/sync/wire.ts +0 -61
  862. package/src/sync.ts +0 -37
  863. package/src/table-text.ts +0 -8
  864. package/src/testing/css-variables.generated.ts +0 -112
  865. package/src/testing/css-variables.ts +0 -189
  866. package/src/testing/index.ts +0 -29
  867. package/src/testing/react.ts +0 -58
  868. package/src/testing/tour.ts +0 -41
  869. package/src/testing/viewport.ts +0 -357
  870. package/src/theme/chart-palette.ts +0 -232
  871. package/src/theme/color.ts +0 -272
  872. package/src/theme/contrast-tokens.ts +0 -268
  873. package/src/theme/contrast.ts +0 -250
  874. package/src/theme/palette-derive.ts +0 -825
  875. package/src/theme/palette-presets.ts +0 -544
  876. package/src/theme/palette-store.ts +0 -108
  877. package/src/theme/text-size.ts +0 -289
  878. package/src/theme/theme-store.ts +0 -157
  879. package/src/tour/tour-catalogue-labels.ts +0 -75
  880. package/src/tour/tour-catalogue.tsx +0 -335
  881. package/src/tour/tour-dock.ts +0 -134
  882. package/src/tour/tour-engine.ts +0 -37
  883. package/src/tour/tour-gates.ts +0 -218
  884. package/src/tour/tour-guide-button.tsx +0 -64
  885. package/src/tour/tour-guide-labels.ts +0 -15
  886. package/src/tour/tour-info.ts +0 -144
  887. package/src/tour/tour-labels.ts +0 -23
  888. package/src/tour/tour-overlay.tsx +0 -1170
  889. package/src/tour/tour.tsx +0 -750
  890. package/src/tour/use-tour-progress.ts +0 -671
  891. package/src/tour/use-tour-url-sync.ts +0 -266
  892. package/src/tour.ts +0 -21
  893. package/src/vite-env.d.ts +0 -23
  894. package/src/wizard/stepper-nav.tsx +0 -360
  895. package/src/wizard/types.ts +0 -275
  896. package/src/wizard/use-wizard.ts +0 -560
  897. package/src/wizard/validation.ts +0 -39
  898. package/src/wizard/wizard-context.tsx +0 -74
  899. package/src/wizard/wizard-labels.ts +0 -29
  900. package/src/wizard/wizard-step.tsx +0 -76
  901. package/src/wizard/wizard-summary.tsx +0 -84
  902. package/src/wizard.ts +0 -15
@@ -52,16 +52,21 @@ export interface FeedbackContextInput {
52
52
  viewport?: string;
53
53
  /** Default `navigator.userAgent`. */
54
54
  ua?: string;
55
+ /** What the app attached about the thing reported — `useFeedbackSubmit().open(category,
56
+ * { diagnostics })` (keksdose live #481). Sent whatever `attachUrl` says, as the box
57
+ * shows it; left out of the object when it has no key to show. */
58
+ diagnostics?: Readonly<Record<string, unknown>> | null;
55
59
  }
56
60
  /**
57
61
  * The `context` object of `POST /feedback` (§3.2), keys in keksdose's order: `url`, `route`,
58
62
  * `origin`, `environment`, `user_id`, `user_email`, `user_display_name`, `viewport`, `ua`,
59
- * `version`.
63
+ * `version`, then the app's `diagnostics`.
60
64
  *
61
65
  * With `attachUrl: false`, `url` and `route` are `""` — present and empty, as keksdose
62
66
  * sends them, so a reader can tell "withheld" from "an old row without the key".
63
67
  * `environment` and `version` are omitted when the app passes none (kastlan had no
64
- * version), rather than sent as `undefined`.
68
+ * version), rather than sent as `undefined`; `diagnostics` when the box would show no
69
+ * line of it (none, `{}`, not a record).
65
70
  *
66
71
  * Reads `window` / `navigator` only for the defaults it was not given, so it is a pure
67
72
  * function in a test that passes everything.
@@ -78,6 +83,9 @@ export interface FeedbackContextLabels {
78
83
  user: string;
79
84
  /** The checkbox. The URL it is about is the line beneath it. */
80
85
  attachUrl: string;
86
+ /** The heading over what the app attached — `open(category, { diagnostics })`, shown
87
+ * read-only under the URL (keksdose live #481). de-CH: "Mitgesendete Diagnose" */
88
+ diagnostics: string;
81
89
  }
82
90
  export { DEFAULT_FEEDBACK_CONTEXT_LABELS };
83
91
  export interface FeedbackContextBoxProps {
@@ -88,6 +96,10 @@ export interface FeedbackContextBoxProps {
88
96
  /** The checkbox, on by default in the dialog (§4.2) — the same `attachUrl`. */
89
97
  attachUrl: boolean;
90
98
  onAttachUrlChange: (next: boolean) => void;
99
+ /** What the app attached — the same `diagnostics` handed to {@link feedbackContext}.
100
+ * Shown read-only, each key and its value as the row detail draws them; no block when
101
+ * there is no line to show. */
102
+ diagnostics?: Readonly<Record<string, unknown>> | null;
91
103
  /** Prop > `<UiKitProvider labels={{ feedbackContext }}>` > English. */
92
104
  labels?: LabelOverride<FeedbackContextLabels>;
93
105
  className?: string;
@@ -104,7 +116,11 @@ export interface FeedbackContextBoxProps {
104
116
  * against whatever screen happened to be open, the queue reads as if it were about that
105
117
  * screen.
106
118
  *
119
+ * Below the URL, what the app attached (`diagnostics`, keksdose live #481: a stuck receipt
120
+ * scan's bookkeeping), read-only and in the row detail's own lines: the reporter sees what
121
+ * goes with the report, and that the URL checkbox does not withhold it.
122
+ *
107
123
  * Nothing in here is the app's: hand it the values handed to {@link feedbackContext}, and
108
124
  * what the box shows is what is sent.
109
125
  */
110
- export declare function FeedbackContextBox({ user, url, attachUrl, onAttachUrlChange, labels: labelsProp, className, }: FeedbackContextBoxProps): import("react").JSX.Element;
126
+ export declare function FeedbackContextBox({ user, url, attachUrl, onAttachUrlChange, diagnostics, labels: labelsProp, className, }: FeedbackContextBoxProps): import("react").JSX.Element;
@@ -1,9 +1,11 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useId } from "react";
3
4
  import { Checkbox } from "../components/checkbox.js";
4
5
  import { DEFAULT_COMMON_LABELS, useKitLabels } from "../i18n/kit-labels.js";
5
6
  import { cn } from "../lib/cn.js";
6
7
  import { DEFAULT_FEEDBACK_CONTEXT_LABELS } from "./feedback-context-labels.js";
8
+ import { diagnosticsEntries, FeedbackDiagnosticsList } from "./feedback-diagnostics.js";
7
9
  function submitterLine(user) {
8
10
  const name = user?.display_name?.trim();
9
11
  const email = user?.email?.trim();
@@ -34,6 +36,7 @@ function feedbackContext(input) {
34
36
  context.viewport = input.viewport ?? (win ? `${win.innerWidth}x${win.innerHeight}` : "");
35
37
  context.ua = input.ua ?? (typeof navigator === "undefined" ? "" : navigator.userAgent);
36
38
  if (input.version !== void 0) context.version = input.version;
39
+ if (input.diagnostics && diagnosticsEntries(input.diagnostics).length) context.diagnostics = input.diagnostics;
37
40
  return context;
38
41
  }
39
42
  function FeedbackContextBox({
@@ -41,11 +44,14 @@ function FeedbackContextBox({
41
44
  url,
42
45
  attachUrl,
43
46
  onAttachUrlChange,
47
+ diagnostics,
44
48
  labels: labelsProp,
45
49
  className
46
50
  }) {
47
51
  const labels = useKitLabels("feedbackContext", DEFAULT_FEEDBACK_CONTEXT_LABELS, labelsProp);
48
52
  const common = useKitLabels("common", DEFAULT_COMMON_LABELS);
53
+ const diagnosticsId = useId();
54
+ const attached = diagnosticsEntries(diagnostics);
49
55
  const submitter = submitterLine(user);
50
56
  const line = common.fieldValue(labels.user, submitter);
51
57
  const lead = line.endsWith(submitter) ? line.slice(0, line.length - submitter.length) : null;
@@ -77,7 +83,12 @@ function FeedbackContextBox({
77
83
  )
78
84
  ) : void 0
79
85
  }
80
- )
86
+ ),
87
+ attached.length > 0 && // A named group, so a screen reader hears what the pairs are before it reads them.
88
+ /* @__PURE__ */ jsxs("div", { role: "group", "aria-labelledby": diagnosticsId, className: "space-y-0.5 pt-1", children: [
89
+ /* @__PURE__ */ jsx("div", { id: diagnosticsId, className: "font-medium text-secondary", children: labels.diagnostics }),
90
+ /* @__PURE__ */ jsx(FeedbackDiagnosticsList, { entries: attached })
91
+ ] })
81
92
  ]
82
93
  }
83
94
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feedback/feedback-context.tsx"],"sourcesContent":["import { Checkbox } from \"../components/checkbox\";\nimport { DEFAULT_COMMON_LABELS, useKitLabels, type LabelOverride } from \"../i18n/kit-labels\";\nimport { cn } from \"../lib/cn\";\nimport type { FeedbackContext, FeedbackEnvironment } from \"./feedback-record\";\nimport { DEFAULT_FEEDBACK_CONTEXT_LABELS } from \"./feedback-context-labels\";\n\n/**\n * The reporter context of a feedback report: the box the submit dialog shows, and the\n * `context` object `POST /feedback` sends (0.27.0, docs/feedback-harmonization.md §3.2,\n * §4.2). One file for both, so what the box SAYS will be sent and what IS sent cannot\n * drift apart.\n *\n * Each app had written both halves itself (keksdose `use-feedback-dialog.tsx:105` and\n * `:222`, kastlan `feedback-button.tsx:80`, Kurvenschmiede `use-feedback-dialog.tsx:124`),\n * and they had drifted: kastlan sent six keys with `user_email: null` and no version,\n * Kurvenschmiede a `page_path` column and a sentence where keksdose had a labelled box,\n * and only keksdose showed the full URL it was about to send.\n */\n\n/* ── Who is filing ───────────────────────────────────────────────────────── */\n\n/**\n * The person filing, as the app knows them. Snake case on purpose: keksdose's and\n * Kurvenschmiede's user objects already have this shape (`id`, `email`, `display_name`),\n * so they pass their `user` as it is; kastlan maps its token's `sub` and name parts.\n *\n * A SNAPSHOT for the report and the box. The server should overwrite the three `user_*`\n * keys from the session (§3.2; Kurvenschmiede does), so nobody can file in someone else's\n * name — this is what the reporter is SHOWN, not proof of who they are.\n */\nexport interface FeedbackSubmitter {\n id?: number | null;\n email?: string | null;\n display_name?: string | null;\n}\n\n/** \"Ada Example (ada@example.com)\", the name alone, the email alone, or \"—\" when the app\n * knows neither (keksdose `use-feedback-dialog.tsx:228`). */\nfunction submitterLine(user: FeedbackSubmitter | null | undefined): string {\n const name = user?.display_name?.trim();\n const email = user?.email?.trim();\n if (name && email) return `${name} (${email})`;\n return name || email || \"—\";\n}\n\n/* ── The object (§3.2) ───────────────────────────────────────────────────── */\n\n/** What {@link feedbackContext} is built from. */\nexport interface FeedbackContextInput {\n /** The submitter, or `null` when signed out / unknown — the three `user_*` keys are then\n * `null`, as keksdose sends them. */\n user?: FeedbackSubmitter | null;\n /** The box's \"Attach current page URL\" checkbox. `false` withholds `url` and `route`\n * (both `\"\"`); nothing else is withheld — `origin` says which copy of the app, which is\n * not personal, and triage needs it first (keksdose `use-feedback-dialog.tsx:110`). */\n attachUrl: boolean;\n /** `location.href` when the dialog OPENED — the page the report is about, not the one\n * the reporter may have navigated to while typing. */\n url: string;\n /** Its pathname. Default: read off `url` (a path-only `url` works too). */\n route?: string;\n /** Default `location.origin`. */\n origin?: string;\n /** `\"prod\"` / `\"dev\"` / `\"local\"` — the app's own reading (keksdose\n * `app/deploy-environment.ts`). Left out of the object when not given. */\n environment?: FeedbackEnvironment | (string & {});\n /** The app build (`__APP_VERSION__`). Left out of the object when not given. */\n version?: string;\n /** Default `${innerWidth}x${innerHeight}` at the time of the call — \"406x816\". */\n viewport?: string;\n /** Default `navigator.userAgent`. */\n ua?: string;\n}\n\n/** The pathname of a full or path-only URL; `\"\"` for something that is neither. */\nfunction pathOf(url: string, base: string | undefined): string {\n if (!url) return \"\";\n try {\n return new URL(url, base || \"http://localhost\").pathname;\n } catch {\n return \"\";\n }\n}\n\n/**\n * The `context` object of `POST /feedback` (§3.2), keys in keksdose's order: `url`, `route`,\n * `origin`, `environment`, `user_id`, `user_email`, `user_display_name`, `viewport`, `ua`,\n * `version`.\n *\n * With `attachUrl: false`, `url` and `route` are `\"\"` — present and empty, as keksdose\n * sends them, so a reader can tell \"withheld\" from \"an old row without the key\".\n * `environment` and `version` are omitted when the app passes none (kastlan had no\n * version), rather than sent as `undefined`.\n *\n * Reads `window` / `navigator` only for the defaults it was not given, so it is a pure\n * function in a test that passes everything.\n */\nexport function feedbackContext(input: FeedbackContextInput): FeedbackContext {\n const { user, attachUrl, url } = input;\n const win = typeof window === \"undefined\" ? undefined : window;\n const origin = input.origin ?? win?.location.origin ?? \"\";\n const context: FeedbackContext = {\n url: attachUrl ? url : \"\",\n route: attachUrl ? (input.route ?? pathOf(url, origin || win?.location.href)) : \"\",\n origin,\n };\n if (input.environment !== undefined) context.environment = input.environment;\n context.user_id = user?.id ?? null;\n context.user_email = user?.email ?? null;\n context.user_display_name = user?.display_name ?? null;\n context.viewport = input.viewport ?? (win ? `${win.innerWidth}x${win.innerHeight}` : \"\");\n context.ua = input.ua ?? (typeof navigator === \"undefined\" ? \"\" : navigator.userAgent);\n if (input.version !== undefined) context.version = input.version;\n return context;\n}\n\n/* ── The box (§4.2) ──────────────────────────────────────────────────────── */\n\n/**\n * `feedbackContext` — the context box's words. de-CH canon (keksdose `de-CH.json`):\n * `user` \"Nutzer\", `attachUrl` \"Aktuelle Seiten-URL anhängen\".\n */\nexport interface FeedbackContextLabels {\n /** The submitter line's label — the box draws \"**User:** Ada Example (ada@example.com)\".\n * The label alone: the colon between it and the person is the language's\n * `common.fieldValue` (fr \"Utilisateur : …\", zh \"用户:…\"). */\n user: string;\n /** The checkbox. The URL it is about is the line beneath it. */\n attachUrl: string;\n}\n\n// Defined in ./feedback-context-labels, which holds no component code (0.34, KS U8).\nexport { DEFAULT_FEEDBACK_CONTEXT_LABELS };\n\nexport interface FeedbackContextBoxProps {\n /** Who is filing — the same value handed to {@link feedbackContext}. */\n user?: FeedbackSubmitter | null;\n /** The URL that goes with the report — the same `url` handed to {@link feedbackContext}. */\n url: string;\n /** The checkbox, on by default in the dialog (§4.2) — the same `attachUrl`. */\n attachUrl: boolean;\n onAttachUrlChange: (next: boolean) => void;\n /** Prop > `<UiKitProvider labels={{ feedbackContext }}>` > English. */\n labels?: LabelOverride<FeedbackContextLabels>;\n className?: string;\n}\n\n/**\n * The submit dialog's context box — the dialog's `contextSlot` (keksdose\n * `use-feedback-dialog.tsx:222`, §4.2): who is filing, and the page URL with a checkbox to\n * leave it out, ON by default.\n *\n * The URL stays visible when the box is off, struck through: the reporter sees what they\n * withheld rather than a line that vanished, and ticking it back on is the same glance.\n * Kurvenschmiede's argument for the checkbox is why it exists at all (its feedback #101):\n * the route is right for a bug and wrong for an idea about a screen one is not on — filed\n * against whatever screen happened to be open, the queue reads as if it were about that\n * screen.\n *\n * Nothing in here is the app's: hand it the values handed to {@link feedbackContext}, and\n * what the box shows is what is sent.\n */\nexport function FeedbackContextBox({\n user,\n url,\n attachUrl,\n onAttachUrlChange,\n labels: labelsProp,\n className,\n}: FeedbackContextBoxProps) {\n const labels = useKitLabels(\"feedbackContext\", DEFAULT_FEEDBACK_CONTEXT_LABELS, labelsProp);\n const common = useKitLabels(\"common\", DEFAULT_COMMON_LABELS);\n const submitter = submitterLine(user);\n // \"User: Ada …\" through `common.fieldValue`, so French gets its space before the colon\n // and Chinese its full-width one; the label and its punctuation are drawn bold, as\n // keksdose's box does. A `fieldValue` that does not end in the value (an app's own\n // order) is shown whole, unbolded, rather than cut in the wrong place.\n const line = common.fieldValue(labels.user, submitter);\n const lead = line.endsWith(submitter) ? line.slice(0, line.length - submitter.length) : null;\n return (\n <div\n className={cn(\"space-y-1 rounded-md border border-subtle bg-surface-2 px-3 py-2 text-xs text-muted\", className)}\n >\n <div className=\"[overflow-wrap:anywhere]\">\n {lead === null ? (\n line\n ) : (\n <>\n <span className=\"font-medium text-secondary\">{lead}</span>\n {submitter}\n </>\n )}\n </div>\n <Checkbox\n checked={attachUrl}\n onCheckedChange={onAttachUrlChange}\n label={<span className=\"text-xs font-medium text-secondary\">{labels.attachUrl}</span>}\n description={\n url ? (\n // `break-all`: a URL is one unbreakable word, and at 390px a long query string\n // would otherwise push the dialog sideways.\n <span\n data-withheld={attachUrl ? undefined : \"\"}\n className={cn(\"break-all text-xs\", !attachUrl && \"line-through opacity-60\")}\n >\n {url}\n </span>\n ) : undefined\n }\n />\n </div>\n );\n}\n"],"mappings":";AA2LU,mBACE,KADF;AA3LV,SAAS,gBAAgB;AACzB,SAAS,uBAAuB,oBAAwC;AACxE,SAAS,UAAU;AAEnB,SAAS,uCAAuC;AAkChD,SAAS,cAAc,MAAoD;AACzE,QAAM,OAAO,MAAM,cAAc,KAAK;AACtC,QAAM,QAAQ,MAAM,OAAO,KAAK;AAChC,MAAI,QAAQ,MAAO,QAAO,GAAG,IAAI,KAAK,KAAK;AAC3C,SAAO,QAAQ,SAAS;AAC1B;AAgCA,SAAS,OAAO,KAAa,MAAkC;AAC7D,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI;AACF,WAAO,IAAI,IAAI,KAAK,QAAQ,kBAAkB,EAAE;AAAA,EAClD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAeO,SAAS,gBAAgB,OAA8C;AAC5E,QAAM,EAAE,MAAM,WAAW,IAAI,IAAI;AACjC,QAAM,MAAM,OAAO,WAAW,cAAc,SAAY;AACxD,QAAM,SAAS,MAAM,UAAU,KAAK,SAAS,UAAU;AACvD,QAAM,UAA2B;AAAA,IAC/B,KAAK,YAAY,MAAM;AAAA,IACvB,OAAO,YAAa,MAAM,SAAS,OAAO,KAAK,UAAU,KAAK,SAAS,IAAI,IAAK;AAAA,IAChF;AAAA,EACF;AACA,MAAI,MAAM,gBAAgB,OAAW,SAAQ,cAAc,MAAM;AACjE,UAAQ,UAAU,MAAM,MAAM;AAC9B,UAAQ,aAAa,MAAM,SAAS;AACpC,UAAQ,oBAAoB,MAAM,gBAAgB;AAClD,UAAQ,WAAW,MAAM,aAAa,MAAM,GAAG,IAAI,UAAU,IAAI,IAAI,WAAW,KAAK;AACrF,UAAQ,KAAK,MAAM,OAAO,OAAO,cAAc,cAAc,KAAK,UAAU;AAC5E,MAAI,MAAM,YAAY,OAAW,SAAQ,UAAU,MAAM;AACzD,SAAO;AACT;AAgDO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AACF,GAA4B;AAC1B,QAAM,SAAS,aAAa,mBAAmB,iCAAiC,UAAU;AAC1F,QAAM,SAAS,aAAa,UAAU,qBAAqB;AAC3D,QAAM,YAAY,cAAc,IAAI;AAKpC,QAAM,OAAO,OAAO,WAAW,OAAO,MAAM,SAAS;AACrD,QAAM,OAAO,KAAK,SAAS,SAAS,IAAI,KAAK,MAAM,GAAG,KAAK,SAAS,UAAU,MAAM,IAAI;AACxF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,uFAAuF,SAAS;AAAA,MAE9G;AAAA,4BAAC,SAAI,WAAU,4BACZ,mBAAS,OACR,OAEA,iCACE;AAAA,8BAAC,UAAK,WAAU,8BAA8B,gBAAK;AAAA,UAClD;AAAA,WACH,GAEJ;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,iBAAiB;AAAA,YACjB,OAAO,oBAAC,UAAK,WAAU,sCAAsC,iBAAO,WAAU;AAAA,YAC9E,aACE;AAAA;AAAA;AAAA,cAGE;AAAA,gBAAC;AAAA;AAAA,kBACC,iBAAe,YAAY,SAAY;AAAA,kBACvC,WAAW,GAAG,qBAAqB,CAAC,aAAa,yBAAyB;AAAA,kBAEzE;AAAA;AAAA,cACH;AAAA,gBACE;AAAA;AAAA,QAER;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/feedback/feedback-context.tsx"],"sourcesContent":["import { useId } from \"react\";\nimport { Checkbox } from \"../components/checkbox\";\nimport { DEFAULT_COMMON_LABELS, useKitLabels, type LabelOverride } from \"../i18n/kit-labels\";\nimport { cn } from \"../lib/cn\";\nimport type { FeedbackContext, FeedbackEnvironment } from \"./feedback-record\";\nimport { DEFAULT_FEEDBACK_CONTEXT_LABELS } from \"./feedback-context-labels\";\nimport { diagnosticsEntries, FeedbackDiagnosticsList } from \"./feedback-diagnostics\";\n\n/**\n * The reporter context of a feedback report: the box the submit dialog shows, and the\n * `context` object `POST /feedback` sends (0.27.0, docs/feedback-harmonization.md §3.2,\n * §4.2). One file for both, so what the box SAYS will be sent and what IS sent cannot\n * drift apart.\n *\n * Each app had written both halves itself (keksdose `use-feedback-dialog.tsx:105` and\n * `:222`, kastlan `feedback-button.tsx:80`, Kurvenschmiede `use-feedback-dialog.tsx:124`),\n * and they had drifted: kastlan sent six keys with `user_email: null` and no version,\n * Kurvenschmiede a `page_path` column and a sentence where keksdose had a labelled box,\n * and only keksdose showed the full URL it was about to send.\n */\n\n/* ── Who is filing ───────────────────────────────────────────────────────── */\n\n/**\n * The person filing, as the app knows them. Snake case on purpose: keksdose's and\n * Kurvenschmiede's user objects already have this shape (`id`, `email`, `display_name`),\n * so they pass their `user` as it is; kastlan maps its token's `sub` and name parts.\n *\n * A SNAPSHOT for the report and the box. The server should overwrite the three `user_*`\n * keys from the session (§3.2; Kurvenschmiede does), so nobody can file in someone else's\n * name — this is what the reporter is SHOWN, not proof of who they are.\n */\nexport interface FeedbackSubmitter {\n id?: number | null;\n email?: string | null;\n display_name?: string | null;\n}\n\n/** \"Ada Example (ada@example.com)\", the name alone, the email alone, or \"—\" when the app\n * knows neither (keksdose `use-feedback-dialog.tsx:228`). */\nfunction submitterLine(user: FeedbackSubmitter | null | undefined): string {\n const name = user?.display_name?.trim();\n const email = user?.email?.trim();\n if (name && email) return `${name} (${email})`;\n return name || email || \"—\";\n}\n\n/* ── The object (§3.2) ───────────────────────────────────────────────────── */\n\n/** What {@link feedbackContext} is built from. */\nexport interface FeedbackContextInput {\n /** The submitter, or `null` when signed out / unknown — the three `user_*` keys are then\n * `null`, as keksdose sends them. */\n user?: FeedbackSubmitter | null;\n /** The box's \"Attach current page URL\" checkbox. `false` withholds `url` and `route`\n * (both `\"\"`); nothing else is withheld — `origin` says which copy of the app, which is\n * not personal, and triage needs it first (keksdose `use-feedback-dialog.tsx:110`). */\n attachUrl: boolean;\n /** `location.href` when the dialog OPENED — the page the report is about, not the one\n * the reporter may have navigated to while typing. */\n url: string;\n /** Its pathname. Default: read off `url` (a path-only `url` works too). */\n route?: string;\n /** Default `location.origin`. */\n origin?: string;\n /** `\"prod\"` / `\"dev\"` / `\"local\"` — the app's own reading (keksdose\n * `app/deploy-environment.ts`). Left out of the object when not given. */\n environment?: FeedbackEnvironment | (string & {});\n /** The app build (`__APP_VERSION__`). Left out of the object when not given. */\n version?: string;\n /** Default `${innerWidth}x${innerHeight}` at the time of the call — \"406x816\". */\n viewport?: string;\n /** Default `navigator.userAgent`. */\n ua?: string;\n /** What the app attached about the thing reported — `useFeedbackSubmit().open(category,\n * { diagnostics })` (keksdose live #481). Sent whatever `attachUrl` says, as the box\n * shows it; left out of the object when it has no key to show. */\n diagnostics?: Readonly<Record<string, unknown>> | null;\n}\n\n/** The pathname of a full or path-only URL; `\"\"` for something that is neither. */\nfunction pathOf(url: string, base: string | undefined): string {\n if (!url) return \"\";\n try {\n return new URL(url, base || \"http://localhost\").pathname;\n } catch {\n return \"\";\n }\n}\n\n/**\n * The `context` object of `POST /feedback` (§3.2), keys in keksdose's order: `url`, `route`,\n * `origin`, `environment`, `user_id`, `user_email`, `user_display_name`, `viewport`, `ua`,\n * `version`, then the app's `diagnostics`.\n *\n * With `attachUrl: false`, `url` and `route` are `\"\"` — present and empty, as keksdose\n * sends them, so a reader can tell \"withheld\" from \"an old row without the key\".\n * `environment` and `version` are omitted when the app passes none (kastlan had no\n * version), rather than sent as `undefined`; `diagnostics` when the box would show no\n * line of it (none, `{}`, not a record).\n *\n * Reads `window` / `navigator` only for the defaults it was not given, so it is a pure\n * function in a test that passes everything.\n */\nexport function feedbackContext(input: FeedbackContextInput): FeedbackContext {\n const { user, attachUrl, url } = input;\n const win = typeof window === \"undefined\" ? undefined : window;\n const origin = input.origin ?? win?.location.origin ?? \"\";\n const context: FeedbackContext = {\n url: attachUrl ? url : \"\",\n route: attachUrl ? (input.route ?? pathOf(url, origin || win?.location.href)) : \"\",\n origin,\n };\n if (input.environment !== undefined) context.environment = input.environment;\n context.user_id = user?.id ?? null;\n context.user_email = user?.email ?? null;\n context.user_display_name = user?.display_name ?? null;\n context.viewport = input.viewport ?? (win ? `${win.innerWidth}x${win.innerHeight}` : \"\");\n context.ua = input.ua ?? (typeof navigator === \"undefined\" ? \"\" : navigator.userAgent);\n if (input.version !== undefined) context.version = input.version;\n // The box's own test: what it draws no line of is not sent either.\n if (input.diagnostics && diagnosticsEntries(input.diagnostics).length) context.diagnostics = input.diagnostics;\n return context;\n}\n\n/* ── The box (§4.2) ──────────────────────────────────────────────────────── */\n\n/**\n * `feedbackContext` — the context box's words. de-CH canon (keksdose `de-CH.json`):\n * `user` \"Nutzer\", `attachUrl` \"Aktuelle Seiten-URL anhängen\".\n */\nexport interface FeedbackContextLabels {\n /** The submitter line's label — the box draws \"**User:** Ada Example (ada@example.com)\".\n * The label alone: the colon between it and the person is the language's\n * `common.fieldValue` (fr \"Utilisateur : …\", zh \"用户:…\"). */\n user: string;\n /** The checkbox. The URL it is about is the line beneath it. */\n attachUrl: string;\n /** The heading over what the app attached — `open(category, { diagnostics })`, shown\n * read-only under the URL (keksdose live #481). de-CH: \"Mitgesendete Diagnose\" */\n diagnostics: string;\n}\n\n// Defined in ./feedback-context-labels, which holds no component code (0.34, KS U8).\nexport { DEFAULT_FEEDBACK_CONTEXT_LABELS };\n\nexport interface FeedbackContextBoxProps {\n /** Who is filing — the same value handed to {@link feedbackContext}. */\n user?: FeedbackSubmitter | null;\n /** The URL that goes with the report — the same `url` handed to {@link feedbackContext}. */\n url: string;\n /** The checkbox, on by default in the dialog (§4.2) — the same `attachUrl`. */\n attachUrl: boolean;\n onAttachUrlChange: (next: boolean) => void;\n /** What the app attached — the same `diagnostics` handed to {@link feedbackContext}.\n * Shown read-only, each key and its value as the row detail draws them; no block when\n * there is no line to show. */\n diagnostics?: Readonly<Record<string, unknown>> | null;\n /** Prop > `<UiKitProvider labels={{ feedbackContext }}>` > English. */\n labels?: LabelOverride<FeedbackContextLabels>;\n className?: string;\n}\n\n/**\n * The submit dialog's context box — the dialog's `contextSlot` (keksdose\n * `use-feedback-dialog.tsx:222`, §4.2): who is filing, and the page URL with a checkbox to\n * leave it out, ON by default.\n *\n * The URL stays visible when the box is off, struck through: the reporter sees what they\n * withheld rather than a line that vanished, and ticking it back on is the same glance.\n * Kurvenschmiede's argument for the checkbox is why it exists at all (its feedback #101):\n * the route is right for a bug and wrong for an idea about a screen one is not on — filed\n * against whatever screen happened to be open, the queue reads as if it were about that\n * screen.\n *\n * Below the URL, what the app attached (`diagnostics`, keksdose live #481: a stuck receipt\n * scan's bookkeeping), read-only and in the row detail's own lines: the reporter sees what\n * goes with the report, and that the URL checkbox does not withhold it.\n *\n * Nothing in here is the app's: hand it the values handed to {@link feedbackContext}, and\n * what the box shows is what is sent.\n */\nexport function FeedbackContextBox({\n user,\n url,\n attachUrl,\n onAttachUrlChange,\n diagnostics,\n labels: labelsProp,\n className,\n}: FeedbackContextBoxProps) {\n const labels = useKitLabels(\"feedbackContext\", DEFAULT_FEEDBACK_CONTEXT_LABELS, labelsProp);\n const common = useKitLabels(\"common\", DEFAULT_COMMON_LABELS);\n const diagnosticsId = useId();\n const attached = diagnosticsEntries(diagnostics);\n const submitter = submitterLine(user);\n // \"User: Ada …\" through `common.fieldValue`, so French gets its space before the colon\n // and Chinese its full-width one; the label and its punctuation are drawn bold, as\n // keksdose's box does. A `fieldValue` that does not end in the value (an app's own\n // order) is shown whole, unbolded, rather than cut in the wrong place.\n const line = common.fieldValue(labels.user, submitter);\n const lead = line.endsWith(submitter) ? line.slice(0, line.length - submitter.length) : null;\n return (\n <div\n className={cn(\"space-y-1 rounded-md border border-subtle bg-surface-2 px-3 py-2 text-xs text-muted\", className)}\n >\n <div className=\"[overflow-wrap:anywhere]\">\n {lead === null ? (\n line\n ) : (\n <>\n <span className=\"font-medium text-secondary\">{lead}</span>\n {submitter}\n </>\n )}\n </div>\n <Checkbox\n checked={attachUrl}\n onCheckedChange={onAttachUrlChange}\n label={<span className=\"text-xs font-medium text-secondary\">{labels.attachUrl}</span>}\n description={\n url ? (\n // `break-all`: a URL is one unbreakable word, and at 390px a long query string\n // would otherwise push the dialog sideways.\n <span\n data-withheld={attachUrl ? undefined : \"\"}\n className={cn(\"break-all text-xs\", !attachUrl && \"line-through opacity-60\")}\n >\n {url}\n </span>\n ) : undefined\n }\n />\n {attached.length > 0 && (\n // A named group, so a screen reader hears what the pairs are before it reads them.\n <div role=\"group\" aria-labelledby={diagnosticsId} className=\"space-y-0.5 pt-1\">\n <div id={diagnosticsId} className=\"font-medium text-secondary\">\n {labels.diagnostics}\n </div>\n <FeedbackDiagnosticsList entries={attached} />\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `context.diagnostics` (§3.2), drawn one way wherever it shows: in the submit dialog's
3
+ * context box, to the reporter before it goes (§4.2), and in the row detail, to the admin
4
+ * and the author afterwards (§4.4.2). One module for both, so the reporter is shown the
5
+ * very lines the admin will read (keksdose live #481).
6
+ *
7
+ * Internal: neither `@eifi1/ui-kit/feedback` nor the barrel names it.
8
+ */
9
+ /** `diagnostics` as [key, text] pairs, in the app's order: a string, number or boolean as
10
+ * written, an object or a list as JSON, nothing as "—". Empty for no diagnostics, and for
11
+ * a value that is not a plain object — the server stores whatever the client sent. */
12
+ export declare function diagnosticsEntries(diagnostics: unknown): Array<[string, string]>;
13
+ /** The pairs as a definition list: each key beside its value, in monospace. Read-only in
14
+ * both places; the heading over it is the caller's. */
15
+ export declare function FeedbackDiagnosticsList({ entries }: {
16
+ entries: ReadonlyArray<readonly [string, string]>;
17
+ }): import("react").JSX.Element;
@@ -0,0 +1,27 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ function diagnosticsEntries(diagnostics) {
4
+ if (!diagnostics || typeof diagnostics !== "object" || Array.isArray(diagnostics)) return [];
5
+ return Object.entries(diagnostics).map(([key, v]) => [
6
+ key,
7
+ v === null || v === void 0 || v === "" ? "\u2014" : typeof v === "object" ? JSON.stringify(v) : String(v)
8
+ ]);
9
+ }
10
+ function FeedbackDiagnosticsList({ entries }) {
11
+ return /* @__PURE__ */ jsx(
12
+ "dl",
13
+ {
14
+ className: "grid grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-0.5 font-mono text-xs",
15
+ "data-feedback-diagnostics": "",
16
+ children: entries.map(([key, text]) => /* @__PURE__ */ jsxs("div", { className: "contents", children: [
17
+ /* @__PURE__ */ jsx("dt", { className: "text-muted", children: key }),
18
+ /* @__PURE__ */ jsx("dd", { className: "min-w-0 break-words text-secondary", children: text })
19
+ ] }, key))
20
+ }
21
+ );
22
+ }
23
+ export {
24
+ FeedbackDiagnosticsList,
25
+ diagnosticsEntries
26
+ };
27
+ //# sourceMappingURL=feedback-diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/feedback/feedback-diagnostics.tsx"],"sourcesContent":["/**\n * `context.diagnostics` (§3.2), drawn one way wherever it shows: in the submit dialog's\n * context box, to the reporter before it goes (§4.2), and in the row detail, to the admin\n * and the author afterwards (§4.4.2). One module for both, so the reporter is shown the\n * very lines the admin will read (keksdose live #481).\n *\n * Internal: neither `@eifi1/ui-kit/feedback` nor the barrel names it.\n */\n\n/** `diagnostics` as [key, text] pairs, in the app's order: a string, number or boolean as\n * written, an object or a list as JSON, nothing as \"—\". Empty for no diagnostics, and for\n * a value that is not a plain object — the server stores whatever the client sent. */\nexport function diagnosticsEntries(diagnostics: unknown): Array<[string, string]> {\n if (!diagnostics || typeof diagnostics !== \"object\" || Array.isArray(diagnostics)) return [];\n return Object.entries(diagnostics).map(([key, v]) => [\n key,\n v === null || v === undefined || v === \"\"\n ? \"—\"\n : typeof v === \"object\"\n ? JSON.stringify(v)\n : String(v as string | number | boolean | bigint),\n ]);\n}\n\n/** The pairs as a definition list: each key beside its value, in monospace. Read-only in\n * both places; the heading over it is the caller's. */\nexport function FeedbackDiagnosticsList({ entries }: { entries: ReadonlyArray<readonly [string, string]> }) {\n return (\n <dl\n className=\"grid grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-0.5 font-mono text-xs\"\n data-feedback-diagnostics=\"\"\n >\n {entries.map(([key, text]) => (\n <div key={key} className=\"contents\">\n <dt className=\"text-muted\">{key}</dt>\n <dd className=\"min-w-0 break-words text-secondary\">{text}</dd>\n </div>\n ))}\n </dl>\n );\n}\n"],"mappings":";AAiCQ,SACE,KADF;AArBD,SAAS,mBAAmB,aAA+C;AAChF,MAAI,CAAC,eAAe,OAAO,gBAAgB,YAAY,MAAM,QAAQ,WAAW,EAAG,QAAO,CAAC;AAC3F,SAAO,OAAO,QAAQ,WAAW,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM;AAAA,IACnD;AAAA,IACA,MAAM,QAAQ,MAAM,UAAa,MAAM,KACnC,WACA,OAAO,MAAM,WACX,KAAK,UAAU,CAAC,IAChB,OAAO,CAAuC;AAAA,EACtD,CAAC;AACH;AAIO,SAAS,wBAAwB,EAAE,QAAQ,GAA0D;AAC1G,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,6BAA0B;AAAA,MAEzB,kBAAQ,IAAI,CAAC,CAAC,KAAK,IAAI,MACtB,qBAAC,SAAc,WAAU,YACvB;AAAA,4BAAC,QAAG,WAAU,cAAc,eAAI;AAAA,QAChC,oBAAC,QAAG,WAAU,sCAAsC,gBAAK;AAAA,WAFjD,GAGV,CACD;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -120,6 +120,16 @@ interface FeedbackDialogBaseProps<C extends string = string> {
120
120
  * English. Optional since 0.12.0; a whole `FeedbackDialogLabels` still fits. */
121
121
  labels?: LabelOverride<FeedbackDialogLabels>;
122
122
  submitting?: boolean;
123
+ /**
124
+ * The subject and the body each opening starts with, in place of empty fields — the
125
+ * reporter edits them like anything typed. `useFeedbackSubmit().open(category, { title,
126
+ * body })` passes them (keksdose live #481: "Report this problem" opens on words the
127
+ * screen already knows). Read when the dialog opens; a change while it is open leaves
128
+ * the draft alone.
129
+ */
130
+ defaultTitle?: string;
131
+ /** The body's, as `defaultTitle` is the subject's. */
132
+ defaultBody?: string;
123
133
  contextSlot?: ReactNode;
124
134
  attachmentAccept?: string[];
125
135
  maxAttachmentBytes?: number;
@@ -26,6 +26,8 @@ function FeedbackDialog(props) {
26
26
  onCategoryChange,
27
27
  labels: labelsProp,
28
28
  submitting = false,
29
+ defaultTitle = "",
30
+ defaultBody = "",
29
31
  contextSlot,
30
32
  attachmentAccept = DEFAULT_ATTACHMENT_ACCEPT,
31
33
  maxAttachmentBytes = DEFAULT_MAX_ATTACHMENT_BYTES,
@@ -35,8 +37,8 @@ function FeedbackDialog(props) {
35
37
  attachmentButtonSize,
36
38
  publicNotice
37
39
  } = props;
38
- const [title, setTitle] = useState("");
39
- const [body, setBody] = useState("");
40
+ const [title, setTitle] = useState(defaultTitle);
41
+ const [body, setBody] = useState(defaultBody);
40
42
  const [attachment, setAttachment] = useState(null);
41
43
  const [screenshot, setScreenshot] = useState(null);
42
44
  const [files, setFiles] = useState([]);
@@ -51,8 +53,8 @@ function FeedbackDialog(props) {
51
53
  if (open !== wasOpen) {
52
54
  setWasOpen(open);
53
55
  if (open) {
54
- setTitle("");
55
- setBody("");
56
+ setTitle(defaultTitle);
57
+ setBody(defaultBody);
56
58
  setAttachment(null);
57
59
  setScreenshot(null);
58
60
  setFiles([]);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/feedback/feedback-dialog.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Button } from \"../components/button\";\nimport { Input } from \"../components/input\";\nimport { Select } from \"../components/select\";\nimport { Textarea } from \"../components/textarea\";\nimport type { ButtonSize, ButtonVariant } from \"../components/button-look\";\nimport { Modal } from \"../components/modal\";\nimport { isApplePlatform } from \"../hooks/use-hotkey\";\nimport { usePhoneLayout } from \"../hooks/use-breakpoint\";\nimport { useKitLabels, type LabelOverride } from \"../i18n/kit-labels\";\nimport { hasContent } from \"../lib/presence\";\nimport {\n DEFAULT_ATTACHMENT_ACCEPT,\n DEFAULT_FEEDBACK_ATTACHMENT_LABELS,\n DEFAULT_MAX_ATTACHMENT_BYTES,\n FeedbackAttachmentField,\n type FeedbackAttachmentError,\n type FeedbackAttachmentErrorInfo,\n} from \"./feedback-attachment\";\nimport { DEFAULT_FEEDBACK_DIALOG_LABELS } from \"./feedback-dialog-labels\";\n\n/** One category the dialog offers. `C` (0.52): the app's category type — the kit's\n * `FeedbackCategory`, or `string` (the default) for a vocabulary of the app's own. */\nexport interface FeedbackCategoryOption<C extends string = string> {\n value: C;\n label: string;\n}\n\nexport interface FeedbackAttachmentLabels {\n /** The heading over the field. Optional: a note editor puts the buttons\n * straight under its textarea, where a second heading is noise. */\n attachment?: string;\n attachmentAdd: string;\n /** Label for the \"capture screenshot\" button. Optional — falls back to the provider's\n * `feedbackAttachment.attachmentCapture`, then English. */\n attachmentCapture?: string;\n /** The line under the attachment buttons saying a screenshot can be pasted\n * straight in. Optional — falls back to the provider's `feedbackAttachment`, then English. */\n attachmentPaste?: string;\n attachmentRemove: string;\n /** `multiple` mode (0.15.5): the chip list's accessible name — and, in\n * `<FeedbackDialog attachments=\"multiple\">`, the heading over it (0.16.0). Optional,\n * as are the keys below — they fall back to the provider's `feedbackAttachment`,\n * then English. */\n attachmentList?: string;\n /** `multiple` mode (0.16.0): the screenshot slot's chip title, in place of its file name. */\n attachmentScreenshot?: string;\n /** `multiple` mode: one chip's remove button, given the file's name. */\n attachmentRemoveFile?: (name: string) => string;\n /** `multiple` mode: the line shown once `max` files are attached. */\n attachmentLimit?: (max: number) => string;\n /** `refs` mode (0.22.0): the second line of a chip whose upload is still running. */\n attachmentUploading?: string;\n}\n\nexport interface FeedbackDialogLabels extends FeedbackAttachmentLabels {\n title: string;\n category: string;\n subject: string;\n body: string;\n attachment: string;\n /** See {@link FeedbackDialogTextLabels.submitHint}. */\n submitHint: FeedbackSubmitHint;\n cancel: string;\n save: string;\n}\n\n/** The submit hint: a string, or the line for the platform (`apple`: Mac, iPhone, iPad). */\nexport type FeedbackSubmitHint = string | ((apple: boolean) => string);\n\n/**\n * The dialog's own strings — the `feedbackDialog` namespace of `<UiKitProvider\n * labels>` (0.12.0). The attachment keys are not repeated here: they are the\n * `feedbackAttachment` namespace's, which the field inside already reads.\n *\n * Before, every key was required at the call site, so each app restated ten strings\n * wherever it mounted the dialog (kastlan feedback-button.tsx built the object inline).\n */\nexport interface FeedbackDialogTextLabels {\n title: string;\n category: string;\n subject: string;\n body: string;\n /** The body's label when `requireBody={false}`: \"What happened? (optional)\".\n * Optional, so a complete `UiKitLabels` typed before 0.14.2 still compiles. */\n bodyOptional?: string;\n /** The heading over the attachment buttons. */\n attachment: string;\n /**\n * The line beside the buttons naming the shortcut. Since 0.27.0 a function of the\n * platform, like `form.submitShortcut`: `apple` is true on a Mac, iPhone or iPad, where\n * the key is Cmd — \"⌘ Enter to send\" there, keksdose's \"Ctrl+Enter to send\" elsewhere\n * (§7.12). A plain string is still taken and shown everywhere, as before 0.27.0.\n */\n submitHint: FeedbackSubmitHint;\n cancel: string;\n save: string;\n /** 0.38 (docs/feedback-harmonization.md §9.2 decision 6): the line under the body when\n * reports are public — `useFeedbackSubmit({ publicNotice: true })` shows it. Optional,\n * so a complete `UiKitLabels` typed before 0.38 still compiles. de-CH \"Andere Personen\n * sehen Titel und Text (nie Ihre Screenshots oder Dateien).\" */\n publicNotice?: string;\n}\n\n// Defined in ./feedback-dialog-labels, which holds no component code (0.34, KS U8).\nexport { DEFAULT_FEEDBACK_DIALOG_LABELS };\n\nexport interface FeedbackSubmission<C extends string = string> {\n title: string;\n body: string;\n category: C;\n attachment: File | null;\n}\n\n/**\n * What `onSubmit` gets under `attachments=\"multiple\"` (0.15.5): the screenshot and\n * the picked/pasted files apart, because an app files them differently — keksdose\n * attaches the screenshot to the report and the photos as its evidence list. No\n * `attachment`: there is no one file it could name.\n */\nexport interface FeedbackMultipleSubmission<C extends string = string> {\n title: string;\n body: string;\n category: C;\n /** What `onCaptureScreenshot` returned, or `null` — at most one. */\n screenshot: File | null;\n /** Picked and pasted files, in the order they were added; at most `maxAttachments`. */\n attachments: File[];\n}\n\n/**\n * `C` (0.52, refactor audit 2026-10-30, API-7): the category type, inferred from\n * `categories` and `category` — `FeedbackCategory` hands `onCategoryChange` and\n * `onSubmit` a `FeedbackCategory` back, where a plain `string` had to be cast (the kit's\n * own `useFeedbackSubmit` did). `string` by default, so an app's own vocabulary fits.\n */\ninterface FeedbackDialogBaseProps<C extends string = string> {\n open: boolean;\n onClose: () => void;\n /** `readonly` since 0.52: the dialog never changes it. */\n categories: readonly FeedbackCategoryOption<C>[];\n category: C;\n onCategoryChange: (value: C) => void;\n /** Prop > `<UiKitProvider labels={{ feedbackDialog, feedbackAttachment }}>` >\n * English. Optional since 0.12.0; a whole `FeedbackDialogLabels` still fits. */\n labels?: LabelOverride<FeedbackDialogLabels>;\n submitting?: boolean;\n contextSlot?: ReactNode;\n attachmentAccept?: string[];\n maxAttachmentBytes?: number;\n /**\n * Optional: capture a screenshot of the underlying app view and return it as a\n * File. When provided, a \"Capture screenshot\" button is shown next to \"Add\n * attachment\"; the returned file is fed through the same validation + preview.\n */\n onCaptureScreenshot?: () => Promise<File | null>;\n /**\n * `false`: a report with only a subject can be sent, and the body's label says it is\n * optional (`bodyOptional`, unless `labels.body` is passed). Default `true`, the\n * dialog's behaviour until 0.14.2 (keksdose K1: its backend takes title-only reports).\n */\n requireBody?: boolean;\n /**\n * The attachment field's add and capture buttons: its `buttonVariant` (0.25.0),\n * Button's own `variant`. Default `\"secondary\"`, the look they always had.\n *\n * The field took `buttonVariant` / `buttonSize` in 0.24.0 (keksdose's support chat),\n * but the dialog builds its field itself and passed neither, so a host that wanted\n * quieter buttons here — a dialog that already ends in a row of Cancel / Send — had\n * no way to say so short of rebuilding the dialog. Named after the dialog's other\n * attachment options (`attachmentAccept`, `onAttachmentError`) and handed through\n * unchanged, in both `attachments` modes.\n */\n attachmentButtonVariant?: ButtonVariant;\n /** The attachment field's `buttonSize` (0.25.0) — with {@link attachmentButtonVariant}.\n * Default `\"md\"`; `\"sm\"` draws the paperclip and camera at 14px. */\n attachmentButtonSize?: ButtonSize;\n /**\n * A muted line under the body saying who will read it (0.38, docs/feedback-harmonization.md\n * §9.2 decision 6) — the kit's sentence is `feedbackDialog.publicNotice`, \"Other users\n * will see the title and text (never your screenshots or files)\", which\n * `useFeedbackSubmit({ publicNotice: true })` passes. Attached to the body field with\n * `aria-describedby`, so it is heard where the text is written. Left out: no line.\n */\n publicNotice?: ReactNode;\n}\n\n/** One attachment — a screenshot, a picked or a pasted image; a second replaces\n * nothing, it has to wait for the first to be removed. The default. */\nexport interface FeedbackDialogSingleProps<C extends string = string> extends FeedbackDialogBaseProps<C> {\n attachments?: \"single\";\n onSubmit: (data: FeedbackSubmission<C>) => void | Promise<void>;\n /** `info` (0.23.0) names the refused file and the limit — see\n * {@link FeedbackAttachmentErrorInfo}. */\n onAttachmentError?: (kind: \"type\" | \"size\", info: FeedbackAttachmentErrorInfo) => void;\n /** Multiple mode only — refused here rather than silently ignored. */\n maxAttachments?: never;\n}\n\n/**\n * One screenshot plus up to `maxAttachments` picked or pasted files (0.15.5, keksdose\n * dev#578: \"pasted two photos, the second overwrote the first\"). The capture button is\n * offered while there is no screenshot yet; the add button while there is room.\n */\nexport interface FeedbackDialogMultipleProps<C extends string = string> extends FeedbackDialogBaseProps<C> {\n attachments: \"multiple\";\n /** Default `DEFAULT_MAX_ATTACHMENTS` (5). The screenshot does not count. */\n maxAttachments?: number;\n onSubmit: (data: FeedbackMultipleSubmission<C>) => void | Promise<void>;\n /** `\"count\"`: more files arrived at once than there was room for; the surplus was\n * dropped. `info` (0.23.0) names the refused file(s) and the limit. */\n onAttachmentError?: (kind: FeedbackAttachmentError, info: FeedbackAttachmentErrorInfo) => void;\n}\n\nexport type FeedbackDialogProps<C extends string = string> =\n FeedbackDialogSingleProps<C> | FeedbackDialogMultipleProps<C>;\n\n/**\n * The generic feedback form dialog: category + subject + body + an optional image\n * attachment, with Ctrl/Cmd+Enter to submit. Domain-free — the app supplies the\n * category options, labels and an `onSubmit` that talks to its own backend, plus\n * an optional `contextSlot` for app-specific context (user, current URL, …).\n *\n * **A screenshot can be pasted straight in.** Ctrl/Cmd+V anywhere in the dialog\n * takes an image off the clipboard and makes it the attachment, through the same\n * validation and the same preview as the file picker. It is the gesture the two\n * ways in did not cover: `onCaptureScreenshot` snapshots the *whole* app view,\n * and the file picker needs a file — so somebody who wanted to show one panel,\n * or one region of one, had to save a crop to disk first and then find it again\n * (Steering Design feedback #39). The clipboard is where a region snip already\n * is on every platform.\n *\n * **`attachments=\"multiple\"`** (0.15.5) takes several: every paste and pick adds a\n * chip, and `onSubmit` gets `{ screenshot, attachments }` ({@link\n * FeedbackMultipleSubmission}) instead of `attachment`. Opt-in, so a caller typed\n * against the one-file submission keeps compiling and behaving as before.\n */\nexport function FeedbackDialog<C extends string = string>(props: FeedbackDialogProps<C>) {\n const {\n open,\n onClose,\n categories,\n category,\n onCategoryChange,\n labels: labelsProp,\n submitting = false,\n contextSlot,\n attachmentAccept = DEFAULT_ATTACHMENT_ACCEPT,\n maxAttachmentBytes = DEFAULT_MAX_ATTACHMENT_BYTES,\n onCaptureScreenshot,\n requireBody = true,\n attachmentButtonVariant,\n attachmentButtonSize,\n publicNotice,\n } = props;\n const [title, setTitle] = useState(\"\");\n const [body, setBody] = useState(\"\");\n const [attachment, setAttachment] = useState<File | null>(null);\n // `attachments=\"multiple\"` only: the capture, apart from the picked/pasted files.\n const [screenshot, setScreenshot] = useState<File | null>(null);\n const [files, setFiles] = useState<File[]>([]);\n const isMobile = usePhoneLayout();\n const noticeId = useId();\n const hasNotice = hasContent(publicNotice);\n const labels = useKitLabels(\"feedbackDialog\", DEFAULT_FEEDBACK_DIALOG_LABELS, labelsProp);\n const attachmentText = useKitLabels(\"feedbackAttachment\", DEFAULT_FEEDBACK_ATTACHMENT_LABELS, labelsProp);\n // Under `multiple` the heading is `attachmentList` — a screenshot AND photos — which\n // also names the chip list beneath it: one string, so the two cannot disagree. Its old\n // second name, `feedbackDialog.attachments`, went in 0.34.\n const listHeading =\n labelsProp?.attachmentList ?? attachmentText.attachmentList ?? DEFAULT_FEEDBACK_ATTACHMENT_LABELS.attachmentList!;\n // The attachment field resolves its own keys from `feedbackAttachment`; it gets the\n // prop's (so a caller's `attachmentAdd` still wins) plus the resolved heading.\n const attachmentLabels =\n props.attachments === \"multiple\"\n ? { ...labelsProp, attachment: listHeading, attachmentList: listHeading }\n : { ...labelsProp, attachment: labels.attachment };\n\n // Reset the form whenever the dialog is (re)opened — during render, on the\n // closed-to-open transition, so the old draft never paints for a frame.\n const [wasOpen, setWasOpen] = useState(open);\n if (open !== wasOpen) {\n setWasOpen(open);\n if (open) {\n setTitle(\"\");\n setBody(\"\");\n setAttachment(null);\n setScreenshot(null);\n setFiles([]);\n }\n }\n\n // Trimmed: a subject or body of spaces is empty (keksdose's API answers a blank title\n // with a 422, and a blank report is no report).\n const canSubmit = !!title.trim() && (!requireBody || !!body.trim()) && !submitting;\n const trySubmit = () => {\n if (!canSubmit) return;\n if (props.attachments === \"multiple\") {\n void props.onSubmit({ title, body, category, screenshot, attachments: files });\n } else {\n void props.onSubmit({ title, body, category, attachment });\n }\n };\n\n if (!open) return null;\n\n const categoryField = (\n // The select offers exactly `categories`' values, so what it answers is one of them.\n <Select label={labels.category} value={category} onChange={(e) => onCategoryChange(e.target.value as C)}>\n {categories.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n </Select>\n );\n // On a phone the subject leads as a heading rather than as the second of two\n // identical boxes under a select (Keksdose feedback #179). `variant=\"display\"`\n // is a no-op above the phone breakpoint, so the desktop dialog is unchanged.\n const subjectField = (\n <Input label={labels.subject} value={title} onChange={(e) => setTitle(e.target.value)} variant=\"display\" />\n );\n const bodyTextarea = (\n <Textarea\n rows={5}\n label={requireBody ? labels.body : (labelsProp?.body ?? labels.bodyOptional ?? labels.body)}\n value={body}\n onChange={(e) => setBody(e.target.value)}\n aria-describedby={hasNotice ? noticeId : undefined}\n />\n );\n // 0.38: who will read it, right under what they are writing (§9.2 decision 6).\n const bodyField = hasNotice ? (\n <div className=\"space-y-1\">\n {bodyTextarea}\n <p id={noticeId} className=\"text-xs text-muted\" data-feedback-public-notice=\"\">\n {publicNotice}\n </p>\n </div>\n ) : (\n bodyTextarea\n );\n const fieldProps = {\n labels: attachmentLabels,\n accept: attachmentAccept,\n maxBytes: maxAttachmentBytes,\n onCaptureScreenshot,\n // Left undefined they are the field's own defaults (secondary / md).\n buttonVariant: attachmentButtonVariant,\n buttonSize: attachmentButtonSize,\n // On `document`, not on the panel: the Modal focuses its own panel on open\n // and traps Tab inside it, so while this dialog is up every paste in the\n // page is meant for it — including the one made with nothing in\n // particular focused, which never reaches a React `onPaste` on a child.\n documentPaste: open,\n };\n const attachmentField =\n props.attachments === \"multiple\" ? (\n <FeedbackAttachmentField\n {...fieldProps}\n multiple\n value={files}\n onChange={setFiles}\n max={props.maxAttachments}\n // The capture goes to its own slot, so it is offered once and never crowds\n // out a photo; a paste is a photo (a region snip is chosen evidence, not \"the\n // screenshot\").\n screenshot={screenshot}\n onScreenshotChange={setScreenshot}\n onError={props.onAttachmentError}\n />\n ) : (\n <FeedbackAttachmentField\n {...fieldProps}\n value={attachment}\n onChange={setAttachment}\n onError={props.onAttachmentError}\n />\n );\n\n return (\n <Modal\n onClose={onClose}\n // The one dialog whose subject is the page behind it (Keksdose dev#460: \"Make\n // the feedback dialog draggable so I can see behind it if it blocks\n // something\") — you are describing what is under it while you type.\n draggable\n onKeyDown={(e) => {\n if ((e.ctrlKey || e.metaKey) && e.key === \"Enter\") {\n e.preventDefault();\n trySubmit();\n }\n }}\n >\n {/* Also the drag handle: pressing anywhere on the panel's own chrome moves it,\n and the heading is the strip a user reaches for. */}\n <h2 className=\"mb-3 text-lg font-semibold\">{labels.title}</h2>\n <div className=\"space-y-3\">\n {isMobile ? (\n // Phone shape, the same reasoning as the transaction editor's (#177):\n // the desktop order is the DATA MODEL's order — category, then subject,\n // then body — but nobody opens this dialog to pick a category. What they\n // came to do is say the thing, so that leads; the classification and the\n // evidence follow, a tier down.\n <>\n {subjectField}\n {bodyField}\n <div className=\"space-y-3 border-t border-subtle pt-3\">\n {categoryField}\n {attachmentField}\n {contextSlot}\n </div>\n </>\n ) : (\n <>\n {categoryField}\n {subjectField}\n {bodyField}\n {attachmentField}\n {contextSlot}\n </>\n )}\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"text-xs text-placeholder\">\n {typeof labels.submitHint === \"function\" ? labels.submitHint(isApplePlatform()) : labels.submitHint}\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"ghost\" onClick={onClose}>\n {labels.cancel}\n </Button>\n <Button onClick={trySubmit} disabled={!canSubmit}>\n {labels.save}\n </Button>\n </div>\n </div>\n </div>\n </Modal>\n );\n}\n"],"mappings":";AAuTQ,SA8FE,UA9FF,KAuBJ,YAvBI;AAvTR,SAAS,OAAO,gBAAgB;AAEhC,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,cAAc;AACvB,SAAS,gBAAgB;AAEzB,SAAS,aAAa;AACtB,SAAS,uBAAuB;AAChC,SAAS,sBAAsB;AAC/B,SAAS,oBAAwC;AACjD,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,sCAAsC;AA0NxC,SAAS,eAA0C,OAA+B;AACvF,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,aAAa;AAAA,IACb;AAAA,IACA,mBAAmB;AAAA,IACnB,qBAAqB;AAAA,IACrB;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE;AACnC,QAAM,CAAC,YAAY,aAAa,IAAI,SAAsB,IAAI;AAE9D,QAAM,CAAC,YAAY,aAAa,IAAI,SAAsB,IAAI;AAC9D,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAiB,CAAC,CAAC;AAC7C,QAAM,WAAW,eAAe;AAChC,QAAM,WAAW,MAAM;AACvB,QAAM,YAAY,WAAW,YAAY;AACzC,QAAM,SAAS,aAAa,kBAAkB,gCAAgC,UAAU;AACxF,QAAM,iBAAiB,aAAa,sBAAsB,oCAAoC,UAAU;AAIxG,QAAM,cACJ,YAAY,kBAAkB,eAAe,kBAAkB,mCAAmC;AAGpG,QAAM,mBACJ,MAAM,gBAAgB,aAClB,EAAE,GAAG,YAAY,YAAY,aAAa,gBAAgB,YAAY,IACtE,EAAE,GAAG,YAAY,YAAY,OAAO,WAAW;AAIrD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,MAAI,SAAS,SAAS;AACpB,eAAW,IAAI;AACf,QAAI,MAAM;AACR,eAAS,EAAE;AACX,cAAQ,EAAE;AACV,oBAAc,IAAI;AAClB,oBAAc,IAAI;AAClB,eAAS,CAAC,CAAC;AAAA,IACb;AAAA,EACF;AAIA,QAAM,YAAY,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,eAAe,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC;AACxE,QAAM,YAAY,MAAM;AACtB,QAAI,CAAC,UAAW;AAChB,QAAI,MAAM,gBAAgB,YAAY;AACpC,WAAK,MAAM,SAAS,EAAE,OAAO,MAAM,UAAU,YAAY,aAAa,MAAM,CAAC;AAAA,IAC/E,OAAO;AACL,WAAK,MAAM,SAAS,EAAE,OAAO,MAAM,UAAU,WAAW,CAAC;AAAA,IAC3D;AAAA,EACF;AAEA,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM;AAAA;AAAA,IAEJ,oBAAC,UAAO,OAAO,OAAO,UAAU,OAAO,UAAU,UAAU,CAAC,MAAM,iBAAiB,EAAE,OAAO,KAAU,GACnG,qBAAW,IAAI,CAAC,MACf,oBAAC,YAAqB,OAAO,EAAE,OAC5B,YAAE,SADQ,EAAE,KAEf,CACD,GACH;AAAA;AAKF,QAAM,eACJ,oBAAC,SAAM,OAAO,OAAO,SAAS,OAAO,OAAO,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK,GAAG,SAAQ,WAAU;AAE3G,QAAM,eACJ;AAAA,IAAC;AAAA;AAAA,MACC,MAAM;AAAA,MACN,OAAO,cAAc,OAAO,OAAQ,YAAY,QAAQ,OAAO,gBAAgB,OAAO;AAAA,MACtF,OAAO;AAAA,MACP,UAAU,CAAC,MAAM,QAAQ,EAAE,OAAO,KAAK;AAAA,MACvC,oBAAkB,YAAY,WAAW;AAAA;AAAA,EAC3C;AAGF,QAAM,YAAY,YAChB,qBAAC,SAAI,WAAU,aACZ;AAAA;AAAA,IACD,oBAAC,OAAE,IAAI,UAAU,WAAU,sBAAqB,+BAA4B,IACzE,wBACH;AAAA,KACF,IAEA;AAEF,QAAM,aAAa;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,UAAU;AAAA,IACV;AAAA;AAAA,IAEA,eAAe;AAAA,IACf,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,IAKZ,eAAe;AAAA,EACjB;AACA,QAAM,kBACJ,MAAM,gBAAgB,aACpB;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,UAAQ;AAAA,MACR,OAAO;AAAA,MACP,UAAU;AAAA,MACV,KAAK,MAAM;AAAA,MAIX;AAAA,MACA,oBAAoB;AAAA,MACpB,SAAS,MAAM;AAAA;AAAA,EACjB,IAEA;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,OAAO;AAAA,MACP,UAAU;AAAA,MACV,SAAS,MAAM;AAAA;AAAA,EACjB;AAGJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MAIA,WAAS;AAAA,MACT,WAAW,CAAC,MAAM;AAChB,aAAK,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,SAAS;AACjD,YAAE,eAAe;AACjB,oBAAU;AAAA,QACZ;AAAA,MACF;AAAA,MAIA;AAAA,4BAAC,QAAG,WAAU,8BAA8B,iBAAO,OAAM;AAAA,QACzD,qBAAC,SAAI,WAAU,aACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAMC,iCACG;AAAA;AAAA,cACA;AAAA,cACD,qBAAC,SAAI,WAAU,yCACZ;AAAA;AAAA,gBACA;AAAA,gBACA;AAAA,iBACH;AAAA,eACF;AAAA,cAEA,iCACG;AAAA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,aACH;AAAA,UAEF,qBAAC,SAAI,WAAU,2CACb;AAAA,gCAAC,SAAI,WAAU,4BACZ,iBAAO,OAAO,eAAe,aAAa,OAAO,WAAW,gBAAgB,CAAC,IAAI,OAAO,YAC3F;AAAA,YACA,qBAAC,SAAI,WAAU,cACb;AAAA,kCAAC,UAAO,SAAQ,SAAQ,SAAS,SAC9B,iBAAO,QACV;AAAA,cACA,oBAAC,UAAO,SAAS,WAAW,UAAU,CAAC,WACpC,iBAAO,MACV;AAAA,eACF;AAAA,aACF;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/feedback/feedback-dialog.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Button } from \"../components/button\";\nimport { Input } from \"../components/input\";\nimport { Select } from \"../components/select\";\nimport { Textarea } from \"../components/textarea\";\nimport type { ButtonSize, ButtonVariant } from \"../components/button-look\";\nimport { Modal } from \"../components/modal\";\nimport { isApplePlatform } from \"../hooks/use-hotkey\";\nimport { usePhoneLayout } from \"../hooks/use-breakpoint\";\nimport { useKitLabels, type LabelOverride } from \"../i18n/kit-labels\";\nimport { hasContent } from \"../lib/presence\";\nimport {\n DEFAULT_ATTACHMENT_ACCEPT,\n DEFAULT_FEEDBACK_ATTACHMENT_LABELS,\n DEFAULT_MAX_ATTACHMENT_BYTES,\n FeedbackAttachmentField,\n type FeedbackAttachmentError,\n type FeedbackAttachmentErrorInfo,\n} from \"./feedback-attachment\";\nimport { DEFAULT_FEEDBACK_DIALOG_LABELS } from \"./feedback-dialog-labels\";\n\n/** One category the dialog offers. `C` (0.52): the app's category type — the kit's\n * `FeedbackCategory`, or `string` (the default) for a vocabulary of the app's own. */\nexport interface FeedbackCategoryOption<C extends string = string> {\n value: C;\n label: string;\n}\n\nexport interface FeedbackAttachmentLabels {\n /** The heading over the field. Optional: a note editor puts the buttons\n * straight under its textarea, where a second heading is noise. */\n attachment?: string;\n attachmentAdd: string;\n /** Label for the \"capture screenshot\" button. Optional — falls back to the provider's\n * `feedbackAttachment.attachmentCapture`, then English. */\n attachmentCapture?: string;\n /** The line under the attachment buttons saying a screenshot can be pasted\n * straight in. Optional — falls back to the provider's `feedbackAttachment`, then English. */\n attachmentPaste?: string;\n attachmentRemove: string;\n /** `multiple` mode (0.15.5): the chip list's accessible name — and, in\n * `<FeedbackDialog attachments=\"multiple\">`, the heading over it (0.16.0). Optional,\n * as are the keys below — they fall back to the provider's `feedbackAttachment`,\n * then English. */\n attachmentList?: string;\n /** `multiple` mode (0.16.0): the screenshot slot's chip title, in place of its file name. */\n attachmentScreenshot?: string;\n /** `multiple` mode: one chip's remove button, given the file's name. */\n attachmentRemoveFile?: (name: string) => string;\n /** `multiple` mode: the line shown once `max` files are attached. */\n attachmentLimit?: (max: number) => string;\n /** `refs` mode (0.22.0): the second line of a chip whose upload is still running. */\n attachmentUploading?: string;\n}\n\nexport interface FeedbackDialogLabels extends FeedbackAttachmentLabels {\n title: string;\n category: string;\n subject: string;\n body: string;\n attachment: string;\n /** See {@link FeedbackDialogTextLabels.submitHint}. */\n submitHint: FeedbackSubmitHint;\n cancel: string;\n save: string;\n}\n\n/** The submit hint: a string, or the line for the platform (`apple`: Mac, iPhone, iPad). */\nexport type FeedbackSubmitHint = string | ((apple: boolean) => string);\n\n/**\n * The dialog's own strings — the `feedbackDialog` namespace of `<UiKitProvider\n * labels>` (0.12.0). The attachment keys are not repeated here: they are the\n * `feedbackAttachment` namespace's, which the field inside already reads.\n *\n * Before, every key was required at the call site, so each app restated ten strings\n * wherever it mounted the dialog (kastlan feedback-button.tsx built the object inline).\n */\nexport interface FeedbackDialogTextLabels {\n title: string;\n category: string;\n subject: string;\n body: string;\n /** The body's label when `requireBody={false}`: \"What happened? (optional)\".\n * Optional, so a complete `UiKitLabels` typed before 0.14.2 still compiles. */\n bodyOptional?: string;\n /** The heading over the attachment buttons. */\n attachment: string;\n /**\n * The line beside the buttons naming the shortcut. Since 0.27.0 a function of the\n * platform, like `form.submitShortcut`: `apple` is true on a Mac, iPhone or iPad, where\n * the key is Cmd — \"⌘ Enter to send\" there, keksdose's \"Ctrl+Enter to send\" elsewhere\n * (§7.12). A plain string is still taken and shown everywhere, as before 0.27.0.\n */\n submitHint: FeedbackSubmitHint;\n cancel: string;\n save: string;\n /** 0.38 (docs/feedback-harmonization.md §9.2 decision 6): the line under the body when\n * reports are public — `useFeedbackSubmit({ publicNotice: true })` shows it. Optional,\n * so a complete `UiKitLabels` typed before 0.38 still compiles. de-CH \"Andere Personen\n * sehen Titel und Text (nie Ihre Screenshots oder Dateien).\" */\n publicNotice?: string;\n}\n\n// Defined in ./feedback-dialog-labels, which holds no component code (0.34, KS U8).\nexport { DEFAULT_FEEDBACK_DIALOG_LABELS };\n\nexport interface FeedbackSubmission<C extends string = string> {\n title: string;\n body: string;\n category: C;\n attachment: File | null;\n}\n\n/**\n * What `onSubmit` gets under `attachments=\"multiple\"` (0.15.5): the screenshot and\n * the picked/pasted files apart, because an app files them differently — keksdose\n * attaches the screenshot to the report and the photos as its evidence list. No\n * `attachment`: there is no one file it could name.\n */\nexport interface FeedbackMultipleSubmission<C extends string = string> {\n title: string;\n body: string;\n category: C;\n /** What `onCaptureScreenshot` returned, or `null` — at most one. */\n screenshot: File | null;\n /** Picked and pasted files, in the order they were added; at most `maxAttachments`. */\n attachments: File[];\n}\n\n/**\n * `C` (0.52, refactor audit 2026-10-30, API-7): the category type, inferred from\n * `categories` and `category` — `FeedbackCategory` hands `onCategoryChange` and\n * `onSubmit` a `FeedbackCategory` back, where a plain `string` had to be cast (the kit's\n * own `useFeedbackSubmit` did). `string` by default, so an app's own vocabulary fits.\n */\ninterface FeedbackDialogBaseProps<C extends string = string> {\n open: boolean;\n onClose: () => void;\n /** `readonly` since 0.52: the dialog never changes it. */\n categories: readonly FeedbackCategoryOption<C>[];\n category: C;\n onCategoryChange: (value: C) => void;\n /** Prop > `<UiKitProvider labels={{ feedbackDialog, feedbackAttachment }}>` >\n * English. Optional since 0.12.0; a whole `FeedbackDialogLabels` still fits. */\n labels?: LabelOverride<FeedbackDialogLabels>;\n submitting?: boolean;\n /**\n * The subject and the body each opening starts with, in place of empty fields — the\n * reporter edits them like anything typed. `useFeedbackSubmit().open(category, { title,\n * body })` passes them (keksdose live #481: \"Report this problem\" opens on words the\n * screen already knows). Read when the dialog opens; a change while it is open leaves\n * the draft alone.\n */\n defaultTitle?: string;\n /** The body's, as `defaultTitle` is the subject's. */\n defaultBody?: string;\n contextSlot?: ReactNode;\n attachmentAccept?: string[];\n maxAttachmentBytes?: number;\n /**\n * Optional: capture a screenshot of the underlying app view and return it as a\n * File. When provided, a \"Capture screenshot\" button is shown next to \"Add\n * attachment\"; the returned file is fed through the same validation + preview.\n */\n onCaptureScreenshot?: () => Promise<File | null>;\n /**\n * `false`: a report with only a subject can be sent, and the body's label says it is\n * optional (`bodyOptional`, unless `labels.body` is passed). Default `true`, the\n * dialog's behaviour until 0.14.2 (keksdose K1: its backend takes title-only reports).\n */\n requireBody?: boolean;\n /**\n * The attachment field's add and capture buttons: its `buttonVariant` (0.25.0),\n * Button's own `variant`. Default `\"secondary\"`, the look they always had.\n *\n * The field took `buttonVariant` / `buttonSize` in 0.24.0 (keksdose's support chat),\n * but the dialog builds its field itself and passed neither, so a host that wanted\n * quieter buttons here — a dialog that already ends in a row of Cancel / Send — had\n * no way to say so short of rebuilding the dialog. Named after the dialog's other\n * attachment options (`attachmentAccept`, `onAttachmentError`) and handed through\n * unchanged, in both `attachments` modes.\n */\n attachmentButtonVariant?: ButtonVariant;\n /** The attachment field's `buttonSize` (0.25.0) — with {@link attachmentButtonVariant}.\n * Default `\"md\"`; `\"sm\"` draws the paperclip and camera at 14px. */\n attachmentButtonSize?: ButtonSize;\n /**\n * A muted line under the body saying who will read it (0.38, docs/feedback-harmonization.md\n * §9.2 decision 6) — the kit's sentence is `feedbackDialog.publicNotice`, \"Other users\n * will see the title and text (never your screenshots or files)\", which\n * `useFeedbackSubmit({ publicNotice: true })` passes. Attached to the body field with\n * `aria-describedby`, so it is heard where the text is written. Left out: no line.\n */\n publicNotice?: ReactNode;\n}\n\n/** One attachment — a screenshot, a picked or a pasted image; a second replaces\n * nothing, it has to wait for the first to be removed. The default. */\nexport interface FeedbackDialogSingleProps<C extends string = string> extends FeedbackDialogBaseProps<C> {\n attachments?: \"single\";\n onSubmit: (data: FeedbackSubmission<C>) => void | Promise<void>;\n /** `info` (0.23.0) names the refused file and the limit — see\n * {@link FeedbackAttachmentErrorInfo}. */\n onAttachmentError?: (kind: \"type\" | \"size\", info: FeedbackAttachmentErrorInfo) => void;\n /** Multiple mode only — refused here rather than silently ignored. */\n maxAttachments?: never;\n}\n\n/**\n * One screenshot plus up to `maxAttachments` picked or pasted files (0.15.5, keksdose\n * dev#578: \"pasted two photos, the second overwrote the first\"). The capture button is\n * offered while there is no screenshot yet; the add button while there is room.\n */\nexport interface FeedbackDialogMultipleProps<C extends string = string> extends FeedbackDialogBaseProps<C> {\n attachments: \"multiple\";\n /** Default `DEFAULT_MAX_ATTACHMENTS` (5). The screenshot does not count. */\n maxAttachments?: number;\n onSubmit: (data: FeedbackMultipleSubmission<C>) => void | Promise<void>;\n /** `\"count\"`: more files arrived at once than there was room for; the surplus was\n * dropped. `info` (0.23.0) names the refused file(s) and the limit. */\n onAttachmentError?: (kind: FeedbackAttachmentError, info: FeedbackAttachmentErrorInfo) => void;\n}\n\nexport type FeedbackDialogProps<C extends string = string> =\n FeedbackDialogSingleProps<C> | FeedbackDialogMultipleProps<C>;\n\n/**\n * The generic feedback form dialog: category + subject + body + an optional image\n * attachment, with Ctrl/Cmd+Enter to submit. Domain-free — the app supplies the\n * category options, labels and an `onSubmit` that talks to its own backend, plus\n * an optional `contextSlot` for app-specific context (user, current URL, …).\n *\n * **A screenshot can be pasted straight in.** Ctrl/Cmd+V anywhere in the dialog\n * takes an image off the clipboard and makes it the attachment, through the same\n * validation and the same preview as the file picker. It is the gesture the two\n * ways in did not cover: `onCaptureScreenshot` snapshots the *whole* app view,\n * and the file picker needs a file — so somebody who wanted to show one panel,\n * or one region of one, had to save a crop to disk first and then find it again\n * (Steering Design feedback #39). The clipboard is where a region snip already\n * is on every platform.\n *\n * **`attachments=\"multiple\"`** (0.15.5) takes several: every paste and pick adds a\n * chip, and `onSubmit` gets `{ screenshot, attachments }` ({@link\n * FeedbackMultipleSubmission}) instead of `attachment`. Opt-in, so a caller typed\n * against the one-file submission keeps compiling and behaving as before.\n */\nexport function FeedbackDialog<C extends string = string>(props: FeedbackDialogProps<C>) {\n const {\n open,\n onClose,\n categories,\n category,\n onCategoryChange,\n labels: labelsProp,\n submitting = false,\n defaultTitle = \"\",\n defaultBody = \"\",\n contextSlot,\n attachmentAccept = DEFAULT_ATTACHMENT_ACCEPT,\n maxAttachmentBytes = DEFAULT_MAX_ATTACHMENT_BYTES,\n onCaptureScreenshot,\n requireBody = true,\n attachmentButtonVariant,\n attachmentButtonSize,\n publicNotice,\n } = props;\n const [title, setTitle] = useState(defaultTitle);\n const [body, setBody] = useState(defaultBody);\n const [attachment, setAttachment] = useState<File | null>(null);\n // `attachments=\"multiple\"` only: the capture, apart from the picked/pasted files.\n const [screenshot, setScreenshot] = useState<File | null>(null);\n const [files, setFiles] = useState<File[]>([]);\n const isMobile = usePhoneLayout();\n const noticeId = useId();\n const hasNotice = hasContent(publicNotice);\n const labels = useKitLabels(\"feedbackDialog\", DEFAULT_FEEDBACK_DIALOG_LABELS, labelsProp);\n const attachmentText = useKitLabels(\"feedbackAttachment\", DEFAULT_FEEDBACK_ATTACHMENT_LABELS, labelsProp);\n // Under `multiple` the heading is `attachmentList` — a screenshot AND photos — which\n // also names the chip list beneath it: one string, so the two cannot disagree. Its old\n // second name, `feedbackDialog.attachments`, went in 0.34.\n const listHeading =\n labelsProp?.attachmentList ?? attachmentText.attachmentList ?? DEFAULT_FEEDBACK_ATTACHMENT_LABELS.attachmentList!;\n // The attachment field resolves its own keys from `feedbackAttachment`; it gets the\n // prop's (so a caller's `attachmentAdd` still wins) plus the resolved heading.\n const attachmentLabels =\n props.attachments === \"multiple\"\n ? { ...labelsProp, attachment: listHeading, attachmentList: listHeading }\n : { ...labelsProp, attachment: labels.attachment };\n\n // Reset the form whenever the dialog is (re)opened — during render, on the\n // closed-to-open transition, so the old draft never paints for a frame.\n const [wasOpen, setWasOpen] = useState(open);\n if (open !== wasOpen) {\n setWasOpen(open);\n if (open) {\n setTitle(defaultTitle);\n setBody(defaultBody);\n setAttachment(null);\n setScreenshot(null);\n setFiles([]);\n }\n }\n\n // Trimmed: a subject or body of spaces is empty (keksdose's API answers a blank title\n // with a 422, and a blank report is no report).\n const canSubmit = !!title.trim() && (!requireBody || !!body.trim()) && !submitting;\n const trySubmit = () => {\n if (!canSubmit) return;\n if (props.attachments === \"multiple\") {\n void props.onSubmit({ title, body, category, screenshot, attachments: files });\n } else {\n void props.onSubmit({ title, body, category, attachment });\n }\n };\n\n if (!open) return null;\n\n const categoryField = (\n // The select offers exactly `categories`' values, so what it answers is one of them.\n <Select label={labels.category} value={category} onChange={(e) => onCategoryChange(e.target.value as C)}>\n {categories.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n </Select>\n );\n // On a phone the subject leads as a heading rather than as the second of two\n // identical boxes under a select (Keksdose feedback #179). `variant=\"display\"`\n // is a no-op above the phone breakpoint, so the desktop dialog is unchanged.\n const subjectField = (\n <Input label={labels.subject} value={title} onChange={(e) => setTitle(e.target.value)} variant=\"display\" />\n );\n const bodyTextarea = (\n <Textarea\n rows={5}\n label={requireBody ? labels.body : (labelsProp?.body ?? labels.bodyOptional ?? labels.body)}\n value={body}\n onChange={(e) => setBody(e.target.value)}\n aria-describedby={hasNotice ? noticeId : undefined}\n />\n );\n // 0.38: who will read it, right under what they are writing (§9.2 decision 6).\n const bodyField = hasNotice ? (\n <div className=\"space-y-1\">\n {bodyTextarea}\n <p id={noticeId} className=\"text-xs text-muted\" data-feedback-public-notice=\"\">\n {publicNotice}\n </p>\n </div>\n ) : (\n bodyTextarea\n );\n const fieldProps = {\n labels: attachmentLabels,\n accept: attachmentAccept,\n maxBytes: maxAttachmentBytes,\n onCaptureScreenshot,\n // Left undefined they are the field's own defaults (secondary / md).\n buttonVariant: attachmentButtonVariant,\n buttonSize: attachmentButtonSize,\n // On `document`, not on the panel: the Modal focuses its own panel on open\n // and traps Tab inside it, so while this dialog is up every paste in the\n // page is meant for it — including the one made with nothing in\n // particular focused, which never reaches a React `onPaste` on a child.\n documentPaste: open,\n };\n const attachmentField =\n props.attachments === \"multiple\" ? (\n <FeedbackAttachmentField\n {...fieldProps}\n multiple\n value={files}\n onChange={setFiles}\n max={props.maxAttachments}\n // The capture goes to its own slot, so it is offered once and never crowds\n // out a photo; a paste is a photo (a region snip is chosen evidence, not \"the\n // screenshot\").\n screenshot={screenshot}\n onScreenshotChange={setScreenshot}\n onError={props.onAttachmentError}\n />\n ) : (\n <FeedbackAttachmentField\n {...fieldProps}\n value={attachment}\n onChange={setAttachment}\n onError={props.onAttachmentError}\n />\n );\n\n return (\n <Modal\n onClose={onClose}\n // The one dialog whose subject is the page behind it (Keksdose dev#460: \"Make\n // the feedback dialog draggable so I can see behind it if it blocks\n // something\") — you are describing what is under it while you type.\n draggable\n onKeyDown={(e) => {\n if ((e.ctrlKey || e.metaKey) && e.key === \"Enter\") {\n e.preventDefault();\n trySubmit();\n }\n }}\n >\n {/* Also the drag handle: pressing anywhere on the panel's own chrome moves it,\n and the heading is the strip a user reaches for. */}\n <h2 className=\"mb-3 text-lg font-semibold\">{labels.title}</h2>\n <div className=\"space-y-3\">\n {isMobile ? (\n // Phone shape, the same reasoning as the transaction editor's (#177):\n // the desktop order is the DATA MODEL's order — category, then subject,\n // then body — but nobody opens this dialog to pick a category. What they\n // came to do is say the thing, so that leads; the classification and the\n // evidence follow, a tier down.\n <>\n {subjectField}\n {bodyField}\n <div className=\"space-y-3 border-t border-subtle pt-3\">\n {categoryField}\n {attachmentField}\n {contextSlot}\n </div>\n </>\n ) : (\n <>\n {categoryField}\n {subjectField}\n {bodyField}\n {attachmentField}\n {contextSlot}\n </>\n )}\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"text-xs text-placeholder\">\n {typeof labels.submitHint === \"function\" ? labels.submitHint(isApplePlatform()) : labels.submitHint}\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"ghost\" onClick={onClose}>\n {labels.cancel}\n </Button>\n <Button onClick={trySubmit} disabled={!canSubmit}>\n {labels.save}\n </Button>\n </div>\n </div>\n </div>\n </Modal>\n );\n}\n"],"mappings":"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","names":[]}