@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 +1 @@
1
- {"version":3,"sources":["../../src/rhf/fields.tsx"],"sourcesContent":["/**\n * Bound fields: one line per field of a react-hook-form form. `@eifi1/ui-kit/rhf`.\n *\n * ```tsx\n * <Form {...form}>\n * <RhfTextField name=\"name\" label=\"Name\" hint=\"As on the lease\" required\n * rules={{ required: \"Enter a name\" }} />\n * <RhfMoneyField name=\"rent\" label=\"Net rent\" currency=\"CHF\" />\n * <RhfDateField name=\"start\" label=\"Start\" />\n * <RhfSelect name=\"type\" label=\"Type\" options={TYPES} />\n * <RhfCombobox name=\"tenantId\" label=\"Tenant\" options={tenants} clearable />\n * <RhfCheckbox name=\"isDefault\" label=\"Default account\" />\n * </Form>\n * ```\n *\n * Each folds the `FormField → FormItem → FormLabel → FormControl → field →\n * FormDescription → FormMessage` scaffold (see ./form) into one element, the way\n * kastlan's shared/components/form/fields.tsx does for its forms — with what that file\n * left out:\n *\n * - **The red border.** Every field gets `invalid` from the field state, so an errored\n * field PAINTS as well as announces. kastlan's number, money, date and entity fields\n * passed only `aria-invalid` through `FormControl`, or nothing, and `Input`, `Select`\n * and `Textarea` paint only from the prop (see the note in ./form).\n * - **Focus on error.** `field.ref` reaches the focusable element — the element itself\n * where the kit field forwards a ref, a focus handle on it where it does not (the\n * number field, the pickers) — so `handleSubmit` and `trigger(…, { shouldFocus })`\n * land the caret on the first field in error.\n * - **`control` is optional**: under `<Form {...form}>` the fields find the form\n * through react-hook-form's context. Pass it for the field's value types\n * (`control={form.control}` checks `name` against the form's values).\n *\n * The common props: `name`, `control`, `label` (a {@link FormLabel} above the field;\n * omitted, none — then give the field an `aria-label`), `hint` (standing advice under\n * the field, attached to it with `aria-describedby`), `required` (the label's mark,\n * and `aria-required` where the control takes it — validation is `rules`' or the\n * resolver's), `rules`, `disabled` (the control only — the value is still submitted;\n * `excludeWhenDisabled` for react-hook-form's drop-the-value semantics), and\n * `className` for the item's box.\n *\n * {@link RhfField} is the shell they are all built on, for a control the kit does not\n * ship (an address autocomplete): it takes a `render` and wires the rest.\n */\nimport { useLayoutEffect, useRef, useState, type ReactElement, type ReactNode } from \"react\";\nimport type {\n ControllerFieldState,\n ControllerProps,\n ControllerRenderProps,\n FieldPath,\n FieldValues,\n} from \"react-hook-form\";\nimport { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField } from \"./form\";\nimport { Input, Select, Textarea, type InputProps, type SelectProps, type TextareaProps } from \"../components/ui\";\nimport { NumberField, type NumberFieldProps } from \"../components/number-field\";\nimport { AmountInput } from \"../components/amount-input\";\nimport { DatePicker, type DatePickerProps } from \"../components/date-picker\";\nimport { Checkbox, type CheckboxProps } from \"../components/checkbox\";\nimport { EntityCombobox, type EntityComboboxProps } from \"../components/entity-combobox\";\nimport { Combobox, type ComboboxProps } from \"../components/combobox\";\nimport type { ComboClearValue } from \"../components/combobox-core\";\nimport { cn } from \"../lib/cn\";\n\n// ── the shell ────────────────────────────────────────────────────────────────\n\n/** What every bound field takes. */\nexport interface RhfFieldBaseProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> {\n name: TName;\n /** `form.control`. Optional under `<Form {...form}>`; pass it to type-check `name`. */\n control?: ControllerProps<TFieldValues, TName, TTransformed>[\"control\"];\n /** react-hook-form's `rules` (`required`, `min`, `validate` …). */\n rules?: ControllerProps<TFieldValues, TName, TTransformed>[\"rules\"];\n /** A {@link FormLabel} above the field. Omitted: no label — name the control with\n * an `aria-label` instead. */\n label?: ReactNode;\n /** Standing advice under the field (\"As printed on the card\"), attached to the\n * control with `aria-describedby`. */\n hint?: ReactNode;\n /** Draws the label's required mark and sets `aria-required` where the control\n * takes it. Whether the field IS required is `rules`' or the resolver's to say. */\n required?: boolean;\n /** Disables the control and KEEPS the value: a field locked to a preset (a lease's\n * preselected unit, a fixed period) still submits it, and `rules` still run.\n * react-hook-form's own Controller `disabled` drops the value from `handleSubmit`'s\n * data instead, which a locked preset must never do (kastlan, 0.12). To get that,\n * add `excludeWhenDisabled`. A form-wide `useForm({ disabled })` still disables\n * every field the RHF way. */\n disabled?: boolean;\n /** With `disabled`: disable through react-hook-form, so the value is left out of\n * the submitted data and validation skips it, like a disabled native input in a\n * plain form post. Default `false`. */\n excludeWhenDisabled?: boolean;\n /** Classes for the item's box (a `grid gap-1`). */\n className?: string;\n}\n\n/** What {@link RhfField}'s `render` receives. */\nexport interface RhfFieldRenderContext<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> {\n field: ControllerRenderProps<TFieldValues, TName>;\n fieldState: ControllerFieldState;\n /** The field has an error: pass it to the control's `invalid` so it paints. */\n invalid: boolean;\n /** The error's message, if any. */\n error: string | undefined;\n /** The control's id, which the label points at. `FormControl` sets it on the\n * rendered element already; this is for a control that routes it elsewhere. */\n id: string;\n /** The label's id, for a control that is named with `aria-labelledby`. */\n labelId: string;\n /** The ids of the rendered hint and message, if any. */\n describedBy: string | undefined;\n}\n\nexport interface RhfFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> extends RhfFieldBaseProps<TFieldValues, TName, TTransformed> {\n /** The control. Wrapped in {@link FormControl} (its `id`, `aria-describedby` and\n * `aria-invalid`) unless `asControl` is false. */\n render: (ctx: RhfFieldRenderContext<TFieldValues, TName>) => ReactElement;\n /** `false`: render the control as is, for one that wires its own ids from the\n * context. Default `true`. */\n asControl?: boolean;\n /** `false`: no {@link FormMessage}, for a control that renders its own error (its\n * `error` prop). Default `true`. */\n message?: boolean;\n /** `false`: no {@link FormLabel}, for a control that carries its label itself (a\n * checkbox). Default `true`. */\n showLabel?: boolean;\n}\n\nfunction hasContent(node: ReactNode): boolean {\n return node !== undefined && node !== null && node !== false && node !== \"\";\n}\n\n/** The label, with an id the control can be named by. Inside the item, so it can read\n * the item's id. */\nfunction RhfLabel({ required, children }: { required?: boolean; children: ReactNode }) {\n const { id } = useFormField();\n return (\n <FormLabel id={`${id}-label`} required={required}>\n {children}\n </FormLabel>\n );\n}\n\nfunction ControlSlot<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>({\n field,\n fieldState,\n render,\n asControl,\n}: {\n field: ControllerRenderProps<TFieldValues, TName>;\n fieldState: ControllerFieldState;\n render: RhfFieldProps<TFieldValues, TName>[\"render\"];\n asControl: boolean;\n}) {\n const { id, formItemId, describedBy } = useFormField();\n const element = render({\n field,\n fieldState,\n invalid: fieldState.invalid,\n error: fieldState.error?.message,\n id: formItemId,\n labelId: `${id}-label`,\n describedBy,\n });\n return asControl ? <FormControl>{element}</FormControl> : element;\n}\n\n/**\n * The shell every bound field is built on: label, control, hint and message around\n * a `render` of your own.\n *\n * ```tsx\n * <RhfField name=\"address\" label=\"Address\" render={({ field, invalid }) => (\n * <AddressAutocomplete value={field.value ?? \"\"} onChange={field.onChange} invalid={invalid} />\n * )} />\n * ```\n */\nexport function RhfField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n render,\n asControl = true,\n message = true,\n showLabel = true,\n}: RhfFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <FormField\n control={control}\n name={name}\n rules={rules}\n disabled={excludeWhenDisabled ? disabled : undefined}\n render={({ field, fieldState }) => (\n <FormItem className={className}>\n {showLabel && hasContent(label) && <RhfLabel required={required}>{label}</RhfLabel>}\n <ControlSlot\n field={disabled && !field.disabled ? { ...field, disabled: true } : field}\n fieldState={fieldState}\n render={render}\n asControl={asControl}\n />\n {hasContent(hint) && <FormDescription>{hint}</FormDescription>}\n {message && <FormMessage />}\n </FormItem>\n )}\n />\n );\n}\n\n/**\n * Hands react-hook-form a focus handle for a control that forwards no ref: its\n * `shouldFocusError` calls `focus()` on whatever `field.ref` was given. `find` runs at\n * focus time, so it sees the element as it is then.\n */\nfunction useFocusHandle(ref: ControllerRenderProps[\"ref\"], find: () => HTMLElement | null | undefined) {\n const findRef = useRef(find);\n useLayoutEffect(() => {\n findRef.current = find;\n });\n useLayoutEffect(() => {\n ref({ focus: () => findRef.current()?.focus() });\n }, [ref]);\n}\n\n// ── text ─────────────────────────────────────────────────────────────────────\n\ntype OwnInputProps = Omit<\n InputProps,\n \"name\" | \"value\" | \"defaultValue\" | \"onChange\" | \"onBlur\" | \"ref\" | \"label\" | \"error\" | \"invalid\" | \"className\" | \"disabled\" | \"required\" | \"inputClassName\"\n> & {\n /**\n * Classes for the `<input>` — `className` is the item's box (kastlan 42: a\n * `font-mono` IBAN, a `tabular-nums` reference number). {@link RhfTextarea} and\n * {@link RhfNumberField} had it; this one only reached `Input`'s prop of the same\n * name by accident of the rest-spread, undocumented and one refactor from being\n * dropped. Declared, it is part of the contract the three share.\n */\n inputClassName?: string;\n};\n\nexport type RhfTextFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnInputProps;\n\n/** A text {@link Input} — `type` for email, tel, password, url. Stores the string. */\nexport function RhfTextField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...inputProps\n}: RhfTextFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Input\n aria-required={required || undefined}\n {...inputProps}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n )}\n />\n );\n}\n\ntype OwnTextareaProps = Omit<\n TextareaProps,\n \"name\" | \"value\" | \"defaultValue\" | \"onChange\" | \"onBlur\" | \"ref\" | \"label\" | \"error\" | \"invalid\" | \"className\" | \"disabled\" | \"required\"\n> & {\n /** Classes for the `<textarea>`. */\n inputClassName?: string;\n};\n\nexport type RhfTextareaProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnTextareaProps;\n\n/** A multi-line {@link Textarea}; takes `rows`. Stores the string. */\nexport function RhfTextarea<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n inputClassName,\n ...areaProps\n}: RhfTextareaProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Textarea\n aria-required={required || undefined}\n {...areaProps}\n className={inputClassName}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n )}\n />\n );\n}\n\n// ── numbers ──────────────────────────────────────────────────────────────────\n\n/** A form value → the number field's `number | null`. Defaults hold `\"\"`, `null`, a\n * number, or a numeric string. */\nfunction toNumber(value: unknown): number | null {\n if (value === null || value === undefined || value === \"\") return null;\n const n = typeof value === \"number\" ? value : Number(String(value).replace(\",\", \".\"));\n return Number.isFinite(n) ? n : null;\n}\n\nexport type RhfNumberFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n NumberFieldProps,\n | \"digits\"\n | \"min\"\n | \"max\"\n | \"step\"\n | \"calculator\"\n | \"unit\"\n | \"unitPlacement\"\n | \"placeholder\"\n | \"inputClassName\"\n | \"locale\"\n | \"ariaLabel\"\n | \"autoFocus\"\n > & {\n /** What an emptied field stores. Default `null`; `\"\"` for a schema written\n * against a native number input (`z.coerce.number()` over `\"\"`). */\n emptyValue?: null | \"\";\n /** `false`: an emptied field snaps back to its last number instead of storing\n * `emptyValue`. Default `true`. */\n nullable?: boolean;\n };\n\n/**\n * The kit's {@link NumberField}: a parsed, rounded (`digits`) and clamped (`min` /\n * `max`) number, committed on blur or Enter in the locale's decimal mark. Stores a\n * number, or `emptyValue` when emptied.\n */\nexport function RhfNumberField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n emptyValue = null,\n nullable = true,\n ...numberProps\n}: RhfNumberFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid, id }) => (\n // FormControl clones this element with `id` / `aria-describedby` /\n // `aria-invalid`, which NumberControl hands on to the field.\n <NumberControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n emptyValue={emptyValue}\n nullable={nullable}\n numberProps={numberProps}\n />\n )}\n />\n );\n}\n\nfunction NumberControl({\n field,\n invalid,\n required,\n id,\n emptyValue,\n nullable,\n numberProps,\n ...aria\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n emptyValue: null | \"\";\n nullable: boolean;\n numberProps: Omit<RhfNumberFieldProps, keyof RhfFieldBaseProps | \"emptyValue\" | \"nullable\">;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: NumberFieldProps[\"aria-invalid\"];\n}) {\n // NumberField forwards no ref; it routes `id` to its <input>, where the handle\n // finds it.\n useFocusHandle(field.ref, () => document.getElementById(id));\n return (\n <NumberField\n {...numberProps}\n aria-describedby={aria[\"aria-describedby\"]}\n aria-invalid={aria[\"aria-invalid\"]}\n aria-required={required || undefined}\n id={id}\n value={toNumber(field.value)}\n onCommit={(n) => {\n field.onChange(n ?? emptyValue);\n field.onBlur();\n }}\n nullable={nullable}\n disabled={field.disabled}\n invalid={invalid}\n />\n );\n}\n\nexport type RhfIntegerFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfNumberFieldProps<TFieldValues, TName, TTransformed>;\n\n/**\n * {@link RhfNumberField} for a whole number — a floor, a room count, a year, a\n * notice period in months. Every such call site in kastlan (item 41) spelled out the\n * same three props, `digits={0} calculator={false} emptyValue=\"\"`, and a preset\n * written thirty times is one that is eventually written wrong once:\n *\n * - `digits={0}`: rounds on commit, so \"2.5\" rooms settles to 3 instead of reaching\n * an `Integer` column and failing server-side;\n * - `calculator={false}`: a count is typed, not worked out — the trigger is noise\n * beside a two-digit field;\n * - `emptyValue=\"\"`: kastlan's integer schemas are `z.coerce.number()` over `\"\"`,\n * written against the native number inputs these fields replaced.\n *\n * Each is only a default: pass the prop to override it (`emptyValue={null}` for a\n * nullable column). Everything else is {@link RhfNumberField}'s.\n */\nexport function RhfIntegerField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>(props: RhfIntegerFieldProps<TFieldValues, TName, TTransformed>) {\n // `??` / `=== undefined` rather than a spread over the defaults, so a caller\n // forwarding its own optional prop (`digits={props.digits}`) still gets the preset,\n // while an explicit `emptyValue={null}` keeps its null.\n return (\n <RhfNumberField\n {...props}\n digits={props.digits ?? 0}\n calculator={props.calculator ?? false}\n emptyValue={props.emptyValue === undefined ? \"\" : props.emptyValue}\n />\n );\n}\n\n// ── money ────────────────────────────────────────────────────────────────────\n\nexport type RhfMoneyFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & {\n placeholder?: string;\n /** The currency chip's code (\"CHF\"). */\n currency?: string;\n /** Makes the chip a currency picker. Bind it to another field with\n * `useController`, or to state. */\n onCurrencyChange?: (code: string) => void;\n /** Colours the figure for the direction of money. */\n tone?: \"neutral\" | \"outflow\" | \"inflow\";\n align?: \"start\" | \"center\";\n ariaLabel?: string;\n autoFocus?: boolean;\n /**\n * What the form stores: `\"number\"` (default) — `12.5`, or `emptyValue` while the\n * field is empty — or `\"string\"`, the field's own text (\"12.50\") for a schema that\n * parses it itself. A half-typed sum (\"12+\") leaves the stored number as it was\n * until it resolves.\n */\n valueAs?: \"number\" | \"string\";\n /** What an emptied field stores when `valueAs` is `\"number\"`. Default `null`. */\n emptyValue?: null | \"\";\n /** Decimals the amount settles to on blur, Enter or a calculator result. Default:\n * the currency's minor unit (CHF 2, JPY 0). ⚠️ A unit price or a rate needs its\n * column's scale here (`digits={4}` for 1.789 €/l), or it is stored rounded to\n * cents without a word (keksdose G2). See {@link AmountInput}'s `digits`. */\n digits?: number;\n /** Clamp the settled amount (a release capped at the deposit's balance). Validate\n * with `rules` as well if a clamp needs explaining. */\n min?: number;\n max?: number;\n};\n\n/** The amount a text reads as, or `undefined` for a draft that is not one yet. */\nfunction parseAmount(text: string): number | null | undefined {\n const trimmed = text.trim();\n if (trimmed === \"\") return null;\n if (!/^-?\\d*[.,]?\\d*$/.test(trimmed)) return undefined;\n const n = Number(trimmed.replace(\",\", \".\"));\n return Number.isFinite(n) ? n : undefined;\n}\n\nfunction MoneyControl({\n field,\n invalid,\n required,\n id,\n describedBy,\n props,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n describedBy: string | undefined;\n props: Omit<RhfMoneyFieldProps, keyof RhfFieldBaseProps>;\n}) {\n const { valueAs = \"number\", emptyValue = null, ariaLabel, ...amountProps } = props;\n const value: unknown = field.value;\n const external = value === null || value === undefined ? \"\" : String(value);\n // The text being typed. A stored NUMBER cannot hold \"12.\" or \"12+5\", so the draft\n // lives here and is re-read from the form only when the form's value moves away\n // from what the draft already says (a reset, a setValue).\n const [draft, setDraft] = useState(external);\n const [seen, setSeen] = useState<unknown>(value);\n if (seen !== value) {\n setSeen(value);\n const current = valueAs === \"string\" ? draft : parseAmount(draft);\n const same = valueAs === \"string\" ? current === external : current === toNumber(value);\n if (!same) setDraft(external);\n }\n const input = useRef<HTMLInputElement | null>(null);\n // AmountInput reports no blur, and react-hook-form needs one to mark the field\n // touched: listen on its <input>.\n const onBlur = field.onBlur;\n useLayoutEffect(() => {\n const el = input.current;\n if (!el) return;\n el.addEventListener(\"blur\", onBlur);\n return () => el.removeEventListener(\"blur\", onBlur);\n }, [onBlur]);\n return (\n <div>\n <AmountInput\n {...amountProps}\n ariaLabel={ariaLabel}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n ref={(el) => {\n input.current = el;\n field.ref(el);\n }}\n value={draft}\n disabled={field.disabled}\n invalid={invalid}\n onChange={(text) => {\n setDraft(text);\n if (valueAs === \"string\") {\n field.onChange(text);\n return;\n }\n const parsed = parseAmount(text);\n if (parsed === undefined) return;\n field.onChange(parsed ?? emptyValue);\n }}\n />\n </div>\n );\n}\n\n/**\n * The kit's {@link AmountInput}: a money figure with its currency chip and the\n * calculator (\"1200+80\" resolves on blur or Enter). Stores a number by default — see\n * `valueAs`.\n */\nexport function RhfMoneyField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...amountProps\n}: RhfMoneyFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n render={({ field, invalid, id, describedBy }) => (\n <MoneyControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n describedBy={describedBy}\n props={amountProps}\n />\n )}\n />\n );\n}\n\n// ── date ─────────────────────────────────────────────────────────────────────\n\nexport type RhfDateFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Omit<DatePickerProps, \"value\" | \"onChange\" | \"label\" | \"invalid\" | \"disabled\" | \"className\" | \"id\"> & {\n /** Classes for the picker. Default `w-full`. */\n inputClassName?: string;\n /** What a cleared date stores. Default `\"\"`, the empty ISO string; `null` for a\n * nullable schema. */\n emptyValue?: \"\" | null;\n };\n\nfunction DateControl({\n field,\n invalid,\n required,\n id,\n emptyValue,\n inputClassName,\n pickerProps,\n ...aria\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n emptyValue: \"\" | null;\n inputClassName?: string;\n pickerProps: Omit<DatePickerProps, \"value\" | \"onChange\" | \"label\" | \"invalid\" | \"disabled\" | \"className\" | \"id\">;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: DatePickerProps[\"aria-invalid\"];\n}) {\n useFocusHandle(field.ref, () => document.getElementById(id));\n const value: unknown = field.value;\n return (\n <DatePicker\n {...pickerProps}\n {...aria}\n aria-required={required || undefined}\n id={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(iso) => {\n field.onChange(iso === \"\" ? emptyValue : iso);\n field.onBlur();\n }}\n disabled={field.disabled}\n invalid={invalid}\n className={inputClassName ?? \"w-full\"}\n />\n );\n}\n\n/** The kit's {@link DatePicker}, holding an ISO `\"YYYY-MM-DD\"` string. */\nexport function RhfDateField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n inputClassName,\n emptyValue = \"\",\n ...pickerProps\n}: RhfDateFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid, id }) => (\n // FormControl clones this element with `aria-describedby` / `aria-invalid`,\n // which DateControl hands on to the picker's trigger.\n <DateControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n emptyValue={emptyValue}\n inputClassName={inputClassName}\n pickerProps={pickerProps}\n />\n )}\n />\n );\n}\n\n// ── select ───────────────────────────────────────────────────────────────────\n\nexport interface RhfSelectOption {\n value: string | number;\n label: ReactNode;\n disabled?: boolean;\n}\n\nexport type RhfSelectProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<SelectProps, \"size\" | \"autoFocus\" | \"aria-label\"> & {\n /** The options, as data. Or pass `<option>` children. */\n options?: readonly RhfSelectOption[];\n children?: ReactNode;\n /** A first, empty option (\"Choose…\"), selected while the value is empty. */\n placeholder?: string;\n /** Store `Number(value)` rather than the option's string. An empty choice still\n * stores `\"\"`. */\n valueAsNumber?: boolean;\n /** Classes for the select. Default `w-full`. */\n selectClassName?: string;\n };\n\n/** A native {@link Select}, from `options` or `<option>` children. */\nexport function RhfSelect<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n options,\n children,\n placeholder,\n valueAsNumber,\n selectClassName,\n ...selectProps\n}: RhfSelectProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Select\n aria-required={required || undefined}\n {...selectProps}\n className={cn(\"w-full\", selectClassName)}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string | number}\n onChange={(e) => {\n const raw = e.target.value;\n field.onChange(valueAsNumber && raw !== \"\" ? Number(raw) : raw);\n }}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n >\n {placeholder !== undefined && <option value=\"\">{placeholder}</option>}\n {options\n ? options.map((o) => (\n <option key={String(o.value)} value={o.value} disabled={o.disabled}>\n {o.label}\n </option>\n ))\n : children}\n </Select>\n )}\n />\n );\n}\n\n// ── checkbox ─────────────────────────────────────────────────────────────────\n\nexport type RhfCheckboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<CheckboxProps, \"inputClassName\" | \"autoFocus\" | \"aria-label\">;\n\n/**\n * The kit's {@link Checkbox}, label beside the box and `hint` under it (the\n * checkbox's own `description`). Stores a boolean. `required` is the native one here\n * — see Checkbox — so a `<form>` refuses to submit it unticked.\n */\nexport function RhfCheckbox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...boxProps\n}: RhfCheckboxProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, required, disabled, excludeWhenDisabled, className }}\n showLabel={false}\n render={({ field, invalid }) => (\n <Checkbox\n {...boxProps}\n ref={field.ref}\n name={field.name}\n checked={Boolean(field.value)}\n onCheckedChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n required={required}\n invalid={invalid}\n label={label}\n description={hint}\n />\n )}\n />\n );\n}\n\n// ── comboboxes ───────────────────────────────────────────────────────────────\n\nexport type RhfComboboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n V extends string | number = string | number,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n EntityComboboxProps<V>,\n | \"options\"\n | \"loadOptions\"\n | \"loading\"\n | \"placeholder\"\n | \"searchPlaceholder\"\n | \"emptyLabel\"\n | \"clearable\"\n | \"clearLabel\"\n | \"onCreate\"\n | \"createLabel\"\n | \"filter\"\n | \"minChars\"\n | \"debounceMs\"\n > & {\n /** What a clear stores — the picker's `clearValue`. Default `null`; `\"\"` for a\n * schema that spells \"no choice\" as an empty string. */\n clearValue?: ComboClearValue;\n /** Classes for the picker. */\n comboClassName?: string;\n };\n\nfunction EntityControl<V extends string | number>({\n field,\n invalid,\n required,\n error,\n id,\n describedBy,\n clearValue,\n comboClassName,\n comboProps,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n error: string | undefined;\n id: string;\n describedBy: string | undefined;\n clearValue: ComboClearValue;\n comboClassName?: string;\n comboProps: Omit<RhfComboboxProps<FieldValues, string, V>, keyof RhfFieldBaseProps | \"clearValue\" | \"comboClassName\">;\n}) {\n const box = useRef<HTMLDivElement>(null);\n // EntityCombobox puts `id` and the ARIA below on its trigger, so the label's\n // `htmlFor` names it, the hint describes it and the focus handle finds it by id.\n useFocusHandle(field.ref, () => document.getElementById(id));\n // EntityCombobox reports no blur: focus leaving the picker marks the field touched.\n const onBlur = field.onBlur;\n useLayoutEffect(() => {\n const el = box.current;\n if (!el) return;\n el.addEventListener(\"focusout\", onBlur);\n return () => el.removeEventListener(\"focusout\", onBlur);\n }, [onBlur]);\n const value: unknown = field.value;\n return (\n <div ref={box}>\n <EntityCombobox<V, ComboClearValue>\n {...comboProps}\n className={comboClassName}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n value={(value ?? null) as V | ComboClearValue | null}\n clearValue={clearValue}\n onChange={(v) => field.onChange(v)}\n disabled={field.disabled}\n invalid={invalid}\n // Its own message, which it merges into the trigger's aria-describedby after\n // the hint.\n error={error}\n />\n </div>\n );\n}\n\n/**\n * The kit's {@link EntityCombobox}: an id-keyed pick from `options` or `loadOptions`.\n * Stores the option's `value`, or `clearValue` on a clear (only offered with\n * `clearable`).\n */\nexport function RhfCombobox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n V extends string | number = string | number,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n clearValue = null,\n comboClassName,\n ...comboProps\n}: RhfComboboxProps<TFieldValues, TName, V, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n message={false}\n render={({ field, invalid, error, id, describedBy }) => (\n <EntityControl<V>\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n error={error}\n id={id}\n describedBy={describedBy}\n clearValue={clearValue}\n comboClassName={comboClassName}\n comboProps={comboProps}\n />\n )}\n />\n );\n}\n\nexport type RhfTextComboboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n ComboboxProps,\n | \"options\"\n | \"placeholder\"\n | \"groupBy\"\n | \"maxSuggestions\"\n | \"searchPlaceholder\"\n | \"createLabel\"\n | \"optionAdornment\"\n | \"autoFocus\"\n | \"aria-label\"\n > & {\n /** Classes for the combobox. */\n comboClassName?: string;\n };\n\n/**\n * The kit's free-text {@link Combobox}: type anything, or pick one of `options`.\n * Stores the string.\n */\nexport function RhfTextCombobox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n comboClassName,\n ...comboProps\n}: RhfTextComboboxProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n message={false}\n render={({ field, invalid, error, id, describedBy }) => (\n <TextComboControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n error={error}\n id={id}\n describedBy={describedBy}\n className={comboClassName}\n comboProps={comboProps}\n />\n )}\n />\n );\n}\n\nfunction TextComboControl({\n field,\n invalid,\n required,\n error,\n id,\n describedBy,\n className,\n comboProps,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n error: string | undefined;\n id: string;\n describedBy: string | undefined;\n className?: string;\n comboProps: Omit<RhfTextComboboxProps, keyof RhfFieldBaseProps | \"comboClassName\">;\n}) {\n // The combobox routes `id` and its ARIA to its <input>, so the label's `htmlFor`\n // names it, the hint describes it and the focus handle finds it; the error is its\n // own `error` prop, which it merges in after the hint.\n useFocusHandle(field.ref, () => document.getElementById(id));\n const value: unknown = field.value;\n return (\n <Combobox\n {...comboProps}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n className={className}\n value={typeof value === \"string\" ? value : value == null ? \"\" : String(value)}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n error={error}\n />\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/rhf/fields.tsx"],"sourcesContent":["/**\n * Bound fields: one line per field of a react-hook-form form. `@eifi1/ui-kit/rhf`.\n *\n * ```tsx\n * <Form {...form}>\n * <RhfTextField name=\"name\" label=\"Name\" hint=\"As on the lease\" required\n * rules={{ required: \"Enter a name\" }} />\n * <RhfMoneyField name=\"rent\" label=\"Net rent\" currency=\"CHF\" />\n * <RhfDateField name=\"start\" label=\"Start\" />\n * <RhfSelect name=\"type\" label=\"Type\" options={TYPES} />\n * <RhfCombobox name=\"tenantId\" label=\"Tenant\" options={tenants} clearable />\n * <RhfCheckbox name=\"isDefault\" label=\"Default account\" />\n * <RhfTimeInput name=\"meetingTime\" label=\"Time\" />\n * <RhfDateRangePicker fromName=\"periodFrom\" toName=\"periodTo\" label=\"Period\" />\n * <RhfToggleGroup name=\"interval\" label=\"Interval\" options={INTERVALS} />\n * <RhfCountrySelect name=\"country\" label=\"Country\" preferred={[\"CH\", \"DE\"]} />\n * <RhfMonthPicker name=\"fiscalYear\" label=\"Fiscal year\" mode=\"year\" valueAsNumber />\n * </Form>\n * ```\n *\n * Each folds the `FormField → FormItem → FormLabel → FormControl → field →\n * FormDescription → FormMessage` scaffold (see ./form) into one element, the way\n * kastlan's shared/components/form/fields.tsx does for its forms — with what that file\n * left out:\n *\n * - **The red border.** Every field gets `invalid` from the field state, so an errored\n * field PAINTS as well as announces. kastlan's number, money, date and entity fields\n * passed only `aria-invalid` through `FormControl`, or nothing, and `Input`, `Select`\n * and `Textarea` paint only from the prop (see the note in ./form).\n * - **Focus on error.** `field.ref` reaches the focusable element — the element itself\n * where the kit field forwards a ref, a focus handle on it where it does not (the\n * number field, the pickers) — so `handleSubmit` and `trigger(…, { shouldFocus })`\n * land the caret on the first field in error.\n * - **`control` is optional**: under `<Form {...form}>` the fields find the form\n * through react-hook-form's context. Pass it for the field's value types\n * (`control={form.control}` checks `name` against the form's values).\n *\n * The common props: `name`, `control`, `label` (a {@link FormLabel} above the field;\n * omitted, none — then give the field an `aria-label`), `hint` (standing advice under\n * the field, attached to it with `aria-describedby`), `required` (the label's mark,\n * and `aria-required` where the control takes it — validation is `rules`' or the\n * resolver's), `rules`, `disabled` (the control only — the value is still submitted;\n * `excludeWhenDisabled` for react-hook-form's drop-the-value semantics), and\n * `className` for the item's box.\n *\n * {@link RhfField} is the shell they are all built on, for a control the kit does not\n * ship (an address autocomplete): it takes a `render` and wires the rest.\n */\nimport { useLayoutEffect, useRef, useState, type FocusEvent, type ReactElement, type ReactNode } from \"react\";\nimport {\n useController,\n type ControllerFieldState,\n type ControllerProps,\n type ControllerRenderProps,\n type FieldPath,\n type FieldValues,\n} from \"react-hook-form\";\nimport { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField } from \"./form\";\nimport { Input, Select, Textarea, type InputProps, type SelectProps, type TextareaProps } from \"../components/ui\";\nimport { NumberField, type NumberFieldProps } from \"../components/number-field\";\nimport { AmountInput } from \"../components/amount-input\";\nimport {\n DatePicker,\n DateRangePicker,\n type DatePickerProps,\n type DateRangePickerProps,\n} from \"../components/date-picker\";\nimport { TimeInput, type TimeInputProps } from \"../components/time-input\";\nimport { IbanInput, type IbanInputProps } from \"../components/iban-input\";\nimport { PhoneInput, type PhoneInputProps } from \"../components/phone-input\";\nimport { CountrySelect, type CountrySelectProps } from \"../components/country-select\";\nimport { MonthPicker, type MonthPickerProps } from \"../components/month-picker\";\nimport {\n ToggleGroup,\n type ToggleGroupBaseProps,\n type ToggleGroupClearableProps,\n type ToggleGroupRequiredProps,\n} from \"../components/toggle-group\";\nimport { Checkbox, type CheckboxProps } from \"../components/checkbox\";\nimport { EntityCombobox, type EntityComboboxProps } from \"../components/entity-combobox\";\nimport { Combobox, type ComboboxProps } from \"../components/combobox\";\nimport type { ComboClearValue } from \"../components/combobox-core\";\nimport { cn } from \"../lib/cn\";\n\n// ── the shell ────────────────────────────────────────────────────────────────\n\n/** What every bound field takes. */\nexport interface RhfFieldBaseProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> {\n name: TName;\n /** `form.control`. Optional under `<Form {...form}>`; pass it to type-check `name`. */\n control?: ControllerProps<TFieldValues, TName, TTransformed>[\"control\"];\n /** react-hook-form's `rules` (`required`, `min`, `validate` …). */\n rules?: ControllerProps<TFieldValues, TName, TTransformed>[\"rules\"];\n /** A {@link FormLabel} above the field. Omitted: no label — name the control with\n * an `aria-label` instead. */\n label?: ReactNode;\n /** Standing advice under the field (\"As printed on the card\"), attached to the\n * control with `aria-describedby`. */\n hint?: ReactNode;\n /** Draws the label's required mark and sets `aria-required` where the control\n * takes it. Whether the field IS required is `rules`' or the resolver's to say. */\n required?: boolean;\n /** Disables the control and KEEPS the value: a field locked to a preset (a lease's\n * preselected unit, a fixed period) still submits it, and `rules` still run.\n * react-hook-form's own Controller `disabled` drops the value from `handleSubmit`'s\n * data instead, which a locked preset must never do (kastlan, 0.12). To get that,\n * add `excludeWhenDisabled`. A form-wide `useForm({ disabled })` still disables\n * every field the RHF way. */\n disabled?: boolean;\n /** With `disabled`: disable through react-hook-form, so the value is left out of\n * the submitted data and validation skips it, like a disabled native input in a\n * plain form post. Default `false`. */\n excludeWhenDisabled?: boolean;\n /** Classes for the item's box (a `grid gap-1`). */\n className?: string;\n}\n\n/** What {@link RhfField}'s `render` receives. */\nexport interface RhfFieldRenderContext<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> {\n field: ControllerRenderProps<TFieldValues, TName>;\n fieldState: ControllerFieldState;\n /** The field has an error: pass it to the control's `invalid` so it paints. */\n invalid: boolean;\n /** The error's message, if any. */\n error: string | undefined;\n /** The control's id, which the label points at. `FormControl` sets it on the\n * rendered element already; this is for a control that routes it elsewhere. */\n id: string;\n /** The label's id, for a control that is named with `aria-labelledby`. */\n labelId: string;\n /** The ids of the rendered hint and message, if any. */\n describedBy: string | undefined;\n}\n\nexport interface RhfFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> extends RhfFieldBaseProps<TFieldValues, TName, TTransformed> {\n /** The control. Wrapped in {@link FormControl} (its `id`, `aria-describedby` and\n * `aria-invalid`) unless `asControl` is false. */\n render: (ctx: RhfFieldRenderContext<TFieldValues, TName>) => ReactElement;\n /** `false`: render the control as is, for one that wires its own ids from the\n * context. Default `true`. */\n asControl?: boolean;\n /** `false`: no {@link FormMessage}, for a control that renders its own error (its\n * `error` prop). Default `true`. */\n message?: boolean;\n /** `false`: no {@link FormLabel}, for a control that carries its label itself (a\n * checkbox). Default `true`. */\n showLabel?: boolean;\n}\n\nfunction hasContent(node: ReactNode): boolean {\n return node !== undefined && node !== null && node !== false && node !== \"\";\n}\n\n/** The label, with an id the control can be named by. Inside the item, so it can read\n * the item's id. */\nfunction RhfLabel({ required, children }: { required?: boolean; children: ReactNode }) {\n const { id } = useFormField();\n return (\n <FormLabel id={`${id}-label`} required={required}>\n {children}\n </FormLabel>\n );\n}\n\nfunction ControlSlot<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>({\n field,\n fieldState,\n render,\n asControl,\n}: {\n field: ControllerRenderProps<TFieldValues, TName>;\n fieldState: ControllerFieldState;\n render: RhfFieldProps<TFieldValues, TName>[\"render\"];\n asControl: boolean;\n}) {\n const { id, formItemId, describedBy } = useFormField();\n const element = render({\n field,\n fieldState,\n invalid: fieldState.invalid,\n error: fieldState.error?.message,\n id: formItemId,\n labelId: `${id}-label`,\n describedBy,\n });\n return asControl ? <FormControl>{element}</FormControl> : element;\n}\n\n/**\n * The shell every bound field is built on: label, control, hint and message around\n * a `render` of your own.\n *\n * ```tsx\n * <RhfField name=\"address\" label=\"Address\" render={({ field, invalid }) => (\n * <AddressAutocomplete value={field.value ?? \"\"} onChange={field.onChange} invalid={invalid} />\n * )} />\n * ```\n */\nexport function RhfField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n render,\n asControl = true,\n message = true,\n showLabel = true,\n}: RhfFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <FormField\n control={control}\n name={name}\n rules={rules}\n disabled={excludeWhenDisabled ? disabled : undefined}\n render={({ field, fieldState }) => (\n <FormItem className={className}>\n {showLabel && hasContent(label) && <RhfLabel required={required}>{label}</RhfLabel>}\n <ControlSlot\n field={disabled && !field.disabled ? { ...field, disabled: true } : field}\n fieldState={fieldState}\n render={render}\n asControl={asControl}\n />\n {hasContent(hint) && <FormDescription>{hint}</FormDescription>}\n {message && <FormMessage />}\n </FormItem>\n )}\n />\n );\n}\n\n/**\n * Hands react-hook-form a focus handle for a control that forwards no ref: its\n * `shouldFocusError` calls `focus()` on whatever `field.ref` was given. `find` runs at\n * focus time, so it sees the element as it is then.\n */\nfunction useFocusHandle(ref: ControllerRenderProps[\"ref\"], find: () => HTMLElement | null | undefined) {\n const findRef = useRef(find);\n useLayoutEffect(() => {\n findRef.current = find;\n });\n useLayoutEffect(() => {\n ref({ focus: () => findRef.current()?.focus() });\n }, [ref]);\n}\n\n// ── text ─────────────────────────────────────────────────────────────────────\n\ntype OwnInputProps = Omit<\n InputProps,\n \"name\" | \"value\" | \"defaultValue\" | \"onChange\" | \"onBlur\" | \"ref\" | \"label\" | \"error\" | \"invalid\" | \"className\" | \"disabled\" | \"required\" | \"inputClassName\"\n> & {\n /**\n * Classes for the `<input>` — `className` is the item's box (kastlan 42: a\n * `font-mono` IBAN, a `tabular-nums` reference number). {@link RhfTextarea} and\n * {@link RhfNumberField} had it; this one only reached `Input`'s prop of the same\n * name by accident of the rest-spread, undocumented and one refactor from being\n * dropped. Declared, it is part of the contract the three share.\n */\n inputClassName?: string;\n};\n\nexport type RhfTextFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnInputProps;\n\n/** A text {@link Input} — `type` for email, tel, password, url. Stores the string. */\nexport function RhfTextField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...inputProps\n}: RhfTextFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Input\n aria-required={required || undefined}\n {...inputProps}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n )}\n />\n );\n}\n\ntype OwnTextareaProps = Omit<\n TextareaProps,\n \"name\" | \"value\" | \"defaultValue\" | \"onChange\" | \"onBlur\" | \"ref\" | \"label\" | \"error\" | \"invalid\" | \"className\" | \"disabled\" | \"required\"\n> & {\n /** Classes for the `<textarea>`. */\n inputClassName?: string;\n};\n\nexport type RhfTextareaProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnTextareaProps;\n\n/** A multi-line {@link Textarea}; takes `rows`. Stores the string. */\nexport function RhfTextarea<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n inputClassName,\n ...areaProps\n}: RhfTextareaProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Textarea\n aria-required={required || undefined}\n {...areaProps}\n className={inputClassName}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n )}\n />\n );\n}\n\n// ── numbers ──────────────────────────────────────────────────────────────────\n\n/** A form value → the number field's `number | null`. Defaults hold `\"\"`, `null`, a\n * number, or a numeric string. */\nfunction toNumber(value: unknown): number | null {\n if (value === null || value === undefined || value === \"\") return null;\n const n = typeof value === \"number\" ? value : Number(String(value).replace(\",\", \".\"));\n return Number.isFinite(n) ? n : null;\n}\n\nexport type RhfNumberFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n NumberFieldProps,\n | \"digits\"\n | \"min\"\n | \"max\"\n | \"step\"\n | \"calculator\"\n | \"unit\"\n | \"unitPlacement\"\n | \"placeholder\"\n | \"inputClassName\"\n | \"locale\"\n | \"ariaLabel\"\n | \"autoFocus\"\n > & {\n /** What an emptied field stores. Default `null`; `\"\"` for a schema written\n * against a native number input (`z.coerce.number()` over `\"\"`). */\n emptyValue?: null | \"\";\n /** `false`: an emptied field snaps back to its last number instead of storing\n * `emptyValue`. Default `true`. */\n nullable?: boolean;\n };\n\n/**\n * The kit's {@link NumberField}: a parsed, rounded (`digits`) and clamped (`min` /\n * `max`) number, committed on blur or Enter in the locale's decimal mark. Stores a\n * number, or `emptyValue` when emptied.\n */\nexport function RhfNumberField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n emptyValue = null,\n nullable = true,\n ...numberProps\n}: RhfNumberFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid, id }) => (\n // FormControl clones this element with `id` / `aria-describedby` /\n // `aria-invalid`, which NumberControl hands on to the field.\n <NumberControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n emptyValue={emptyValue}\n nullable={nullable}\n numberProps={numberProps}\n />\n )}\n />\n );\n}\n\nfunction NumberControl({\n field,\n invalid,\n required,\n id,\n emptyValue,\n nullable,\n numberProps,\n ...aria\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n emptyValue: null | \"\";\n nullable: boolean;\n numberProps: Omit<RhfNumberFieldProps, keyof RhfFieldBaseProps | \"emptyValue\" | \"nullable\">;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: NumberFieldProps[\"aria-invalid\"];\n}) {\n // NumberField forwards no ref; it routes `id` to its <input>, where the handle\n // finds it.\n useFocusHandle(field.ref, () => document.getElementById(id));\n return (\n <NumberField\n {...numberProps}\n aria-describedby={aria[\"aria-describedby\"]}\n aria-invalid={aria[\"aria-invalid\"]}\n aria-required={required || undefined}\n id={id}\n value={toNumber(field.value)}\n onCommit={(n) => {\n field.onChange(n ?? emptyValue);\n field.onBlur();\n }}\n nullable={nullable}\n disabled={field.disabled}\n invalid={invalid}\n />\n );\n}\n\nexport type RhfIntegerFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfNumberFieldProps<TFieldValues, TName, TTransformed>;\n\n/**\n * {@link RhfNumberField} for a whole number — a floor, a room count, a year, a\n * notice period in months. Every such call site in kastlan (item 41) spelled out the\n * same three props, `digits={0} calculator={false} emptyValue=\"\"`, and a preset\n * written thirty times is one that is eventually written wrong once:\n *\n * - `digits={0}`: rounds on commit, so \"2.5\" rooms settles to 3 instead of reaching\n * an `Integer` column and failing server-side;\n * - `calculator={false}`: a count is typed, not worked out — the trigger is noise\n * beside a two-digit field;\n * - `emptyValue=\"\"`: kastlan's integer schemas are `z.coerce.number()` over `\"\"`,\n * written against the native number inputs these fields replaced.\n *\n * Each is only a default: pass the prop to override it (`emptyValue={null}` for a\n * nullable column). Everything else is {@link RhfNumberField}'s.\n */\nexport function RhfIntegerField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>(props: RhfIntegerFieldProps<TFieldValues, TName, TTransformed>) {\n // `??` / `=== undefined` rather than a spread over the defaults, so a caller\n // forwarding its own optional prop (`digits={props.digits}`) still gets the preset,\n // while an explicit `emptyValue={null}` keeps its null.\n return (\n <RhfNumberField\n {...props}\n digits={props.digits ?? 0}\n calculator={props.calculator ?? false}\n emptyValue={props.emptyValue === undefined ? \"\" : props.emptyValue}\n />\n );\n}\n\n// ── money ────────────────────────────────────────────────────────────────────\n\nexport type RhfMoneyFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & {\n placeholder?: string;\n /** The currency chip's code (\"CHF\"). */\n currency?: string;\n /** Makes the chip a currency picker. Bind it to another field with\n * `useController`, or to state. */\n onCurrencyChange?: (code: string) => void;\n /** Colours the figure for the direction of money. */\n tone?: \"neutral\" | \"outflow\" | \"inflow\";\n align?: \"start\" | \"center\";\n ariaLabel?: string;\n autoFocus?: boolean;\n /**\n * What the form stores: `\"number\"` (default) — `12.5`, or `emptyValue` while the\n * field is empty — or `\"string\"`, the field's own text (\"12.50\") for a schema that\n * parses it itself. A half-typed sum (\"12+\") leaves the stored number as it was\n * until it resolves.\n */\n valueAs?: \"number\" | \"string\";\n /** What an emptied field stores when `valueAs` is `\"number\"`. Default `null`. */\n emptyValue?: null | \"\";\n /** Decimals the amount settles to on blur, Enter or a calculator result. Default:\n * the currency's minor unit (CHF 2, JPY 0). ⚠️ A unit price or a rate needs its\n * column's scale here (`digits={4}` for 1.789 €/l), or it is stored rounded to\n * cents without a word (keksdose G2). See {@link AmountInput}'s `digits`. */\n digits?: number;\n /** Clamp the settled amount (a release capped at the deposit's balance). Validate\n * with `rules` as well if a clamp needs explaining. */\n min?: number;\n max?: number;\n /** Classes for the `<input>` — `className` is the item's box. {@link RhfTextField},\n * {@link RhfTextarea} and {@link RhfNumberField} take it; since 0.23 AmountInput\n * does too (keksdose G7: `text-end` for a money column). */\n inputClassName?: string;\n};\n\n/** The amount a text reads as, or `undefined` for a draft that is not one yet. */\nfunction parseAmount(text: string): number | null | undefined {\n const trimmed = text.trim();\n if (trimmed === \"\") return null;\n if (!/^-?\\d*[.,]?\\d*$/.test(trimmed)) return undefined;\n const n = Number(trimmed.replace(\",\", \".\"));\n return Number.isFinite(n) ? n : undefined;\n}\n\nfunction MoneyControl({\n field,\n invalid,\n required,\n id,\n describedBy,\n props,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n describedBy: string | undefined;\n props: Omit<RhfMoneyFieldProps, keyof RhfFieldBaseProps>;\n}) {\n const { valueAs = \"number\", emptyValue = null, ariaLabel, ...amountProps } = props;\n const value: unknown = field.value;\n const external = value === null || value === undefined ? \"\" : String(value);\n // The text being typed. A stored NUMBER cannot hold \"12.\" or \"12+5\", so the draft\n // lives here and is re-read from the form only when the form's value moves away\n // from what the draft already says (a reset, a setValue).\n const [draft, setDraft] = useState(external);\n const [seen, setSeen] = useState<unknown>(value);\n if (seen !== value) {\n setSeen(value);\n const current = valueAs === \"string\" ? draft : parseAmount(draft);\n const same = valueAs === \"string\" ? current === external : current === toNumber(value);\n if (!same) setDraft(external);\n }\n const input = useRef<HTMLInputElement | null>(null);\n // AmountInput reports no blur, and react-hook-form needs one to mark the field\n // touched: listen on its <input>.\n const onBlur = field.onBlur;\n useLayoutEffect(() => {\n const el = input.current;\n if (!el) return;\n el.addEventListener(\"blur\", onBlur);\n return () => el.removeEventListener(\"blur\", onBlur);\n }, [onBlur]);\n return (\n <div>\n <AmountInput\n {...amountProps}\n ariaLabel={ariaLabel}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n ref={(el) => {\n input.current = el;\n field.ref(el);\n }}\n value={draft}\n disabled={field.disabled}\n invalid={invalid}\n onChange={(text) => {\n setDraft(text);\n if (valueAs === \"string\") {\n field.onChange(text);\n return;\n }\n const parsed = parseAmount(text);\n if (parsed === undefined) return;\n field.onChange(parsed ?? emptyValue);\n }}\n />\n </div>\n );\n}\n\n/**\n * The kit's {@link AmountInput}: a money figure with its currency chip and the\n * calculator (\"1200+80\" resolves on blur or Enter). Stores a number by default — see\n * `valueAs`.\n */\nexport function RhfMoneyField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...amountProps\n}: RhfMoneyFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n render={({ field, invalid, id, describedBy }) => (\n <MoneyControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n describedBy={describedBy}\n props={amountProps}\n />\n )}\n />\n );\n}\n\n// ── date ─────────────────────────────────────────────────────────────────────\n\nexport type RhfDateFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n // `error`: the form's message is shown by the binding (FormMessage); the picker's own\n // `error` (0.22) would show it a second time.\n Omit<DatePickerProps, \"value\" | \"onChange\" | \"label\" | \"invalid\" | \"disabled\" | \"className\" | \"id\" | \"error\"> & {\n /** Classes for the picker. Default `w-full`. */\n inputClassName?: string;\n /** What a cleared date stores. Default `\"\"`, the empty ISO string; `null` for a\n * nullable schema. */\n emptyValue?: \"\" | null;\n };\n\nfunction DateControl({\n field,\n invalid,\n required,\n id,\n emptyValue,\n inputClassName,\n pickerProps,\n ...aria\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n emptyValue: \"\" | null;\n inputClassName?: string;\n pickerProps: Omit<DatePickerProps, \"value\" | \"onChange\" | \"label\" | \"invalid\" | \"disabled\" | \"className\" | \"id\">;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: DatePickerProps[\"aria-invalid\"];\n}) {\n useFocusHandle(field.ref, () => document.getElementById(id));\n const value: unknown = field.value;\n return (\n <DatePicker\n {...pickerProps}\n {...aria}\n aria-required={required || undefined}\n id={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(iso) => {\n field.onChange(iso === \"\" ? emptyValue : iso);\n field.onBlur();\n }}\n disabled={field.disabled}\n invalid={invalid}\n className={inputClassName ?? \"w-full\"}\n />\n );\n}\n\n/** The kit's {@link DatePicker}, holding an ISO `\"YYYY-MM-DD\"` string. */\nexport function RhfDateField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n inputClassName,\n emptyValue = \"\",\n ...pickerProps\n}: RhfDateFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid, id }) => (\n // FormControl clones this element with `aria-describedby` / `aria-invalid`,\n // which DateControl hands on to the picker's trigger.\n <DateControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n emptyValue={emptyValue}\n inputClassName={inputClassName}\n pickerProps={pickerProps}\n />\n )}\n />\n );\n}\n\n// ── date range ───────────────────────────────────────────────────────────────\n\ntype OwnDateRangeProps = Omit<\n DateRangePickerProps,\n \"from\" | \"to\" | \"onChange\" | \"label\" | \"invalid\" | \"disabled\" | \"className\" | \"id\" | \"error\"\n>;\n\nexport type RhfDateRangePickerProps<\n TFieldValues extends FieldValues = FieldValues,\n TFromName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TToName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = Omit<RhfFieldBaseProps<TFieldValues, TFromName, TTransformed>, \"name\" | \"rules\"> &\n OwnDateRangeProps & {\n /** The form field holding the range's first day, an ISO `\"YYYY-MM-DD\"`. */\n fromName: TFromName;\n /** The form field holding the range's last day. */\n toName: TToName;\n /** react-hook-form's `rules` for the start (`required`, a `validate` …). */\n fromRules?: ControllerProps<TFieldValues, TFromName, TTransformed>[\"rules\"];\n /** react-hook-form's `rules` for the end — the place for \"not before the start\",\n * which can read the start with `getValues`: the start is always written first. */\n toRules?: ControllerProps<TFieldValues, TToName, TTransformed>[\"rules\"];\n /** Classes for the picker. Default `w-full`. */\n inputClassName?: string;\n /** What an empty end stores — a clear, or the half-made range between the first\n * and second click. Default `\"\"`, the empty ISO string; `null` for a nullable\n * schema. */\n emptyValue?: \"\" | null;\n };\n\n/**\n * The kit's {@link DateRangePicker} over TWO form fields — `fromName` and `toName` —\n * the way a period is stored: as two columns, each its own schema key, not one\n * `{ from, to }` object (kastlan 4).\n *\n * ```tsx\n * <RhfDateRangePicker fromName=\"periodFrom\" toName=\"periodTo\" label=\"Billing period\"\n * presets={presets} clearable />\n * ```\n *\n * Why it is not {@link RhfField}: a `Controller` binds one name, and the range is\n * two. Built by hand — an `RhfField` on the start and a second `useController` for\n * the end, which is what kastlan's period fields needed — it works until the END is\n * the one in error: the shell's label, message and `aria-invalid` all read the\n * start's state alone, so \"End before start\" (a `refine` with `path: [\"periodTo\"]`,\n * where such a rule goes) never shows. Here both states are read:\n *\n * - **Either field's error is shown and paints.** The label turns, the trigger is\n * `aria-invalid` and wears the danger border when EITHER field has an error, and\n * both messages are listed under the field (once, if the two say the same thing),\n * each pointed at by the trigger's `aria-describedby`.\n * - **One change writes both.** The picker reports the range whole, so the start and\n * then the end are written on every change — the end too when only the start\n * moved, so a cross-field rule on the end re-runs and an \"End before start\" clears\n * the moment the start is fixed. A clear (`clearable`'s ×) empties both.\n * - **Focus on error** lands on the trigger whichever of the two is in error.\n * - **Touched** once a range is complete or cleared — not on the first click of a\n * pick, which would mark (and, with `mode: \"onTouched\"`, validate) an end the user\n * is still choosing.\n *\n * In `commit=\"immediate\"` mode (the picker's default) the first calendar click is\n * reported on its own, so the form holds `(from, emptyValue)` until the second; with\n * `commit=\"apply\"` nothing reaches the form until Apply.\n *\n * The common props (`label`, `hint`, `required`, `disabled`, `excludeWhenDisabled`,\n * `control`, `className`) apply to the pair; `rules` are per field.\n */\nexport function RhfDateRangePicker<\n TFieldValues extends FieldValues = FieldValues,\n TFromName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TToName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n fromName,\n toName,\n control,\n fromRules,\n toRules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n inputClassName,\n emptyValue = \"\",\n ...pickerProps\n}: RhfDateRangePickerProps<TFieldValues, TFromName, TToName, TTransformed>) {\n const rhfDisabled = excludeWhenDisabled ? disabled : undefined;\n // The end, read here; the start is the FormField below, which gives the label, hint\n // and ids their context. This component re-renders on the end's state, and with it\n // the FormField's render.\n const to = useController<TFieldValues, TToName, TTransformed>({\n name: toName,\n control,\n rules: toRules,\n disabled: rhfDisabled,\n });\n return (\n <FormField\n control={control}\n name={fromName}\n rules={fromRules}\n disabled={rhfDisabled}\n render={({ field, fieldState }) => (\n <FormItem className={className}>\n <RangeBody\n from={field as unknown as ControllerRenderProps}\n fromState={fieldState}\n to={to.field as unknown as ControllerRenderProps}\n toState={to.fieldState}\n label={label}\n hint={hint}\n required={required}\n disabled={Boolean(disabled)}\n emptyValue={emptyValue}\n inputClassName={inputClassName}\n pickerProps={pickerProps}\n />\n </FormItem>\n )}\n />\n );\n}\n\nfunction RangeBody({\n from,\n fromState,\n to,\n toState,\n label,\n hint,\n required,\n disabled,\n emptyValue,\n inputClassName,\n pickerProps,\n}: {\n from: ControllerRenderProps;\n fromState: ControllerFieldState;\n to: ControllerRenderProps;\n toState: ControllerFieldState;\n label: ReactNode;\n hint: ReactNode;\n required?: boolean;\n disabled: boolean;\n emptyValue: \"\" | null;\n inputClassName?: string;\n pickerProps: OwnDateRangeProps;\n}) {\n const { id, formItemId, formMessageId, describedBy } = useFormField();\n // The trigger forwards no ref; both fields focus it, so `shouldFocusError` lands\n // there whichever of the two is first in error.\n useFocusHandle(from.ref, () => document.getElementById(formItemId));\n useFocusHandle(to.ref, () => document.getElementById(formItemId));\n const invalid = fromState.invalid || toState.invalid;\n const messages = [fromState.error?.message, toState.error?.message].filter(\n (m, i, all): m is string => typeof m === \"string\" && m !== \"\" && all.indexOf(m) === i,\n );\n const messageIds = messages.map((_, i) => `${formMessageId}-${i}`);\n const fromValue: unknown = from.value;\n const toValue: unknown = to.value;\n return (\n <>\n {hasContent(label) && (\n // FormLabel colours from the START's error alone (its context is that field);\n // the pair's state says it here.\n <FormLabel id={`${id}-label`} required={required} data-error={invalid || undefined}>\n {label}\n </FormLabel>\n )}\n <DateRangePicker\n {...pickerProps}\n id={formItemId}\n // Merged, never replaced — a caller's own reference first, as FormControl does.\n aria-describedby={\n [pickerProps[\"aria-describedby\"], describedBy, ...messageIds].filter(Boolean).join(\" \") || undefined\n }\n aria-invalid={invalid || undefined}\n aria-required={required || undefined}\n from={typeof fromValue === \"string\" ? fromValue : \"\"}\n to={typeof toValue === \"string\" ? toValue : \"\"}\n onChange={(f, t) => {\n from.onChange(f === \"\" ? emptyValue : f);\n to.onChange(t === \"\" ? emptyValue : t);\n if (t !== \"\" || f === \"\") {\n from.onBlur();\n to.onBlur();\n }\n }}\n disabled={disabled || from.disabled || to.disabled}\n invalid={invalid}\n className={inputClassName ?? \"w-full\"}\n />\n {hasContent(hint) && <FormDescription>{hint}</FormDescription>}\n {messages.map((message, i) => (\n // FormMessage's look and its rule: no `role=\"alert\"` — read when focus reaches\n // the trigger, which names these in its description.\n <p\n key={message}\n id={messageIds[i]}\n data-slot=\"form-message\"\n className=\"text-[11px] leading-tight text-[var(--danger)]\"\n >\n {message}\n </p>\n ))}\n </>\n );\n}\n\n// ── time ─────────────────────────────────────────────────────────────────────\n\nexport type RhfTimeInputProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Omit<\n TimeInputProps,\n | \"name\"\n | \"value\"\n | \"defaultValue\"\n | \"onChange\"\n | \"onValueChange\"\n | \"onBlur\"\n | \"label\"\n | \"error\"\n | \"invalid\"\n | \"className\"\n | \"disabled\"\n | \"required\"\n > & {\n /** What a cleared time stores. Default `\"\"`; `null` for a nullable schema. */\n emptyValue?: \"\" | null;\n };\n\n/**\n * The kit's {@link TimeInput}: a time of day as `\"HH:mm\"` (`\"HH:mm:ss\"` when `step`\n * asks for seconds), normalised before it reaches the form, so the stored value\n * compares and sorts as a string. kastlan 4: the owner meeting's time was an\n * {@link RhfField} with a hand-wired `TimeInput` in its render — `ref`, `name`, the\n * `?? \"\"`, `onValueChange`, `onBlur`, `invalid` — the seven lines every bound field\n * folds into one.\n *\n * `min` / `max` paint an out-of-window time (see TimeInput) but do not fail the form:\n * validation stays the schema's or `rules`'. `rules={{ validate: (v) =>\n * isTimeInRange(v, min, max) || \"…\" }}` says it with the same window.\n */\nexport function RhfTimeInput<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n emptyValue = \"\",\n ...timeProps\n}: RhfTimeInputProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => {\n const value: unknown = field.value;\n return (\n <TimeInput\n aria-required={required || undefined}\n {...timeProps}\n name={field.name}\n ref={field.ref}\n value={typeof value === \"string\" ? value : \"\"}\n onValueChange={(v) => field.onChange(v === \"\" ? emptyValue : v)}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n );\n }}\n />\n );\n}\n\n// ── IBAN and phone (0.22) ────────────────────────────────────────────────────\n\ntype OwnTextishProps<P> = Omit<\n P,\n | \"name\"\n | \"value\"\n | \"defaultValue\"\n | \"onChange\"\n | \"onValueChange\"\n | \"onBlur\"\n | \"label\"\n | \"error\"\n | \"invalid\"\n | \"className\"\n | \"disabled\"\n | \"required\"\n>;\n\nexport type RhfIbanInputProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnTextishProps<IbanInputProps>;\n\n/**\n * {@link IbanInput} bound to one field, which stores the COMPACT upper-case IBAN (what\n * kastlan's server checks and its QR bill prints). The field's own checksum and\n * `kind` messages show while the form has nothing to say; a form error (the schema's\n * or `rules`') replaces them, as a caller's `error` does on the bare field. kastlan\n * asked for the field; it binds everything through react-hook-form.\n */\nexport function RhfIbanInput<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...ibanProps\n}: RhfIbanInputProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => {\n const value: unknown = field.value;\n return (\n <IbanInput\n aria-required={required || undefined}\n {...ibanProps}\n name={field.name}\n ref={field.ref}\n value={typeof value === \"string\" ? value : \"\"}\n onValueChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n );\n }}\n />\n );\n}\n\nexport type RhfPhoneInputProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnTextishProps<PhoneInputProps>;\n\n/**\n * {@link PhoneInput} bound to one field, which stores E.164 when the number reads as\n * one and the typed text unchanged otherwise — kastlan's contacts keep their old free\n * text until someone edits it. Validation (required, a pattern for E.164 only) is the\n * schema's or `rules`'.\n */\nexport function RhfPhoneInput<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...phoneProps\n}: RhfPhoneInputProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => {\n const value: unknown = field.value;\n return (\n <PhoneInput\n aria-required={required || undefined}\n {...phoneProps}\n name={field.name}\n ref={field.ref}\n value={typeof value === \"string\" ? value : \"\"}\n onValueChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n );\n }}\n />\n );\n}\n\n// ── country and month (0.23) ─────────────────────────────────────────────────\n\ntype OwnCountrySelectProps = Omit<\n CountrySelectProps<boolean>,\n | \"value\"\n | \"onChange\"\n | \"onBlur\"\n | \"label\"\n | \"hint\"\n | \"error\"\n | \"invalid\"\n | \"disabled\"\n | \"className\"\n | \"id\"\n | \"ref\"\n | \"clearable\"\n>;\n\nexport type RhfCountrySelectProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n OwnCountrySelectProps & {\n /** Offer the picker's clear \"×\" (and Delete on the trigger) while a country is\n * chosen. A clear stores `clearValue`. */\n clearable?: boolean;\n /** What a clear stores. Default `null`; `\"\"` for a schema that spells \"no\n * country\" as an empty string (a zod `z.string().max(2)`, kastlan's). The picker\n * reads either back as empty. */\n clearValue?: ComboClearValue;\n /** Classes for the picker — `className` is the item's box. */\n selectClassName?: string;\n };\n\n/**\n * {@link CountrySelect} bound to one field, which stores the ISO 3166-1 alpha-2 code\n * (\"CH\", always upper-case), or `clearValue` once cleared (`clearable`). kastlan asked\n * for it (0.22 adoption): its address form wired a `CountrySelect` through\n * {@link RhfField}'s render, and with no ref on the picker react-hook-form's\n * focus-on-error had nothing to focus — the one field on the form a failed submit\n * could not take you to.\n *\n * Bound the way {@link RhfIbanInput} and {@link RhfPhoneInput} are: `field.ref` reaches\n * the trigger (the picker's `ref`, 0.23), the form's error paints the trigger and is\n * the shell's message under it, the hint is the shell's description — so neither is\n * ever handed to the picker, and its box never changes when one comes or goes. The\n * form's label names the trigger together with the chosen country, and is the phone\n * sheet's title. `commit` and `disabledReason` are the picker's own: a country that\n * saves itself stays focusable under a lock and says why.\n *\n * ```tsx\n * <RhfCountrySelect name=\"country\" label=\"Country\" required\n * preferred={[\"CH\", \"LI\", \"DE\", \"AT\", \"FR\", \"IT\"]} rules={{ required: \"Choose a country\" }} />\n * ```\n */\nexport function RhfCountrySelect<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n clearable,\n clearValue = null,\n selectClassName,\n labels,\n ...countryProps\n}: RhfCountrySelectProps<TFieldValues, TName, TTransformed>) {\n const labelled = hasContent(label);\n // A string label is also what the field IS — the picker's `country` word, which\n // titles the phone sheet. A caller's own `labels.country` still wins.\n const ownLabels = typeof label === \"string\" ? { country: label, ...labels } : labels;\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid, labelId }) => {\n const value: unknown = field.value;\n return (\n // FormControl clones this element with `id` / `aria-describedby` /\n // `aria-invalid`, which the picker routes to its trigger.\n <CountrySelect<boolean>\n aria-required={required || undefined}\n // The form's label, then the country (see the picker's `aria-labelledby`).\n aria-labelledby={labelled ? labelId : undefined}\n {...countryProps}\n labels={ownLabels}\n className={selectClassName}\n ref={field.ref}\n value={typeof value === \"string\" ? value : null}\n clearable={clearable}\n onChange={(code) => field.onChange(code ?? clearValue)}\n // Focus leaving the picker (the wrapper's focusout) marks the field touched.\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n );\n }}\n />\n );\n}\n\ntype OwnMonthPickerProps = Omit<\n MonthPickerProps,\n \"value\" | \"onChange\" | \"onBlur\" | \"label\" | \"hint\" | \"error\" | \"invalid\" | \"disabled\" | \"className\" | \"id\" | \"mode\"\n>;\n\n/** `mode` picks what the form stores, and `valueAsNumber` is only offered for a year. */\ntype RhfMonthPickerMode =\n | {\n /** A month, stored as `\"YYYY-MM\"` (the default). */\n mode?: \"month\";\n valueAsNumber?: undefined;\n }\n | {\n /** A year, stored as `\"YYYY\"` — or as a number with `valueAsNumber`. */\n mode: \"year\";\n /** Store the year as a number (`2026`) rather than `\"2026\"` — kastlan's budget\n * `fiscal_year` is an integer column. A number in the form reads back as its\n * year. */\n valueAsNumber?: boolean;\n };\n\nexport type RhfMonthPickerProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n OwnMonthPickerProps & {\n /** Classes for the picker — `className` is the item's box. As {@link RhfDateField}'s. */\n inputClassName?: string;\n } & RhfMonthPickerMode;\n\nfunction MonthControl({\n field,\n invalid,\n id,\n valueAsNumber,\n mode,\n inputClassName,\n pickerProps,\n required,\n ...aria\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n id: string;\n valueAsNumber?: boolean;\n mode?: \"month\" | \"year\";\n inputClassName?: string;\n pickerProps: OwnMonthPickerProps;\n required?: boolean;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: MonthPickerProps[\"aria-invalid\"];\n}) {\n // MonthPicker forwards no ref; it routes `id` to its trigger, where the handle finds\n // it — RhfDateField's way.\n useFocusHandle(field.ref, () => document.getElementById(id));\n const value: unknown = field.value;\n return (\n <MonthPicker\n {...pickerProps}\n {...aria}\n // MonthPicker routes `aria-required` to its trigger since 0.23.0.\n aria-required={required || undefined}\n id={id}\n mode={mode}\n value={value === null || value === undefined ? \"\" : String(value)}\n onChange={(key) => {\n field.onChange(mode === \"year\" && valueAsNumber ? Number(key) : key);\n // A pick is the whole interaction — there is no text to leave — so it touches.\n field.onBlur();\n }}\n disabled={field.disabled}\n invalid={invalid}\n className={inputClassName}\n />\n );\n}\n\n/**\n * {@link MonthPicker} bound to one field: a month as `\"YYYY-MM\"`, or with `mode=\"year\"` a\n * year as `\"YYYY\"` (`valueAsNumber` stores `2026`). kastlan asked for it with\n * {@link RhfCountrySelect}: its budget wizard's fiscal year was a `MonthPicker\n * mode=\"year\"` inside {@link RhfField}'s render — the `String()` in, the `Number()`\n * out, `invalid` by hand — and a failed submit could not focus it, because the picker\n * forwards no ref.\n *\n * Bound as {@link RhfDateField} is: a focus handle finds the trigger by its id, so\n * focus-on-error lands there; the form's error paints the trigger and is the shell's\n * message; the hint is the shell's description; neither is handed to the picker, so\n * its box never changes. Picking marks the field touched.\n *\n * ```tsx\n * <RhfMonthPicker name=\"fiscalYear\" label=\"Fiscal year\" mode=\"year\" valueAsNumber\n * min=\"2020\" max=\"2029\" rules={{ required: \"Choose a year\" }} />\n * ```\n */\nexport function RhfMonthPicker<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n inputClassName,\n mode,\n valueAsNumber,\n ...pickerProps\n}: RhfMonthPickerProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid, id }) => (\n // FormControl clones this element with `aria-describedby` / `aria-invalid`,\n // which MonthControl hands on to the picker's trigger.\n <MonthControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n id={id}\n mode={mode}\n valueAsNumber={valueAsNumber}\n inputClassName={inputClassName}\n pickerProps={pickerProps}\n required={required}\n />\n )}\n />\n );\n}\n\n// ── select ───────────────────────────────────────────────────────────────────\n\nexport interface RhfSelectOption {\n value: string | number;\n label: ReactNode;\n disabled?: boolean;\n}\n\nexport type RhfSelectProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<SelectProps, \"size\" | \"autoFocus\" | \"aria-label\"> & {\n /** The options, as data. Or pass `<option>` children. */\n options?: readonly RhfSelectOption[];\n children?: ReactNode;\n /** A first, empty option (\"Choose…\"), selected while the value is empty. */\n placeholder?: string;\n /** Store `Number(value)` rather than the option's string. An empty choice still\n * stores `\"\"`. */\n valueAsNumber?: boolean;\n /** Classes for the select. Default `w-full`. */\n selectClassName?: string;\n };\n\n/** A native {@link Select}, from `options` or `<option>` children. */\nexport function RhfSelect<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n options,\n children,\n placeholder,\n valueAsNumber,\n selectClassName,\n ...selectProps\n}: RhfSelectProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Select\n aria-required={required || undefined}\n {...selectProps}\n className={cn(\"w-full\", selectClassName)}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string | number}\n onChange={(e) => {\n const raw = e.target.value;\n field.onChange(valueAsNumber && raw !== \"\" ? Number(raw) : raw);\n }}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n >\n {placeholder !== undefined && <option value=\"\">{placeholder}</option>}\n {options\n ? options.map((o) => (\n <option key={String(o.value)} value={o.value} disabled={o.disabled}>\n {o.label}\n </option>\n ))\n : children}\n </Select>\n )}\n />\n );\n}\n\n// ── checkbox ─────────────────────────────────────────────────────────────────\n\nexport type RhfCheckboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<CheckboxProps, \"inputClassName\" | \"autoFocus\" | \"aria-label\">;\n\n/**\n * The kit's {@link Checkbox}, label beside the box and `hint` under it (the\n * checkbox's own `description`). Stores a boolean. `required` is the native one here\n * — see Checkbox — so a `<form>` refuses to submit it unticked.\n */\nexport function RhfCheckbox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...boxProps\n}: RhfCheckboxProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, required, disabled, excludeWhenDisabled, className }}\n showLabel={false}\n render={({ field, invalid }) => (\n <Checkbox\n {...boxProps}\n ref={field.ref}\n name={field.name}\n checked={Boolean(field.value)}\n onCheckedChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n required={required}\n invalid={invalid}\n label={label}\n description={hint}\n />\n )}\n />\n );\n}\n\n// ── toggle group ─────────────────────────────────────────────────────────────\n\n/** The two shapes a {@link ToggleGroup} comes in, carried over: `allowEmpty` picks\n * whether a press on the chosen option clears it, and types the caption to match. */\ntype RhfToggleGroupMode<T extends string> =\n | {\n /** One option is always the answer (the default): a press on the chosen\n * option re-sends it. */\n allowEmpty?: false;\n semantics?: ToggleGroupRequiredProps<T>[\"semantics\"];\n caption?: ToggleGroupRequiredProps<T>[\"caption\"];\n emptyValue?: undefined;\n }\n | {\n /** A press on the chosen option clears it, and the form stores `emptyValue`. */\n allowEmpty: true;\n semantics?: ToggleGroupClearableProps<T>[\"semantics\"];\n caption?: ToggleGroupClearableProps<T>[\"caption\"];\n /** What a cleared group stores. Default `null`; `\"\"` for a schema that spells\n * \"no choice\" as an empty string. */\n emptyValue?: null | \"\";\n };\n\nexport type RhfToggleGroupProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n T extends string = string,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n ToggleGroupBaseProps<T>,\n \"options\" | \"optionClassName\" | \"overflow\" | \"size\" | \"aria-label\" | \"commit\" | \"disabledReason\"\n > & {\n /** Classes for the group itself — `className` is the item's box. */\n groupClassName?: string;\n } & RhfToggleGroupMode<T>;\n\n/**\n * The kit's {@link ToggleGroup} bound to one field: a choice between a few answers\n * (\"Monthly / Quarterly / Yearly\"), stored as the chosen option's `value`. kastlan 4\n * asked for it with {@link RhfTimeInput} and {@link RhfDateRangePicker}: the controls\n * its forms still had to wire by hand through {@link RhfField}'s render.\n *\n * The label is the form's {@link FormLabel} above the bare group, as on every other\n * bound field — the `labelPlacement=\"above\"` shape, not the group's own field chrome —\n * and it names the group (`aria-labelledby`); the hint and the message describe it,\n * and an error paints the group's border. Focus on error goes to the option a\n * keyboard user would land on (the chosen one, else the first); touched is set when\n * focus leaves the group, not when it moves between options.\n *\n * Required by default, as the group is: a press on the chosen option keeps it. With\n * `allowEmpty`, a second press clears the choice and the form stores `emptyValue`\n * (`null` by default) — the options then become toggle buttons, see ToggleGroup. A\n * value that matches no option (an empty default) leaves nothing pressed; that the\n * field still needs answering is the schema's or `rules`' to say.\n */\nexport function RhfToggleGroup<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n T extends string = string,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...groupProps\n}: RhfToggleGroupProps<TFieldValues, TName, T, TTransformed>) {\n const labelled = hasContent(label);\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n render={({ field, invalid, id, labelId, describedBy }) => (\n <ToggleControl<T>\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n labelledBy={labelled ? labelId : undefined}\n describedBy={describedBy}\n groupProps={groupProps}\n />\n )}\n />\n );\n}\n\nfunction ToggleControl<T extends string>({\n field,\n invalid,\n required,\n id,\n labelledBy,\n describedBy,\n groupProps,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n labelledBy: string | undefined;\n describedBy: string | undefined;\n groupProps: Omit<RhfToggleGroupProps<FieldValues, string, T>, keyof RhfFieldBaseProps>;\n}) {\n const { groupClassName, emptyValue, allowEmpty, semantics, caption, ...rest } = groupProps;\n // ToggleGroup forwards no ref. Its options are buttons: the radio shape's one tab\n // stop (`tabindex=\"0\"`), or in the pressed shape the pressed one — else the first.\n useFocusHandle(field.ref, () => {\n const group = document.getElementById(id);\n return (\n group?.querySelector<HTMLElement>('button[tabindex=\"0\"], button[aria-pressed=\"true\"]') ??\n group?.querySelector<HTMLElement>(\"button\")\n );\n });\n // React's onBlur is focusout: it fires on every move between options as well, and\n // only leaving the group is a blur of the FIELD.\n const onBlur = (e: FocusEvent<HTMLDivElement>) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) field.onBlur();\n };\n const raw: unknown = field.value;\n const value = raw === null || raw === undefined || raw === \"\" ? null : (String(raw) as T);\n const common = {\n ...rest,\n id,\n className: groupClassName,\n \"aria-labelledby\": labelledBy,\n \"aria-describedby\": describedBy,\n \"aria-invalid\": invalid || undefined,\n disabled: field.disabled,\n onBlur,\n };\n // The props' union pairs `allowEmpty` with its caption's type; taken apart above it no\n // longer narrows, so each branch says which half it is.\n if (allowEmpty) {\n return (\n <ToggleGroup<T>\n {...common}\n allowEmpty\n caption={caption as ToggleGroupClearableProps<T>[\"caption\"]}\n value={value}\n onChange={(v) => field.onChange(v ?? emptyValue ?? null)}\n />\n );\n }\n return (\n <ToggleGroup<T>\n {...common}\n allowEmpty={false}\n semantics={semantics}\n caption={caption as ToggleGroupRequiredProps<T>[\"caption\"]}\n // A radiogroup takes `aria-required`; a group of toggle buttons does not.\n aria-required={required && semantics !== \"pressed\" ? true : undefined}\n // An empty default matches no option: nothing pressed, the first option the tab\n // stop.\n value={(value ?? \"\") as T}\n onChange={(v) => field.onChange(v)}\n />\n );\n}\n\n// ── comboboxes ───────────────────────────────────────────────────────────────\n\nexport type RhfComboboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n V extends string | number = string | number,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n EntityComboboxProps<V>,\n | \"options\"\n | \"loadOptions\"\n | \"loading\"\n | \"placeholder\"\n | \"searchPlaceholder\"\n | \"emptyLabel\"\n | \"clearable\"\n | \"clearLabel\"\n | \"onCreate\"\n | \"createLabel\"\n | \"filter\"\n | \"minChars\"\n | \"debounceMs\"\n > & {\n /** What a clear stores — the picker's `clearValue`. Default `null`; `\"\"` for a\n * schema that spells \"no choice\" as an empty string. */\n clearValue?: ComboClearValue;\n /** Classes for the picker. */\n comboClassName?: string;\n };\n\nfunction EntityControl<V extends string | number>({\n field,\n invalid,\n required,\n error,\n id,\n describedBy,\n clearValue,\n comboClassName,\n comboProps,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n error: string | undefined;\n id: string;\n describedBy: string | undefined;\n clearValue: ComboClearValue;\n comboClassName?: string;\n comboProps: Omit<RhfComboboxProps<FieldValues, string, V>, keyof RhfFieldBaseProps | \"clearValue\" | \"comboClassName\">;\n}) {\n const box = useRef<HTMLDivElement>(null);\n // EntityCombobox puts `id` and the ARIA below on its trigger, so the label's\n // `htmlFor` names it, the hint describes it and the focus handle finds it by id.\n useFocusHandle(field.ref, () => document.getElementById(id));\n // EntityCombobox reports no blur: focus leaving the picker marks the field touched.\n const onBlur = field.onBlur;\n useLayoutEffect(() => {\n const el = box.current;\n if (!el) return;\n el.addEventListener(\"focusout\", onBlur);\n return () => el.removeEventListener(\"focusout\", onBlur);\n }, [onBlur]);\n const value: unknown = field.value;\n return (\n <div ref={box}>\n <EntityCombobox<V, ComboClearValue>\n {...comboProps}\n className={comboClassName}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n value={(value ?? null) as V | ComboClearValue | null}\n clearValue={clearValue}\n onChange={(v) => field.onChange(v)}\n disabled={field.disabled}\n invalid={invalid}\n // Its own message, which it merges into the trigger's aria-describedby after\n // the hint.\n error={error}\n />\n </div>\n );\n}\n\n/**\n * The kit's {@link EntityCombobox}: an id-keyed pick from `options` or `loadOptions`.\n * Stores the option's `value`, or `clearValue` on a clear (only offered with\n * `clearable`).\n */\nexport function RhfCombobox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n V extends string | number = string | number,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n clearValue = null,\n comboClassName,\n ...comboProps\n}: RhfComboboxProps<TFieldValues, TName, V, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n message={false}\n render={({ field, invalid, error, id, describedBy }) => (\n <EntityControl<V>\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n error={error}\n id={id}\n describedBy={describedBy}\n clearValue={clearValue}\n comboClassName={comboClassName}\n comboProps={comboProps}\n />\n )}\n />\n );\n}\n\nexport type RhfTextComboboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n ComboboxProps,\n | \"options\"\n | \"placeholder\"\n | \"groupBy\"\n | \"maxSuggestions\"\n | \"searchPlaceholder\"\n | \"createLabel\"\n | \"optionAdornment\"\n | \"autoFocus\"\n | \"aria-label\"\n > & {\n /** Classes for the combobox. */\n comboClassName?: string;\n };\n\n/**\n * The kit's free-text {@link Combobox}: type anything, or pick one of `options`.\n * Stores the string.\n */\nexport function RhfTextCombobox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n comboClassName,\n ...comboProps\n}: RhfTextComboboxProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n message={false}\n render={({ field, invalid, error, id, describedBy }) => (\n <TextComboControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n error={error}\n id={id}\n describedBy={describedBy}\n className={comboClassName}\n comboProps={comboProps}\n />\n )}\n />\n );\n}\n\nfunction TextComboControl({\n field,\n invalid,\n required,\n error,\n id,\n describedBy,\n className,\n comboProps,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n error: string | undefined;\n id: string;\n describedBy: string | undefined;\n className?: string;\n comboProps: Omit<RhfTextComboboxProps, keyof RhfFieldBaseProps | \"comboClassName\">;\n}) {\n // The combobox routes `id` and its ARIA to its <input>, so the label's `htmlFor`\n // names it, the hint describes it and the focus handle finds it; the error is its\n // own `error` prop, which it merges in after the hint.\n useFocusHandle(field.ref, () => document.getElementById(id));\n const value: unknown = field.value;\n return (\n <Combobox\n {...comboProps}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n className={className}\n value={typeof value === \"string\" ? value : value == null ? \"\" : String(value)}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n error={error}\n />\n );\n}\n"],"mappings":"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","names":[]}
@@ -2,17 +2,21 @@ import * as react from 'react';
2
2
  import { ReactElement, ComponentProps } from 'react';
