@eifi1/ui-kit 0.21.0 → 0.23.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 (320) hide show
  1. package/README.md +42 -25
  2. package/dist/chart.d.ts +19 -14
  3. package/dist/components/account-chips.d.ts +10 -3
  4. package/dist/components/account-chips.js +5 -2
  5. package/dist/components/account-chips.js.map +1 -1
  6. package/dist/components/account-settings.d.ts +33 -2
  7. package/dist/components/account-settings.js +43 -21
  8. package/dist/components/account-settings.js.map +1 -1
  9. package/dist/components/amount-input.d.ts +53 -14
  10. package/dist/components/amount-input.js +17 -28
  11. package/dist/components/amount-input.js.map +1 -1
  12. package/dist/components/autocomplete.d.ts +29 -0
  13. package/dist/components/autocomplete.js +134 -104
  14. package/dist/components/autocomplete.js.map +1 -1
  15. package/dist/components/button-group.d.ts +19 -14
  16. package/dist/components/calculator.d.ts +19 -14
  17. package/dist/components/checkbox-group.d.ts +104 -0
  18. package/dist/components/checkbox-group.js +111 -0
  19. package/dist/components/checkbox-group.js.map +1 -0
  20. package/dist/components/checkbox.d.ts +19 -0
  21. package/dist/components/checkbox.js +30 -7
  22. package/dist/components/checkbox.js.map +1 -1
  23. package/dist/components/chip.d.ts +18 -0
  24. package/dist/components/chip.js +47 -10
  25. package/dist/components/chip.js.map +1 -1
  26. package/dist/components/column-mapper.d.ts +182 -0
  27. package/dist/components/column-mapper.js +375 -0
  28. package/dist/components/column-mapper.js.map +1 -0
  29. package/dist/components/combobox-core.d.ts +39 -2
  30. package/dist/components/combobox-core.js +29 -6
  31. package/dist/components/combobox-core.js.map +1 -1
  32. package/dist/components/combobox.d.ts +91 -2
  33. package/dist/components/combobox.js +454 -308
  34. package/dist/components/combobox.js.map +1 -1
  35. package/dist/components/confirm-dialog.d.ts +69 -161
  36. package/dist/components/confirm-dialog.js +7 -8
  37. package/dist/components/confirm-dialog.js.map +1 -1
  38. package/dist/components/copy-button.d.ts +16 -11
  39. package/dist/components/country-select.d.ts +167 -0
  40. package/dist/components/country-select.js +293 -0
  41. package/dist/components/country-select.js.map +1 -0
  42. package/dist/components/currency-select.d.ts +17 -1
  43. package/dist/components/currency-select.js +56 -23
  44. package/dist/components/currency-select.js.map +1 -1
  45. package/dist/components/danger-confirm.d.ts +69 -166
  46. package/dist/components/danger-confirm.js +144 -50
  47. package/dist/components/danger-confirm.js.map +1 -1
  48. package/dist/components/data-table-cells.d.ts +1 -2
  49. package/dist/components/data-table-filter-popover.d.ts +1 -2
  50. package/dist/components/data-table-filters.d.ts +1 -2
  51. package/dist/components/data-table-labels.d.ts +4 -97
  52. package/dist/components/data-table-labels.js +9 -1
  53. package/dist/components/data-table-labels.js.map +1 -1
  54. package/dist/components/data-table-pagination.d.ts +3 -1
  55. package/dist/components/data-table.d.ts +1 -2
  56. package/dist/components/data-table.js +98 -3
  57. package/dist/components/data-table.js.map +1 -1
  58. package/dist/components/date-picker.d.ts +66 -5
  59. package/dist/components/date-picker.js +378 -66
  60. package/dist/components/date-picker.js.map +1 -1
  61. package/dist/components/entity-combobox.d.ts +42 -1
  62. package/dist/components/entity-combobox.js +154 -113
  63. package/dist/components/entity-combobox.js.map +1 -1
  64. package/dist/components/facing-pair.d.ts +19 -14
  65. package/dist/components/field-parts.d.ts +224 -0
  66. package/dist/components/field-parts.js +156 -0
  67. package/dist/components/field-parts.js.map +1 -0
  68. package/dist/components/field-strip.d.ts +105 -0
  69. package/dist/components/field-strip.js +46 -0
  70. package/dist/components/field-strip.js.map +1 -0
  71. package/dist/components/file-button.d.ts +19 -14
  72. package/dist/components/file-button.js +13 -3
  73. package/dist/components/file-button.js.map +1 -1
  74. package/dist/components/file-dropzone.d.ts +41 -15
  75. package/dist/components/file-dropzone.js +57 -34
  76. package/dist/components/file-dropzone.js.map +1 -1
  77. package/dist/components/form-actions.d.ts +18 -13
  78. package/dist/components/form-actions.js +69 -5
  79. package/dist/components/form-actions.js.map +1 -1
  80. package/dist/components/iban-input.d.ts +69 -0
  81. package/dist/components/iban-input.js +125 -0
  82. package/dist/components/iban-input.js.map +1 -0
  83. package/dist/components/icon-picker.d.ts +21 -2
  84. package/dist/components/icon-picker.js +19 -4
  85. package/dist/components/icon-picker.js.map +1 -1
  86. package/dist/components/inline-edit-field.d.ts +167 -0
  87. package/dist/components/inline-edit-field.js +293 -0
  88. package/dist/components/inline-edit-field.js.map +1 -0
  89. package/dist/components/language-select.d.ts +130 -0
  90. package/dist/components/language-select.js +18 -0
  91. package/dist/components/language-select.js.map +1 -0
  92. package/dist/components/line-items.d.ts +25 -3
  93. package/dist/components/line-items.js +55 -46
  94. package/dist/components/line-items.js.map +1 -1
  95. package/dist/components/list.d.ts +25 -0
  96. package/dist/components/list.js +16 -5
  97. package/dist/components/list.js.map +1 -1
  98. package/dist/components/money-field.d.ts +32 -14
  99. package/dist/components/money-field.js.map +1 -1
  100. package/dist/components/month-picker.d.ts +52 -4
  101. package/dist/components/month-picker.js +291 -86
  102. package/dist/components/month-picker.js.map +1 -1
  103. package/dist/components/multi-entity-combobox.d.ts +26 -1
  104. package/dist/components/multi-entity-combobox.js +143 -102
  105. package/dist/components/multi-entity-combobox.js.map +1 -1
  106. package/dist/components/multi-select.d.ts +8 -1
  107. package/dist/components/multi-select.js +9 -4
  108. package/dist/components/multi-select.js.map +1 -1
  109. package/dist/components/number-field.d.ts +34 -19
  110. package/dist/components/number-field.js +6 -20
  111. package/dist/components/number-field.js.map +1 -1
  112. package/dist/components/number-input.d.ts +79 -19
  113. package/dist/components/number-input.js +90 -38
  114. package/dist/components/number-input.js.map +1 -1
  115. package/dist/components/numpad-sheet.d.ts +19 -14
  116. package/dist/components/one-time-code-input.d.ts +100 -0
  117. package/dist/components/one-time-code-input.js +137 -0
  118. package/dist/components/one-time-code-input.js.map +1 -0
  119. package/dist/components/phone-input.d.ts +69 -0
  120. package/dist/components/phone-input.js +171 -0
  121. package/dist/components/phone-input.js.map +1 -0
  122. package/dist/components/reauth-dialog.d.ts +2 -2
  123. package/dist/components/reauth-dialog.js +6 -8
  124. package/dist/components/reauth-dialog.js.map +1 -1
  125. package/dist/components/series-chart.d.ts +19 -14
  126. package/dist/components/settings-fields.d.ts +19 -14
  127. package/dist/components/share-card.d.ts +16 -11
  128. package/dist/components/sign-chip.d.ts +66 -0
  129. package/dist/components/sign-chip.js +39 -0
  130. package/dist/components/sign-chip.js.map +1 -0
  131. package/dist/components/swatch-picker.d.ts +43 -2
  132. package/dist/components/swatch-picker.js +80 -32
  133. package/dist/components/swatch-picker.js.map +1 -1
  134. package/dist/components/switch.d.ts +19 -0
  135. package/dist/components/switch.js +24 -6
  136. package/dist/components/switch.js.map +1 -1
  137. package/dist/components/text-link.d.ts +18 -13
  138. package/dist/components/tile-radio.d.ts +88 -13
  139. package/dist/components/tile-radio.js +28 -11
  140. package/dist/components/tile-radio.js.map +1 -1
  141. package/dist/components/time-input.d.ts +24 -15
  142. package/dist/components/time-input.js.map +1 -1
  143. package/dist/components/toggle-group.d.ts +47 -1
  144. package/dist/components/toggle-group.js +110 -69
  145. package/dist/components/toggle-group.js.map +1 -1
  146. package/dist/components/trigger-aria.d.ts +3 -0
  147. package/dist/components/trigger-aria.js +3 -1
  148. package/dist/components/trigger-aria.js.map +1 -1
  149. package/dist/components/ui.d.ts +16 -11
  150. package/dist/components/ui.js +284 -88
  151. package/dist/components/ui.js.map +1 -1
  152. package/dist/components/use-table-state.d.ts +1 -2
  153. package/dist/{data-table-3mi2R3so.d.ts → data-table-labels-B7OdnM0S.d.ts} +140 -3
  154. package/dist/data-table.d.ts +1 -2
  155. package/dist/data-table.js +2 -1
  156. package/dist/data-table.js.map +1 -1
  157. package/dist/feedback/feedback-attachment.d.ts +1 -1
  158. package/dist/feedback/feedback-attachment.js +348 -41
  159. package/dist/feedback/feedback-attachment.js.map +1 -1
  160. package/dist/feedback/feedback-dialog.d.ts +1 -1
  161. package/dist/feedback/feedback-dialog.js.map +1 -1
  162. package/dist/feedback/feedback-inbox.d.ts +3 -2
  163. package/dist/feedback/feedback-inbox.js.map +1 -1
  164. package/dist/feedback/feedback-thread.d.ts +68 -253
  165. package/dist/feedback/feedback-thread.js +46 -10
  166. package/dist/feedback/feedback-thread.js.map +1 -1
  167. package/dist/{kit-labels-D1J2_jyD.d.ts → feedback-BxeQVzwq.d.ts} +1206 -20
  168. package/dist/{feedback-attachment-WFiXJ8We.d.ts → feedback-attachment-fGAzZPf0.d.ts} +178 -11
  169. package/dist/feedback.d.ts +66 -2
  170. package/dist/hooks/use-file-drop.d.ts +19 -14
  171. package/dist/i18n/defaults.d.ts +19 -14
  172. package/dist/i18n/defaults.js +19 -2
  173. package/dist/i18n/defaults.js.map +1 -1
  174. package/dist/i18n/german.d.ts +19 -14
  175. package/dist/i18n/german.js +84 -5
  176. package/dist/i18n/german.js.map +1 -1
  177. package/dist/i18n/kit-labels.d.ts +15 -10
  178. package/dist/i18n/kit-labels.js +8 -2
  179. package/dist/i18n/kit-labels.js.map +1 -1
  180. package/dist/i18n/languages.d.ts +19 -14
  181. package/dist/i18n/locales/de-CH.d.ts +19 -14
  182. package/dist/i18n/locales/en.d.ts +19 -14
  183. package/dist/i18n/locales/en.js +16 -0
  184. package/dist/i18n/locales/en.js.map +1 -1
  185. package/dist/i18n/locales/es.d.ts +19 -14
  186. package/dist/i18n/locales/es.js +83 -5
  187. package/dist/i18n/locales/es.js.map +1 -1
  188. package/dist/i18n/locales/fr.d.ts +19 -14
  189. package/dist/i18n/locales/fr.js +82 -5
  190. package/dist/i18n/locales/fr.js.map +1 -1
  191. package/dist/i18n/locales/hu.d.ts +19 -14
  192. package/dist/i18n/locales/hu.js +85 -5
  193. package/dist/i18n/locales/hu.js.map +1 -1
  194. package/dist/i18n/locales/it.d.ts +19 -14
  195. package/dist/i18n/locales/it.js +84 -5
  196. package/dist/i18n/locales/it.js.map +1 -1
  197. package/dist/i18n/locales/zh.d.ts +19 -14
  198. package/dist/i18n/locales/zh.js +80 -5
  199. package/dist/i18n/locales/zh.js.map +1 -1
  200. package/dist/i18n/review.d.ts +19 -14
  201. package/dist/i18n/review.js +27 -1
  202. package/dist/i18n/review.js.map +1 -1
  203. package/dist/index.d.ts +21 -10
  204. package/dist/index.js +73 -2
  205. package/dist/index.js.map +1 -1
  206. package/dist/lib/column-mapping.d.ts +81 -0
  207. package/dist/lib/column-mapping.js +108 -0
  208. package/dist/lib/column-mapping.js.map +1 -0
  209. package/dist/lib/countries.d.ts +43 -0
  210. package/dist/lib/countries.js +39 -0
  211. package/dist/lib/countries.js.map +1 -0
  212. package/dist/lib/decimal-marks.d.ts +46 -0
  213. package/dist/lib/decimal-marks.js +40 -0
  214. package/dist/lib/decimal-marks.js.map +1 -0
  215. package/dist/lib/iban.d.ts +98 -0
  216. package/dist/lib/iban.js +154 -0
  217. package/dist/lib/iban.js.map +1 -0
  218. package/dist/lib/isin.d.ts +30 -0
  219. package/dist/lib/isin.js +36 -0
  220. package/dist/lib/isin.js.map +1 -0
  221. package/dist/lib/phone.d.ts +69 -0
  222. package/dist/lib/phone.js +121 -0
  223. package/dist/lib/phone.js.map +1 -0
  224. package/dist/lib/table-text.d.ts +109 -1
  225. package/dist/lib/table-text.js +122 -1
  226. package/dist/lib/table-text.js.map +1 -1
  227. package/dist/rhf/fields.d.ts +233 -18
  228. package/dist/rhf/fields.js +456 -3
  229. package/dist/rhf/fields.js.map +1 -1
  230. package/dist/rhf/form.d.ts +19 -14
  231. package/dist/rhf.d.ts +22 -15
  232. package/dist/rhf.js.map +1 -1
  233. package/dist/shell/app-shell.d.ts +18 -13
  234. package/dist/shell/top-bar-brand.d.ts +19 -14
  235. package/dist/shell/topbar-action-menu.d.ts +36 -3
  236. package/dist/shell/topbar-action-menu.js +74 -33
  237. package/dist/shell/topbar-action-menu.js.map +1 -1
  238. package/dist/shell.d.ts +18 -13
  239. package/dist/table-text.d.ts +1 -1
  240. package/dist/tour/tour.js +20 -24
  241. package/dist/tour/tour.js.map +1 -1
  242. package/dist/wizard/stepper-nav.d.ts +49 -16
  243. package/dist/wizard/stepper-nav.js +4 -0
  244. package/dist/wizard/stepper-nav.js.map +1 -1
  245. package/dist/wizard.d.ts +19 -14
  246. package/package.json +1 -1
  247. package/src/components/account-chips.tsx +17 -3
  248. package/src/components/account-settings.tsx +92 -26
  249. package/src/components/amount-input.tsx +68 -56
  250. package/src/components/autocomplete.tsx +198 -114
  251. package/src/components/checkbox-group.tsx +229 -0
  252. package/src/components/checkbox.tsx +72 -8
  253. package/src/components/chip.tsx +80 -10
  254. package/src/components/column-mapper.tsx +666 -0
  255. package/src/components/combobox-core.tsx +82 -9
  256. package/src/components/combobox.tsx +661 -340
  257. package/src/components/confirm-dialog.tsx +12 -8
  258. package/src/components/country-select.tsx +556 -0
  259. package/src/components/currency-select.tsx +109 -33
  260. package/src/components/danger-confirm.tsx +429 -82
  261. package/src/components/data-table-labels.ts +16 -1
  262. package/src/components/data-table.tsx +175 -6
  263. package/src/components/date-picker.tsx +595 -71
  264. package/src/components/entity-combobox.tsx +235 -124
  265. package/src/components/field-parts.tsx +403 -0
  266. package/src/components/field-strip.tsx +149 -0
  267. package/src/components/file-button.tsx +36 -3
  268. package/src/components/file-dropzone.tsx +106 -38
  269. package/src/components/form-actions.tsx +147 -6
  270. package/src/components/iban-input.tsx +231 -0
  271. package/src/components/icon-picker.tsx +47 -6
  272. package/src/components/inline-edit-field.tsx +533 -0
  273. package/src/components/language-select.tsx +78 -0
  274. package/src/components/line-items.tsx +35 -2
  275. package/src/components/list.tsx +55 -6
  276. package/src/components/money-field.tsx +13 -0
  277. package/src/components/month-picker.tsx +400 -63
  278. package/src/components/multi-entity-combobox.tsx +207 -120
  279. package/src/components/multi-select.tsx +80 -58
  280. package/src/components/number-field.tsx +28 -46
  281. package/src/components/number-input.tsx +210 -43
  282. package/src/components/one-time-code-input.tsx +288 -0
  283. package/src/components/phone-input.tsx +299 -0
  284. package/src/components/reauth-dialog.tsx +17 -18
  285. package/src/components/sign-chip.tsx +103 -0
  286. package/src/components/swatch-picker.tsx +143 -31
  287. package/src/components/switch.tsx +58 -7
  288. package/src/components/tile-radio.tsx +145 -29
  289. package/src/components/time-input.tsx +8 -1
  290. package/src/components/toggle-group.tsx +206 -73
  291. package/src/components/trigger-aria.ts +5 -0
  292. package/src/components/ui.tsx +479 -138
  293. package/src/data-table.ts +2 -1
  294. package/src/feedback/feedback-attachment.tsx +597 -46
  295. package/src/feedback/feedback-dialog.tsx +9 -3
  296. package/src/feedback/feedback-inbox.tsx +3 -2
  297. package/src/feedback/feedback-thread.tsx +113 -9
  298. package/src/i18n/defaults.ts +18 -1
  299. package/src/i18n/german.ts +89 -0
  300. package/src/i18n/kit-labels.tsx +82 -2
  301. package/src/i18n/locales/en.ts +36 -4
  302. package/src/i18n/locales/es.ts +87 -0
  303. package/src/i18n/locales/fr.ts +87 -0
  304. package/src/i18n/locales/hu.ts +83 -0
  305. package/src/i18n/locales/it.ts +88 -0
  306. package/src/i18n/locales/zh.ts +76 -0
  307. package/src/i18n/review.ts +26 -0
  308. package/src/index.ts +71 -3
  309. package/src/lib/column-mapping.ts +234 -0
  310. package/src/lib/countries.ts +91 -0
  311. package/src/lib/decimal-marks.ts +99 -0
  312. package/src/lib/iban.ts +171 -0
  313. package/src/lib/isin.ts +62 -0
  314. package/src/lib/phone.ts +211 -0
  315. package/src/lib/table-text.ts +271 -0
  316. package/src/rhf/fields.tsx +860 -9
  317. package/src/rhf.ts +3 -1
  318. package/src/shell/topbar-action-menu.tsx +134 -38
  319. package/src/tour/tour.tsx +66 -28
  320. package/src/wizard/stepper-nav.tsx +35 -1
