@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.
- package/dist/chart.d.ts +10 -8
- package/dist/components/account-chips.d.ts +10 -3
- package/dist/components/account-chips.js +5 -2
- package/dist/components/account-chips.js.map +1 -1
- package/dist/components/account-settings.d.ts +33 -2
- package/dist/components/account-settings.js +43 -21
- package/dist/components/account-settings.js.map +1 -1
- package/dist/components/amount-input.d.ts +27 -8
- package/dist/components/amount-input.js +15 -28
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/autocomplete.d.ts +8 -0
- package/dist/components/autocomplete.js +9 -4
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/button-group.d.ts +10 -8
- package/dist/components/calculator.d.ts +10 -8
- package/dist/components/checkbox-group.d.ts +104 -0
- package/dist/components/checkbox-group.js +111 -0
- package/dist/components/checkbox-group.js.map +1 -0
- package/dist/components/checkbox.d.ts +19 -0
- package/dist/components/checkbox.js +30 -7
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/chip.d.ts +18 -0
- package/dist/components/chip.js +47 -10
- package/dist/components/chip.js.map +1 -1
- package/dist/components/combobox.d.ts +13 -2
- package/dist/components/combobox.js +17 -8
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +66 -161
- package/dist/components/copy-button.d.ts +10 -8
- package/dist/components/country-select.d.ts +124 -0
- package/dist/components/country-select.js +237 -0
- package/dist/components/country-select.js.map +1 -0
- package/dist/components/currency-select.d.ts +17 -1
- package/dist/components/currency-select.js +56 -23
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +66 -166
- package/dist/components/danger-confirm.js +133 -49
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-cells.d.ts +1 -2
- package/dist/components/data-table-filter-popover.d.ts +1 -2
- package/dist/components/data-table-filters.d.ts +1 -2
- package/dist/components/data-table-labels.d.ts +4 -97
- package/dist/components/data-table-labels.js +9 -1
- package/dist/components/data-table-labels.js.map +1 -1
- package/dist/components/data-table-pagination.d.ts +3 -1
- package/dist/components/data-table.d.ts +1 -2
- package/dist/components/data-table.js +98 -3
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.d.ts +25 -5
- package/dist/components/date-picker.js +110 -59
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/entity-combobox.d.ts +8 -1
- package/dist/components/entity-combobox.js +9 -4
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/facing-pair.d.ts +10 -8
- package/dist/components/field-anatomy.d.ts +95 -0
- package/dist/components/field-anatomy.js +84 -0
- package/dist/components/field-anatomy.js.map +1 -0
- package/dist/components/field-parts.d.ts +114 -0
- package/dist/components/field-parts.js +72 -0
- package/dist/components/field-parts.js.map +1 -0
- package/dist/components/file-button.d.ts +10 -8
- package/dist/components/file-button.js +13 -3
- package/dist/components/file-button.js.map +1 -1
- package/dist/components/file-dropzone.d.ts +32 -9
- package/dist/components/file-dropzone.js +57 -34
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/form-actions.d.ts +10 -8
- package/dist/components/form-actions.js +61 -3
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/iban-input.d.ts +66 -0
- package/dist/components/iban-input.js +125 -0
- package/dist/components/iban-input.js.map +1 -0
- package/dist/components/icon-picker.d.ts +12 -2
- package/dist/components/icon-picker.js +9 -2
- package/dist/components/icon-picker.js.map +1 -1
- package/dist/components/inline-edit-field.d.ts +167 -0
- package/dist/components/inline-edit-field.js +293 -0
- package/dist/components/inline-edit-field.js.map +1 -0
- package/dist/components/language-select.d.ts +127 -0
- package/dist/components/language-select.js +18 -0
- package/dist/components/language-select.js.map +1 -0
- package/dist/components/line-items.d.ts +25 -3
- package/dist/components/line-items.js +55 -46
- package/dist/components/line-items.js.map +1 -1
- package/dist/components/list.d.ts +25 -0
- package/dist/components/list.js +16 -5
- package/dist/components/list.js.map +1 -1
- package/dist/components/money-field.d.ts +20 -8
- package/dist/components/money-field.js.map +1 -1
- package/dist/components/month-picker.d.ts +52 -4
- package/dist/components/month-picker.js +290 -86
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-select.d.ts +8 -1
- package/dist/components/multi-select.js +9 -4
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/number-field.d.ts +25 -13
- package/dist/components/number-field.js +6 -20
- package/dist/components/number-field.js.map +1 -1
- package/dist/components/number-input.d.ts +70 -13
- package/dist/components/number-input.js +90 -38
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numpad-sheet.d.ts +10 -8
- package/dist/components/one-time-code-input.d.ts +100 -0
- package/dist/components/one-time-code-input.js +137 -0
- package/dist/components/one-time-code-input.js.map +1 -0
- package/dist/components/phone-input.d.ts +66 -0
- package/dist/components/phone-input.js +171 -0
- package/dist/components/phone-input.js.map +1 -0
- package/dist/components/series-chart.d.ts +10 -8
- package/dist/components/settings-fields.d.ts +10 -8
- package/dist/components/share-card.d.ts +8 -6
- package/dist/components/sign-chip.d.ts +66 -0
- package/dist/components/sign-chip.js +39 -0
- package/dist/components/sign-chip.js.map +1 -0
- package/dist/components/swatch-picker.d.ts +27 -2
- package/dist/components/swatch-picker.js +73 -31
- package/dist/components/swatch-picker.js.map +1 -1
- package/dist/components/switch.d.ts +19 -0
- package/dist/components/switch.js +24 -6
- package/dist/components/switch.js.map +1 -1
- package/dist/components/text-link.d.ts +10 -8
- package/dist/components/tile-radio.d.ts +68 -13
- package/dist/components/tile-radio.js +3 -3
- package/dist/components/tile-radio.js.map +1 -1
- package/dist/components/time-input.d.ts +15 -9
- package/dist/components/time-input.js.map +1 -1
- package/dist/components/toggle-group.d.ts +47 -1
- package/dist/components/toggle-group.js +110 -69
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/ui.d.ts +10 -8
- package/dist/components/ui.js +280 -78
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-table-state.d.ts +1 -2
- package/dist/{data-table-3mi2R3so.d.ts → data-table-labels-B7OdnM0S.d.ts} +140 -3
- package/dist/data-table.d.ts +1 -2
- package/dist/data-table.js +2 -1
- package/dist/data-table.js.map +1 -1
- package/dist/feedback/feedback-attachment.d.ts +1 -1
- package/dist/feedback/feedback-attachment.js +210 -3
- package/dist/feedback/feedback-attachment.js.map +1 -1
- package/dist/feedback/feedback-dialog.d.ts +1 -1
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-inbox.d.ts +1 -1
- package/dist/feedback/feedback-thread.d.ts +37 -3
- package/dist/feedback/feedback-thread.js +38 -9
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/{feedback-attachment-WFiXJ8We.d.ts → feedback-attachment-NhUm7Zga.d.ts} +70 -5
- package/dist/feedback.d.ts +2 -2
- package/dist/hooks/use-file-drop.d.ts +10 -8
- package/dist/i18n/defaults.d.ts +10 -8
- package/dist/i18n/defaults.js +17 -2
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.d.ts +10 -8
- package/dist/i18n/german.js +50 -5
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +10 -8
- package/dist/i18n/kit-labels.js +8 -2
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.d.ts +10 -8
- package/dist/i18n/locales/de-CH.d.ts +10 -8
- package/dist/i18n/locales/en.d.ts +10 -8
- package/dist/i18n/locales/en.js +9 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +10 -8
- package/dist/i18n/locales/es.js +48 -5
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +10 -8
- package/dist/i18n/locales/fr.js +48 -5
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +10 -8
- package/dist/i18n/locales/hu.js +49 -5
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +10 -8
- package/dist/i18n/locales/it.js +49 -5
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +10 -8
- package/dist/i18n/locales/zh.js +48 -5
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +10 -8
- package/dist/i18n/review.js +8 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +17 -10
- package/dist/index.js +57 -2
- package/dist/index.js.map +1 -1
- package/dist/{kit-labels-D1J2_jyD.d.ts → kit-labels-R8mIAc9N.d.ts} +811 -8
- package/dist/lib/countries.d.ts +43 -0
- package/dist/lib/countries.js +39 -0
- package/dist/lib/countries.js.map +1 -0
- package/dist/lib/decimal-marks.d.ts +46 -0
- package/dist/lib/decimal-marks.js +40 -0
- package/dist/lib/decimal-marks.js.map +1 -0
- package/dist/lib/iban.d.ts +98 -0
- package/dist/lib/iban.js +154 -0
- package/dist/lib/iban.js.map +1 -0
- package/dist/lib/isin.d.ts +30 -0
- package/dist/lib/isin.js +36 -0
- package/dist/lib/isin.js.map +1 -0
- package/dist/lib/phone.d.ts +69 -0
- package/dist/lib/phone.js +121 -0
- package/dist/lib/phone.js.map +1 -0
- package/dist/rhf/fields.d.ts +148 -11
- package/dist/rhf/fields.js +332 -3
- package/dist/rhf/fields.js.map +1 -1
- package/dist/rhf/form.d.ts +10 -8
- package/dist/rhf.d.ts +13 -9
- package/dist/rhf.js.map +1 -1
- package/dist/shell/app-shell.d.ts +10 -8
- package/dist/shell/top-bar-brand.d.ts +10 -8
- package/dist/shell.d.ts +10 -8
- package/dist/tour/tour.js +20 -24
- package/dist/tour/tour.js.map +1 -1
- package/dist/wizard/stepper-nav.d.ts +10 -8
- package/dist/wizard.d.ts +10 -8
- package/package.json +1 -1
- package/src/components/account-chips.tsx +17 -3
- package/src/components/account-settings.tsx +92 -26
- package/src/components/amount-input.tsx +49 -56
- package/src/components/autocomplete.tsx +133 -110
- package/src/components/checkbox-group.tsx +229 -0
- package/src/components/checkbox.tsx +72 -8
- package/src/components/chip.tsx +80 -10
- package/src/components/combobox.tsx +292 -253
- package/src/components/country-select.tsx +443 -0
- package/src/components/currency-select.tsx +109 -33
- package/src/components/danger-confirm.tsx +345 -77
- package/src/components/data-table-labels.ts +16 -1
- package/src/components/data-table.tsx +175 -6
- package/src/components/date-picker.tsx +173 -62
- package/src/components/entity-combobox.tsx +107 -87
- package/src/components/field-anatomy.tsx +190 -0
- package/src/components/field-parts.tsx +184 -0
- package/src/components/file-button.tsx +36 -3
- package/src/components/file-dropzone.tsx +106 -38
- package/src/components/form-actions.tsx +115 -2
- package/src/components/iban-input.tsx +231 -0
- package/src/components/icon-picker.tsx +26 -4
- package/src/components/inline-edit-field.tsx +533 -0
- package/src/components/language-select.tsx +78 -0
- package/src/components/line-items.tsx +35 -2
- package/src/components/list.tsx +55 -6
- package/src/components/money-field.tsx +10 -0
- package/src/components/month-picker.tsx +399 -63
- package/src/components/multi-select.tsx +80 -58
- package/src/components/number-field.tsx +28 -46
- package/src/components/number-input.tsx +210 -43
- package/src/components/one-time-code-input.tsx +288 -0
- package/src/components/phone-input.tsx +299 -0
- package/src/components/sign-chip.tsx +103 -0
- package/src/components/swatch-picker.tsx +118 -30
- package/src/components/switch.tsx +58 -7
- package/src/components/tile-radio.tsx +71 -16
- package/src/components/time-input.tsx +8 -1
- package/src/components/toggle-group.tsx +206 -73
- package/src/components/ui.tsx +472 -105
- package/src/data-table.ts +2 -1
- package/src/feedback/feedback-attachment.tsx +313 -9
- package/src/feedback/feedback-dialog.tsx +2 -0
- package/src/feedback/feedback-thread.tsx +66 -5
- package/src/i18n/defaults.ts +16 -1
- package/src/i18n/german.ts +47 -0
- package/src/i18n/kit-labels.tsx +78 -2
- package/src/i18n/locales/en.ts +10 -0
- package/src/i18n/locales/es.ts +46 -0
- package/src/i18n/locales/fr.ts +45 -0
- package/src/i18n/locales/hu.ts +46 -0
- package/src/i18n/locales/it.ts +47 -0
- package/src/i18n/locales/zh.ts +44 -0
- package/src/i18n/review.ts +7 -0
- package/src/index.ts +53 -3
- package/src/lib/countries.ts +91 -0
- package/src/lib/decimal-marks.ts +99 -0
- package/src/lib/iban.ts +171 -0
- package/src/lib/isin.ts +62 -0
- package/src/lib/phone.ts +211 -0
- package/src/rhf/fields.tsx +606 -9
- package/src/rhf.ts +2 -1
- 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":";AA+CA,SAAS,IAAI,KAAa,OAA2B;AACnD,QAAM,MAAgB,CAAC;AACvB,MAAI,KAAK;AACT,aAAW,QAAQ,OAAO;AACxB,QAAI,MAAM,IAAI,OAAQ;AACtB,QAAI,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,CAAC;AACjC,UAAM;AAAA,EACR;AACA,MAAI,KAAK,IAAI,OAAQ,KAAI,KAAK,IAAI,MAAM,EAAE,CAAC;AAC3C,SAAO;AACT;AAEA,MAAM,QAA+C;AAAA;AAAA,EAEnD,IAAI;AAAA,IACF,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO,CAAC,MAAO,QAAQ,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,EAC1E;AAAA;AAAA,EAEA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO,CAAC,MAAO,EAAE,WAAW,IAAI,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,WAAW,IAAI,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AAAA,EAC7F;AAAA;AAAA;AAAA,EAGA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO,CAAC,MACN,MAAM,KAAK,CAAC,IACR,IAAI,GAAG,CAAC,CAAC,CAAC,IACV,SAAS,KAAK,CAAC,IACb,IAAI,GAAG,CAAC,CAAC,CAAC,IACV,iBAAiB,KAAK,CAAC,IACrB,IAAI,GAAG,CAAC,CAAC,CAAC,IACV,CAAC,CAAC;AAAA,EACd;AAAA;AAAA,EAEA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO,CAAC,MAAO,KAAK,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAAA,EAC7E;AAAA;AAAA,EAEA,IAAI,EAAE,MAAM,MAAM,OAAO,MAAM,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,EAAE;AAAA;AAAA,EAErF,IAAI;AAAA,IACF,MAAM;AAAA,IACN,OAAO;AAAA,IACP,WAAW;AAAA,IACX,KAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO,CAAC,MAAO,KAAK,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,SAAS,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AAAA,EACvF;AACF;AAGO,MAAM,mBAA+D,OAAO,OAAO;AAAA,EACxF,IAAI,MAAM,GAAG;AAAA,EACb,IAAI,MAAM,GAAG;AAAA,EACb,IAAI,MAAM,GAAG;AAAA,EACb,IAAI,MAAM,GAAG;AAAA,EACb,IAAI,MAAM,GAAG;AAAA,EACb,IAAI,MAAM,GAAG;AACf,CAAC;AAGM,MAAM,kBAA+C,OAAO,OAAO,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI,CAAC;AAG9G,MAAM,UAAU,CAAC,GAAG,eAAe,EAAE,KAAK,CAAC,GAAG,MAAM,MAAM,CAAC,EAAE,KAAK,SAAS,MAAM,CAAC,EAAE,KAAK,MAAM;AAc/F,SAAS,SAAS,QAAgB,MAAkC;AAClE,QAAM,MAAM,KAAK,SAAS,OAAO,WAAW,GAAG,IAAI,OAAO,MAAM,CAAC,IAAI;AAErE,MAAI,IAAI,WAAW,GAAG,KAAK,CAAC,KAAK,UAAW,QAAO;AACnD,MAAI,IAAI,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK,IAAK,QAAO;AAC3D,SAAO;AACT;AAaO,SAAS,WAAW,OAAe,UAAwB,MAA0B;AAC1F,QAAM,OAAO,MAAM,KAAK;AACxB,MAAI,SAAS,MAAM,CAAC,qBAAqB,KAAK,IAAI,EAAG,QAAO;AAC5D,MAAI,SAAS,KAAK,QAAQ,OAAO,EAAE;AACnC,MAAI,gBAAgB,KAAK,WAAW,GAAG;AACvC,MAAI,CAAC,iBAAiB,OAAO,WAAW,IAAI,GAAG;AAC7C,oBAAgB;AAChB,aAAS,OAAO,MAAM,CAAC;AAAA,EACzB;AACA,MAAI,eAAe;AAEjB,aAAS,KAAK,QAAQ,gBAAgB,EAAE,EAAE,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,EAAE;AAC9E,QAAI,OAAO,WAAW,GAAG,EAAG,QAAO;AACnC,UAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM,OAAO,WAAW,MAAM,CAAC,EAAE,IAAI,CAAC;AAClE,QAAI,OAAO;AACT,YAAMA,QAAO,MAAM,KAAK;AACxB,YAAMC,OAAM,SAAS,OAAO,MAAMD,MAAK,KAAK,MAAM,GAAGA,KAAI;AACzD,aAAOC,SAAQ,OAAO,OAAO,EAAE,MAAM,IAAID,MAAK,IAAI,GAAGC,IAAG,IAAI,SAAS,OAAO,UAAUA,KAAI;AAAA,IAC5F;AACA,QAAI,OAAO,SAAS,KAAK,OAAO,SAAS,GAAI,QAAO;AACpD,WAAO,EAAE,MAAM,IAAI,MAAM,IAAI,SAAS,MAAM,UAAU,OAAO;AAAA,EAC/D;AACA,MAAI,YAAY,QAAS,QAAO;AAChC,QAAM,OAAO,MAAM,OAAO;AAC1B,QAAM,MAAM,SAAS,QAAQ,IAAI;AACjC,SAAO,QAAQ,OAAO,OAAO,EAAE,MAAM,IAAI,KAAK,IAAI,GAAG,GAAG,IAAI,SAAS,UAAU,IAAI;AACrF;AAGO,SAAS,oBAAoB,KAAa,SAAmC;AAClF,SAAO,MAAM,OAAO,EAAE,MAAM,GAAG,EAAE,KAAK,GAAG;AAC3C;AAQO,SAAS,YAAY,OAAuB;AACjD,QAAM,SAAS,MAAM,KAAK,EAAE,WAAW,GAAG,IAAI,WAAW,OAAO,OAAO,IAAI;AAC3E,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,CAAC,OAAO,QAAS,QAAO,OAAO;AACnC,SAAO,IAAI,MAAM,OAAO,OAAO,EAAE,IAAI,IAAI,oBAAoB,OAAO,UAAU,OAAO,OAAO,CAAC;AAC/F;AAIO,SAAS,OAAO,OAAwB;AAC7C,SAAO,oBAAoB,KAAK,KAAK;AACvC;","names":["rule","nsn"]}
|
package/dist/rhf/fields.d.ts
CHANGED
|
@@ -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 {
|
|
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 '../
|
|
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-
|
|
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 };
|