3
3
  import * as react_hook_form from 'react-hook-form';
4
4
  import { FieldValues, FieldPath, ControllerProps } from 'react-hook-form';
5
- import { aJ as LabelProps } from '../kit-labels-D1J2_jyD.js';
6
- import '../components/data-table-labels.js';
5
+ import { bm as LabelProps } from '../feedback-BxeQVzwq.js';
6
+ import '../feedback-attachment-fGAzZPf0.js';
7
+ import '../feedback/feedback-inbox.js';
8
+ import 'lucide-react';
9
+ import '../components/tooltip.js';
10
+ import '../hooks/use-anchored-rect.js';
11
+ import '../lib/clipping.js';
12
+ import '../data-table-labels-B7OdnM0S.js';
13
+ import '../components/data-table-sort.js';
14
+ import '../components/swipeable-row.js';
7
15
  import '../components/mini-calendar.js';
8
16
  import '../components/calendar-heatmap.js';
9
17
  import '../components/popover.js';
10
18
  import '../components/chip.js';
11
- import 'lucide-react';
12
19
  import '../components/field-sync.js';
13
- import '../components/tooltip.js';
14
- import '../hooks/use-anchored-rect.js';
15
- import '../lib/clipping.js';
16
20
  import '../wizard/types.js';
17
21
  import '../tour/tour.js';
