@eifi1/ui-kit 0.21.0 → 0.22.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 (278) hide show
  1. package/dist/chart.d.ts +10 -8
  2. package/dist/components/account-chips.d.ts +10 -3
  3. package/dist/components/account-chips.js +5 -2
  4. package/dist/components/account-chips.js.map +1 -1
  5. package/dist/components/account-settings.d.ts +33 -2
  6. package/dist/components/account-settings.js +43 -21
  7. package/dist/components/account-settings.js.map +1 -1
  8. package/dist/components/amount-input.d.ts +27 -8
  9. package/dist/components/amount-input.js +15 -28
  10. package/dist/components/amount-input.js.map +1 -1
  11. package/dist/components/autocomplete.d.ts +8 -0
  12. package/dist/components/autocomplete.js +9 -4
  13. package/dist/components/autocomplete.js.map +1 -1
  14. package/dist/components/button-group.d.ts +10 -8
  15. package/dist/components/calculator.d.ts +10 -8
  16. package/dist/components/checkbox-group.d.ts +104 -0
  17. package/dist/components/checkbox-group.js +111 -0
  18. package/dist/components/checkbox-group.js.map +1 -0
  19. package/dist/components/checkbox.d.ts +19 -0
  20. package/dist/components/checkbox.js +30 -7
  21. package/dist/components/checkbox.js.map +1 -1
  22. package/dist/components/chip.d.ts +18 -0
  23. package/dist/components/chip.js +47 -10
  24. package/dist/components/chip.js.map +1 -1
  25. package/dist/components/combobox.d.ts +13 -2
  26. package/dist/components/combobox.js +17 -8
  27. package/dist/components/combobox.js.map +1 -1
  28. package/dist/components/confirm-dialog.d.ts +66 -161
  29. package/dist/components/copy-button.d.ts +10 -8
  30. package/dist/components/country-select.d.ts +124 -0
  31. package/dist/components/country-select.js +237 -0
  32. package/dist/components/country-select.js.map +1 -0
  33. package/dist/components/currency-select.d.ts +17 -1
  34. package/dist/components/currency-select.js +56 -23
  35. package/dist/components/currency-select.js.map +1 -1
  36. package/dist/components/danger-confirm.d.ts +66 -166
  37. package/dist/components/danger-confirm.js +133 -49
  38. package/dist/components/danger-confirm.js.map +1 -1
  39. package/dist/components/data-table-cells.d.ts +1 -2
  40. package/dist/components/data-table-filter-popover.d.ts +1 -2
  41. package/dist/components/data-table-filters.d.ts +1 -2
  42. package/dist/components/data-table-labels.d.ts +4 -97
  43. package/dist/components/data-table-labels.js +9 -1
  44. package/dist/components/data-table-labels.js.map +1 -1
  45. package/dist/components/data-table-pagination.d.ts +3 -1
  46. package/dist/components/data-table.d.ts +1 -2
  47. package/dist/components/data-table.js +98 -3
  48. package/dist/components/data-table.js.map +1 -1
  49. package/dist/components/date-picker.d.ts +25 -5
  50. package/dist/components/date-picker.js +110 -59
  51. package/dist/components/date-picker.js.map +1 -1
  52. package/dist/components/entity-combobox.d.ts +8 -1
  53. package/dist/components/entity-combobox.js +9 -4
  54. package/dist/components/entity-combobox.js.map +1 -1
  55. package/dist/components/facing-pair.d.ts +10 -8
  56. package/dist/components/field-anatomy.d.ts +95 -0
  57. package/dist/components/field-anatomy.js +84 -0
  58. package/dist/components/field-anatomy.js.map +1 -0
  59. package/dist/components/field-parts.d.ts +114 -0
  60. package/dist/components/field-parts.js +72 -0
  61. package/dist/components/field-parts.js.map +1 -0
  62. package/dist/components/file-button.d.ts +10 -8
  63. package/dist/components/file-button.js +13 -3
  64. package/dist/components/file-button.js.map +1 -1
  65. package/dist/components/file-dropzone.d.ts +32 -9
  66. package/dist/components/file-dropzone.js +57 -34
  67. package/dist/components/file-dropzone.js.map +1 -1
  68. package/dist/components/form-actions.d.ts +10 -8
  69. package/dist/components/form-actions.js +61 -3
  70. package/dist/components/form-actions.js.map +1 -1
  71. package/dist/components/iban-input.d.ts +66 -0
  72. package/dist/components/iban-input.js +125 -0
  73. package/dist/components/iban-input.js.map +1 -0
  74. package/dist/components/icon-picker.d.ts +12 -2
  75. package/dist/components/icon-picker.js +9 -2
  76. package/dist/components/icon-picker.js.map +1 -1
  77. package/dist/components/inline-edit-field.d.ts +167 -0
  78. package/dist/components/inline-edit-field.js +293 -0
  79. package/dist/components/inline-edit-field.js.map +1 -0
  80. package/dist/components/language-select.d.ts +127 -0
  81. package/dist/components/language-select.js +18 -0
  82. package/dist/components/language-select.js.map +1 -0
  83. package/dist/components/line-items.d.ts +25 -3
  84. package/dist/components/line-items.js +55 -46
  85. package/dist/components/line-items.js.map +1 -1
  86. package/dist/components/list.d.ts +25 -0
  87. package/dist/components/list.js +16 -5
  88. package/dist/components/list.js.map +1 -1
  89. package/dist/components/money-field.d.ts +20 -8
  90. package/dist/components/money-field.js.map +1 -1
  91. package/dist/components/month-picker.d.ts +52 -4
  92. package/dist/components/month-picker.js +290 -86
  93. package/dist/components/month-picker.js.map +1 -1
  94. package/dist/components/multi-select.d.ts +8 -1
  95. package/dist/components/multi-select.js +9 -4
  96. package/dist/components/multi-select.js.map +1 -1
  97. package/dist/components/number-field.d.ts +25 -13
  98. package/dist/components/number-field.js +6 -20
  99. package/dist/components/number-field.js.map +1 -1
  100. package/dist/components/number-input.d.ts +70 -13
  101. package/dist/components/number-input.js +90 -38
  102. package/dist/components/number-input.js.map +1 -1
  103. package/dist/components/numpad-sheet.d.ts +10 -8
  104. package/dist/components/one-time-code-input.d.ts +100 -0
  105. package/dist/components/one-time-code-input.js +137 -0
  106. package/dist/components/one-time-code-input.js.map +1 -0
  107. package/dist/components/phone-input.d.ts +66 -0
  108. package/dist/components/phone-input.js +171 -0
  109. package/dist/components/phone-input.js.map +1 -0
  110. package/dist/components/series-chart.d.ts +10 -8
  111. package/dist/components/settings-fields.d.ts +10 -8
  112. package/dist/components/share-card.d.ts +8 -6
  113. package/dist/components/sign-chip.d.ts +66 -0
  114. package/dist/components/sign-chip.js +39 -0
  115. package/dist/components/sign-chip.js.map +1 -0
  116. package/dist/components/swatch-picker.d.ts +27 -2
  117. package/dist/components/swatch-picker.js +73 -31
  118. package/dist/components/swatch-picker.js.map +1 -1
  119. package/dist/components/switch.d.ts +19 -0
  120. package/dist/components/switch.js +24 -6
  121. package/dist/components/switch.js.map +1 -1
  122. package/dist/components/text-link.d.ts +10 -8
  123. package/dist/components/tile-radio.d.ts +68 -13
  124. package/dist/components/tile-radio.js +3 -3
  125. package/dist/components/tile-radio.js.map +1 -1
  126. package/dist/components/time-input.d.ts +15 -9
  127. package/dist/components/time-input.js.map +1 -1
  128. package/dist/components/toggle-group.d.ts +47 -1
  129. package/dist/components/toggle-group.js +110 -69
  130. package/dist/components/toggle-group.js.map +1 -1
  131. package/dist/components/ui.d.ts +10 -8
  132. package/dist/components/ui.js +280 -78
  133. package/dist/components/ui.js.map +1 -1
  134. package/dist/components/use-table-state.d.ts +1 -2
  135. package/dist/{data-table-3mi2R3so.d.ts → data-table-labels-B7OdnM0S.d.ts} +140 -3
  136. package/dist/data-table.d.ts +1 -2
  137. package/dist/data-table.js +2 -1
  138. package/dist/data-table.js.map +1 -1
  139. package/dist/feedback/feedback-attachment.d.ts +1 -1
  140. package/dist/feedback/feedback-attachment.js +210 -3
  141. package/dist/feedback/feedback-attachment.js.map +1 -1
  142. package/dist/feedback/feedback-dialog.d.ts +1 -1
  143. package/dist/feedback/feedback-dialog.js.map +1 -1
  144. package/dist/feedback/feedback-inbox.d.ts +1 -1
  145. package/dist/feedback/feedback-thread.d.ts +37 -3
  146. package/dist/feedback/feedback-thread.js +38 -9
  147. package/dist/feedback/feedback-thread.js.map +1 -1
  148. package/dist/{feedback-attachment-WFiXJ8We.d.ts → feedback-attachment-NhUm7Zga.d.ts} +70 -5
  149. package/dist/feedback.d.ts +2 -2
  150. package/dist/hooks/use-file-drop.d.ts +10 -8
  151. package/dist/i18n/defaults.d.ts +10 -8
  152. package/dist/i18n/defaults.js +17 -2
  153. package/dist/i18n/defaults.js.map +1 -1
  154. package/dist/i18n/german.d.ts +10 -8
  155. package/dist/i18n/german.js +50 -5
  156. package/dist/i18n/german.js.map +1 -1
  157. package/dist/i18n/kit-labels.d.ts +10 -8
  158. package/dist/i18n/kit-labels.js +8 -2
  159. package/dist/i18n/kit-labels.js.map +1 -1
  160. package/dist/i18n/languages.d.ts +10 -8
  161. package/dist/i18n/locales/de-CH.d.ts +10 -8
  162. package/dist/i18n/locales/en.d.ts +10 -8
  163. package/dist/i18n/locales/en.js +9 -0
  164. package/dist/i18n/locales/en.js.map +1 -1
  165. package/dist/i18n/locales/es.d.ts +10 -8
  166. package/dist/i18n/locales/es.js +48 -5
  167. package/dist/i18n/locales/es.js.map +1 -1
  168. package/dist/i18n/locales/fr.d.ts +10 -8
  169. package/dist/i18n/locales/fr.js +48 -5
  170. package/dist/i18n/locales/fr.js.map +1 -1
  171. package/dist/i18n/locales/hu.d.ts +10 -8
  172. package/dist/i18n/locales/hu.js +49 -5
  173. package/dist/i18n/locales/hu.js.map +1 -1
  174. package/dist/i18n/locales/it.d.ts +10 -8
  175. package/dist/i18n/locales/it.js +49 -5
  176. package/dist/i18n/locales/it.js.map +1 -1
  177. package/dist/i18n/locales/zh.d.ts +10 -8
  178. package/dist/i18n/locales/zh.js +48 -5
  179. package/dist/i18n/locales/zh.js.map +1 -1
  180. package/dist/i18n/review.d.ts +10 -8
  181. package/dist/i18n/review.js +8 -1
  182. package/dist/i18n/review.js.map +1 -1
  183. package/dist/index.d.ts +17 -10
  184. package/dist/index.js +57 -2
  185. package/dist/index.js.map +1 -1
  186. package/dist/{kit-labels-D1J2_jyD.d.ts → kit-labels-R8mIAc9N.d.ts} +811 -8
  187. package/dist/lib/countries.d.ts +43 -0
  188. package/dist/lib/countries.js +39 -0
  189. package/dist/lib/countries.js.map +1 -0
  190. package/dist/lib/decimal-marks.d.ts +46 -0
  191. package/dist/lib/decimal-marks.js +40 -0
  192. package/dist/lib/decimal-marks.js.map +1 -0
  193. package/dist/lib/iban.d.ts +98 -0
  194. package/dist/lib/iban.js +154 -0
  195. package/dist/lib/iban.js.map +1 -0
  196. package/dist/lib/isin.d.ts +30 -0
  197. package/dist/lib/isin.js +36 -0
  198. package/dist/lib/isin.js.map +1 -0
  199. package/dist/lib/phone.d.ts +69 -0
  200. package/dist/lib/phone.js +121 -0
  201. package/dist/lib/phone.js.map +1 -0
  202. package/dist/rhf/fields.d.ts +148 -11
  203. package/dist/rhf/fields.js +332 -3
  204. package/dist/rhf/fields.js.map +1 -1
  205. package/dist/rhf/form.d.ts +10 -8
  206. package/dist/rhf.d.ts +13 -9
  207. package/dist/rhf.js.map +1 -1
  208. package/dist/shell/app-shell.d.ts +10 -8
  209. package/dist/shell/top-bar-brand.d.ts +10 -8
  210. package/dist/shell.d.ts +10 -8
  211. package/dist/tour/tour.js +20 -24
  212. package/dist/tour/tour.js.map +1 -1
  213. package/dist/wizard/stepper-nav.d.ts +10 -8
  214. package/dist/wizard.d.ts +10 -8
  215. package/package.json +1 -1
  216. package/src/components/account-chips.tsx +17 -3
  217. package/src/components/account-settings.tsx +92 -26
  218. package/src/components/amount-input.tsx +49 -56
  219. package/src/components/autocomplete.tsx +133 -110
  220. package/src/components/checkbox-group.tsx +229 -0
  221. package/src/components/checkbox.tsx +72 -8
  222. package/src/components/chip.tsx +80 -10
  223. package/src/components/combobox.tsx +292 -253
  224. package/src/components/country-select.tsx +443 -0
  225. package/src/components/currency-select.tsx +109 -33
  226. package/src/components/danger-confirm.tsx +345 -77
  227. package/src/components/data-table-labels.ts +16 -1
  228. package/src/components/data-table.tsx +175 -6
  229. package/src/components/date-picker.tsx +173 -62
  230. package/src/components/entity-combobox.tsx +107 -87
  231. package/src/components/field-anatomy.tsx +190 -0
  232. package/src/components/field-parts.tsx +184 -0
  233. package/src/components/file-button.tsx +36 -3
  234. package/src/components/file-dropzone.tsx +106 -38
  235. package/src/components/form-actions.tsx +115 -2
  236. package/src/components/iban-input.tsx +231 -0
  237. package/src/components/icon-picker.tsx +26 -4
  238. package/src/components/inline-edit-field.tsx +533 -0
  239. package/src/components/language-select.tsx +78 -0
  240. package/src/components/line-items.tsx +35 -2
  241. package/src/components/list.tsx +55 -6
  242. package/src/components/money-field.tsx +10 -0
  243. package/src/components/month-picker.tsx +399 -63
  244. package/src/components/multi-select.tsx +80 -58
  245. package/src/components/number-field.tsx +28 -46
  246. package/src/components/number-input.tsx +210 -43
  247. package/src/components/one-time-code-input.tsx +288 -0
  248. package/src/components/phone-input.tsx +299 -0
  249. package/src/components/sign-chip.tsx +103 -0
  250. package/src/components/swatch-picker.tsx +118 -30
  251. package/src/components/switch.tsx +58 -7
  252. package/src/components/tile-radio.tsx +71 -16
  253. package/src/components/time-input.tsx +8 -1
  254. package/src/components/toggle-group.tsx +206 -73
  255. package/src/components/ui.tsx +472 -105
  256. package/src/data-table.ts +2 -1
  257. package/src/feedback/feedback-attachment.tsx +313 -9
  258. package/src/feedback/feedback-dialog.tsx +2 -0
  259. package/src/feedback/feedback-thread.tsx +66 -5
  260. package/src/i18n/defaults.ts +16 -1
  261. package/src/i18n/german.ts +47 -0
  262. package/src/i18n/kit-labels.tsx +78 -2
  263. package/src/i18n/locales/en.ts +10 -0
  264. package/src/i18n/locales/es.ts +46 -0
  265. package/src/i18n/locales/fr.ts +45 -0
  266. package/src/i18n/locales/hu.ts +46 -0
  267. package/src/i18n/locales/it.ts +47 -0
  268. package/src/i18n/locales/zh.ts +44 -0
  269. package/src/i18n/review.ts +7 -0
  270. package/src/index.ts +53 -3
  271. package/src/lib/countries.ts +91 -0
  272. package/src/lib/decimal-marks.ts +99 -0
  273. package/src/lib/iban.ts +171 -0
  274. package/src/lib/isin.ts +62 -0
  275. package/src/lib/phone.ts +211 -0
  276. package/src/rhf/fields.tsx +606 -9
  277. package/src/rhf.ts +2 -1
  278. package/src/tour/tour.tsx +66 -28