@@ -1,166 +1,69 @@
1
- import * as react from 'react';
2
- import { Ref, ComponentPropsWithoutRef, ReactNode } from 'react';
3
-
4
- /**
5
- * How typed text is compared with the text it has to repeat — shared by
6
- * `DangerConfirm`'s `phraseMatch` and `useConfirm`'s `typedMatch`.
7
- *
8
- * - `"trim"` ignores spaces around the typed text — a phone keyboard's autocomplete
9
- * likes to add one. Case counts: "delete" is not "DELETE".
10
- * - `"exact"` compares character for character, spaces included.
11
- * - `"caseless"` trims AND ignores case: for an e-mail address, whose domain is
12
- * case-insensitive and whose local part every real mail server treats so. Both apps'
13
- * "type the account's address" rules (keksdose's `TYPE_EMAIL`, Kurvenschmiede's
14
- * `TypedConfirm`) compared `trim().toLowerCase()`, and a capital the user's keyboard
15
- * put at the start must not make the right row look like the wrong one.
16
- */
17
- type TypedMatch = "trim" | "exact" | "caseless";
18
- /** Whether `typed` repeats `target` under `mode` — see {@link TypedMatch}. Exported for
19
- * a caller that draws its own field (a dialog that also picks a recipient) and wants
20
- * the same rule as the kit's. */
21
- declare function typedMatches(typed: string, target: string, mode?: TypedMatch): boolean;
22
- /**
23
- * Busy-while-a-promise-runs, for an action that MAY return one: `run(result, onResolved)`
24
- * marks the caller pending until `result` settles, calls `onResolved` if it fulfilled,
25
- * and only clears the flag if it rejected — the caller shows why and the user retries.
26
- * Nothing runs after unmount. Shared by `DangerConfirm` and `ReauthDialog`, whose
27
- * contract is the same: resolve = done, reject = stay put.
28
- *
29
- * @internal
30
- */
31
- declare function usePromisePending(): {
32
- pending: boolean;
33
- run: (result: unknown, onResolved: () => void) => boolean;
34
- };
35
- /**
36
- * The "prove it is you" field: a password input the browser's password manager fills
37
- * with the CURRENT password (`autocomplete="current-password"`), never offers to
38
- * generate a new one for. `readOnly` rather than `disabled` while busy: disabling the
39
- * field that has focus (Enter was pressed in it) drops focus to <body>.
40
- *
41
- * @internal DangerConfirm's field. ReauthDialog spells it out with the field's own
42
- * `error`, which keeps the `<input>` mounted while its message comes and goes.
43
- */
44
- declare function CurrentPasswordInput({ inputRef, label, value, onValueChange, busy, invalid, describedBy, }: {
45
- inputRef?: Ref<HTMLInputElement>;
46
- label: string;
47
- value: string;
48
- onValueChange: (value: string) => void;
49
- busy: boolean;
50
- invalid?: boolean;
51
- describedBy?: string;
52
- }): react.JSX.Element;
53
- /**
54
- * Every string the tile renders — the `dangerConfirm` namespace of
55
- * `<UiKitProvider labels>`, overridable per instance through `labels`. The arm and
56
- * confirm buttons are usually worded per action ("Delete budget"), which is what the
57
- * `armLabel` / `confirmLabel` props are for; these are the fallbacks.
58
- */
59
- interface DangerConfirmLabels {
60
- /** The button that arms the tile. */
61
- arm: string;
62
- /** The button that runs the action once the guards are satisfied. */
63
- confirm: string;
64
- cancel: string;
65
- /** The warning above the fields, when no `prompt` is given. */
66
- prompt: string;
67
- /** Label of the password field (`requirePassword`). */
68
- password: string;
69
- /** Label of the type-to-confirm field. A FUNCTION of the phrase by default, like
70
- * every message that carries a value: where the phrase sits in the sentence moves
71
- * with the language. A plain STRING is taken as the finished label — for an app
72
- * whose catalogue already words it ("Type DELETE to confirm") and would otherwise
73
- * wrap it as `() => label`. */
74
- phrase: string | ((phrase: string) => string);
75
- /** Placeholder of the type-to-confirm field — a string, or a function of the
76
- * phrase (`(p) => p` echoes it). Optional and unset by default: the field keeps its
77
- * floating label, as before. Given, the label moves ABOVE the field (a floating
78
- * label occupies the empty field, which is exactly where a placeholder shows) and
79
- * the placeholder fills the field. An empty string means none. */
80
- phrasePlaceholder?: string | ((phrase: string) => string);
81
- }
82
- /** `satisfies` rather than a type annotation, so `DEFAULT_DANGER_CONFIRM_LABELS.phrase`
83
- * stays callable for a caller that composes its own label from it. */
84
- declare const DEFAULT_DANGER_CONFIRM_LABELS: {
85
- arm: string;
86
- confirm: string;
87
- cancel: string;
88
- prompt: string;
89
- password: string;
90
- phrase: (phrase: string) => string;
91
- };
92
- interface DangerConfirmProps extends Omit<ComponentPropsWithoutRef<"div">, "onChange"> {
93
- /**
94
- * Runs the action, with the entered password when `requirePassword` is on.
95
- *
96
- * Return a promise and the tile manages itself: busy until it settles, disarmed
97
- * (fields wiped) when it resolves, still armed when it rejects — so the user can
98
- * correct a wrong password and retry. The rejection is not swallowed for you to
99
- * miss: handle it (and show why) in the caller, as with any mutation.
100
- */
101
- onConfirm: (password?: string) => void | Promise<unknown>;
102
- /** Show a password field; confirm stays disabled until it is filled. */
103
- requirePassword?: boolean;
104
- /** Show a "type <phrase> to confirm" field; confirm stays disabled until the field
105
- * matches (case-sensitive; surrounding spaces ignored unless `phraseMatch="exact"`). */
106
- phrase?: string;
107
- /**
108
- * How the typed text is compared with `phrase`. `"trim"` (default) ignores spaces
109
- * around it — a phone keyboard's autocomplete likes to add one. `"exact"` compares
110
- * character for character, spaces included, for an app whose contract is "type
111
- * exactly this". `"caseless"` (0.18) also ignores case — for a phrase that is an
112
- * e-mail address (keksdose's "type the user's address" admin rule). See
113
- * {@link TypedMatch}.
114
- */
115
- phraseMatch?: TypedMatch;
116
- /** The warning above the fields. Defaults to `labels.prompt`. */
117
- prompt?: ReactNode;
118
- /** `"danger"` (default) for what cannot be undone; `"warning"` for what can, at a
119
- * cost (loading demo data over your own). Colours the prompt and the confirm. */
120
- tone?: "danger" | "warning";
121
- /** Visible text of the arm button; defaults to `labels.arm`. */
122
- armLabel?: ReactNode;
123
- /** Visible text of the confirm button; defaults to `labels.confirm`. */
124
- confirmLabel?: ReactNode;
125
- /** The action is running: confirm shows a spinner and nothing can be pressed. For a
126
- * caller that tracks the mutation itself (a `useMutation`'s `isPending`); a
127
- * promise returned from `onConfirm` does the same on its own. */
128
- busy?: boolean;
129
- /** The arm button is disabled. */
130
- disabled?: boolean;
131
- /**
132
- * Why the action is not available — a read-only demo, a write lock, a missing
133
- * permission. Disables the arm button like `disabled`, and SAYS so: the sentence is
134
- * shown under the button and attached to it with `aria-describedby`, and the button
135
- * stays focusable (`aria-disabled`) so a keyboard user can land on it and hear why.
136
- *
137
- * On the ARM button rather than the confirm: arming asks for a password, and asking
138
- * for a password for a write that can never land is the worse of the two.
139
- */
140
- lockedReason?: ReactNode;
141
- /** Controlled armed state. The parent can then collapse the tile from a mutation's
142
- * own `onSuccess` without returning a promise. */
143
- armed?: boolean;
144
- /** Called with the next armed state — on arm, cancel, and a resolved `onConfirm`. */
145
- onArmedChange?: (armed: boolean) => void;
146
- /** User-facing strings; see {@link DangerConfirmLabels}. */
147
- labels?: Partial<DangerConfirmLabels>;
148
- }
149
- /**
150
- * An "arm → confirm" tile for destructive actions: one button, which expands into a
151
- * warning, an optional password field, an optional type-to-confirm field and a
152
- * confirm that stays disabled until every guard is satisfied.
153
- *
154
- * Keksdose hand-rolled it three times (load demo data, wipe everything, reset a
155
- * budget) and then as `shared/components/danger-confirm.tsx`; the only app-specific
156
- * part was its write-lock hook, which is `lockedReason` here.
157
- *
158
- * The fields are a `<form>`, so Enter confirms once the guards allow it. They are
159
- * wiped every time the tile disarms — a password must not sit in a collapsed tile.
160
- * Arming moves focus to the first field (or Cancel, when there is none — never to the
161
- * destructive button itself), and disarming moves it back to the arm button, so the
162
- * keyboard user is never left on an element that just vanished.
163
- */
164
- declare function DangerConfirm({ onConfirm, requirePassword, phrase, phraseMatch, prompt, tone, armLabel, confirmLabel, busy: busyProp, disabled, lockedReason, armed: armedProp, onArmedChange, labels: labelsProp, className, ...rest }: DangerConfirmProps): react.JSX.Element;
165
-
166
- export { CurrentPasswordInput, DEFAULT_DANGER_CONFIRM_LABELS, DangerConfirm, type DangerConfirmLabels, type DangerConfirmProps, type TypedMatch, typedMatches, usePromisePending };
1
+ import 'react';
2
+ export { S as CurrentPasswordInput, T as CurrentPasswordInputLabels, U as CurrentPasswordInputProps, a1 as DEFAULT_DANGER_CONFIRM_LABELS, ah as DangerConfirm, ai as DangerConfirmLabels, aj as DangerConfirmProps, ak as DangerConfirmValues, al as DangerConsequence, bT as TypedConfirmField, bU as TypedConfirmFieldLabels, bV as TypedConfirmFieldProps, bW as TypedMatch, c6 as typedMatches, ci as usePromisePending } from '../feedback-BxeQVzwq.js';
3
+ import '../feedback-attachment-fGAzZPf0.js';
4
+ import '../feedback/feedback-inbox.js';
5
+ import 'lucide-react';
6
+ import './tooltip.js';
7
+ import '../hooks/use-anchored-rect.js';
8
+ import '../lib/clipping.js';
9
+ import '../data-table-labels-B7OdnM0S.js';
10
+ import './data-table-sort.js';
11
+ import './swipeable-row.js';
12
+ import './mini-calendar.js';
13
+ import './calendar-heatmap.js';
14
+ import './popover.js';
15
+ import './chip.js';
16
+ import './field-sync.js';
17
+ import '../wizard/types.js';
18
+ import '../tour/tour.js';
19
+ import '../search/command-palette.js';
20
+ import '../search/global-search.js';
21
+ import '../search/search-index.js';
22
+ import './month-picker.js';
23
+ import './page-contents.js';
24
+ import './series-chart-labels.js';
25
+ import './pie-chart-labels.js';
26
+ import './sparkline.js';
27
+ import './stat-tile.js';
28
+ import './signature-pad.js';
29
+ import './password-strength.js';
30
+ import './swatch-picker.js';
31
+ import './tile-radio.js';
32
+ import './icon-picker.js';
33
+ import './dialog-frame.js';
34
+ import './modal.js';
35
+ import '../hooks/use-search-param-state.js';
36
+ import './measured-grid.js';
37
+ import './account-settings-labels.js';
38
+ import './floating-panel.js';
39
+ import './bulk-action-bar.js';
40
+ import './list.js';
41
+ import './signed-amount.js';
42
+ import './breadcrumbs.js';
43
+ import './toast.js';
44
+ import './description-list.js';
45
+ import './line-items.js';
46
+ import './progress-bar.js';
47
+ import './error-boundary.js';
48
+ import './authed-image.js';
49
+ import '../hooks/use-authed-src.js';
50
+ import './image-grid.js';
51
+ import './lightbox.js';
52
+ import './write-lock.js';
53
+ import './legal.js';
54
+ import './account-chips.js';
55
+ import '../lib/format.js';
56
+ import './reauth-dialog.js';
57
+ import './server-wake.js';
58
+ import '../lib/server-wake.js';
59
+ import './translation-review-labels.js';
60
+ import '../lib/translation-review.js';
61
+ import './country-select.js';
62
+ import './inline-edit-field.js';
63
+ import '../lib/iban.js';
64
+ import '../lib/phone.js';
65
+ import './sign-chip.js';
66
+ import './column-mapper.js';
67
+ import '../lib/column-mapping.js';
68
+ import '../lib/table-text.js';
69
+ import './field-parts.js';
@@ -1,10 +1,12 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import { useCallback, useEffect, useId, useRef, useState } from "react";
3
+ import { forwardRef, useCallback, useEffect, useId, useRef, useState } from "react";
4
4
  import { cn } from "../lib/cn.js";