18
22
  import '../search/command-palette.js';
@@ -26,7 +30,6 @@ import '../components/sparkline.js';
26
30
  import '../components/stat-tile.js';
27
31
  import '../components/signature-pad.js';
28
32
  import '../components/password-strength.js';
29
- import '../components/danger-confirm.js';
30
33
  import '../components/swatch-picker.js';
31
34
  import '../components/tile-radio.js';
32
35
  import '../components/icon-picker.js';
@@ -34,11 +37,7 @@ import '../components/dialog-frame.js';
34
37
  import '../components/modal.js';
35
38
  import '../hooks/use-search-param-state.js';
36
39
  import '../components/measured-grid.js';
37
- import '../feedback-attachment-WFiXJ8We.js';
38
- import '../feedback/feedback-thread.js';
39
- import '../feedback/feedback-inbox.js';
40
40
  import '../components/account-settings-labels.js';
41
- import '../components/confirm-dialog.js';
42
41
  import '../components/floating-panel.js';
43
42
  import '../components/bulk-action-bar.js';
44
43
  import '../components/list.js';
@@ -57,14 +56,20 @@ import '../components/write-lock.js';
57
56
  import '../components/legal.js';
58
57
  import '../components/account-chips.js';
59
58
  import '../lib/format.js';
60
- import '../data-table-3mi2R3so.js';
61
- import '../components/data-table-sort.js';
62
- import '../components/swipeable-row.js';
63
59
  import '../components/reauth-dialog.js';