@@ -0,0 +1,121 @@
1
+ "use client";
2
+ function cut(nsn, sizes) {
3
+ const out = [];
4
+ let at = 0;
5
+ for (const size of sizes) {
6
+ if (at >= nsn.length) break;
7
+ out.push(nsn.slice(at, at + size));
8
+ at += size;
9
+ }
10
+ if (at < nsn.length) out.push(nsn.slice(at));
11
+ return out;
12
+ }
13
+ const RULES = {
14
+ // 9 digits, 2-3-2-2 ("21 000 00 01"); the 08xx/09xx service numbers 3-3-3.
15
+ CH: {
16
+ dial: "41",
17
+ trunk: true,
18
+ min: 9,
19
+ max: 9,
20
+ group: (n) => /^[89]/.test(n) ? cut(n, [3, 3, 3]) : cut(n, [2, 3, 2, 2])
21
+ },
22
+ // 7 digits, 3-2-2 ("100 00 01"), and 9 for some mobile ranges (3-3-3). No trunk prefix.
23
+ LI: {
24
+ dial: "423",
25
+ trunk: false,
26
+ min: 7,
27
+ max: 9,
28
+ group: (n) => n.length === 7 ? cut(n, [3, 2, 2]) : n.length === 9 ? cut(n, [3, 3, 3]) : [n]
29
+ },
30
+ // Area codes of two to five digits: only the mobile prefixes and the four
31
+ // two-digit cities are split; anything else is one block rather than a wrong split.
32
+ DE: {
33
+ dial: "49",
34
+ trunk: true,
35
+ min: 6,
36
+ max: 13,
37
+ group: (n) => /^15/.test(n) ? cut(n, [4]) : /^1[67]/.test(n) ? cut(n, [3]) : /^(30|40|69|89)/.test(n) ? cut(n, [2]) : [n]
38
+ },
39
+ // Vienna is "1"; mobile numbers start 6xx; other area codes vary, so one block.
40
+ AT: {
41
+ dial: "43",
42
+ trunk: true,
43
+ min: 6,
44
+ max: 13,
45
+ group: (n) => /^6/.test(n) ? cut(n, [3]) : /^1/.test(n) ? cut(n, [1]) : [n]
46
+ },
47
+ // 9 digits, 1-2-2-2-2 ("1 99 00 00 01").
48
+ FR: { dial: "33", trunk: true, min: 9, max: 9, group: (n) => cut(n, [1, 2, 2, 2, 2]) },
49
+ // The 0 of a fixed line is part of the number ("+39 06 …"); mobiles start with 3.
50
+ IT: {
51
+ dial: "39",
52
+ trunk: false,
53
+ zeroStart: true,
54
+ min: 6,
55
+ max: 11,
56
+ group: (n) => /^3/.test(n) ? cut(n, [3, 3]) : /^0[26]/.test(n) ? cut(n, [2, 4]) : [n]
57
+ }
58
+ };
59
+ const PHONE_DIAL_CODES = Object.freeze({
60
+ CH: RULES.CH.dial,
61
+ LI: RULES.LI.dial,
62
+ DE: RULES.DE.dial,
63
+ AT: RULES.AT.dial,
64
+ FR: RULES.FR.dial,
65
+ IT: RULES.IT.dial
66
+ });
67
+ const PHONE_COUNTRIES = Object.freeze(["CH", "LI", "DE", "AT", "FR", "IT"]);
68
+ const BY_DIAL = [...PHONE_COUNTRIES].sort((a, b) => RULES[b].dial.length - RULES[a].dial.length);
69
+ function national(digits, rule) {
70
+ const nsn = rule.trunk && digits.startsWith("0") ? digits.slice(1) : digits;
71
+ if (nsn.startsWith("0") && !rule.zeroStart) return null;
72
+ if (nsn.length < rule.min || nsn.length > rule.max) return null;
73
+ return nsn;
74
+ }
75
+ function parsePhone(input, country = "CH") {
76
+ const text = input.trim();
77
+ if (text === "" || !/^\+?[\d\s().\-/]+$/.test(text)) return null;
78
+ let digits = text.replace(/\D/g, "");
79
+ let international = text.startsWith("+");
80
+ if (!international && digits.startsWith("00")) {
81
+ international = true;
82
+ digits = digits.slice(2);
83
+ }
84
+ if (international) {
85
+ digits = text.replace(/\(\s*0\s*\)/g, "").replace(/\D/g, "").replace(/^00/, "");
86
+ if (digits.startsWith("0")) return null;
87
+ const known = BY_DIAL.find((c) => digits.startsWith(RULES[c].dial));
88
+ if (known) {
89
+ const rule2 = RULES[known];
90
+ const nsn2 = national(digits.slice(rule2.dial.length), rule2);
91
+ return nsn2 === null ? null : { e164: `+${rule2.dial}${nsn2}`, country: known, national: nsn2 };
92
+ }
93
+ if (digits.length < 8 || digits.length > 15) return null;
94
+ return { e164: `+${digits}`, country: null, national: digits };
95
+ }
96
+ if (country === "other") return null;
97
+ const rule = RULES[country];
98
+ const nsn = national(digits, rule);
99
+ return nsn === null ? null : { e164: `+${rule.dial}${nsn}`, country, national: nsn };
100
+ }
101
+ function formatNationalPhone(nsn, country) {
102
+ return RULES[country].group(nsn).join(" ");
103
+ }
104
+ function formatPhone(value) {
105
+ const parsed = value.trim().startsWith("+") ? parsePhone(value, "other") : null;
106
+ if (!parsed) return value;
107
+ if (!parsed.country) return parsed.e164;
108
+ return `+${RULES[parsed.country].dial} ${formatNationalPhone(parsed.national, parsed.country)}`;
109
+ }
110
+ function isE164(value) {
111
+ return /^\+[1-9]\d{7,14}$/.test(value);
112
+ }
113
+ export {
114
+ PHONE_COUNTRIES,
115
+ PHONE_DIAL_CODES,
116
+ formatNationalPhone,
117
+ formatPhone,
118
+ isE164,
119
+ parsePhone
120
+ };
121
+ //# sourceMappingURL=phone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/phone.ts"],"sourcesContent":["/**\n * Phone numbers — E.164 in, grouped out — for kastlan's contacts, without a\n * libphonenumber dependency.\n *\n * kastlan stored whatever was typed (\"079 …\", \"+41 (0)79 …\", \"0041 79 …\") and could\n * neither dial nor de-duplicate it. What it needs is one canonical form to store —\n * E.164, \"+41210000001\" — and a readable one to show. libphonenumber gets both right\n * for every country, at ~150 kB of metadata in every app's bundle; the kit's apps are\n * Swiss and their neighbours, so this is **light per-country rules** for the six that\n * matter and a generic shape check for the rest:\n *\n * - **CH, LI, DE, AT, FR, IT**: the national trunk prefix is dropped (a leading 0 —\n * but NOT for Italy, whose fixed-line numbers keep their 0 after +39, and not for\n * Liechtenstein, which has none), and the remaining national number has to be a\n * plausible length for the country.\n * - **Anything else** typed with its own \"+\" (or \"00\"): the digits, 8 to 15 in all,\n * are taken as an E.164 number as they stand.\n *\n * **The limitation:** a plausible length is not a valid number. There is no check of\n * area codes or number ranges, so a well-formed number that does not exist passes, and\n * a German or Austrian number (whose area codes run from one to five digits) is\n * grouped only where the split is known (mobile prefixes, the largest cities) and\n * otherwise shown in one block. A number these rules cannot read is not an error —\n * {@link parsePhone} returns `null` and the field keeps the text as typed.\n */\n\n/** The countries with their own rules. */\nexport type PhoneCountryCode = \"CH\" | \"LI\" | \"DE\" | \"AT\" | \"FR\" | \"IT\";\n\n/** A country with rules, or `\"other\"`: a number typed with its own \"+\". */\nexport type PhoneCountry = PhoneCountryCode | \"other\";\n\ninterface CountryRule {\n /** The country calling code, without the \"+\". */\n dial: string;\n /** A national number starts with a trunk 0 that is dropped after the country code. */\n trunk: boolean;\n /** The national significant number itself may start with 0 (Italy's fixed lines). */\n zeroStart?: boolean;\n /** The national significant number's length, inclusive. */\n min: number;\n max: number;\n /** Groups for display, given the national significant number. */\n group: (nsn: string) => string[];\n}\n\n/** `nsn` cut into the given sizes; whatever is left is one last group. */\nfunction cut(nsn: string, sizes: number[]): string[] {\n const out: string[] = [];\n let at = 0;\n for (const size of sizes) {\n if (at >= nsn.length) break;\n out.push(nsn.slice(at, at + size));\n at += size;\n }\n if (at < nsn.length) out.push(nsn.slice(at));\n return out;\n}\n\nconst RULES: Record<PhoneCountryCode, CountryRule> = {\n // 9 digits, 2-3-2-2 (\"21 000 00 01\"); the 08xx/09xx service numbers 3-3-3.\n CH: {\n dial: \"41\",\n trunk: true,\n min: 9,\n max: 9,\n group: (n) => (/^[89]/.test(n) ? cut(n, [3, 3, 3]) : cut(n, [2, 3, 2, 2])),\n },\n // 7 digits, 3-2-2 (\"100 00 01\"), and 9 for some mobile ranges (3-3-3). No trunk prefix.\n LI: {\n dial: \"423\",\n trunk: false,\n min: 7,\n max: 9,\n group: (n) => (n.length === 7 ? cut(n, [3, 2, 2]) : n.length === 9 ? cut(n, [3, 3, 3]) : [n]),\n },\n // Area codes of two to five digits: only the mobile prefixes and the four\n // two-digit cities are split; anything else is one block rather than a wrong split.\n DE: {\n dial: \"49\",\n trunk: true,\n min: 6,\n max: 13,\n group: (n) =>\n /^15/.test(n)\n ? cut(n, [4])\n : /^1[67]/.test(n)\n ? cut(n, [3])\n : /^(30|40|69|89)/.test(n)\n ? cut(n, [2])\n : [n],\n },\n // Vienna is \"1\"; mobile numbers start 6xx; other area codes vary, so one block.\n AT: {\n dial: \"43\",\n trunk: true,\n min: 6,\n max: 13,\n group: (n) => (/^6/.test(n) ? cut(n, [3]) : /^1/.test(n) ? cut(n, [1]) : [n]),\n },\n // 9 digits, 1-2-2-2-2 (\"1 99 00 00 01\").\n FR: { dial: \"33\", trunk: true, min: 9, max: 9, group: (n) => cut(n, [1, 2, 2, 2, 2]) },\n // The 0 of a fixed line is part of the number (\"+39 06 …\"); mobiles start with 3.\n IT: {\n dial: \"39\",\n trunk: false,\n zeroStart: true,\n min: 6,\n max: 11,\n group: (n) => (/^3/.test(n) ? cut(n, [3, 3]) : /^0[26]/.test(n) ? cut(n, [2, 4]) : [n]),\n },\n};\n\n/** The country calling codes with rules, \"+\" left off: `{ CH: \"41\", … }`. */\nexport const PHONE_DIAL_CODES: Readonly<Record<PhoneCountryCode, string>> = Object.freeze({\n CH: RULES.CH.dial,\n LI: RULES.LI.dial,\n DE: RULES.DE.dial,\n AT: RULES.AT.dial,\n FR: RULES.FR.dial,\n IT: RULES.IT.dial,\n});\n\n/** The countries with rules, in the order a picker offers them by default. */\nexport const PHONE_COUNTRIES: readonly PhoneCountryCode[] = Object.freeze([\"CH\", \"LI\", \"DE\", \"AT\", \"FR\", \"IT\"]);\n\n/** Longest dial code first, so \"+423\" is Liechtenstein before anything shorter. */\nconst BY_DIAL = [...PHONE_COUNTRIES].sort((a, b) => RULES[b].dial.length - RULES[a].dial.length);\n\n/** What {@link parsePhone} reads out of a number. */\nexport interface ParsedPhone {\n /** The number in E.164: \"+\", the country code, the national number. */\n e164: string;\n /** The country whose rules read it, or `null` for a generic \"+…\" number. */\n country: PhoneCountryCode | null;\n /** The national significant number — the digits after the country code. For a\n * generic number, every digit after the \"+\" (the country code is not split off). */\n national: string;\n}\n\n/** A national significant number that passes `rule`, or `null`. */\nfunction national(digits: string, rule: CountryRule): string | null {\n const nsn = rule.trunk && digits.startsWith(\"0\") ? digits.slice(1) : digits;\n // A national number starts with 0 only where 0 is part of it (Italy's fixed lines).\n if (nsn.startsWith(\"0\") && !rule.zeroStart) return null;\n if (nsn.length < rule.min || nsn.length > rule.max) return null;\n return nsn;\n}\n\n/**\n * Read a typed number. With a leading \"+\" or \"00\" the number carries its own country\n * code — one of the six with rules, or any other (8–15 digits in all, the E.164\n * limit). Without one it is a national number of `country` (default `\"CH\"`), its\n * trunk 0 optional; with `country=\"other\"` a number without \"+\" cannot be read.\n *\n * Spaces, hyphens, dots, slashes and parentheses are ignored (\"(030) 1234567\"), and\n * so is the \"(0)\" of \"+41 (0)21 …\". Anything else — a letter, an extension (\"ext. 12\"), a note —\n * and the result is `null`: the text is not a number these rules can read, and a field\n * keeps it as it is rather than guess.\n */\nexport function parsePhone(input: string, country: PhoneCountry = \"CH\"): ParsedPhone | null {\n const text = input.trim();\n if (text === \"\" || !/^\\+?[\\d\\s().\\-/]+$/.test(text)) return null;\n let digits = text.replace(/\\D/g, \"\");\n let international = text.startsWith(\"+\");\n if (!international && digits.startsWith(\"00\")) {\n international = true;\n digits = digits.slice(2);\n }\n if (international) {\n // \"+41 (0)21 …\": the bracketed trunk prefix written for callers inside the country.\n digits = text.replace(/\\(\\s*0\\s*\\)/g, \"\").replace(/\\D/g, \"\").replace(/^00/, \"\");\n if (digits.startsWith(\"0\")) return null;\n const known = BY_DIAL.find((c) => digits.startsWith(RULES[c].dial));\n if (known) {\n const rule = RULES[known];\n const nsn = national(digits.slice(rule.dial.length), rule);\n return nsn === null ? null : { e164: `+${rule.dial}${nsn}`, country: known, national: nsn };\n }\n if (digits.length < 8 || digits.length > 15) return null;\n return { e164: `+${digits}`, country: null, national: digits };\n }\n if (country === \"other\") return null;\n const rule = RULES[country];\n const nsn = national(digits, rule);\n return nsn === null ? null : { e164: `+${rule.dial}${nsn}`, country, national: nsn };\n}\n\n/** The national number grouped by its country's rules (\"21 000 00 01\"). */\nexport function formatNationalPhone(nsn: string, country: PhoneCountryCode): string {\n return RULES[country].group(nsn).join(\" \");\n}\n\n/**\n * A number for display: an E.164 number (or anything {@link parsePhone} reads with a\n * \"+\") grouped by its country's rules — \"+41 21 000 00 01\" — and a generic one as\n * \"+\" and its digits. Anything it cannot read comes back exactly as it went in, so a\n * list of contacts can format every row without first sorting out the free text.\n */\nexport function formatPhone(value: string): string {\n const parsed = value.trim().startsWith(\"+\") ? parsePhone(value, \"other\") : null;\n if (!parsed) return value;\n if (!parsed.country) return parsed.e164;\n return `+${RULES[parsed.country].dial} ${formatNationalPhone(parsed.national, parsed.country)}`;\n}\n\n/** Whether `value` is in E.164 shape: \"+\" and 8–15 digits, nothing else. Shape only —\n * what {@link PhoneInput} emits for every number it could read. */\nexport function isE164(value: string): boolean {\n return /^\\+[1-9]\\d{7,14}$/.test(value);\n}\n"],"mappings":"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","names":["rule","nsn"]}
@@ -1,14 +1,18 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ReactElement } from 'react';
3
3
  import { FieldValues, FieldPath, ControllerProps, ControllerRenderProps, ControllerFieldState } from 'react-hook-form';