5
5
  import { useKitLabels } from "../i18n/kit-labels.js";
6
6
  import { Button, Input, Label, Spinner } from "./ui.js";
7
+ import { Checkbox } from "./checkbox.js";
7
8
  import { Tooltip } from "./tooltip.js";
9
+ import { useCommitReason } from "./write-lock.js";
8
10
  function typedMatches(typed, target, mode = "trim") {
9
11
  if (mode === "exact") return typed === target;
10
12
  if (mode === "trim") return typed.trim() === target;
@@ -36,41 +38,106 @@ function usePromisePending() {
36
38
  }, []);
37
39
  return { pending, run };
38
40
  }
39
- function CurrentPasswordInput({
40
- inputRef,
41
- label,
42
- value,
41
+ function hasContent(node) {
42
+ return node !== void 0 && node !== null && node !== false && node !== "";
43
+ }
44
+ const CurrentPasswordInput = forwardRef(
45
+ function CurrentPasswordInput2({ label, onValueChange, onChange, busy, readOnly, labels: labelsProp, ...rest }, ref) {
46
+ const labels = useKitLabels("dangerConfirm", DEFAULT_DANGER_CONFIRM_LABELS, labelsProp);
47
+ const namedOtherwise = rest["aria-label"] !== void 0 || rest["aria-labelledby"] !== void 0;
48
+ return /* @__PURE__ */ jsx(
49
+ Input,
50
+ {
51
+ ...rest,
52
+ ref,
53
+ type: "password",
54
+ autoComplete: "current-password",
55
+ label: label === void 0 ? namedOtherwise ? void 0 : labels.password : hasContent(label) ? label : void 0,
56
+ readOnly: Boolean(busy) || readOnly,
57
+ onChange: (e) => {
58
+ onChange?.(e);
59
+ onValueChange?.(e.target.value);
60
+ }
61
+ }
62
+ );
63
+ }
64
+ );
65
+ CurrentPasswordInput.displayName = "CurrentPasswordInput";
66
+ const TypedConfirmField = forwardRef(function TypedConfirmField2({
67
+ target,
68
+ match = "trim",
69
+ value: valueProp,
70
+ defaultValue = "",
43
71
  onValueChange,
72
+ onMatchedChange,
73
+ onChange,
74
+ label: labelProp,
75
+ placeholder: placeholderProp,
44
76
  busy,
45
- invalid,
46
- describedBy
47
- }) {
48
- return /* @__PURE__ */ jsx(
49
- Input,
50
- {
51
- ref: inputRef,
52
- type: "password",
53
- autoComplete: "current-password",
54
- label,
55
- value,
56
- readOnly: busy,
57
- invalid,
58
- "aria-describedby": describedBy,
59
- onChange: (e) => onValueChange(e.target.value)
77
+ readOnly,
78
+ labels: labelsProp,
79
+ id,
80
+ className,
81
+ ...rest
82
+ }, ref) {
83
+ const labels = useKitLabels("dangerConfirm", DEFAULT_DANGER_CONFIRM_LABELS, labelsProp);
84
+ const [own, setOwn] = useState(defaultValue);
85
+ const value = valueProp ?? own;
86
+ const matched = typedMatches(value, target, match);
87
+ const generated = useId();
88
+ const fieldId = id ?? generated;
89
+ const label = labelProp !== void 0 ? labelProp : typeof labels.phrase === "function" ? labels.phrase(target) : labels.phrase;
90
+ const fromLabels = labels.phrasePlaceholder === void 0 ? void 0 : typeof labels.phrasePlaceholder === "function" ? labels.phrasePlaceholder(target) : labels.phrasePlaceholder;
91
+ const placeholder = placeholderProp ?? fromLabels;
92
+ const fieldProps = {
93
+ ...rest,
94
+ ref,
95
+ id: fieldId,
96
+ value,
97
+ autoComplete: "off",
98
+ autoCapitalize: "off",
99
+ autoCorrect: "off",
100
+ spellCheck: false,
101
+ readOnly: Boolean(busy) || readOnly,
102
+ "data-matched": matched || void 0,
103
+ onChange: (e) => {
104
+ onChange?.(e);
105
+ const next = e.target.value;
106
+ if (valueProp === void 0) setOwn(next);
107
+ onValueChange?.(next);
108
+ const nextMatched = typedMatches(next, target, match);
109
+ if (nextMatched !== matched) onMatchedChange?.(nextMatched);
60
110
  }
61
- );
62
- }
111
+ };
112
+ if (placeholder) {
113
+ return (
114
+ // A static label above, so the placeholder has the empty field to itself.
115
+ /* @__PURE__ */ jsxs("div", { className: cn("space-y-1.5", className), children: [
116
+ /* @__PURE__ */ jsx(Label, { htmlFor: fieldId, children: label }),
117
+ /* @__PURE__ */ jsx(Input, { ...fieldProps, placeholder })
118
+ ] })
119
+ );
120
+ }
121
+ return /* @__PURE__ */ jsx(Input, { ...fieldProps, label, className });
122
+ });
123
+ TypedConfirmField.displayName = "TypedConfirmField";
63
124
  const DEFAULT_DANGER_CONFIRM_LABELS = {
64
125
  arm: "Delete\u2026",
65
126
  confirm: "Delete",
66
127
  cancel: "Cancel",
67
128
  prompt: "This cannot be undone.",
68
129
  password: "Password",
69
- phrase: (phrase) => `Type \u201C${phrase}\u201D to confirm`
130
+ phrase: (phrase) => `Type \u201C${phrase}\u201D to confirm`,
131
+ acknowledge: "I have read what this does and want to continue.",
132
+ needsPhrase: (phrase) => `Type \u201C${phrase}\u201D to confirm`,
133
+ needsAcknowledge: "Tick the box to confirm",
134
+ needsPassword: "Enter your password to confirm"
70
135
  };
71
136
  function DangerConfirm({
72
137
  onConfirm,
73
138
  requirePassword,
139
+ requireAcknowledge,
140
+ consequences,
74
141
  phrase,
75
142
  phraseMatch = "trim",
76
143
  prompt,
@@ -79,7 +146,8 @@ function DangerConfirm({
79
146
  confirmLabel,
80
147
  busy: busyProp,
81
148
  disabled,
82
- lockedReason,
149
+ lockedReason: ownLockedReason,
150
+ commit,
83
151
  armed: armedProp,
84
152
  onArmedChange,
85
153
  labels: labelsProp,
@@ -87,15 +155,17 @@ function DangerConfirm({
87
155
  ...rest
88
156
  }) {
89
157
  const labels = useKitLabels("dangerConfirm", DEFAULT_DANGER_CONFIRM_LABELS, labelsProp);
158
+ const lockedReason = useCommitReason(commit, ownLockedReason);
90
159
  const [armedState, setArmedState] = useState(false);
91
160
  const armed = armedProp ?? armedState;
92
161
  const [password, setPassword] = useState("");
93
162
  const [typed, setTyped] = useState("");
163
+ const [acknowledged, setAcknowledged] = useState(false);
94
164
  const { pending, run } = usePromisePending();
95
165
  const busy = Boolean(busyProp) || pending;
96
166
  const promptId = useId();
167
+ const consequencesId = useId();
97
168
  const reasonId = useId();
98
- const phraseFieldId = useId();
99
169
  const armId = useId();
100
170
  const cancelId = useId();
101
171
  const firstFieldRef = useRef(null);
@@ -106,6 +176,7 @@ function DangerConfirm({
106
176
  if (!armed) {
107
177
  setPassword("");
108
178
  setTyped("");
179
+ setAcknowledged(false);
109
180
  }
110
181
  }
111
182
  const prevArmed = useRef(armed);
@@ -127,26 +198,29 @@ function DangerConfirm({
127
198
  if (armedProp === void 0) setArmedState(next);
128
199
  onArmedChange?.(next);
129
200
  };
130
- const locked = lockedReason !== void 0 && lockedReason !== null && lockedReason !== false && lockedReason !== "";
201
+ const locked = hasContent(lockedReason);
202
+ const acknowledgeLabel = requireAcknowledge === true ? labels.acknowledge : hasContent(requireAcknowledge) ? requireAcknowledge : null;
203
+ const asksAcknowledge = acknowledgeLabel !== null;
131
204
  const passwordOk = !requirePassword || password !== "";
132
205
  const phraseOk = phrase === void 0 || typedMatches(typed, phrase, phraseMatch);
133
- const canConfirm = passwordOk && phraseOk && !busy;
206
+ const acknowledgeOk = !asksAcknowledge || acknowledged;
207
+ const canConfirm = passwordOk && phraseOk && acknowledgeOk && !busy;
208
+ const guardReason = !acknowledgeOk ? labels.needsAcknowledge : !phraseOk ? typeof labels.needsPhrase === "function" ? labels.needsPhrase(phrase ?? "") : labels.needsPhrase : !passwordOk ? labels.needsPassword : void 0;
209
+ const confirmReason = locked ? lockedReason : busy ? void 0 : guardReason;
134
210
  const submit = (e) => {
135
211
  e.preventDefault();
136
- if (!canConfirm) return;
137
- run(onConfirm(requirePassword ? password : void 0), () => setArmed(false));
138
- };
139
- const phrasePlaceholder = phrase === void 0 || labels.phrasePlaceholder === void 0 ? void 0 : typeof labels.phrasePlaceholder === "function" ? labels.phrasePlaceholder(phrase) : labels.phrasePlaceholder;
140
- const phraseLabel = phrase === void 0 ? "" : typeof labels.phrase === "function" ? labels.phrase(phrase) : labels.phrase;
141
- const phraseFieldProps = {
142
- ref: firstFieldRef,
143
- value: typed,
144
- autoComplete: "off",
145
- autoCapitalize: "off",
146
- spellCheck: false,
147
- readOnly: busy,
148
- onChange: (e) => setTyped(e.target.value)
212
+ if (!canConfirm || locked) return;
213
+ const values = {
214
+ ...phrase !== void 0 && { typed: phraseMatch === "exact" ? typed : typed.trim() },
215
+ ...requirePassword && { password },
216
+ ...asksAcknowledge && { acknowledged: true }
217
+ };
218
+ run(onConfirm(values.password, values), () => setArmed(false));
149
219
  };
220
+ const firstField = asksAcknowledge ? "acknowledge" : phrase !== void 0 ? "phrase" : "password";
221
+ const lines = (consequences ?? []).map(
222
+ (item, index) => typeof item === "string" ? { key: item, text: item, severe: false } : { key: item.key ?? String(index), text: item.text, severe: Boolean(item.severe) }
223
+ );
150
224
  const toneText = tone === "warning" ? "text-[var(--warning)]" : "text-[var(--danger)]";
151
225
  if (!armed) {
152
226
  const arm = /* @__PURE__ */ jsx(
@@ -184,23 +258,40 @@ function DangerConfirm({
184
258
  "form",
185
259
  {
186
260
  className: "space-y-2",
187
- "aria-describedby": promptId,
261
+ "aria-describedby": lines.length > 0 ? `${promptId} ${consequencesId}` : promptId,
188
262
  "aria-busy": busy || void 0,
189
263
  onSubmit: submit,
190
264
  noValidate: true,
191
265
  children: [
192
266
  /* @__PURE__ */ jsx("p", { id: promptId, className: cn("text-xs font-medium", toneText), children: prompt ?? labels.prompt }),
193
- phrase !== void 0 && (phrasePlaceholder ? (
194
- // A static label above, so the placeholder has the empty field to itself.
195
- /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
196
- /* @__PURE__ */ jsx(Label, { htmlFor: phraseFieldId, children: phraseLabel }),
197
- /* @__PURE__ */ jsx(Input, { id: phraseFieldId, placeholder: phrasePlaceholder, ...phraseFieldProps })
198
- ] })
199
- ) : /* @__PURE__ */ jsx(Input, { label: phraseLabel, ...phraseFieldProps })),
267
+ lines.length > 0 && /* @__PURE__ */ jsx("ul", { id: consequencesId, className: "list-disc space-y-1 ps-5 text-xs text-[var(--text-secondary)]", children: lines.map((line) => /* @__PURE__ */ jsx("li", { className: line.severe ? "text-[var(--danger)]" : void 0, children: line.text }, line.key)) }),
268
+ asksAcknowledge && /* @__PURE__ */ jsx(
269
+ Checkbox,
270
+ {
271
+ ref: firstField === "acknowledge" ? firstFieldRef : void 0,
272
+ label: acknowledgeLabel,
273
+ checked: acknowledged,
274
+ onCheckedChange: (next) => {
275
+ if (!busy) setAcknowledged(next);
276
+ }
277
+ }
278
+ ),
279
+ phrase !== void 0 && /* @__PURE__ */ jsx(
280
+ TypedConfirmField,
281
+ {
282
+ ref: firstField === "phrase" ? firstFieldRef : void 0,
283
+ target: phrase,
284
+ match: phraseMatch,
285
+ value: typed,
286
+ onValueChange: setTyped,
287
+ busy,
288
+ labels: { phrase: labels.phrase, phrasePlaceholder: labels.phrasePlaceholder }
289
+ }
290
+ ),
200
291
  requirePassword && /* @__PURE__ */ jsx(
201
292
  CurrentPasswordInput,
202
293
  {
203
- inputRef: phrase === void 0 ? firstFieldRef : void 0,
294
+ ref: firstField === "password" ? firstFieldRef : void 0,
204
295
  label: labels.password,
205
296
  value: password,
206
297
  busy,
@@ -215,6 +306,7 @@ function DangerConfirm({
215
306
  type: "submit",
216
307
  variant: tone === "warning" ? "primary" : "danger",
217
308
  disabled: !canConfirm,
309
+ disabledReason: confirmReason,
218
310
  "aria-busy": busy || void 0,
219
311
  children: [
220
312
  busy && /* @__PURE__ */ jsx(Spinner, { label: null, className: "h-4 w-4" }),
@@ -222,7 +314,8 @@ function DangerConfirm({
222
314
  ]
223
315
  }
224
316
  )
225
- ] })
317
+ ] }),
318
+ locked && /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--text-muted)]", children: lockedReason })
226
319
  ]
227
320
  }
228
321
  ) });
@@ -231,6 +324,7 @@ export {
231
324
  CurrentPasswordInput,
232
325
  DEFAULT_DANGER_CONFIRM_LABELS,
233
326
  DangerConfirm,
327
+ TypedConfirmField,
234
328
  typedMatches,
235
329
  usePromisePending
236
330
  };