64
60
  import '../components/server-wake.js';
65
61
  import '../lib/server-wake.js';
66
62
  import '../components/translation-review-labels.js';
67
63
  import '../lib/translation-review.js';
64
+ import '../components/country-select.js';
65
+ import '../components/inline-edit-field.js';
66
+ import '../lib/iban.js';
67
+ import '../lib/phone.js';
68
+ import '../components/sign-chip.js';
69
+ import '../components/column-mapper.js';
70
+ import '../lib/column-mapping.js';
71
+ import '../lib/table-text.js';
72
+ import '../components/field-parts.js';
68
73
 
69
74
  /** The form's `useForm()` return, spread in: `<Form {...form}>`. react-hook-form's own
70
75
  * `FormProvider`, under the name the shadcn file gave it. */
package/dist/rhf.d.ts CHANGED
@@ -1,20 +1,24 @@
1
1
  export { Form, FormControl, FormControlProps, FormDescription, FormDescriptionProps, FormField, FormItem, FormItemProps, FormLabel, FormLabelProps, FormMessage, FormMessageProps, useFormField } from './rhf/form.js';
2
2
  export { RhfWizardStepOptions, useRhfWizardStep } from './rhf/use-rhf-wizard-step.js';
3
- export { RhfCheckbox, RhfCheckboxProps, RhfCombobox, RhfComboboxProps, RhfDateField, RhfDateFieldProps, RhfField, RhfFieldBaseProps, RhfFieldProps, RhfFieldRenderContext, RhfIntegerField, RhfIntegerFieldProps, RhfMoneyField, RhfMoneyFieldProps, RhfNumberField, RhfNumberFieldProps, RhfSelect, RhfSelectOption, RhfSelectProps, RhfTextCombobox, RhfTextComboboxProps, RhfTextField, RhfTextFieldProps, RhfTextarea, RhfTextareaProps } from './rhf/fields.js';
3
+ export { RhfCheckbox, RhfCheckboxProps, RhfCombobox, RhfComboboxProps, RhfCountrySelect, RhfCountrySelectProps, RhfDateField, RhfDateFieldProps, RhfDateRangePicker, RhfDateRangePickerProps, RhfField, RhfFieldBaseProps, RhfFieldProps, RhfFieldRenderContext, RhfIbanInput, RhfIbanInputProps, RhfIntegerField, RhfIntegerFieldProps, RhfMoneyField, RhfMoneyFieldProps, RhfMonthPicker, RhfMonthPickerProps, RhfNumberField, RhfNumberFieldProps, RhfPhoneInput, RhfPhoneInputProps, RhfSelect, RhfSelectOption, RhfSelectProps, RhfTextCombobox, RhfTextComboboxProps, RhfTextField, RhfTextFieldProps, RhfTextarea, RhfTextareaProps, RhfTimeInput, RhfTimeInputProps, RhfToggleGroup, RhfToggleGroupProps } from './rhf/fields.js';
4
4
  export { RhfLineItemCellContext, RhfLineItems, RhfLineItemsColumn, RhfLineItemsProps } from './rhf/line-items.js';