4
- import { aQ as SelectProps, aE as InputProps, b9 as TextareaProps } from '../kit-labels-D1J2_jyD.js';
4
+ import { aR as IbanInputProps, bc as PhoneInputProps, bg as SelectProps, a$ as InputProps, bB as TextareaProps } from '../kit-labels-R8mIAc9N.js';
5
5
  import { NumberFieldProps } from '../components/number-field.js';
6
- import { DatePickerProps } from '../components/date-picker.js';
6
+ import { DatePickerProps, DateRangePickerProps } from '../components/date-picker.js';
7
+ import { TimeInputProps } from '../components/time-input.js';
8
+ import { ToggleGroupBaseProps, ToggleGroupRequiredProps, ToggleGroupClearableProps } from '../components/toggle-group.js';
7
9
  import { CheckboxProps } from '../components/checkbox.js';
8
10
  import { EntityComboboxProps } from '../components/entity-combobox.js';
9
11
  import { ComboboxProps } from '../components/combobox.js';
10
12
  import { ComboClearValue } from '../components/combobox-core.js';
11
- import '../components/data-table-labels.js';
13
+ import '../data-table-labels-B7OdnM0S.js';
14
+ import '../components/data-table-sort.js';
15
+ import '../components/swipeable-row.js';
12
16
  import '../components/mini-calendar.js';
13
17
  import '../components/calendar-heatmap.js';
14
18
  import '../components/popover.js';
@@ -31,7 +35,6 @@ import '../components/sparkline.js';
31
35
  import '../components/stat-tile.js';
32
36
  import '../components/signature-pad.js';
33
37
  import '../components/password-strength.js';
34
- import '../components/danger-confirm.js';
35
38
  import '../components/swatch-picker.js';
36
39
  import '../components/tile-radio.js';
37
40
  import '../components/icon-picker.js';
@@ -39,11 +42,10 @@ import '../components/dialog-frame.js';
39
42
  import '../components/modal.js';
40
43
  import '../hooks/use-search-param-state.js';
41
44
  import '../components/measured-grid.js';
42
- import '../feedback-attachment-WFiXJ8We.js';
45
+ import '../feedback-attachment-NhUm7Zga.js';
43
46
  import '../feedback/feedback-thread.js';
44
47
  import '../feedback/feedback-inbox.js';
45
48
  import '../components/account-settings-labels.js';
46
- import '../components/confirm-dialog.js';
47
49
  import '../components/floating-panel.js';
48
50
  import '../components/bulk-action-bar.js';
49
51
  import '../components/list.js';
@@ -62,14 +64,16 @@ import '../components/write-lock.js';
62
64
  import '../components/legal.js';