5
5
  import 'react';
6
6
  import 'react-hook-form';
7
- import './kit-labels-D1J2_jyD.js';
8
- import './components/data-table-labels.js';
7
+ import './feedback-BxeQVzwq.js';
8
+ import './feedback-attachment-fGAzZPf0.js';
9
+ import './feedback/feedback-inbox.js';
10
+ import 'lucide-react';
11
+ import './components/tooltip.js';
12
+ import './hooks/use-anchored-rect.js';
13
+ import './lib/clipping.js';
14
+ import './data-table-labels-B7OdnM0S.js';
15
+ import './components/data-table-sort.js';
16
+ import './components/swipeable-row.js';
9
17
  import './components/mini-calendar.js';
10
18
  import './components/calendar-heatmap.js';
11
19
  import './components/popover.js';
12
20
  import './components/chip.js';
13
- import 'lucide-react';
14
21
  import './components/field-sync.js';
15
- import './components/tooltip.js';
16
- import './hooks/use-anchored-rect.js';
17
- import './lib/clipping.js';
18
22
  import './wizard/types.js';
19
23
  import './tour/tour.js';
20
24
  import './search/command-palette.js';
@@ -28,7 +32,6 @@ import './components/sparkline.js';
28
32
  import './components/stat-tile.js';
29
33
  import './components/signature-pad.js';