63
65
  import '../components/account-chips.js';
64
66
  import '../lib/format.js';
65
- import '../data-table-3mi2R3so.js';
66
- import '../components/data-table-sort.js';
67
- import '../components/swipeable-row.js';
68
67
  import '../components/reauth-dialog.js';
69
68
  import '../components/server-wake.js';
70
69
  import '../lib/server-wake.js';
71
70
  import '../components/translation-review-labels.js';
72
71
  import '../lib/translation-review.js';
72
+ import '../components/country-select.js';
73
+ import '../components/inline-edit-field.js';
74
+ import '../lib/iban.js';
75
+ import '../lib/phone.js';
76
+ import '../components/sign-chip.js';
73
77
  import '../components/number-input.js';
74
78
  import '../components/calculator.js';
75
79
  import '../components/numpad-sheet.js';
@@ -235,7 +239,7 @@ type RhfMoneyFieldProps<TFieldValues extends FieldValues = FieldValues, TName ex
235
239
  * `valueAs`.
236
240
  */
237
241
  declare function RhfMoneyField<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues>({ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className, ...amountProps }: RhfMoneyFieldProps<TFieldValues, TName, TTransformed>): react.JSX.Element;
238
- type RhfDateFieldProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & Omit<DatePickerProps, "value" | "onChange" | "label" | "invalid" | "disabled" | "className" | "id"> & {
242
+ type RhfDateFieldProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & Omit<DatePickerProps, "value" | "onChange" | "label" | "invalid" | "disabled" | "className" | "id" | "error"> & {
239
243
  /** Classes for the picker. Default `w-full`. */
240
244
  inputClassName?: string;
241
245
  /** What a cleared date stores. Default `""`, the empty ISO string; `null` for a
@@ -244,6 +248,97 @@ type RhfDateFieldProps<TFieldValues extends FieldValues = FieldValues, TName ext
244
248
  };
245
249
  /** The kit's {@link DatePicker}, holding an ISO `"YYYY-MM-DD"` string. */
246
250
  declare function RhfDateField<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues>({ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className, inputClassName, emptyValue, ...pickerProps }: RhfDateFieldProps<TFieldValues, TName, TTransformed>): react.JSX.Element;
251
+ type OwnDateRangeProps = Omit<DateRangePickerProps, "from" | "to" | "onChange" | "label" | "invalid" | "disabled" | "className" | "id" | "error">;
252
+ type RhfDateRangePickerProps<TFieldValues extends FieldValues = FieldValues, TFromName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TToName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues> = Omit<RhfFieldBaseProps<TFieldValues, TFromName, TTransformed>, "name" | "rules"> & OwnDateRangeProps & {
253
+ /** The form field holding the range's first day, an ISO `"YYYY-MM-DD"`. */
254
+ fromName: TFromName;
255
+ /** The form field holding the range's last day. */
256
+ toName: TToName;
257
+ /** react-hook-form's `rules` for the start (`required`, a `validate` …). */
258
+ fromRules?: ControllerProps<TFieldValues, TFromName, TTransformed>["rules"];
259
+ /** react-hook-form's `rules` for the end — the place for "not before the start",
260
+ * which can read the start with `getValues`: the start is always written first. */
261
+ toRules?: ControllerProps<TFieldValues, TToName, TTransformed>["rules"];
262
+ /** Classes for the picker. Default `w-full`. */
263
+ inputClassName?: string;
264
+ /** What an empty end stores — a clear, or the half-made range between the first
265
+ * and second click. Default `""`, the empty ISO string; `null` for a nullable
266
+ * schema. */
267
+ emptyValue?: "" | null;
268
+ };
269
+ /**
270
+ * The kit's {@link DateRangePicker} over TWO form fields — `fromName` and `toName` —
271
+ * the way a period is stored: as two columns, each its own schema key, not one
272
+ * `{ from, to }` object (kastlan 4).
273
+ *
274
+ * ```tsx
275
+ * <RhfDateRangePicker fromName="periodFrom" toName="periodTo" label="Billing period"
276
+ * presets={presets} clearable />
277
+ * ```
278
+ *
279
+ * Why it is not {@link RhfField}: a `Controller` binds one name, and the range is
280
+ * two. Built by hand — an `RhfField` on the start and a second `useController` for
281
+ * the end, which is what kastlan's period fields needed — it works until the END is
282
+ * the one in error: the shell's label, message and `aria-invalid` all read the
283
+ * start's state alone, so "End before start" (a `refine` with `path: ["periodTo"]`,
284
+ * where such a rule goes) never shows. Here both states are read:
285
+ *
286
+ * - **Either field's error is shown and paints.** The label turns, the trigger is
287
+ * `aria-invalid` and wears the danger border when EITHER field has an error, and
288
+ * both messages are listed under the field (once, if the two say the same thing),
289
+ * each pointed at by the trigger's `aria-describedby`.
290
+ * - **One change writes both.** The picker reports the range whole, so the start and
291
+ * then the end are written on every change — the end too when only the start
292
+ * moved, so a cross-field rule on the end re-runs and an "End before start" clears
293
+ * the moment the start is fixed. A clear (`clearable`'s ×) empties both.
294
+ * - **Focus on error** lands on the trigger whichever of the two is in error.
295
+ * - **Touched** once a range is complete or cleared — not on the first click of a
296
+ * pick, which would mark (and, with `mode: "onTouched"`, validate) an end the user
297
+ * is still choosing.
298
+ *
299
+ * In `commit="immediate"` mode (the picker's default) the first calendar click is
300
+ * reported on its own, so the form holds `(from, emptyValue)` until the second; with
301
+ * `commit="apply"` nothing reaches the form until Apply.
302
+ *
303
+ * The common props (`label`, `hint`, `required`, `disabled`, `excludeWhenDisabled`,
304
+ * `control`, `className`) apply to the pair; `rules` are per field.
305
+ */
306
+ declare function RhfDateRangePicker<TFieldValues extends FieldValues = FieldValues, TFromName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TToName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues>({ fromName, toName, control, fromRules, toRules, label, hint, required, disabled, excludeWhenDisabled, className, inputClassName, emptyValue, ...pickerProps }: RhfDateRangePickerProps<TFieldValues, TFromName, TToName, TTransformed>): react.JSX.Element;
307
+ type RhfTimeInputProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & Omit<TimeInputProps, "name" | "value" | "defaultValue" | "onChange" | "onValueChange" | "onBlur" | "label" | "error" | "invalid" | "className" | "disabled" | "required"> & {
308
+ /** What a cleared time stores. Default `""`; `null` for a nullable schema. */
309
+ emptyValue?: "" | null;
310
+ };
311
+ /**
312
+ * The kit's {@link TimeInput}: a time of day as `"HH:mm"` (`"HH:mm:ss"` when `step`
313
+ * asks for seconds), normalised before it reaches the form, so the stored value
314
+ * compares and sorts as a string. kastlan 4: the owner meeting's time was an
315
+ * {@link RhfField} with a hand-wired `TimeInput` in its render — `ref`, `name`, the
316
+ * `?? ""`, `onValueChange`, `onBlur`, `invalid` — the seven lines every bound field
317
+ * folds into one.
318
+ *
319
+ * `min` / `max` paint an out-of-window time (see TimeInput) but do not fail the form:
320
+ * validation stays the schema's or `rules`'. `rules={{ validate: (v) =>
321
+ * isTimeInRange(v, min, max) || "…" }}` says it with the same window.
322
+ */
323
+ declare function RhfTimeInput<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues>({ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className, emptyValue, ...timeProps }: RhfTimeInputProps<TFieldValues, TName, TTransformed>): react.JSX.Element;
324
+ type OwnTextishProps<P> = Omit<P, "name" | "value" | "defaultValue" | "onChange" | "onValueChange" | "onBlur" | "label" | "error" | "invalid" | "className" | "disabled" | "required">;
325
+ type RhfIbanInputProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnTextishProps<IbanInputProps>;
326
+ /**
327
+ * {@link IbanInput} bound to one field, which stores the COMPACT upper-case IBAN (what
328
+ * kastlan's server checks and its QR bill prints). The field's own checksum and
329
+ * `kind` messages show while the form has nothing to say; a form error (the schema's
330
+ * or `rules`') replaces them, as a caller's `error` does on the bare field. kastlan
331
+ * asked for the field; it binds everything through react-hook-form.
332
+ */
333
+ declare function RhfIbanInput<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues>({ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className, ...ibanProps }: RhfIbanInputProps<TFieldValues, TName, TTransformed>): react.JSX.Element;
334
+ type RhfPhoneInputProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnTextishProps<PhoneInputProps>;
335
+ /**
336
+ * {@link PhoneInput} bound to one field, which stores E.164 when the number reads as
337
+ * one and the typed text unchanged otherwise — kastlan's contacts keep their old free
338
+ * text until someone edits it. Validation (required, a pattern for E.164 only) is the
339
+ * schema's or `rules`'.
340
+ */
341
+ declare function RhfPhoneInput<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues>({ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className, ...phoneProps }: RhfPhoneInputProps<TFieldValues, TName, TTransformed>): react.JSX.Element;
247
342
  interface RhfSelectOption {
248
343
  value: string | number;
249
344
  label: ReactNode;
@@ -270,6 +365,48 @@ type RhfCheckboxProps<TFieldValues extends FieldValues = FieldValues, TName exte
270
365
  * — see Checkbox — so a `<form>` refuses to submit it unticked.
271
366
  */
272
367
  declare function RhfCheckbox<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues>({ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className, ...boxProps }: RhfCheckboxProps<TFieldValues, TName, TTransformed>): react.JSX.Element;
368
+ /** The two shapes a {@link ToggleGroup} comes in, carried over: `allowEmpty` picks
369
+ * whether a press on the chosen option clears it, and types the caption to match. */
370
+ type RhfToggleGroupMode<T extends string> = {
371
+ /** One option is always the answer (the default): a press on the chosen
372
+ * option re-sends it. */
373
+ allowEmpty?: false;
374
+ semantics?: ToggleGroupRequiredProps<T>["semantics"];
375
+ caption?: ToggleGroupRequiredProps<T>["caption"];
376
+ emptyValue?: undefined;
377
+ } | {
378
+ /** A press on the chosen option clears it, and the form stores `emptyValue`. */
379
+ allowEmpty: true;
380
+ semantics?: ToggleGroupClearableProps<T>["semantics"];
381
+ caption?: ToggleGroupClearableProps<T>["caption"];
382
+ /** What a cleared group stores. Default `null`; `""` for a schema that spells
383
+ * "no choice" as an empty string. */
384
+ emptyValue?: null | "";
385
+ };
386
+ type RhfToggleGroupProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, T extends string = string, TTransformed = TFieldValues> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & Pick<ToggleGroupBaseProps<T>, "options" | "optionClassName" | "overflow" | "size" | "aria-label" | "commit" | "disabledReason"> & {
387
+ /** Classes for the group itself — `className` is the item's box. */
388
+ groupClassName?: string;
389
+ } & RhfToggleGroupMode<T>;
390
+ /**
391
+ * The kit's {@link ToggleGroup} bound to one field: a choice between a few answers
392
+ * ("Monthly / Quarterly / Yearly"), stored as the chosen option's `value`. kastlan 4
393
+ * asked for it with {@link RhfTimeInput} and {@link RhfDateRangePicker}: the controls
394
+ * its forms still had to wire by hand through {@link RhfField}'s render.
395
+ *
396
+ * The label is the form's {@link FormLabel} above the bare group, as on every other
397
+ * bound field — the `labelPlacement="above"` shape, not the group's own field chrome —
398
+ * and it names the group (`aria-labelledby`); the hint and the message describe it,
399
+ * and an error paints the group's border. Focus on error goes to the option a
400
+ * keyboard user would land on (the chosen one, else the first); touched is set when
401
+ * focus leaves the group, not when it moves between options.
402
+ *
403
+ * Required by default, as the group is: a press on the chosen option keeps it. With
404
+ * `allowEmpty`, a second press clears the choice and the form stores `emptyValue`
405
+ * (`null` by default) — the options then become toggle buttons, see ToggleGroup. A
406
+ * value that matches no option (an empty default) leaves nothing pressed; that the
407
+ * field still needs answering is the schema's or `rules`' to say.
408
+ */
409
+ declare function RhfToggleGroup<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, T extends string = string, TTransformed = TFieldValues>({ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className, ...groupProps }: RhfToggleGroupProps<TFieldValues, TName, T, TTransformed>): react.JSX.Element;
273
410
  type RhfComboboxProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, V extends string | number = string | number, TTransformed = TFieldValues> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & Pick<EntityComboboxProps<V>, "options" | "loadOptions" | "loading" | "placeholder" | "searchPlaceholder" | "emptyLabel" | "clearable" | "clearLabel" | "onCreate" | "createLabel" | "filter" | "minChars" | "debounceMs"> & {
274
411
  /** What a clear stores — the picker's `clearValue`. Default `null`; `""` for a
275
412
  * schema that spells "no choice" as an empty string. */
@@ -293,4 +430,4 @@ type RhfTextComboboxProps<TFieldValues extends FieldValues = FieldValues, TName
293
430
  */
294
431
  declare function RhfTextCombobox<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, TTransformed = TFieldValues>({ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className, comboClassName, ...comboProps }: RhfTextComboboxProps<TFieldValues, TName, TTransformed>): react.JSX.Element;
295
432
 
296
- export { RhfCheckbox, type RhfCheckboxProps, RhfCombobox, type RhfComboboxProps, RhfDateField, type RhfDateFieldProps, RhfField, type RhfFieldBaseProps, type RhfFieldProps, type RhfFieldRenderContext, RhfIntegerField, type RhfIntegerFieldProps, RhfMoneyField, type RhfMoneyFieldProps, RhfNumberField, type RhfNumberFieldProps, RhfSelect, type RhfSelectOption, type RhfSelectProps, RhfTextCombobox, type RhfTextComboboxProps, RhfTextField, type RhfTextFieldProps, RhfTextarea, type RhfTextareaProps };
433
+ export { RhfCheckbox, type RhfCheckboxProps, RhfCombobox, type RhfComboboxProps, RhfDateField, type RhfDateFieldProps, RhfDateRangePicker, type RhfDateRangePickerProps, RhfField, type RhfFieldBaseProps, type RhfFieldProps, type RhfFieldRenderContext, RhfIbanInput, type RhfIbanInputProps, RhfIntegerField, type RhfIntegerFieldProps, RhfMoneyField, type RhfMoneyFieldProps, RhfNumberField, type RhfNumberFieldProps, RhfPhoneInput, type RhfPhoneInputProps, RhfSelect, type RhfSelectOption, type RhfSelectProps, RhfTextCombobox, type RhfTextComboboxProps, RhfTextField, type RhfTextFieldProps, RhfTextarea, type RhfTextareaProps, RhfTimeInput, type RhfTimeInputProps, RhfToggleGroup, type RhfToggleGroupProps };