30
34
  import './components/password-strength.js';
31
- import './components/danger-confirm.js';
32
35
  import './components/swatch-picker.js';
33
36
  import './components/tile-radio.js';
34
37
  import './components/icon-picker.js';
@@ -36,11 +39,7 @@ import './components/dialog-frame.js';
36
39
  import './components/modal.js';
37
40
  import './hooks/use-search-param-state.js';
38
41
  import './components/measured-grid.js';
39
- import './feedback-attachment-WFiXJ8We.js';
40
- import './feedback/feedback-thread.js';
41
- import './feedback/feedback-inbox.js';
42
42
  import './components/account-settings-labels.js';
43
- import './components/confirm-dialog.js';
44
43
  import './components/floating-panel.js';
45
44
  import './components/bulk-action-bar.js';
46
45
  import './components/list.js';
@@ -59,19 +58,27 @@ import './components/write-lock.js';
59
58
  import './components/legal.js';
60
59
  import './components/account-chips.js';
61
60
  import './lib/format.js';
62
- import './data-table-3mi2R3so.js';
63
- import './components/data-table-sort.js';
64
- import './components/swipeable-row.js';
65
61
  import './components/reauth-dialog.js';
66
62
  import './components/server-wake.js';
67
63
  import './lib/server-wake.js';
68
64
  import './components/translation-review-labels.js';
69
65
  import './lib/translation-review.js';
66
+ import './components/country-select.js';
67
+ import './components/inline-edit-field.js';
68
+ import './lib/iban.js';
69
+ import './lib/phone.js';
70
+ import './components/sign-chip.js';
71
+ import './components/column-mapper.js';
72
+ import './lib/column-mapping.js';
73
+ import './lib/table-text.js';
74
+ import './components/field-parts.js';
70
75
  import './components/number-field.js';
71
76
  import './components/number-input.js';
72
77
  import './components/calculator.js';
73
78
  import './components/numpad-sheet.js';
74
79
  import './components/date-picker.js';
80
+ import './components/time-input.js';
81
+ import './components/toggle-group.js';
75
82
  import './components/checkbox.js';
76
83
  import './components/entity-combobox.js';
77
84
  import './components/combobox-core.js';
package/dist/rhf.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/rhf.ts"],"sourcesContent":["// `@eifi1/ui-kit/rhf` — the react-hook-form adapter: Form, FormField, FormItem,\n// FormLabel, FormControl, FormDescription, FormMessage and useFormField.\n//\n// The only entry point in the package that requires `react-hook-form`, and an optional\n// peer for that reason: an app without a form library installs nothing for it. NOT\n// re-exported from the main barrel, which would make the peer everyone's — the reason\n// the barrel dropped its last react-hook-form import (see the wizard section of\n// src/index.ts). The packaging contract test holds that line.\nexport * from \"./rhf/form\";\n// The react-hook-form bridge to the wizard's Next gate (useWizard lives in /wizard).\nexport * from \"./rhf/use-rhf-wizard-step\";\n// Bound fields — one line per field (RhfTextField, RhfNumberField, RhfIntegerField, RhfMoneyField,\n// RhfDateField, RhfTextarea, RhfSelect, RhfCheckbox, RhfCombobox, RhfTextCombobox)\n// and RhfField, the shell they are built on.\nexport * from \"./rhf/fields\";\n// LineItems over useFieldArray.\nexport * from \"./rhf/line-items\";\n"],"mappings":";AAQA,cAAc;AAEd,cAAc;AAId,cAAc;AAEd,cAAc;","names":[]}
1
+ {"version":3,"sources":["../src/rhf.ts"],"sourcesContent":["// `@eifi1/ui-kit/rhf` — the react-hook-form adapter: Form, FormField, FormItem,\n// FormLabel, FormControl, FormDescription, FormMessage and useFormField.\n//\n// The only entry point in the package that requires `react-hook-form`, and an optional\n// peer for that reason: an app without a form library installs nothing for it. NOT\n// re-exported from the main barrel, which would make the peer everyone's — the reason\n// the barrel dropped its last react-hook-form import (see the wizard section of\n// src/index.ts). The packaging contract test holds that line.\nexport * from \"./rhf/form\";\n// The react-hook-form bridge to the wizard's Next gate (useWizard lives in /wizard).\nexport * from \"./rhf/use-rhf-wizard-step\";\n// Bound fields — one line per field (RhfTextField, RhfNumberField, RhfIntegerField, RhfMoneyField,\n// RhfDateField, RhfTextarea, RhfSelect, RhfCheckbox, RhfCombobox, RhfTextCombobox; 0.22: RhfTimeInput,\n// RhfDateRangePicker, RhfToggleGroup, RhfIbanInput, RhfPhoneInput; 0.23: RhfCountrySelect,\n// RhfMonthPicker)\n// and RhfField, the shell they are built on.\nexport * from \"./rhf/fields\";\n// LineItems over useFieldArray.\nexport * from \"./rhf/line-items\";\n"],"mappings":";AAQA,cAAc;AAEd,cAAc;AAMd,cAAc;AAEd,cAAc;","names":[]}
@@ -1,16 +1,20 @@
1
1
  import * as react from 'react';
2
2
  import { ComponentPropsWithoutRef, ReactNode } from 'react';
3
3
  import { LucideIcon } from 'lucide-react';
4
- import { aF as KitLinkComponent } from '../kit-labels-D1J2_jyD.js';
5
- import '../components/data-table-labels.js';
4
+ import { bi as KitLinkComponent } from '../feedback-BxeQVzwq.js';
5
+ import '../feedback-attachment-fGAzZPf0.js';
6
+ import '../feedback/feedback-inbox.js';
7
+ import '../components/tooltip.js';
8
+ import '../hooks/use-anchored-rect.js';
9
+ import '../lib/clipping.js';
10
+ import '../data-table-labels-B7OdnM0S.js';
11
+ import '../components/data-table-sort.js';
12
+ import '../components/swipeable-row.js';
6
13
  import '../components/mini-calendar.js';
7
14
  import '../components/calendar-heatmap.js';
8
15
  import '../components/popover.js';
9
16
  import '../components/chip.js';
10
17
  import '../components/field-sync.js';
11
- import '../components/tooltip.js';
12
- import '../hooks/use-anchored-rect.js';
13
- import '../lib/clipping.js';
14
18
  import '../wizard/types.js';
15
19
  import '../tour/tour.js';
16
20
  import '../search/command-palette.js';
@@ -24,7 +28,6 @@ import '../components/sparkline.js';
24
28
  import '../components/stat-tile.js';
25
29
  import '../components/signature-pad.js';
26
30
  import '../components/password-strength.js';
27
- import '../components/danger-confirm.js';
28
31
  import '../components/swatch-picker.js';
29
32
  import '../components/tile-radio.js';
30
33
  import '../components/icon-picker.js';
@@ -32,11 +35,7 @@ import '../components/dialog-frame.js';
32
35
  import '../components/modal.js';
33
36
  import '../hooks/use-search-param-state.js';
34
37
  import '../components/measured-grid.js';
35
- import '../feedback-attachment-WFiXJ8We.js';
36
- import '../feedback/feedback-thread.js';
37
- import '../feedback/feedback-inbox.js';
38
38
  import '../components/account-settings-labels.js';
39
- import '../components/confirm-dialog.js';
40
39
  import '../components/floating-panel.js';
41
40
  import '../components/bulk-action-bar.js';
42
41
  import '../components/list.js';
@@ -55,14 +54,20 @@ import '../components/write-lock.js';
55
54
  import '../components/legal.js';
56
55
  import '../components/account-chips.js';
57
56
  import '../lib/format.js';
58
- import '../data-table-3mi2R3so.js';
59
- import '../components/data-table-sort.js';
60
- import '../components/swipeable-row.js';
61
57
  import '../components/reauth-dialog.js';
62
58
  import '../components/server-wake.js';
63
59
  import '../lib/server-wake.js';
64
60
  import '../components/translation-review-labels.js';
65
61
  import '../lib/translation-review.js';
62
+ import '../components/country-select.js';
63
+ import '../components/inline-edit-field.js';
64
+ import '../lib/iban.js';
65
+ import '../lib/phone.js';
66
+ import '../components/sign-chip.js';
67
+ import '../components/column-mapper.js';
68
+ import '../lib/column-mapping.js';
69
+ import '../lib/table-text.js';
70
+ import '../components/field-parts.js';
66
71
 
67
72
  interface AppShellSubItem {
68
73
  to: string;