@desource/phone-mask-vue 0.2.3 → 1.0.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/CHANGELOG.md +46 -0
- package/LICENSE +1 -1
- package/README.md +154 -11
- package/dist/index.cjs +858 -961
- package/dist/index.js +858 -961
- package/dist/index.mjs +859 -962
- package/dist/phone-mask-vue.css +64 -64
- package/dist/types/components/PhoneInput.vue.d.ts +7 -7
- package/dist/types/components/PhoneInput.vue.d.ts.map +1 -1
- package/dist/types/composables/internal/useCopyAction.d.ts +14 -0
- package/dist/types/composables/internal/useCopyAction.d.ts.map +1 -0
- package/dist/types/composables/internal/useCountry.d.ts +22 -0
- package/dist/types/composables/internal/useCountry.d.ts.map +1 -0
- package/dist/types/composables/internal/useCountrySelector.d.ts +30 -0
- package/dist/types/composables/internal/useCountrySelector.d.ts.map +1 -0
- package/dist/types/composables/internal/useFormatter.d.ts +46 -0
- package/dist/types/composables/internal/useFormatter.d.ts.map +1 -0
- package/dist/types/composables/internal/useInputHandlers.d.ts +20 -0
- package/dist/types/composables/internal/useInputHandlers.d.ts.map +1 -0
- package/dist/types/composables/internal/useTheme.d.ts +10 -0
- package/dist/types/composables/internal/useTheme.d.ts.map +1 -0
- package/dist/types/composables/internal/useValidationHint.d.ts +6 -0
- package/dist/types/composables/internal/useValidationHint.d.ts.map +1 -0
- package/dist/types/composables/usePhoneMask.d.ts +8 -0
- package/dist/types/composables/usePhoneMask.d.ts.map +1 -0
- package/dist/types/composables/{useClipboard.d.ts → utility/useClipboard.d.ts} +1 -2
- package/dist/types/composables/utility/useClipboard.d.ts.map +1 -0
- package/dist/types/composables/utility/useTimer.d.ts +9 -0
- package/dist/types/composables/utility/useTimer.d.ts.map +1 -0
- package/dist/types/directives/vPhoneMask.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types.d.ts +31 -13
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +18 -12
- package/dist/types/composables/useClipboard.d.ts.map +0 -1
- package/dist/types/composables/useCountrySelector.d.ts +0 -21
- package/dist/types/composables/useCountrySelector.d.ts.map +0 -1
- package/dist/types/composables/useMask.d.ts +0 -20
- package/dist/types/composables/useMask.d.ts.map +0 -1
- package/dist/types/composables/usePhoneFormatter.d.ts +0 -16
- package/dist/types/composables/usePhoneFormatter.d.ts.map +0 -1
- package/dist/types/consts.d.ts +0 -8
- package/dist/types/consts.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,66 +1,101 @@
|
|
|
1
1
|
var lib = (function(exports, vue) {
|
|
2
2
|
"use strict";
|
|
3
3
|
const M = { AC: "+247 #####", AD: ["+376 ### ###", "+376 #### ####"], AE: ["+971 # ### ####", "+971 ## ### ####", "+971 ### ######", "+971 ### # #####"], AF: "+93 ## ### ####", AG: "+1 ###-###-####", AI: "+1 ###-###-####", AL: ["+355 ## ### ###", "+355 ## ### ####", "+355 ### ####", "+355 ### ###", "+355 ### #####"], AM: ["+374 ## ######", "+374 ### ## ###"], AO: "+244 ### ### ###", AR: ["+54 ## ####-####", "+54 # ## ####-####", "+54 ###-###-####"], AS: "+1 ###-###-####", AT: ["+43 # #########", "+43 ### ######"], AU: ["+61 # #### ####", "+61 ### ### ###", "+61 #### ### ###", "+61 ## ### ##"], AW: "+297 ### ####", AX: ["+358 ## #######", "+358 ### ######"], AZ: ["+994 ## ### ## ##", "+994 ### ## ## ##"], BA: ["+387 ## ###-###", "+387 ## ### ###"], BB: "+1 ###-###-####", BD: ["+880 #-#######", "+880 ####-######", "+880 ###-#######"], BE: ["+32 ## ## ## ##", "+32 ### ## ## ##", "+32 ### ## ###"], BF: "+226 ## ## ## ##", BG: ["+359 # ### ###", "+359 ## ### ###", "+359 ### ## ###"], BH: "+973 #### ####", BI: "+257 ## ## ## ##", BJ: ["+229 ## ## ## ## ##", "+229 ## ## ## ##"], BL: "+590 ### ## ## ##", BM: "+1 ###-###-####", BN: "+673 ### ####", BO: ["+591 # #######", "+591 ########", "+591 ### ## ####"], BQ: "+599 ### ####", BR: ["+55 ## ####-####", "+55 ## #####-####", "+55 ### ## ####", "+55 ####-####"], BS: "+1 ###-###-####", BT: ["+975 # ### ###", "+975 ## ## ## ##"], BW: ["+267 ### ####", "+267 ## ### ###", "+267 #### ### ###", "+267 ## #####"], BY: ["+375 ### ##-##-##", "+375 ## ###-##-##", "+375 ### ### ####"], BZ: ["+501 ###-####", "+501 #-###-####-###"], CA: "+1 ###-###-####", CC: ["+61 # #### ####", "+61 ### ### ###", "+61 #### ### ###"], CD: ["+243 ## #####", "+243 ### ### ###"], CF: "+236 ## ## ## ##", CG: ["+242 ## ### ####", "+242 # #### ####"], CH: ["+41 ## ### ## ##", "+41 ### ### ###"], CI: ["+225 ## ## # #####", "+225 ## ## ## ####"], CK: "+682 ## ###", CL: ["+56 ### ### ###", "+56 # #### ####", "+56 ### ### ####", "+56 ## ### ####"], CM: ["+237 # ## ## ## ##", "+237 ## ## ## ##"], CN: ["+86 ## #### ####", "+86 ### #### ####", "+86 ### ### ####", "+86 ########"], CO: ["+57 ### #######", "+57 # ### #######"], CR: ["+506 #### ####", "+506 ###-###-####"], CU: ["+53 # #######", "+53 ### #######"], CV: "+238 ### ## ##", CW: ["+599 # ### ####", "+599 ### ####"], CX: ["+61 # #### ####", "+61 ### ### ###", "+61 #### ### ###"], CY: "+357 ## ######", CZ: "+420 ### ### ###", DE: ["+49 ## ######", "+49 #### #######", "+49 ### ##########", "+49 ### # ######", "+49 ### # ####", "+49 ### #### ####", "+49 ########"], DJ: "+253 ## ## ## ##", DK: "+45 ## ## ## ##", DM: "+1 ###-###-####", DO: "+1 ###-###-####", DZ: ["+213 ## ## ## ##", "+213 ### ## ## ##", "+213 ## ### ## ##"], EC: ["+593 #-###-####", "+593 ## ### ####", "+593 #### ### ####"], EE: ["+372 ### ####", "+372 #### ####", "+372 ## ## ####"], EG: ["+20 # ########", "+20 ## ########", "+20 ### ### ####"], EH: ["+212 # ## ## ## ##", "+212 ##-#######"], ER: "+291 # ### ###", ES: ["+34 ### ## ## ##", "+34 ### ### ###"], ET: "+251 ## ### ####", FI: ["+358 ## #######", "+358 ### ######"], FJ: ["+679 ### ####", "+679 #### ### ####"], FK: "+500 #####", FM: "+691 ### ####", FO: "+298 ######", FR: ["+33 # ## ## ## ##", "+33 ### ## ## ##"], GA: "+241 ## ## ## ##", GB: ["+44 ### ### ####", "+44 #### ######", "+44 ## #### ####"], GD: "+1 ###-###-####", GE: ["+995 ## ### ## ##", "+995 ### ## ## ##", "+995 ### ### ###"], GF: "+594 ### ## ## ##", GG: ["+44 #### ######", "+44 ### ### ####", "+44 ## #### ####"], GH: ["+233 ## ### ####", "+233 ### #####"], GI: ["+350 ### #####", "+350 ########"], GL: "+299 ## ## ##", GM: "+220 ### ####", GN: ["+224 ## ## ## ##", "+224 ### ## ## ##"], GP: "+590 ### ## ## ##", GQ: ["+240 ### ### ###", "+240 ### ######"], GR: ["+30 ## #### ####", "+30 ### ### ####"], GT: ["+502 #### ####", "+502 #### ### ####"], GU: "+1 ###-###-####", GW: ["+245 ### ### ###", "+245 ### ####"], GY: "+592 ### ####", HK: ["+852 #### ####", "+852 ### ### ###", "+852 ### ## ### ###"], HN: ["+504 ####-####", "+504 ###########"], HR: ["+385 # #### ###", "+385 ## ### ####", "+385 ### ### ###", "+385 ## ## ###", "+385 ## ### ###"], HT: "+509 ## ## ####", HU: ["+36 # ### ####", "+36 ## ### ####", "+36 ## ### ###"], ID: ["+62 ## #######", "+62 ###-###-###", "+62 ### #######", "+62 ### # ### ###", "+62 ### ### ####"], IE: ["+353 ## #####", "+353 ## ### ####", "+353 #### ### ###", "+353 ### ### ###"], IL: ["+972 #-###-####", "+972 ##-###-####", "+972 #-###-###-###"], IM: ["+44 #### ######", "+44 ### ### ####", "+44 ## #### ####"], IN: ["+91 ##### #####", "+91 #### ## ####", "+91 #### ### ### ###", "+91 #### ### ####"], IO: "+246 ### ####", IQ: ["+964 # ### ####", "+964 ### ### ####"], IR: ["+98 ## #### ####", "+98 ### ### ####"], IS: "+354 ### ####", IT: ["+39 ## #### ####", "+39 ### ### ####", "+39 ### ### ###"], JE: ["+44 #### ######", "+44 ### ### ####", "+44 ## #### ####"], JM: "+1 ###-###-####", JO: ["+962 # ### ####", "+962 # #### ####", "+962 ### #####", "+962 ## #######"], JP: ["+81 #-####-####", "+81 ##-####-####", "+81 ###-###-###", "+81 ##-###-####"], KE: ["+254 ## #######", "+254 ### ######", "+254 ### ### ###"], KG: ["+996 ### ### ###", "+996 ### ### # ##"], KH: ["+855 ## ### ###", "+855 #### ### ###"], KI: ["+686 #####", "+686 ########"], KM: "+269 ### ## ##", KN: "+1 ###-###-####", KP: ["+850 # ### ####", "+850 ### ### ####"], KR: ["+82 #-###-####", "+82 ##-####-####", "+82 ##-###-####"], KW: ["+965 #### ####", "+965 ### #####", "+965 #### ###"], KY: "+1 ###-###-####", KZ: ["+7 ##### # ## ##", "+7 ### ### ####", "+7 ### ###-##-##"], LA: ["+856 ## ### ###", "+856 ## ## ### ###"], LB: ["+961 # ### ###", "+961 ## ### ###"], LC: "+1 ###-###-####", LI: ["+423 ### ## ##", "+423 ### ### ###"], LK: ["+94 ### ### ###", "+94 ## ### ####"], LR: ["+231 ## ### ###", "+231 ## ### ####"], LS: "+266 #### ####", LT: ["+370 ### #####", "+370 ### ## ###"], LU: ["+352 ## ## ## ##", "+352 ### ### ###", "+352 ### ## ###"], LV: "+371 ## ### ###", LY: "+218 ##-#######", MA: ["+212 # ## ## ## ##", "+212 ##-#######"], MC: ["+377 ## ## ## ##", "+377 # ## ## ## ##"], MD: ["+373 ## ### ###", "+373 ### ## ###", "+373 ### #####"], ME: "+382 ## ### ###", MF: "+590 ### ## ## ##", MG: "+261 ## ## ### ##", MH: "+692 ###-####", MK: ["+389 # ### ####", "+389 ## ### ###", "+389 ### # ## ##"], ML: "+223 ## ## ## ##", MM: ["+95 # ### ###", "+95 # ### ####", "+95 ### ### ####"], MN: "+976 #### ####", MO: ["+853 #### ####", "+853 #### ###"], MP: "+1 ###-###-####", MQ: "+596 ### ## ## ##", MR: "+222 ## ## ## ##", MS: "+1 ###-###-####", MT: "+356 #### ####", MU: ["+230 #### ####", "+230 ### ####"], MV: ["+960 ###-####", "+960 ### ### ####"], MW: ["+265 # ### ###", "+265 ### ## ## ##"], MX: "+52 ### ### ####", MY: ["+60 #-#### ####", "+60 ##-### ####", "+60 #-###-##-####", "+60 ###-### ####"], MZ: ["+258 ## ### ###", "+258 ## ### ####", "+258 ### ### ###"], NA: ["+264 ## ### ###", "+264 ## ### ####", "+264 ### ### ###"], NC: "+687 ##.##.##", NE: ["+227 ## ## ## ##", "+227 ## ### ###"], NF: ["+672 ## ####", "+672 # #####"], NG: ["+234 #### ## ####", "+234 ### ### ####", "+234 ### #### ####"], NI: "+505 #### ####", NL: ["+31 ## ### ####", "+31 # ########", "+31 ### ####", "+31 ## #######"], NO: ["+47 ## ## ## ##", "+47 ### ## ###"], NP: ["+977 #-#######", "+977 ###-#######", "+977 ###########"], NR: "+674 ### ####", NU: ["+683 ####", "+683 ### ####"], NZ: ["+64 # ### ####", "+64 ## ### ####", "+64 ### ### ###"], OM: ["+968 ## ######", "+968 #### ####", "+968 ### #####"], PA: ["+507 ###-####", "+507 ####-####"], PE: ["+51 # #######", "+51 ### ### ###", "+51 ### #####"], PF: ["+689 ## ## ## ##", "+689 ### ## ## ##"], PG: ["+675 ### ####", "+675 #### ####"], PH: ["+63 # #### ####", "+63 ### ### ####", "+63 #### # ### ####"], PK: ["+92 ## ########", "+92 ### #######", "+92 ### ### ##", "+92 #### #####"], PL: ["+48 ## ### ## ##", "+48 ### ### ###"], PM: ["+508 ## ## ##", "+508 ### ## ## ##"], PR: "+1 ###-###-####", PS: ["+970 # ### ####", "+970 ### ### ###", "+970 #### ### ###"], PT: ["+351 ## ### ####", "+351 ### ### ###"], PW: "+680 ### ####", PY: ["+595 ## ### ####", "+595 ### ######", "+595 #### ### ####"], QA: ["+974 #### ####", "+974 ### ####"], RE: "+262 ### ## ## ##", RO: ["+40 ## ### ####", "+40 ### ### ###"], RS: ["+381 ## ######", "+381 ## #######", "+381 ### #####"], RU: "+7 ### ###-##-##", RW: "+250 ### ### ###", SA: ["+966 ## ### ####", "+966 ### ### ####", "+966 #### #####"], SB: ["+677 #####", "+677 ## #####"], SC: ["+248 # ### ###", "+248 #######"], SD: "+249 ## ### ####", SE: ["+46 # ## ## ##", "+46 ## ### ## ##", "+46 ## ## ## ##", "+46 ### ## ## ###"], SG: ["+65 #### ####", "+65 #### ### ####"], SH: "+290 #####", SI: ["+386 # ### ## ##", "+386 ## ### ###", "+386 ## ######", "+386 ### #####"], SJ: ["+47 ## ## ## ##", "+47 ### ## ###"], SK: ["+421 #/### ### ##", "+421 ### ### ###", "+421 #######"], SL: "+232 ## ######", SM: ["+378 #### ######", "+378 ## ## ## ##"], SN: ["+221 ## ### ## ##", "+221 ### ## ## ##"], SO: ["+252 # ######", "+252 # #######"], SR: ["+597 ###-###", "+597 ###-####", "+597 ##-##-##"], SS: "+211 ### ### ###", ST: "+239 ### ####", SV: ["+503 #### ####", "+503 ### ####"], SX: "+1 ###-###-####", SY: ["+963 ## ### ####", "+963 ### ### ###"], SZ: ["+268 #### ####", "+268 ##### ####"], TA: "+290 ####", TC: "+1 ###-###-####", TD: "+235 ## ## ## ##", TG: "+228 ## ## ## ##", TH: ["+66 # ### ####", "+66 ## ### ####", "+66 #### ### ###"], TJ: ["+992 ### ## ####", "+992 ## ### ####"], TK: "+690 ####", TL: ["+670 ### ####", "+670 #### ####"], TM: ["+993 ## ##-##-##", "+993 ## ######"], TN: "+216 ## ### ###", TO: ["+676 ##-###", "+676 ### ####", "+676 #### ###"], TR: ["+90 ### ### ## ##", "+90 ### ### ####"], TT: "+1 ###-###-####", TV: ["+688 ## ###", "+688 ## ####"], TW: ["+886 # #### ####", "+886 ### ### ###", "+886 ## ### ####", "+886 ## #### ####"], TZ: ["+255 ## ### ####", "+255 ### ### ###", "+255 ### ## ####"], UA: ["+380 #### #####", "+380 ## ### ####", "+380 ### ### ###"], UG: ["+256 ## #######", "+256 ### ######"], US: "+1 ###-###-####", UY: ["+598 #### ####", "+598 ## ### ###", "+598 ### ####"], UZ: "+998 ## ### ## ##", VA: ["+39 ## #### ####", "+39 ### ### ####", "+39 ### ### ###"], VC: "+1 ###-###-####", VE: "+58 ###-#######", VG: "+1 ###-###-####", VI: "+1 ###-###-####", VN: ["+84 ### #### ###", "+84 ### ### ###", "+84 #### ######", "+84 ## ### ## ##"], VU: ["+678 #####", "+678 ### ####"], WF: ["+681 ## ## ##", "+681 ### ## ## ##"], WS: ["+685 #####", "+685 ## #####", "+685 ### ###"], XK: ["+383 ## ### ###", "+383 ### #####"], YE: ["+967 # ### ###", "+967 ### ### ###"], YT: "+262 ### ## ## ##", ZA: ["+27 ## ### ####", "+27 ### ### ###"], ZM: ["+260 ### ### ###", "+260 ## #######", "+260 #########"], ZW: ["+263 ## #####", "+263 ## ### ####", "+263 ### ####", "+263 #### ######"] };
|
|
4
|
-
const t$1 = /^[a-z]{2}$/i, countryCodeEmoji = (
|
|
5
|
-
if (!t$1.test(
|
|
6
|
-
const t2 = typeof
|
|
7
|
-
throw new TypeError(`cc argument must be an ISO 3166-1 alpha-2 string, but got '${"string" === t2 ?
|
|
4
|
+
const t$1 = /^[a-z]{2}$/i, countryCodeEmoji = (o2) => {
|
|
5
|
+
if (!t$1.test(o2)) {
|
|
6
|
+
const t2 = typeof o2;
|
|
7
|
+
throw new TypeError(`cc argument must be an ISO 3166-1 alpha-2 string, but got '${"string" === t2 ? o2 : t2}' instead.`);
|
|
8
8
|
}
|
|
9
|
-
const
|
|
10
|
-
return String.fromCodePoint(...
|
|
9
|
+
const e2 = [...o2.toUpperCase()].map((t2) => (t2.codePointAt(0) ?? 0) + 127397);
|
|
10
|
+
return String.fromCodePoint(...e2);
|
|
11
11
|
};
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
for (const
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
const o$1 = "en", n = /* @__PURE__ */ new Map(), getDisplayNames = (e2) => {
|
|
13
|
+
const t2 = e2.toLowerCase(), s2 = n.get(t2);
|
|
14
|
+
if (s2) return s2;
|
|
15
|
+
const r = new Intl.DisplayNames([e2], { type: "region" });
|
|
16
|
+
if (n.size >= 10) {
|
|
17
|
+
for (const e3 of n.keys()) if (e3 !== o$1) {
|
|
18
|
+
n.delete(e3);
|
|
19
|
+
break;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
}
|
|
22
|
+
return n.set(t2, r), r;
|
|
23
|
+
}, s$1 = Object.entries(M), divideMask = (e2) => e2.split(/ (.*)/s);
|
|
24
|
+
function getCodeAndMask(e2) {
|
|
25
|
+
let t2 = "", o2 = "";
|
|
26
|
+
if (Array.isArray(e2)) {
|
|
27
|
+
const n2 = [];
|
|
28
|
+
for (const o3 of e2) {
|
|
29
|
+
const [e3, s2] = divideMask(o3);
|
|
30
|
+
t2 || (t2 = e3), n2.push(s2);
|
|
31
|
+
}
|
|
32
|
+
o2 = n2;
|
|
22
33
|
} else {
|
|
23
|
-
const [
|
|
24
|
-
|
|
34
|
+
const [n2, s2] = divideMask(e2);
|
|
35
|
+
t2 = n2, o2 = s2;
|
|
25
36
|
}
|
|
26
|
-
return [
|
|
37
|
+
return [t2, o2];
|
|
27
38
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const [
|
|
31
|
-
return
|
|
39
|
+
s$1.map(([e2, t2]) => ({ id: e2, mask: t2 }));
|
|
40
|
+
s$1.reduce((e2, [t2, o2]) => {
|
|
41
|
+
const [n2, s2] = getCodeAndMask(o2);
|
|
42
|
+
return e2[t2] = { code: n2, mask: s2 }, e2;
|
|
32
43
|
}, {});
|
|
33
|
-
|
|
34
|
-
const [
|
|
35
|
-
return { id:
|
|
44
|
+
s$1.map(([e2, t2]) => {
|
|
45
|
+
const [o2, n2] = getCodeAndMask(t2);
|
|
46
|
+
return { id: e2, code: o2, mask: n2 };
|
|
36
47
|
});
|
|
37
|
-
|
|
38
|
-
const [
|
|
39
|
-
return
|
|
48
|
+
s$1.reduce((e2, [o2, n2]) => {
|
|
49
|
+
const [s2, r] = getCodeAndMask(n2);
|
|
50
|
+
return e2[o2] = { code: s2, mask: r, flag: countryCodeEmoji(o2) }, e2;
|
|
40
51
|
}, {});
|
|
41
|
-
|
|
42
|
-
const [
|
|
43
|
-
return { id:
|
|
52
|
+
s$1.map(([e2, o2]) => {
|
|
53
|
+
const [n2, s2] = getCodeAndMask(o2);
|
|
54
|
+
return { id: e2, code: n2, mask: s2, flag: countryCodeEmoji(e2) };
|
|
44
55
|
});
|
|
45
|
-
const MasksFullMap = (
|
|
46
|
-
const
|
|
47
|
-
return
|
|
48
|
-
const [
|
|
49
|
-
return
|
|
56
|
+
const MasksFullMap = (e2) => {
|
|
57
|
+
const o2 = getDisplayNames(e2);
|
|
58
|
+
return s$1.reduce((e3, [n2, s2]) => {
|
|
59
|
+
const [r, a] = getCodeAndMask(s2), d = o2.of(n2) ?? "";
|
|
60
|
+
return e3[n2] = { code: r, mask: a, name: d, flag: countryCodeEmoji(n2) }, e3;
|
|
50
61
|
}, {});
|
|
51
|
-
}, MasksFull = (
|
|
52
|
-
const
|
|
53
|
-
return
|
|
54
|
-
const [
|
|
55
|
-
return { id:
|
|
62
|
+
}, MasksFull = (e2) => {
|
|
63
|
+
const o2 = getDisplayNames(e2);
|
|
64
|
+
return s$1.map(([e3, n2]) => {
|
|
65
|
+
const [s2, r] = getCodeAndMask(n2);
|
|
66
|
+
return { id: e3, code: s2, mask: r, name: o2.of(e3) ?? "", flag: countryCodeEmoji(e3) };
|
|
56
67
|
});
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
}, f = MasksFullMap(o$1);
|
|
69
|
+
MasksFull(o$1);
|
|
70
|
+
const k = countryCodeEmoji;
|
|
71
|
+
function getNavigatorLang() {
|
|
72
|
+
return "undefined" != typeof navigator && navigator.language || "en";
|
|
73
|
+
}
|
|
74
|
+
function detectCountryFromLocale() {
|
|
75
|
+
try {
|
|
76
|
+
const t2 = getNavigatorLang();
|
|
77
|
+
try {
|
|
78
|
+
const e3 = new Intl.Locale(t2);
|
|
79
|
+
if (e3.region) return e3.region.toUpperCase();
|
|
80
|
+
} catch {
|
|
81
|
+
}
|
|
82
|
+
const e2 = t2.split(/[-_]/);
|
|
83
|
+
if (e2.length > 1) return e2[1]?.toUpperCase() || null;
|
|
84
|
+
} catch {
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
function hasCountry(t2) {
|
|
89
|
+
const r = f;
|
|
90
|
+
return t2.toUpperCase() in r;
|
|
91
|
+
}
|
|
92
|
+
function getCountry(e2, r) {
|
|
93
|
+
const n2 = MasksFullMap(r), o2 = e2.toUpperCase();
|
|
94
|
+
return o2 in n2 ? { id: o2, ...n2[o2] } : { id: "US", ...n2.US };
|
|
95
|
+
}
|
|
96
|
+
function parseCountryCode(t2, e2) {
|
|
97
|
+
return t2 && hasCountry(t2) ? t2.toUpperCase() : e2 || "";
|
|
98
|
+
}
|
|
64
99
|
function toArray(t2) {
|
|
65
100
|
return Array.isArray(t2) ? t2 : [t2];
|
|
66
101
|
}
|
|
@@ -70,492 +105,488 @@ var lib = (function(exports, vue) {
|
|
|
70
105
|
function removeCountryCodePrefix(t2) {
|
|
71
106
|
return t2.replace(/^\+\d+\s?/, "");
|
|
72
107
|
}
|
|
73
|
-
function pickMaskVariant(t2,
|
|
108
|
+
function pickMaskVariant(t2, e2) {
|
|
74
109
|
if (1 === t2.length) return t2[0];
|
|
75
|
-
const r = t2.map((t3) => ({ mask: t3, count: countPlaceholders(t3) })),
|
|
76
|
-
if (
|
|
77
|
-
const
|
|
78
|
-
return
|
|
110
|
+
const r = t2.map((t3) => ({ mask: t3, count: countPlaceholders(t3) })), n2 = r.filter((t3) => t3.count >= e2).sort((t3, e3) => t3.count - e3.count);
|
|
111
|
+
if (n2.length > 0) return n2[0].mask;
|
|
112
|
+
const o2 = r.sort((t3, e3) => e3.count - t3.count)[0];
|
|
113
|
+
return o2 ? o2.mask : t2[0];
|
|
79
114
|
}
|
|
80
|
-
function formatDigitsWithMap(t2,
|
|
115
|
+
function formatDigitsWithMap(t2, e2) {
|
|
81
116
|
let r = "";
|
|
82
|
-
const
|
|
83
|
-
let
|
|
84
|
-
const
|
|
85
|
-
for (let
|
|
86
|
-
const
|
|
87
|
-
if ("#" ===
|
|
88
|
-
if (!(
|
|
89
|
-
r +=
|
|
117
|
+
const n2 = [];
|
|
118
|
+
let o2 = 0;
|
|
119
|
+
const a = e2.length, s2 = t2.length;
|
|
120
|
+
for (let c = 0; c < s2; c++) {
|
|
121
|
+
const s3 = t2[c];
|
|
122
|
+
if ("#" === s3) {
|
|
123
|
+
if (!(o2 < a)) break;
|
|
124
|
+
r += e2[o2], n2.push(o2), o2++;
|
|
90
125
|
} else {
|
|
91
|
-
const
|
|
92
|
-
(r.length > 0 ||
|
|
126
|
+
const e3 = -1 !== t2.indexOf("#", c + 1) && o2 < a;
|
|
127
|
+
(r.length > 0 || e3) && (r += s3, n2.push(-1));
|
|
93
128
|
}
|
|
94
129
|
}
|
|
95
|
-
return { display: r, map:
|
|
130
|
+
return { display: r, map: n2 };
|
|
96
131
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (b.score !== a.score) return b.score - a.score;
|
|
144
|
-
return a.country.name.localeCompare(b.country.name);
|
|
145
|
-
}).map(({ country }) => country);
|
|
146
|
-
});
|
|
147
|
-
const selectCountry = (id) => {
|
|
148
|
-
selectedId.value = id;
|
|
149
|
-
closeDropdown();
|
|
150
|
-
};
|
|
151
|
-
const toggleDropdown = async (searchRef) => {
|
|
152
|
-
dropdownOpened.value = !dropdownOpened.value;
|
|
153
|
-
if (!dropdownOpened.value) return;
|
|
154
|
-
await vue.nextTick();
|
|
155
|
-
searchRef.value?.focus({ preventScroll: true });
|
|
156
|
-
focusedIndex.value = 0;
|
|
157
|
-
};
|
|
158
|
-
const closeDropdown = () => {
|
|
159
|
-
dropdownOpened.value = false;
|
|
160
|
-
};
|
|
161
|
-
const focusNextOption = (scrollFn) => {
|
|
162
|
-
if (filteredCountries.value.length === 0) return;
|
|
163
|
-
focusedIndex.value = Math.min(filteredCountries.value.length - 1, focusedIndex.value + 1);
|
|
164
|
-
scrollFn?.();
|
|
165
|
-
};
|
|
166
|
-
const focusPrevOption = (scrollFn) => {
|
|
167
|
-
if (filteredCountries.value.length === 0) return;
|
|
168
|
-
focusedIndex.value = Math.max(0, focusedIndex.value - 1);
|
|
169
|
-
scrollFn?.();
|
|
170
|
-
};
|
|
171
|
-
const chooseFocusedOption = () => {
|
|
172
|
-
const item = filteredCountries.value[focusedIndex.value];
|
|
173
|
-
if (item) selectCountry(item.id);
|
|
174
|
-
};
|
|
175
|
-
const detectFromLocale = () => {
|
|
176
|
-
try {
|
|
177
|
-
const lang = navigator.language || "";
|
|
178
|
-
try {
|
|
179
|
-
const loc = new Intl.Locale(lang);
|
|
180
|
-
if (loc.region && hasCountry(loc.region)) return loc.region.toUpperCase();
|
|
181
|
-
} catch {
|
|
132
|
+
function filterCountries(t2, e2) {
|
|
133
|
+
const r = e2.trim().toUpperCase();
|
|
134
|
+
if (!r) return t2;
|
|
135
|
+
const n2 = r.replace(/\D/g, ""), o2 = n2.length > 0;
|
|
136
|
+
return t2.map((t3) => {
|
|
137
|
+
const e3 = t3.name.toUpperCase(), a = t3.id.toUpperCase(), s2 = t3.code.toUpperCase(), c = t3.code.replace(/\D/g, "");
|
|
138
|
+
let i2 = 0;
|
|
139
|
+
return e3.startsWith(r) ? i2 = 1e3 : e3.includes(r) && (i2 = 500), s2.startsWith(r) ? i2 += 100 : s2.includes(r) && (i2 += 50), a === r ? i2 += 200 : a.startsWith(r) && (i2 += 150), o2 && c.startsWith(n2) ? i2 += 80 : o2 && c.includes(n2) && (i2 += 40), { country: t3, score: i2 };
|
|
140
|
+
}).filter((t3) => t3.score > 0).sort((t3, e3) => e3.score !== t3.score ? e3.score - t3.score : t3.country.name.localeCompare(e3.country.name)).map((t3) => t3.country);
|
|
141
|
+
}
|
|
142
|
+
const t = [" ", "-", "(", ")"], e$1 = ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Home", "End", "Tab"], i = /[^\d\s\-()]/;
|
|
143
|
+
function extractDigits(t2, e2) {
|
|
144
|
+
const i2 = t2.replace(/\D/g, "");
|
|
145
|
+
return e2 ? i2.slice(0, e2) : i2;
|
|
146
|
+
}
|
|
147
|
+
function getSelection(t2) {
|
|
148
|
+
return t2 ? [t2.selectionStart ?? 0, t2.selectionEnd ?? 0] : [0, 0];
|
|
149
|
+
}
|
|
150
|
+
function setCaret(t2, e2) {
|
|
151
|
+
if (t2) try {
|
|
152
|
+
t2.setSelectionRange(e2, e2);
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function processBeforeInput(t2) {
|
|
157
|
+
if (!t2.target) return;
|
|
158
|
+
const e2 = t2.target, n2 = t2.data;
|
|
159
|
+
"insertText" === t2.inputType && n2 && (i.test(n2) || " " === n2 && e2.value.endsWith(" ")) && t2.preventDefault();
|
|
160
|
+
}
|
|
161
|
+
function processInput(t2, e2) {
|
|
162
|
+
if (!t2.target) return;
|
|
163
|
+
const i2 = t2.target, { formatter: n2 } = e2, r = n2.getMaxDigits(), s2 = extractDigits(i2.value, r);
|
|
164
|
+
return { newDigits: s2, caretDigitIndex: s2.length };
|
|
165
|
+
}
|
|
166
|
+
function processKeydown(i2, n2) {
|
|
167
|
+
if (!i2.target) return;
|
|
168
|
+
const r = i2.target, { digits: s2, formatter: c } = n2;
|
|
169
|
+
if (i2.ctrlKey || i2.metaKey || i2.altKey || e$1.includes(i2.key)) return;
|
|
170
|
+
const [g, a] = getSelection(r);
|
|
171
|
+
if ("Backspace" !== i2.key) if ("Delete" !== i2.key) /^[0-9]$/.test(i2.key) ? s2.length >= c.getMaxDigits() && i2.preventDefault() : 1 === i2.key.length && i2.preventDefault();
|
|
172
|
+
else {
|
|
173
|
+
if (i2.preventDefault(), g !== a) {
|
|
174
|
+
const t2 = c.getDigitRange(s2, g, a);
|
|
175
|
+
if (t2) {
|
|
176
|
+
const [e2, i3] = t2;
|
|
177
|
+
return { newDigits: s2.slice(0, e2) + s2.slice(i3), caretDigitIndex: e2 };
|
|
182
178
|
}
|
|
183
|
-
const parts = lang.split(/[-_]/);
|
|
184
|
-
if (parts.length > 1 && hasCountry(parts[1])) return parts[1].toUpperCase();
|
|
185
|
-
} catch {
|
|
186
179
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if (cached) {
|
|
193
|
-
const parsed = JSON.parse(cached);
|
|
194
|
-
const isExpired = Date.now() - parsed.ts > CACHE_EXPIRY_MS;
|
|
195
|
-
if (!isExpired && parsed.country_code && hasCountry(parsed.country_code)) {
|
|
196
|
-
return parsed.country_code.toUpperCase();
|
|
197
|
-
}
|
|
198
|
-
if (isExpired) {
|
|
199
|
-
localStorage.removeItem(CACHE_KEY);
|
|
200
|
-
}
|
|
180
|
+
if (g < r.value.length) {
|
|
181
|
+
const t2 = c.getDigitRange(s2, g, r.value.length);
|
|
182
|
+
if (t2) {
|
|
183
|
+
const [e2] = t2;
|
|
184
|
+
return { newDigits: s2.slice(0, e2) + s2.slice(e2 + 1), caretDigitIndex: e2 };
|
|
201
185
|
}
|
|
202
|
-
} catch {
|
|
203
186
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (!res.ok) {
|
|
212
|
-
return null;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
if (i2.preventDefault(), g !== a) {
|
|
190
|
+
const t2 = c.getDigitRange(s2, g, a);
|
|
191
|
+
if (t2) {
|
|
192
|
+
const [e2, i3] = t2;
|
|
193
|
+
return { newDigits: s2.slice(0, e2) + s2.slice(i3), caretDigitIndex: e2 };
|
|
213
194
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
195
|
+
}
|
|
196
|
+
if (g > 0) {
|
|
197
|
+
const e2 = r.value;
|
|
198
|
+
let i3 = g - 1;
|
|
199
|
+
for (; i3 >= 0 && t.includes(e2[i3]); ) i3--;
|
|
200
|
+
if (i3 >= 0) {
|
|
201
|
+
const t2 = c.getDigitRange(s2, i3, i3 + 1);
|
|
202
|
+
if (t2) {
|
|
203
|
+
const [e3] = t2;
|
|
204
|
+
return { newDigits: s2.slice(0, e3) + s2.slice(e3 + 1), caretDigitIndex: e3 };
|
|
220
205
|
}
|
|
221
|
-
return code;
|
|
222
206
|
}
|
|
223
|
-
} catch {
|
|
224
|
-
} finally {
|
|
225
|
-
clearTimeout(timeoutId);
|
|
226
207
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if (!detect) return;
|
|
241
|
-
const geo = await detectByGeoIp();
|
|
242
|
-
if (geo) {
|
|
243
|
-
selectInitialCountry(geo, emitFn);
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
const loc = detectFromLocale();
|
|
247
|
-
if (loc) {
|
|
248
|
-
selectInitialCountry(loc, emitFn);
|
|
249
|
-
return;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function processPaste(t2, e2) {
|
|
211
|
+
if (!t2.target) return;
|
|
212
|
+
t2.preventDefault();
|
|
213
|
+
const i2 = t2.target, { digits: n2, formatter: r } = e2, s2 = t2.clipboardData?.getData("text") || "", c = r.getMaxDigits(), g = extractDigits(s2, c);
|
|
214
|
+
if (0 === g.length) return;
|
|
215
|
+
const [a, o2] = getSelection(i2);
|
|
216
|
+
if (a !== o2) {
|
|
217
|
+
const t3 = r.getDigitRange(n2, a, o2);
|
|
218
|
+
if (t3) {
|
|
219
|
+
const [e3, i3] = t3;
|
|
220
|
+
return { newDigits: extractDigits(n2.slice(0, e3) + g + n2.slice(i3), c), caretDigitIndex: e3 + g.length };
|
|
250
221
|
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
selectedId,
|
|
255
|
-
selected,
|
|
256
|
-
hasCountry,
|
|
257
|
-
// Dropdown
|
|
258
|
-
hasDropdown,
|
|
259
|
-
dropdownOpened,
|
|
260
|
-
search,
|
|
261
|
-
focusedIndex,
|
|
262
|
-
filteredCountries,
|
|
263
|
-
selectCountry,
|
|
264
|
-
toggleDropdown,
|
|
265
|
-
closeDropdown,
|
|
266
|
-
focusNextOption,
|
|
267
|
-
focusPrevOption,
|
|
268
|
-
chooseFocusedOption,
|
|
269
|
-
// Country Detection
|
|
270
|
-
initCountry
|
|
271
|
-
};
|
|
222
|
+
}
|
|
223
|
+
const l = r.getDigitRange(n2, 0, a), f2 = l ? l[1] : 0;
|
|
224
|
+
return { newDigits: extractDigits(n2.slice(0, f2) + g + n2.slice(f2), c), caretDigitIndex: f2 + g.length };
|
|
272
225
|
}
|
|
273
|
-
function createPhoneFormatter(
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const getMask = (digitLength) => {
|
|
278
|
-
const mask = pickMaskVariant(variants, digitLength);
|
|
279
|
-
return removeCountryCodePrefix(mask);
|
|
226
|
+
function createPhoneFormatter(o2) {
|
|
227
|
+
const a = toArray(o2.mask), i2 = a.map((n2) => countPlaceholders(removeCountryCodePrefix(n2))), g = Math.max(...i2), getMask = (t2) => {
|
|
228
|
+
const n2 = pickMaskVariant(a, t2);
|
|
229
|
+
return removeCountryCodePrefix(n2);
|
|
280
230
|
};
|
|
281
|
-
return {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
},
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
if (digitIndex >= map.length) return display.length;
|
|
298
|
-
for (let i2 = 0; i2 < map.length; i2++) {
|
|
299
|
-
if (map[i2] > digitIndex) return i2;
|
|
300
|
-
}
|
|
301
|
-
return display.length;
|
|
302
|
-
},
|
|
303
|
-
getDigitRange: (digits, selStart, selEnd) => {
|
|
304
|
-
const template = getMask(digits.length);
|
|
305
|
-
const { map } = formatDigitsWithMap(template, digits);
|
|
306
|
-
let min = Infinity;
|
|
307
|
-
let max = -Infinity;
|
|
308
|
-
for (let i2 = selStart; i2 < selEnd && i2 < map.length; i2++) {
|
|
309
|
-
const digitIdx = map[i2];
|
|
310
|
-
if (digitIdx !== void 0 && digitIdx >= 0) {
|
|
311
|
-
min = Math.min(min, digitIdx);
|
|
312
|
-
max = Math.max(max, digitIdx);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
return min === Infinity ? null : [min, max + 1];
|
|
316
|
-
},
|
|
317
|
-
isComplete: (digits) => {
|
|
318
|
-
return variantsDigits.includes(digits.length);
|
|
231
|
+
return { formatDisplay: (t2) => {
|
|
232
|
+
const e2 = getMask(t2.length);
|
|
233
|
+
return formatDigitsWithMap(e2, t2).display;
|
|
234
|
+
}, getMaxDigits: () => g, getPlaceholder: () => getMask(0), getCaretPosition: (t2) => {
|
|
235
|
+
const e2 = getMask(t2), { display: r, map: l } = formatDigitsWithMap(e2, "0".repeat(t2));
|
|
236
|
+
for (let e3 = 0; e3 < l.length; e3++) if (l[e3] === t2) return e3;
|
|
237
|
+
if (t2 >= l.length) return r.length;
|
|
238
|
+
for (let e3 = 0; e3 < l.length; e3++) if (l[e3] > t2) return e3;
|
|
239
|
+
return r.length;
|
|
240
|
+
}, getDigitRange: (t2, e2, r) => {
|
|
241
|
+
const l = getMask(t2.length), { map: o3 } = formatDigitsWithMap(l, t2);
|
|
242
|
+
let a2 = 1 / 0, i3 = -1 / 0;
|
|
243
|
+
for (let t3 = e2; t3 < r && t3 < o3.length; t3++) {
|
|
244
|
+
const e3 = o3[t3];
|
|
245
|
+
void 0 !== e3 && e3 >= 0 && (a2 = Math.min(a2, e3), i3 = Math.max(i3, e3));
|
|
319
246
|
}
|
|
320
|
-
|
|
247
|
+
return a2 === 1 / 0 ? null : [a2, i3 + 1];
|
|
248
|
+
}, isComplete: (t2) => i2.includes(t2.length) };
|
|
321
249
|
}
|
|
322
|
-
|
|
323
|
-
|
|
250
|
+
const o = "https://ipapi.co/json/", e = 1500, p = "@desource/phone-mask:geo", s = 864e5;
|
|
251
|
+
async function detectCountryFromGeoIP(t2 = o, r = e) {
|
|
252
|
+
const n2 = new AbortController(), c = setTimeout(() => n2.abort(), r);
|
|
324
253
|
try {
|
|
325
|
-
|
|
254
|
+
const o2 = await fetch(t2, { signal: n2.signal, headers: { Accept: "application/json" } });
|
|
255
|
+
if (clearTimeout(c), !o2.ok) return null;
|
|
256
|
+
const e2 = await o2.json();
|
|
257
|
+
return (e2.country || e2.country_code || e2.countryCode || e2.country_code2 || "").toString().toUpperCase() || null;
|
|
326
258
|
} catch {
|
|
259
|
+
return clearTimeout(c), null;
|
|
327
260
|
}
|
|
328
261
|
}
|
|
329
|
-
function
|
|
330
|
-
|
|
331
|
-
|
|
262
|
+
async function detectByGeoIp() {
|
|
263
|
+
try {
|
|
264
|
+
const o3 = localStorage.getItem(p);
|
|
265
|
+
if (o3) {
|
|
266
|
+
const e3 = JSON.parse(o3), c = Date.now() - e3.ts > s, a = parseCountryCode(e3.country_code);
|
|
267
|
+
if (a && !c) return a;
|
|
268
|
+
localStorage.removeItem(p);
|
|
269
|
+
}
|
|
270
|
+
} catch {
|
|
271
|
+
}
|
|
272
|
+
const o2 = await detectCountryFromGeoIP(), e2 = parseCountryCode(o2);
|
|
273
|
+
if (e2) {
|
|
274
|
+
try {
|
|
275
|
+
const t2 = JSON.stringify({ country_code: e2, ts: Date.now() });
|
|
276
|
+
localStorage.setItem(p, t2);
|
|
277
|
+
} catch {
|
|
278
|
+
}
|
|
279
|
+
return e2;
|
|
280
|
+
}
|
|
281
|
+
return null;
|
|
332
282
|
}
|
|
333
|
-
function
|
|
334
|
-
|
|
335
|
-
|
|
283
|
+
function useCountry({
|
|
284
|
+
country: countryOption,
|
|
285
|
+
locale: localeOption,
|
|
286
|
+
detect,
|
|
287
|
+
onCountryChange
|
|
288
|
+
} = {}) {
|
|
289
|
+
const locale = vue.computed(() => vue.toValue(localeOption) || getNavigatorLang());
|
|
290
|
+
const countryCode = vue.ref(parseCountryCode(vue.toValue(countryOption), "US"));
|
|
291
|
+
const country = vue.computed(() => getCountry(countryCode.value, locale.value));
|
|
292
|
+
const setCountry = (code) => {
|
|
293
|
+
const parsed = parseCountryCode(code);
|
|
294
|
+
if (parsed) {
|
|
295
|
+
countryCode.value = parsed;
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
return false;
|
|
299
|
+
};
|
|
300
|
+
const detectCountry = async () => {
|
|
301
|
+
const geoCountry = await detectByGeoIp();
|
|
302
|
+
if (setCountry(geoCountry)) return;
|
|
303
|
+
const localeCountry = detectCountryFromLocale();
|
|
304
|
+
setCountry(localeCountry);
|
|
305
|
+
};
|
|
306
|
+
vue.watchEffect(() => {
|
|
307
|
+
const newCountry = vue.toValue(countryOption);
|
|
308
|
+
if (newCountry && newCountry !== countryCode.value) {
|
|
309
|
+
setCountry(newCountry);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
vue.watchEffect(() => {
|
|
313
|
+
if (vue.toValue(detect) && !vue.toValue(countryOption)) {
|
|
314
|
+
detectCountry();
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
vue.watchEffect(() => {
|
|
318
|
+
onCountryChange?.(country.value);
|
|
319
|
+
});
|
|
320
|
+
return { country, setCountry, locale };
|
|
336
321
|
}
|
|
337
|
-
function
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
322
|
+
function useFormatter({
|
|
323
|
+
country,
|
|
324
|
+
value,
|
|
325
|
+
onChange,
|
|
326
|
+
onPhoneChange,
|
|
327
|
+
onValidationChange
|
|
328
|
+
}) {
|
|
329
|
+
const formatter = vue.computed(() => createPhoneFormatter(vue.toValue(country)));
|
|
330
|
+
const maxDigits = vue.computed(() => formatter.value.getMaxDigits());
|
|
331
|
+
const digits = vue.computed(() => extractDigits(vue.toValue(value), maxDigits.value));
|
|
343
332
|
const displayPlaceholder = vue.computed(() => formatter.value.getPlaceholder());
|
|
333
|
+
const displayValue = vue.computed(() => formatter.value.formatDisplay(digits.value));
|
|
334
|
+
const full = vue.computed(() => digits.value ? `${vue.toValue(country).code}${digits.value}` : "");
|
|
335
|
+
const fullFormatted = vue.computed(() => displayValue.value ? `${vue.toValue(country).code} ${displayValue.value}` : "");
|
|
344
336
|
const isComplete = vue.computed(() => formatter.value.isComplete(digits.value));
|
|
345
337
|
const isEmpty = vue.computed(() => digits.value.length === 0);
|
|
346
|
-
const
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
338
|
+
const shouldShowWarn = vue.computed(() => !isEmpty.value && !isComplete.value);
|
|
339
|
+
const phoneData = vue.computed(() => ({
|
|
340
|
+
full: full.value,
|
|
341
|
+
fullFormatted: fullFormatted.value,
|
|
342
|
+
digits: digits.value
|
|
343
|
+
}));
|
|
344
|
+
vue.watchEffect(() => {
|
|
345
|
+
if (vue.toValue(value) !== digits.value) {
|
|
346
|
+
onChange(digits.value);
|
|
347
|
+
}
|
|
351
348
|
});
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
return `${selected.value.code}${digits.value}`;
|
|
349
|
+
vue.watchEffect(() => {
|
|
350
|
+
onPhoneChange?.(phoneData.value);
|
|
355
351
|
});
|
|
356
|
-
|
|
357
|
-
|
|
352
|
+
vue.watchEffect(() => {
|
|
353
|
+
onValidationChange?.(isComplete.value);
|
|
354
|
+
});
|
|
355
|
+
return {
|
|
356
|
+
digits,
|
|
357
|
+
formatter,
|
|
358
|
+
displayPlaceholder,
|
|
359
|
+
displayValue,
|
|
360
|
+
full,
|
|
361
|
+
fullFormatted,
|
|
362
|
+
isComplete,
|
|
363
|
+
isEmpty,
|
|
364
|
+
shouldShowWarn
|
|
358
365
|
};
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
366
|
+
}
|
|
367
|
+
function useTimer() {
|
|
368
|
+
let timerRef = null;
|
|
369
|
+
const clear = () => {
|
|
370
|
+
if (timerRef) {
|
|
371
|
+
clearTimeout(timerRef);
|
|
372
|
+
timerRef = null;
|
|
373
|
+
}
|
|
362
374
|
};
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
375
|
+
const set = (callback, delay) => {
|
|
376
|
+
clear();
|
|
377
|
+
timerRef = setTimeout(callback, delay);
|
|
366
378
|
};
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
379
|
+
vue.onUnmounted(clear);
|
|
380
|
+
return { set, clear };
|
|
381
|
+
}
|
|
382
|
+
function useValidationHint() {
|
|
383
|
+
const showValidationHint = vue.ref(false);
|
|
384
|
+
const validationTimer = useTimer();
|
|
385
|
+
const clearValidationHint = (hideHint = true) => {
|
|
386
|
+
if (hideHint) showValidationHint.value = false;
|
|
387
|
+
validationTimer.clear();
|
|
375
388
|
};
|
|
376
|
-
const
|
|
377
|
-
const el = e.target;
|
|
378
|
-
if (!el) return;
|
|
379
|
-
const newDigits = extractDigits(el.value, maxDigits.value);
|
|
389
|
+
const scheduleValidationHint = (delay) => {
|
|
380
390
|
showValidationHint.value = false;
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
+
validationTimer.set(() => {
|
|
392
|
+
showValidationHint.value = true;
|
|
393
|
+
}, delay);
|
|
394
|
+
};
|
|
395
|
+
return { showValidationHint, clearValidationHint, scheduleValidationHint };
|
|
396
|
+
}
|
|
397
|
+
const HINT_DELAY_INPUT = 500;
|
|
398
|
+
const HINT_DELAY_ACTION = 300;
|
|
399
|
+
function useInputHandlers(options) {
|
|
400
|
+
const { formatter, digits, inactive, onChange, scheduleValidationHint } = options;
|
|
401
|
+
const scheduleCaretUpdate = (el, digitIndex) => {
|
|
391
402
|
vue.nextTick(() => {
|
|
392
|
-
|
|
403
|
+
if (!el) return;
|
|
404
|
+
const pos = vue.toValue(formatter).getCaretPosition(digitIndex);
|
|
405
|
+
setCaret(el, pos);
|
|
393
406
|
});
|
|
394
407
|
};
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
if (!el) return;
|
|
398
|
-
if (e.ctrlKey || e.metaKey || e.altKey || NavigationKeys.includes(e.key)) return;
|
|
399
|
-
const [selStart, selEnd] = getSelection(el);
|
|
400
|
-
if (e.key === "Backspace") {
|
|
401
|
-
e.preventDefault();
|
|
402
|
-
if (selStart !== selEnd) {
|
|
403
|
-
const range = formatter.value.getDigitRange(digits.value, selStart, selEnd);
|
|
404
|
-
if (range) {
|
|
405
|
-
const [start, end] = range;
|
|
406
|
-
removeDigitsRange(start, end);
|
|
407
|
-
updateDisplay2();
|
|
408
|
-
vue.nextTick(() => setCaretToDigitPosition(start));
|
|
409
|
-
}
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
if (selStart > 0) {
|
|
413
|
-
const displayStr = displayValue.value;
|
|
414
|
-
let prevPos = selStart - 1;
|
|
415
|
-
while (prevPos >= 0 && Delimiters.includes(displayStr[prevPos])) {
|
|
416
|
-
prevPos--;
|
|
417
|
-
}
|
|
418
|
-
if (prevPos >= 0) {
|
|
419
|
-
const range = formatter.value.getDigitRange(digits.value, prevPos, prevPos + 1);
|
|
420
|
-
if (range) {
|
|
421
|
-
const [start] = range;
|
|
422
|
-
removeDigitsRange(start, start + 1);
|
|
423
|
-
updateDisplay2();
|
|
424
|
-
vue.nextTick(() => setCaretToDigitPosition(start));
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
430
|
-
if (e.key === "Delete") {
|
|
431
|
-
e.preventDefault();
|
|
432
|
-
if (selStart !== selEnd) {
|
|
433
|
-
const range = formatter.value.getDigitRange(digits.value, selStart, selEnd);
|
|
434
|
-
if (range) {
|
|
435
|
-
const [start, end] = range;
|
|
436
|
-
removeDigitsRange(start, end);
|
|
437
|
-
updateDisplay2();
|
|
438
|
-
vue.nextTick(() => setCaretToDigitPosition(start));
|
|
439
|
-
}
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
if (selStart < displayValue.value.length) {
|
|
443
|
-
const range = formatter.value.getDigitRange(digits.value, selStart, selStart + 1);
|
|
444
|
-
if (range) {
|
|
445
|
-
const [start] = range;
|
|
446
|
-
removeDigitsRange(start, start + 1);
|
|
447
|
-
updateDisplay2();
|
|
448
|
-
vue.nextTick(() => setCaretToDigitPosition(start));
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
if (/^[0-9]$/.test(e.key)) {
|
|
454
|
-
if (digits.value.length >= maxDigits.value) {
|
|
455
|
-
e.preventDefault();
|
|
456
|
-
}
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
if (e.key.length === 1) {
|
|
460
|
-
e.preventDefault();
|
|
461
|
-
}
|
|
408
|
+
const handleBeforeInput = (e2) => {
|
|
409
|
+
processBeforeInput(e2);
|
|
462
410
|
};
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
411
|
+
const handleInput = (e2) => {
|
|
412
|
+
if (vue.toValue(inactive)) return;
|
|
413
|
+
const result = processInput(e2, { formatter: vue.toValue(formatter) });
|
|
414
|
+
if (!result) return;
|
|
415
|
+
onChange?.(result.newDigits);
|
|
416
|
+
scheduleCaretUpdate(e2.target, result.caretDigitIndex);
|
|
417
|
+
scheduleValidationHint?.(HINT_DELAY_INPUT);
|
|
418
|
+
};
|
|
419
|
+
const handleKeydown = (e2) => {
|
|
420
|
+
if (vue.toValue(inactive)) return;
|
|
421
|
+
const result = processKeydown(e2, { digits: vue.toValue(digits), formatter: vue.toValue(formatter) });
|
|
422
|
+
if (!result) return;
|
|
423
|
+
onChange?.(result.newDigits);
|
|
424
|
+
scheduleCaretUpdate(e2.target, result.caretDigitIndex);
|
|
425
|
+
scheduleValidationHint?.(HINT_DELAY_ACTION);
|
|
426
|
+
};
|
|
427
|
+
const handlePaste = (e2) => {
|
|
428
|
+
if (vue.toValue(inactive)) return;
|
|
429
|
+
const result = processPaste(e2, { digits: vue.toValue(digits), formatter: vue.toValue(formatter) });
|
|
430
|
+
if (!result) return;
|
|
431
|
+
onChange?.(result.newDigits);
|
|
432
|
+
scheduleCaretUpdate(e2.target, result.caretDigitIndex);
|
|
433
|
+
scheduleValidationHint?.(HINT_DELAY_ACTION);
|
|
434
|
+
};
|
|
435
|
+
return {
|
|
436
|
+
handleBeforeInput,
|
|
437
|
+
handleInput,
|
|
438
|
+
handleKeydown,
|
|
439
|
+
handlePaste
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
function useCountrySelector({
|
|
443
|
+
rootRef,
|
|
444
|
+
dropdownRef,
|
|
445
|
+
searchRef,
|
|
446
|
+
selectorRef,
|
|
447
|
+
locale,
|
|
448
|
+
countryOption,
|
|
449
|
+
inactive,
|
|
450
|
+
onSelectCountry,
|
|
451
|
+
onAfterSelect
|
|
452
|
+
}) {
|
|
453
|
+
const search = vue.ref("");
|
|
454
|
+
const dropdownOpen = vue.ref(false);
|
|
455
|
+
const dropdownStyle = vue.shallowRef({});
|
|
456
|
+
const focusedIndex = vue.ref(0);
|
|
457
|
+
const countries = vue.computed(() => MasksFull(vue.toValue(locale)));
|
|
458
|
+
const filteredCountries = vue.computed(() => filterCountries(countries.value, search.value));
|
|
459
|
+
const hasDropdown = vue.computed(() => !vue.toValue(countryOption) && countries.value.length > 1);
|
|
460
|
+
const setFocusedIndex = (index2) => {
|
|
461
|
+
focusedIndex.value = index2;
|
|
462
|
+
};
|
|
463
|
+
const focusSearch = () => {
|
|
464
|
+
vue.nextTick(() => searchRef.value?.focus({ preventScroll: true }));
|
|
465
|
+
};
|
|
466
|
+
const closeDropdown = () => {
|
|
467
|
+
dropdownOpen.value = false;
|
|
468
|
+
};
|
|
469
|
+
const openDropdown = () => {
|
|
470
|
+
dropdownOpen.value = true;
|
|
471
|
+
setFocusedIndex(0);
|
|
472
|
+
focusSearch();
|
|
473
|
+
};
|
|
474
|
+
const toggleDropdown = () => {
|
|
475
|
+
if (vue.toValue(inactive) || !hasDropdown.value) return;
|
|
476
|
+
if (dropdownOpen.value) {
|
|
477
|
+
closeDropdown();
|
|
478
|
+
} else {
|
|
479
|
+
openDropdown();
|
|
467
480
|
}
|
|
468
|
-
handleKeydownInternal(e);
|
|
469
|
-
if (validationTimer.value) clearTimeout(validationTimer.value);
|
|
470
|
-
validationTimer.value = setTimeout(() => {
|
|
471
|
-
if (!isComplete.value && !isEmpty.value) showValidationHint.value = true;
|
|
472
|
-
}, 300);
|
|
473
481
|
};
|
|
474
|
-
const
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
482
|
+
const selectCountry = (code) => {
|
|
483
|
+
onSelectCountry(code);
|
|
484
|
+
closeDropdown();
|
|
485
|
+
search.value = "";
|
|
486
|
+
setFocusedIndex(0);
|
|
487
|
+
onAfterSelect?.();
|
|
488
|
+
};
|
|
489
|
+
const handleSearchChange = (e2) => {
|
|
490
|
+
search.value = e2.target.value;
|
|
491
|
+
setFocusedIndex(0);
|
|
492
|
+
};
|
|
493
|
+
const onDocClick = (ev) => {
|
|
494
|
+
const target = ev.target;
|
|
495
|
+
const dropdownEl = dropdownRef.value;
|
|
496
|
+
const selectorEl = selectorRef.value;
|
|
497
|
+
if (!target) return;
|
|
498
|
+
if (dropdownEl?.contains(target)) return;
|
|
499
|
+
if (selectorEl?.contains(target)) return;
|
|
500
|
+
closeDropdown();
|
|
501
|
+
};
|
|
502
|
+
const positionDropdown = (e2) => {
|
|
503
|
+
if (e2?.type === "scroll" && e2.target && dropdownRef.value?.contains(e2.target)) return;
|
|
504
|
+
if (!rootRef.value) return;
|
|
505
|
+
const rect = rootRef.value.getBoundingClientRect();
|
|
506
|
+
dropdownStyle.value = {
|
|
507
|
+
top: `${rect.bottom + window.scrollY + 8}px`,
|
|
508
|
+
left: `${rect.left + window.scrollX}px`,
|
|
509
|
+
width: `${rect.width}px`
|
|
510
|
+
};
|
|
511
|
+
};
|
|
512
|
+
const scrollFocusedIntoView = () => {
|
|
513
|
+
vue.nextTick(() => {
|
|
514
|
+
const list = dropdownRef.value?.lastElementChild;
|
|
515
|
+
const option = list?.children[focusedIndex.value];
|
|
516
|
+
if (!list || !option) return;
|
|
517
|
+
const listRect = list.getBoundingClientRect();
|
|
518
|
+
const optionRect = option.getBoundingClientRect();
|
|
519
|
+
let scrollAmount = 0;
|
|
520
|
+
if (optionRect.top < listRect.top) {
|
|
521
|
+
scrollAmount = list.scrollTop - (listRect.top - optionRect.top);
|
|
522
|
+
} else if (optionRect.bottom > listRect.bottom) {
|
|
523
|
+
scrollAmount = list.scrollTop + (optionRect.bottom - listRect.bottom);
|
|
524
|
+
} else {
|
|
491
525
|
return;
|
|
492
526
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
const insertIndex = range ? range[0] : digits.value.length;
|
|
496
|
-
const left = digits.value.slice(0, insertIndex);
|
|
497
|
-
const right = digits.value.slice(insertIndex);
|
|
498
|
-
digits.value = extractDigits(left + pastedDigits + right, maxDigits.value);
|
|
499
|
-
updateDisplay2();
|
|
500
|
-
if (validationTimer.value) clearTimeout(validationTimer.value);
|
|
501
|
-
validationTimer.value = setTimeout(() => {
|
|
502
|
-
if (!isComplete.value && !isEmpty.value) showValidationHint.value = true;
|
|
503
|
-
}, 300);
|
|
504
|
-
vue.nextTick(() => setCaretToDigitPosition(insertIndex + pastedDigits.length));
|
|
527
|
+
list.scrollTo({ top: scrollAmount, behavior: "smooth" });
|
|
528
|
+
});
|
|
505
529
|
};
|
|
506
|
-
const
|
|
507
|
-
if (
|
|
508
|
-
|
|
530
|
+
const handleSearchKeydown = (e2) => {
|
|
531
|
+
if (e2.key === "ArrowDown") {
|
|
532
|
+
e2.preventDefault();
|
|
533
|
+
setFocusedIndex(Math.min(focusedIndex.value + 1, filteredCountries.value.length - 1));
|
|
534
|
+
scrollFocusedIntoView();
|
|
535
|
+
} else if (e2.key === "ArrowUp") {
|
|
536
|
+
e2.preventDefault();
|
|
537
|
+
setFocusedIndex(Math.max(focusedIndex.value - 1, 0));
|
|
538
|
+
scrollFocusedIntoView();
|
|
539
|
+
} else if (e2.key === "Enter" && filteredCountries.value[focusedIndex.value]) {
|
|
540
|
+
e2.preventDefault();
|
|
541
|
+
selectCountry(filteredCountries.value[focusedIndex.value].id);
|
|
542
|
+
} else if (e2.key === "Escape") {
|
|
543
|
+
closeDropdown();
|
|
509
544
|
}
|
|
510
545
|
};
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
if (validationTimer.value) {
|
|
516
|
-
clearTimeout(validationTimer.value);
|
|
517
|
-
validationTimer.value = null;
|
|
518
|
-
}
|
|
546
|
+
const removeListeners = () => {
|
|
547
|
+
window.removeEventListener("resize", positionDropdown);
|
|
548
|
+
window.removeEventListener("scroll", positionDropdown, true);
|
|
549
|
+
window.removeEventListener("click", onDocClick, true);
|
|
519
550
|
};
|
|
520
|
-
vue.watch(
|
|
521
|
-
if (
|
|
522
|
-
|
|
551
|
+
vue.watch(hasDropdown, (dropdownExists) => {
|
|
552
|
+
if (!dropdownExists && dropdownOpen.value) {
|
|
553
|
+
closeDropdown();
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
vue.watch(dropdownOpen, (isOpen) => {
|
|
557
|
+
if (!isOpen) {
|
|
558
|
+
removeListeners();
|
|
559
|
+
return;
|
|
523
560
|
}
|
|
524
|
-
|
|
561
|
+
positionDropdown();
|
|
562
|
+
window.addEventListener("resize", positionDropdown);
|
|
563
|
+
window.addEventListener("scroll", positionDropdown, true);
|
|
564
|
+
window.addEventListener("click", onDocClick, true);
|
|
525
565
|
});
|
|
526
|
-
|
|
566
|
+
vue.onBeforeUnmount(removeListeners);
|
|
527
567
|
return {
|
|
528
568
|
// State
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
// Methods
|
|
545
|
-
updateDisplayFromDigits: updateDisplay2,
|
|
546
|
-
clear
|
|
569
|
+
dropdownOpen,
|
|
570
|
+
search,
|
|
571
|
+
focusedIndex,
|
|
572
|
+
dropdownStyle,
|
|
573
|
+
// Derived
|
|
574
|
+
filteredCountries,
|
|
575
|
+
hasDropdown,
|
|
576
|
+
// Actions
|
|
577
|
+
openDropdown,
|
|
578
|
+
closeDropdown,
|
|
579
|
+
toggleDropdown,
|
|
580
|
+
selectCountry,
|
|
581
|
+
setFocusedIndex,
|
|
582
|
+
handleSearchChange,
|
|
583
|
+
handleSearchKeydown
|
|
547
584
|
};
|
|
548
585
|
}
|
|
549
|
-
function useClipboard() {
|
|
586
|
+
function useClipboard(delay = 1800) {
|
|
550
587
|
const copied = vue.ref(false);
|
|
551
588
|
const isCopying = vue.ref(false);
|
|
552
|
-
|
|
553
|
-
const clearTimer = () => {
|
|
554
|
-
if (copyTimer) {
|
|
555
|
-
clearTimeout(copyTimer);
|
|
556
|
-
copyTimer = null;
|
|
557
|
-
}
|
|
558
|
-
};
|
|
589
|
+
const copyTimer = useTimer();
|
|
559
590
|
const copy = async (text) => {
|
|
560
591
|
if (isCopying.value) return false;
|
|
561
592
|
const trimmedText = text.trim();
|
|
@@ -564,11 +595,9 @@ var lib = (function(exports, vue) {
|
|
|
564
595
|
try {
|
|
565
596
|
await navigator.clipboard.writeText(trimmedText);
|
|
566
597
|
copied.value = true;
|
|
567
|
-
|
|
568
|
-
copyTimer = setTimeout(() => {
|
|
598
|
+
copyTimer.set(() => {
|
|
569
599
|
copied.value = false;
|
|
570
|
-
|
|
571
|
-
}, 1800);
|
|
600
|
+
}, delay);
|
|
572
601
|
return true;
|
|
573
602
|
} catch (err) {
|
|
574
603
|
console.warn("Copy failed", err);
|
|
@@ -577,24 +606,71 @@ var lib = (function(exports, vue) {
|
|
|
577
606
|
isCopying.value = false;
|
|
578
607
|
}
|
|
579
608
|
};
|
|
580
|
-
|
|
581
|
-
|
|
609
|
+
return { copied, isCopying, copy };
|
|
610
|
+
}
|
|
611
|
+
const DELAY = 1800;
|
|
612
|
+
function useCopyAction({ liveRef, fullFormatted, onCopy }) {
|
|
613
|
+
const liveTimer = useTimer();
|
|
614
|
+
const { copied, copy } = useClipboard(DELAY);
|
|
615
|
+
const copyAriaLabel = vue.computed(() => copied.value ? "Copied" : `Copy ${fullFormatted.value}`);
|
|
616
|
+
const copyButtonTitle = vue.computed(() => copied.value ? "Copied" : "Copy phone number");
|
|
617
|
+
const announceToScreenReader = (message) => {
|
|
618
|
+
if (!liveRef?.value) return;
|
|
619
|
+
liveRef.value.textContent = message;
|
|
620
|
+
liveTimer.set(() => {
|
|
621
|
+
if (liveRef.value) liveRef.value.textContent = "";
|
|
622
|
+
}, DELAY);
|
|
623
|
+
};
|
|
624
|
+
const onCopyClick = async () => {
|
|
625
|
+
const valueToCopy = fullFormatted.value.trim();
|
|
626
|
+
const success = await copy(valueToCopy);
|
|
627
|
+
if (success) {
|
|
628
|
+
onCopy?.(valueToCopy);
|
|
629
|
+
announceToScreenReader("Phone number copied to clipboard");
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
return {
|
|
633
|
+
copied,
|
|
634
|
+
copyAriaLabel,
|
|
635
|
+
copyButtonTitle,
|
|
636
|
+
onCopyClick
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
function useTheme({ theme }) {
|
|
640
|
+
const systemDark = vue.ref(false);
|
|
641
|
+
const themeClass = vue.computed(() => {
|
|
642
|
+
return vue.toValue(theme) !== "auto" ? `theme-${vue.toValue(theme)}` : systemDark.value ? "theme-dark" : "theme-light";
|
|
643
|
+
});
|
|
644
|
+
let mq = null;
|
|
645
|
+
const handler = (e2) => {
|
|
646
|
+
systemDark.value = e2.matches;
|
|
647
|
+
};
|
|
648
|
+
vue.onBeforeMount(() => {
|
|
649
|
+
if (typeof window === "undefined") return;
|
|
650
|
+
mq = window.matchMedia?.("(prefers-color-scheme: dark)") ?? null;
|
|
651
|
+
if (!mq) return;
|
|
652
|
+
systemDark.value = mq.matches;
|
|
653
|
+
mq.addEventListener("change", handler);
|
|
654
|
+
});
|
|
655
|
+
vue.onBeforeUnmount(() => {
|
|
656
|
+
mq?.removeEventListener("change", handler);
|
|
657
|
+
});
|
|
658
|
+
return {
|
|
659
|
+
themeClass
|
|
582
660
|
};
|
|
583
|
-
return { copied, isCopying, copy, onUnmount };
|
|
584
661
|
}
|
|
585
|
-
const _hoisted_1 =
|
|
586
|
-
const _hoisted_2 = ["
|
|
587
|
-
const _hoisted_3 =
|
|
588
|
-
const _hoisted_4 = { class: "pi-
|
|
589
|
-
const _hoisted_5 =
|
|
590
|
-
const _hoisted_6 =
|
|
591
|
-
const _hoisted_7 = {
|
|
662
|
+
const _hoisted_1 = ["disabled", "tabindex", "aria-label", "aria-expanded", "aria-haspopup"];
|
|
663
|
+
const _hoisted_2 = ["aria-label"];
|
|
664
|
+
const _hoisted_3 = { class: "pi-code" };
|
|
665
|
+
const _hoisted_4 = { class: "pi-input-wrap" };
|
|
666
|
+
const _hoisted_5 = ["placeholder", "value", "disabled", "readonly", "aria-invalid"];
|
|
667
|
+
const _hoisted_6 = {
|
|
592
668
|
class: "pi-actions",
|
|
593
669
|
role: "toolbar",
|
|
594
670
|
"aria-label": "Phone input actions"
|
|
595
671
|
};
|
|
596
|
-
const
|
|
597
|
-
const
|
|
672
|
+
const _hoisted_7 = ["aria-label", "title"];
|
|
673
|
+
const _hoisted_8 = {
|
|
598
674
|
key: 1,
|
|
599
675
|
width: "16",
|
|
600
676
|
height: "16",
|
|
@@ -602,7 +678,7 @@ var lib = (function(exports, vue) {
|
|
|
602
678
|
fill: "none",
|
|
603
679
|
"aria-hidden": "true"
|
|
604
680
|
};
|
|
605
|
-
const
|
|
681
|
+
const _hoisted_9 = {
|
|
606
682
|
key: 2,
|
|
607
683
|
width: "16",
|
|
608
684
|
height: "16",
|
|
@@ -610,8 +686,8 @@ var lib = (function(exports, vue) {
|
|
|
610
686
|
fill: "none",
|
|
611
687
|
"aria-hidden": "true"
|
|
612
688
|
};
|
|
613
|
-
const
|
|
614
|
-
const
|
|
689
|
+
const _hoisted_10 = ["aria-label", "title"];
|
|
690
|
+
const _hoisted_11 = {
|
|
615
691
|
key: 0,
|
|
616
692
|
width: "11",
|
|
617
693
|
height: "11",
|
|
@@ -619,14 +695,14 @@ var lib = (function(exports, vue) {
|
|
|
619
695
|
fill: "none",
|
|
620
696
|
"aria-hidden": "true"
|
|
621
697
|
};
|
|
622
|
-
const
|
|
623
|
-
const
|
|
624
|
-
const
|
|
625
|
-
const
|
|
626
|
-
const
|
|
627
|
-
const
|
|
628
|
-
const
|
|
629
|
-
const
|
|
698
|
+
const _hoisted_12 = { class: "pi-search-wrap" };
|
|
699
|
+
const _hoisted_13 = ["value", "placeholder"];
|
|
700
|
+
const _hoisted_14 = ["aria-activedescendant"];
|
|
701
|
+
const _hoisted_15 = ["id", "aria-selected", "title", "onClick", "onMouseenter"];
|
|
702
|
+
const _hoisted_16 = ["aria-label"];
|
|
703
|
+
const _hoisted_17 = { class: "pi-opt-name" };
|
|
704
|
+
const _hoisted_18 = { class: "pi-opt-code" };
|
|
705
|
+
const _hoisted_19 = {
|
|
630
706
|
key: 0,
|
|
631
707
|
class: "pi-empty"
|
|
632
708
|
};
|
|
@@ -649,242 +725,133 @@ var lib = (function(exports, vue) {
|
|
|
649
725
|
dropdownClass: {},
|
|
650
726
|
disableDefaultStyles: { type: Boolean, default: false }
|
|
651
727
|
}, {
|
|
652
|
-
"modelValue": {},
|
|
728
|
+
"modelValue": { default: "" },
|
|
653
729
|
"modelModifiers": {}
|
|
654
730
|
}),
|
|
655
731
|
emits: /* @__PURE__ */ vue.mergeModels(["change", "country-change", "validation-change", "focus", "blur", "copy", "clear"], ["update:modelValue"]),
|
|
656
732
|
setup(__props, { expose: __expose, emit: __emit }) {
|
|
657
733
|
const props = __props;
|
|
658
734
|
const slots = vue.useSlots();
|
|
659
|
-
const model = vue.useModel(__props, "modelValue");
|
|
660
735
|
const emit = __emit;
|
|
736
|
+
const model = vue.useModel(__props, "modelValue");
|
|
737
|
+
const onChange = (v) => {
|
|
738
|
+
model.value = v;
|
|
739
|
+
};
|
|
740
|
+
const { country, setCountry, locale } = useCountry({
|
|
741
|
+
country: () => props.country,
|
|
742
|
+
locale: () => props.locale,
|
|
743
|
+
detect: () => props.detect,
|
|
744
|
+
onCountryChange: (c) => emit("country-change", c)
|
|
745
|
+
});
|
|
746
|
+
const {
|
|
747
|
+
digits,
|
|
748
|
+
formatter,
|
|
749
|
+
displayPlaceholder,
|
|
750
|
+
displayValue,
|
|
751
|
+
full,
|
|
752
|
+
fullFormatted,
|
|
753
|
+
isComplete,
|
|
754
|
+
isEmpty,
|
|
755
|
+
shouldShowWarn
|
|
756
|
+
} = useFormatter({
|
|
757
|
+
country,
|
|
758
|
+
value: model,
|
|
759
|
+
onChange,
|
|
760
|
+
onPhoneChange: (data) => emit("change", data),
|
|
761
|
+
onValidationChange: (complete) => emit("validation-change", complete)
|
|
762
|
+
});
|
|
763
|
+
const { showValidationHint, clearValidationHint, scheduleValidationHint } = useValidationHint();
|
|
661
764
|
const rootRef = vue.useTemplateRef("rootRef");
|
|
662
765
|
const telRef = vue.useTemplateRef("telRef");
|
|
663
|
-
const searchRef = vue.useTemplateRef("searchRef");
|
|
664
766
|
const liveRef = vue.useTemplateRef("liveRef");
|
|
665
767
|
const dropdownRef = vue.useTemplateRef("dropdownRef");
|
|
666
|
-
const
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
768
|
+
const searchRef = vue.useTemplateRef("searchRef");
|
|
769
|
+
const selectorRef = vue.useTemplateRef("selectorRef");
|
|
770
|
+
const inactive = vue.computed(() => props.disabled || props.readonly);
|
|
771
|
+
const incomplete = vue.computed(() => showValidationHint.value && shouldShowWarn.value);
|
|
772
|
+
const showCopyButton = vue.computed(() => props.showCopy && !isEmpty.value && !props.disabled);
|
|
773
|
+
const showClearButton = vue.computed(() => props.showClear && !isEmpty.value && !inactive.value);
|
|
774
|
+
const { copied, copyAriaLabel, copyButtonTitle, onCopyClick } = useCopyAction({
|
|
775
|
+
liveRef,
|
|
776
|
+
fullFormatted,
|
|
777
|
+
onCopy: (v) => emit("copy", v)
|
|
672
778
|
});
|
|
673
|
-
const
|
|
674
|
-
const countrySelector = useCountrySelector(usedLocale);
|
|
779
|
+
const focusInput = () => vue.nextTick(() => telRef.value?.focus());
|
|
675
780
|
const {
|
|
781
|
+
dropdownOpen,
|
|
676
782
|
search,
|
|
677
|
-
filteredCountries,
|
|
678
783
|
focusedIndex,
|
|
679
|
-
|
|
680
|
-
|
|
784
|
+
dropdownStyle,
|
|
785
|
+
filteredCountries,
|
|
681
786
|
hasDropdown,
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
787
|
+
closeDropdown,
|
|
788
|
+
toggleDropdown,
|
|
789
|
+
selectCountry,
|
|
790
|
+
setFocusedIndex,
|
|
791
|
+
handleSearchChange,
|
|
792
|
+
handleSearchKeydown
|
|
793
|
+
} = useCountrySelector({
|
|
794
|
+
rootRef,
|
|
795
|
+
dropdownRef,
|
|
796
|
+
searchRef,
|
|
797
|
+
selectorRef,
|
|
798
|
+
locale,
|
|
799
|
+
countryOption: () => props.country,
|
|
800
|
+
inactive,
|
|
801
|
+
onSelectCountry: setCountry,
|
|
802
|
+
onAfterSelect: focusInput
|
|
803
|
+
});
|
|
804
|
+
const { handleBeforeInput, handleInput, handleKeydown, handlePaste } = useInputHandlers({
|
|
805
|
+
formatter,
|
|
806
|
+
digits,
|
|
807
|
+
inactive,
|
|
808
|
+
onChange,
|
|
809
|
+
scheduleValidationHint
|
|
810
|
+
});
|
|
811
|
+
const handleFocus = (e2) => {
|
|
812
|
+
clearValidationHint(false);
|
|
813
|
+
closeDropdown();
|
|
814
|
+
emit("focus", e2);
|
|
815
|
+
};
|
|
816
|
+
const handleBlur = (e2) => emit("blur", e2);
|
|
817
|
+
const clear = () => {
|
|
818
|
+
onChange("");
|
|
819
|
+
clearValidationHint();
|
|
820
|
+
emit("clear");
|
|
821
|
+
};
|
|
822
|
+
const onClearClick = () => {
|
|
823
|
+
clear();
|
|
824
|
+
focusInput();
|
|
825
|
+
};
|
|
826
|
+
__expose({
|
|
827
|
+
focus: focusInput,
|
|
828
|
+
blur: () => telRef.value?.blur(),
|
|
829
|
+
clear,
|
|
830
|
+
selectCountry,
|
|
831
|
+
getFullNumber: () => full.value,
|
|
832
|
+
getFullFormattedNumber: () => fullFormatted.value,
|
|
833
|
+
getDigits: () => digits.value,
|
|
834
|
+
isValid: () => isComplete.value,
|
|
835
|
+
isComplete: () => isComplete.value
|
|
836
|
+
});
|
|
837
|
+
const { themeClass } = useTheme({
|
|
838
|
+
theme: () => props.theme
|
|
703
839
|
});
|
|
704
840
|
const rootClasses = vue.computed(() => [
|
|
705
841
|
"phone-input",
|
|
706
|
-
|
|
842
|
+
`size-${props.size}`,
|
|
707
843
|
themeClass.value,
|
|
708
844
|
{
|
|
709
845
|
"is-disabled": props.disabled,
|
|
710
846
|
"is-readonly": props.readonly,
|
|
711
847
|
"is-unstyled": props.disableDefaultStyles,
|
|
712
|
-
"is-incomplete": props.withValidity &&
|
|
848
|
+
"is-incomplete": props.withValidity && incomplete.value,
|
|
713
849
|
"is-complete": props.withValidity && isComplete.value
|
|
714
850
|
}
|
|
715
851
|
]);
|
|
716
852
|
const rootStyles = vue.computed(() => ({
|
|
717
853
|
"--pi-actions-count": +showCopyButton.value + +showClearButton.value + (slots["actions-before"] ? 1 : 0)
|
|
718
854
|
}));
|
|
719
|
-
const emitModelUpdate = () => {
|
|
720
|
-
if (model.value === digits.value) return;
|
|
721
|
-
model.value = digits.value;
|
|
722
|
-
emit("change", {
|
|
723
|
-
full: full.value,
|
|
724
|
-
fullFormatted: fullFormatted.value,
|
|
725
|
-
digits: digits.value
|
|
726
|
-
});
|
|
727
|
-
};
|
|
728
|
-
const onInput = async (e) => {
|
|
729
|
-
if (inactive.value) return;
|
|
730
|
-
mask.handleInput(e);
|
|
731
|
-
await vue.nextTick();
|
|
732
|
-
emitModelUpdate();
|
|
733
|
-
};
|
|
734
|
-
const onKeydown = async (e) => {
|
|
735
|
-
if (inactive.value) return;
|
|
736
|
-
mask.handleKeydown(e);
|
|
737
|
-
await vue.nextTick();
|
|
738
|
-
emitModelUpdate();
|
|
739
|
-
};
|
|
740
|
-
const onPaste = async (e) => {
|
|
741
|
-
if (inactive.value) return;
|
|
742
|
-
mask.handlePaste(e);
|
|
743
|
-
await vue.nextTick();
|
|
744
|
-
emitModelUpdate();
|
|
745
|
-
};
|
|
746
|
-
const onFocus = (e) => {
|
|
747
|
-
mask.handleFocus();
|
|
748
|
-
dropdownOpened.value = false;
|
|
749
|
-
emit("focus", e);
|
|
750
|
-
};
|
|
751
|
-
const onBlur = (e) => emit("blur", e);
|
|
752
|
-
const onSelectCountry = async (countryId) => {
|
|
753
|
-
countrySelector.selectCountry(countryId);
|
|
754
|
-
emit("country-change", selected.value);
|
|
755
|
-
await vue.nextTick();
|
|
756
|
-
telRef.value?.focus();
|
|
757
|
-
};
|
|
758
|
-
const onCopyClick = async () => {
|
|
759
|
-
const valueToCopy = fullFormatted.value;
|
|
760
|
-
const success = await copy(valueToCopy);
|
|
761
|
-
if (success) {
|
|
762
|
-
emit("copy", valueToCopy);
|
|
763
|
-
}
|
|
764
|
-
};
|
|
765
|
-
const onClearClick = async () => {
|
|
766
|
-
mask.clear();
|
|
767
|
-
model.value = "";
|
|
768
|
-
emit("change", {
|
|
769
|
-
full: "",
|
|
770
|
-
fullFormatted: "",
|
|
771
|
-
digits: ""
|
|
772
|
-
});
|
|
773
|
-
emit("clear");
|
|
774
|
-
await vue.nextTick();
|
|
775
|
-
telRef.value?.focus();
|
|
776
|
-
};
|
|
777
|
-
const positionDropdown = (e) => {
|
|
778
|
-
if (e?.type === "scroll" && e.target && dropdownRef.value?.contains(e.target)) return;
|
|
779
|
-
const root = rootRef.value;
|
|
780
|
-
if (!root) return;
|
|
781
|
-
const rect = root.getBoundingClientRect();
|
|
782
|
-
dropdownStyle.value = {
|
|
783
|
-
top: `${rect.bottom + window.scrollY + 8}px`,
|
|
784
|
-
left: `${rect.left + window.scrollX}px`,
|
|
785
|
-
width: `${rect.width}px`
|
|
786
|
-
};
|
|
787
|
-
};
|
|
788
|
-
const removeDropdownListeners = () => {
|
|
789
|
-
window.removeEventListener("scroll", positionDropdown, true);
|
|
790
|
-
window.removeEventListener("click", onDocClick, true);
|
|
791
|
-
window.removeEventListener("resize", positionDropdown);
|
|
792
|
-
};
|
|
793
|
-
const toggleDropdown = async () => {
|
|
794
|
-
if (inactive.value || !hasDropdown.value) return;
|
|
795
|
-
await countrySelector.toggleDropdown(searchRef);
|
|
796
|
-
if (dropdownOpened.value) {
|
|
797
|
-
positionDropdown();
|
|
798
|
-
window.addEventListener("scroll", positionDropdown, true);
|
|
799
|
-
window.addEventListener("click", onDocClick, true);
|
|
800
|
-
window.addEventListener("resize", positionDropdown);
|
|
801
|
-
} else {
|
|
802
|
-
removeDropdownListeners();
|
|
803
|
-
}
|
|
804
|
-
};
|
|
805
|
-
const scrollFocusedIntoView = async () => {
|
|
806
|
-
await vue.nextTick();
|
|
807
|
-
const list = dropdownRef.value?.lastElementChild;
|
|
808
|
-
if (!list) return;
|
|
809
|
-
const option = list.children[focusedIndex.value];
|
|
810
|
-
if (!option) return;
|
|
811
|
-
const listRect = list.getBoundingClientRect();
|
|
812
|
-
const optionRect = option.getBoundingClientRect();
|
|
813
|
-
let scrollAmount = 0;
|
|
814
|
-
if (optionRect.top < listRect.top) {
|
|
815
|
-
scrollAmount = list.scrollTop - (listRect.top - optionRect.top);
|
|
816
|
-
} else if (optionRect.bottom > listRect.bottom) {
|
|
817
|
-
scrollAmount = list.scrollTop + (optionRect.bottom - listRect.bottom);
|
|
818
|
-
} else {
|
|
819
|
-
return;
|
|
820
|
-
}
|
|
821
|
-
list.scrollTo({ top: scrollAmount, behavior: "smooth" });
|
|
822
|
-
};
|
|
823
|
-
const onDocClick = (ev) => {
|
|
824
|
-
const dropdown = dropdownRef.value;
|
|
825
|
-
const selector = rootRef.value?.firstChild;
|
|
826
|
-
if (!(dropdown || selector)) return;
|
|
827
|
-
const target = ev.target;
|
|
828
|
-
if (!target || dropdown?.contains(target) || selector?.contains(target)) return;
|
|
829
|
-
dropdownOpened.value = false;
|
|
830
|
-
};
|
|
831
|
-
vue.watch(
|
|
832
|
-
model,
|
|
833
|
-
(newValue) => {
|
|
834
|
-
if (!newValue) {
|
|
835
|
-
if (!isEmpty.value) mask.clear();
|
|
836
|
-
return;
|
|
837
|
-
}
|
|
838
|
-
const currentDigits = digits.value;
|
|
839
|
-
if (newValue !== currentDigits) {
|
|
840
|
-
const incomingDigits = newValue.replace(/\D/g, "");
|
|
841
|
-
if (incomingDigits !== currentDigits) {
|
|
842
|
-
digits.value = incomingDigits;
|
|
843
|
-
mask.updateDisplayFromDigits();
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
},
|
|
847
|
-
{ immediate: true }
|
|
848
|
-
);
|
|
849
|
-
vue.watch(
|
|
850
|
-
[() => props.country, () => props.detect],
|
|
851
|
-
async ([country, detect]) => {
|
|
852
|
-
await vue.nextTick();
|
|
853
|
-
await countrySelector.initCountry(country, detect, () => emit("country-change", selected.value));
|
|
854
|
-
},
|
|
855
|
-
{ immediate: true }
|
|
856
|
-
);
|
|
857
|
-
vue.watch(
|
|
858
|
-
copyMessage,
|
|
859
|
-
(val) => {
|
|
860
|
-
if (liveRef.value && val) {
|
|
861
|
-
liveRef.value.textContent = val;
|
|
862
|
-
}
|
|
863
|
-
},
|
|
864
|
-
{ flush: "post" }
|
|
865
|
-
);
|
|
866
|
-
vue.watch(
|
|
867
|
-
isComplete,
|
|
868
|
-
(valid) => {
|
|
869
|
-
emit("validation-change", valid);
|
|
870
|
-
},
|
|
871
|
-
{ flush: "post" }
|
|
872
|
-
);
|
|
873
|
-
vue.onBeforeUnmount(() => {
|
|
874
|
-
removeDropdownListeners();
|
|
875
|
-
onClipboardUnmount();
|
|
876
|
-
});
|
|
877
|
-
__expose({
|
|
878
|
-
focus: () => telRef.value?.focus(),
|
|
879
|
-
blur: () => telRef.value?.blur(),
|
|
880
|
-
clear: mask.clear,
|
|
881
|
-
selectCountry: countrySelector.selectCountry,
|
|
882
|
-
getFullNumber: () => full.value,
|
|
883
|
-
getFullFormattedNumber: () => fullFormatted.value,
|
|
884
|
-
getDigits: () => digits.value,
|
|
885
|
-
isValid: () => isComplete.value,
|
|
886
|
-
isComplete: () => isComplete.value
|
|
887
|
-
});
|
|
888
855
|
return (_ctx, _cache) => {
|
|
889
856
|
return vue.openBlock(), vue.createElementBlock("div", {
|
|
890
857
|
ref_key: "rootRef",
|
|
@@ -894,36 +861,41 @@ var lib = (function(exports, vue) {
|
|
|
894
861
|
class: vue.normalizeClass(rootClasses.value),
|
|
895
862
|
style: vue.normalizeStyle(rootStyles.value)
|
|
896
863
|
}, [
|
|
897
|
-
vue.createElementVNode("div",
|
|
864
|
+
vue.createElementVNode("div", {
|
|
865
|
+
ref_key: "selectorRef",
|
|
866
|
+
ref: selectorRef,
|
|
867
|
+
class: "pi-selector"
|
|
868
|
+
}, [
|
|
898
869
|
vue.createElementVNode("button", {
|
|
899
870
|
type: "button",
|
|
900
871
|
class: vue.normalizeClass(["pi-selector-btn", { "no-dropdown": !vue.unref(hasDropdown) || __props.readonly }]),
|
|
901
872
|
disabled: __props.disabled,
|
|
902
873
|
tabindex: inactive.value || !vue.unref(hasDropdown) ? -1 : void 0,
|
|
903
|
-
"aria-label": `Selected country: ${vue.unref(
|
|
904
|
-
"aria-expanded": vue.unref(
|
|
874
|
+
"aria-label": `Selected country: ${vue.unref(country).name}`,
|
|
875
|
+
"aria-expanded": vue.unref(dropdownOpen),
|
|
905
876
|
"aria-haspopup": vue.unref(hasDropdown) ? "listbox" : void 0,
|
|
906
|
-
onClick:
|
|
877
|
+
onClick: _cache[0] || (_cache[0] = //@ts-ignore
|
|
878
|
+
(...args) => vue.unref(toggleDropdown) && vue.unref(toggleDropdown)(...args))
|
|
907
879
|
}, [
|
|
908
880
|
vue.createElementVNode("span", {
|
|
909
881
|
class: "pi-flag",
|
|
910
882
|
role: "img",
|
|
911
|
-
"aria-label": `${vue.unref(
|
|
883
|
+
"aria-label": `${vue.unref(country).name} flag`
|
|
912
884
|
}, [
|
|
913
|
-
vue.renderSlot(_ctx.$slots, "flag", { country: vue.unref(
|
|
914
|
-
vue.createTextVNode(vue.toDisplayString(vue.unref(
|
|
885
|
+
vue.renderSlot(_ctx.$slots, "flag", { country: vue.unref(country) }, () => [
|
|
886
|
+
vue.createTextVNode(vue.toDisplayString(vue.unref(country).flag), 1)
|
|
915
887
|
], true)
|
|
916
|
-
], 8,
|
|
917
|
-
vue.createElementVNode("span",
|
|
888
|
+
], 8, _hoisted_2),
|
|
889
|
+
vue.createElementVNode("span", _hoisted_3, vue.toDisplayString(vue.unref(country).code), 1),
|
|
918
890
|
!inactive.value && vue.unref(hasDropdown) ? (vue.openBlock(), vue.createElementBlock("svg", {
|
|
919
891
|
key: 0,
|
|
920
|
-
class: vue.normalizeClass(["pi-chevron", { "is-open": vue.unref(
|
|
892
|
+
class: vue.normalizeClass(["pi-chevron", { "is-open": vue.unref(dropdownOpen) }]),
|
|
921
893
|
width: "12",
|
|
922
894
|
height: "12",
|
|
923
895
|
viewBox: "0 0 12 12",
|
|
924
896
|
fill: "none",
|
|
925
897
|
"aria-hidden": "true"
|
|
926
|
-
}, [..._cache[
|
|
898
|
+
}, [..._cache[8] || (_cache[8] = [
|
|
927
899
|
vue.createElementVNode("path", {
|
|
928
900
|
d: "M2.5 4.5L6 8L9.5 4.5",
|
|
929
901
|
stroke: "currentColor",
|
|
@@ -932,9 +904,9 @@ var lib = (function(exports, vue) {
|
|
|
932
904
|
"stroke-linejoin": "round"
|
|
933
905
|
}, null, -1)
|
|
934
906
|
])], 2)) : vue.createCommentVNode("", true)
|
|
935
|
-
], 10,
|
|
936
|
-
]),
|
|
937
|
-
vue.createElementVNode("div",
|
|
907
|
+
], 10, _hoisted_1)
|
|
908
|
+
], 512),
|
|
909
|
+
vue.createElementVNode("div", _hoisted_4, [
|
|
938
910
|
vue.createElementVNode("input", {
|
|
939
911
|
ref_key: "telRef",
|
|
940
912
|
ref: telRef,
|
|
@@ -949,16 +921,19 @@ var lib = (function(exports, vue) {
|
|
|
949
921
|
value: vue.unref(displayValue),
|
|
950
922
|
disabled: __props.disabled,
|
|
951
923
|
readonly: __props.readonly,
|
|
952
|
-
"aria-invalid":
|
|
953
|
-
onBeforeinput: _cache[
|
|
954
|
-
(...args) => vue.unref(
|
|
955
|
-
onInput
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
924
|
+
"aria-invalid": incomplete.value,
|
|
925
|
+
onBeforeinput: _cache[1] || (_cache[1] = //@ts-ignore
|
|
926
|
+
(...args) => vue.unref(handleBeforeInput) && vue.unref(handleBeforeInput)(...args)),
|
|
927
|
+
onInput: _cache[2] || (_cache[2] = //@ts-ignore
|
|
928
|
+
(...args) => vue.unref(handleInput) && vue.unref(handleInput)(...args)),
|
|
929
|
+
onKeydown: _cache[3] || (_cache[3] = //@ts-ignore
|
|
930
|
+
(...args) => vue.unref(handleKeydown) && vue.unref(handleKeydown)(...args)),
|
|
931
|
+
onPaste: _cache[4] || (_cache[4] = //@ts-ignore
|
|
932
|
+
(...args) => vue.unref(handlePaste) && vue.unref(handlePaste)(...args)),
|
|
933
|
+
onFocus: handleFocus,
|
|
934
|
+
onBlur: handleBlur
|
|
935
|
+
}, null, 40, _hoisted_5),
|
|
936
|
+
vue.createElementVNode("div", _hoisted_6, [
|
|
962
937
|
vue.createVNode(vue.Transition, { name: "fade-scale" }, {
|
|
963
938
|
default: vue.withCtx(() => [
|
|
964
939
|
vue.renderSlot(_ctx.$slots, "actions-before", {}, void 0, true)
|
|
@@ -970,26 +945,27 @@ var lib = (function(exports, vue) {
|
|
|
970
945
|
showCopyButton.value ? (vue.openBlock(), vue.createElementBlock("button", {
|
|
971
946
|
key: 0,
|
|
972
947
|
type: "button",
|
|
973
|
-
class: vue.normalizeClass(["pi-btn", { "is-copied": vue.unref(copied) }]),
|
|
974
|
-
"aria-label": copyAriaLabel
|
|
975
|
-
title: copyButtonTitle
|
|
976
|
-
onClick:
|
|
948
|
+
class: vue.normalizeClass(["pi-btn", "pi-btn-copy", { "is-copied": vue.unref(copied) }]),
|
|
949
|
+
"aria-label": vue.unref(copyAriaLabel),
|
|
950
|
+
title: vue.unref(copyButtonTitle),
|
|
951
|
+
onClick: _cache[5] || (_cache[5] = //@ts-ignore
|
|
952
|
+
(...args) => vue.unref(onCopyClick) && vue.unref(onCopyClick)(...args))
|
|
977
953
|
}, [
|
|
978
954
|
slots["copy-svg"] ? vue.renderSlot(_ctx.$slots, "copy-svg", {
|
|
979
955
|
key: 0,
|
|
980
956
|
copied: vue.unref(copied)
|
|
981
|
-
}, void 0, true) : !vue.unref(copied) ? (vue.openBlock(), vue.createElementBlock("svg",
|
|
957
|
+
}, void 0, true) : !vue.unref(copied) ? (vue.openBlock(), vue.createElementBlock("svg", _hoisted_8, [..._cache[9] || (_cache[9] = [
|
|
982
958
|
vue.createElementVNode("path", {
|
|
983
959
|
d: "M13.5 5.5V13.5H5.5V5.5H13.5ZM13.5 4H5.5C4.67 4 4 4.67 4 5.5V13.5C4 14.33 4.67 15 5.5 15H13.5C14.33 15 15 14.33 15 13.5V5.5C15 4.67 14.33 4 13.5 4ZM10.5 1H2.5V11H4V2.5H10.5V1Z",
|
|
984
960
|
fill: "currentColor"
|
|
985
961
|
}, null, -1)
|
|
986
|
-
])])) : (vue.openBlock(), vue.createElementBlock("svg",
|
|
962
|
+
])])) : (vue.openBlock(), vue.createElementBlock("svg", _hoisted_9, [..._cache[10] || (_cache[10] = [
|
|
987
963
|
vue.createElementVNode("path", {
|
|
988
964
|
d: "M6.5 11.5L3 8L4.06 6.94L6.5 9.38L11.94 3.94L13 5L6.5 11.5Z",
|
|
989
965
|
fill: "currentColor"
|
|
990
966
|
}, null, -1)
|
|
991
967
|
])]))
|
|
992
|
-
], 10,
|
|
968
|
+
], 10, _hoisted_7)) : vue.createCommentVNode("", true)
|
|
993
969
|
]),
|
|
994
970
|
_: 3
|
|
995
971
|
}),
|
|
@@ -998,18 +974,18 @@ var lib = (function(exports, vue) {
|
|
|
998
974
|
showClearButton.value ? (vue.openBlock(), vue.createElementBlock("button", {
|
|
999
975
|
key: 0,
|
|
1000
976
|
type: "button",
|
|
1001
|
-
class: "pi-btn",
|
|
977
|
+
class: "pi-btn pi-btn-clear",
|
|
1002
978
|
"aria-label": __props.clearButtonLabel,
|
|
1003
979
|
title: __props.clearButtonLabel,
|
|
1004
980
|
onClick: onClearClick
|
|
1005
981
|
}, [
|
|
1006
|
-
!slots["clear-svg"] ? (vue.openBlock(), vue.createElementBlock("svg",
|
|
982
|
+
!slots["clear-svg"] ? (vue.openBlock(), vue.createElementBlock("svg", _hoisted_11, [..._cache[11] || (_cache[11] = [
|
|
1007
983
|
vue.createElementVNode("path", {
|
|
1008
984
|
d: "M14 1.41L12.59 0L7 5.59L1.41 0L0 1.41L5.59 7L0 12.59L1.41 14L7 8.41L12.59 14L14 12.59L8.41 7L14 1.41Z",
|
|
1009
985
|
fill: "currentColor"
|
|
1010
986
|
}, null, -1)
|
|
1011
987
|
])])) : vue.renderSlot(_ctx.$slots, "clear-svg", { key: 1 }, void 0, true)
|
|
1012
|
-
], 8,
|
|
988
|
+
], 8, _hoisted_10)) : vue.createCommentVNode("", true)
|
|
1013
989
|
]),
|
|
1014
990
|
_: 3
|
|
1015
991
|
})
|
|
@@ -1018,42 +994,30 @@ var lib = (function(exports, vue) {
|
|
|
1018
994
|
(vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
|
|
1019
995
|
vue.createVNode(vue.Transition, { name: "dropdown" }, {
|
|
1020
996
|
default: vue.withCtx(() => [
|
|
1021
|
-
vue.unref(
|
|
997
|
+
vue.unref(dropdownOpen) ? (vue.openBlock(), vue.createElementBlock("div", {
|
|
1022
998
|
key: 0,
|
|
1023
999
|
ref_key: "dropdownRef",
|
|
1024
1000
|
ref: dropdownRef,
|
|
1025
|
-
class: vue.normalizeClass(["phone-dropdown", [__props.dropdownClass, themeClass
|
|
1001
|
+
class: vue.normalizeClass(["phone-dropdown", [__props.dropdownClass, vue.unref(themeClass)]]),
|
|
1026
1002
|
role: "dialog",
|
|
1027
1003
|
"aria-modal": "false",
|
|
1028
1004
|
"aria-label": "Select country",
|
|
1029
|
-
style: vue.normalizeStyle(dropdownStyle
|
|
1005
|
+
style: vue.normalizeStyle(vue.unref(dropdownStyle))
|
|
1030
1006
|
}, [
|
|
1031
|
-
vue.createElementVNode("div",
|
|
1032
|
-
vue.
|
|
1007
|
+
vue.createElementVNode("div", _hoisted_12, [
|
|
1008
|
+
vue.createElementVNode("input", {
|
|
1033
1009
|
ref_key: "searchRef",
|
|
1034
1010
|
ref: searchRef,
|
|
1035
|
-
|
|
1011
|
+
value: vue.unref(search),
|
|
1036
1012
|
type: "search",
|
|
1037
1013
|
class: "pi-search",
|
|
1038
1014
|
"aria-label": "Search countries",
|
|
1039
1015
|
placeholder: __props.searchPlaceholder,
|
|
1040
|
-
onKeydown: [
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
(...args) => vue.unref(chooseFocusedOption) && vue.unref(chooseFocusedOption)(...args),
|
|
1046
|
-
["prevent"]
|
|
1047
|
-
), ["enter"])),
|
|
1048
|
-
_cache[5] || (_cache[5] = vue.withKeys(
|
|
1049
|
-
//@ts-ignore
|
|
1050
|
-
(...args) => vue.unref(closeDropdown) && vue.unref(closeDropdown)(...args),
|
|
1051
|
-
["escape"]
|
|
1052
|
-
))
|
|
1053
|
-
]
|
|
1054
|
-
}, null, 40, _hoisted_14), [
|
|
1055
|
-
[vue.vModelText, vue.unref(search)]
|
|
1056
|
-
])
|
|
1016
|
+
onKeydown: _cache[6] || (_cache[6] = //@ts-ignore
|
|
1017
|
+
(...args) => vue.unref(handleSearchKeydown) && vue.unref(handleSearchKeydown)(...args)),
|
|
1018
|
+
onInput: _cache[7] || (_cache[7] = //@ts-ignore
|
|
1019
|
+
(...args) => vue.unref(handleSearchChange) && vue.unref(handleSearchChange)(...args))
|
|
1020
|
+
}, null, 40, _hoisted_13)
|
|
1057
1021
|
]),
|
|
1058
1022
|
vue.createElementVNode("ul", {
|
|
1059
1023
|
class: "pi-options",
|
|
@@ -1070,13 +1034,13 @@ var lib = (function(exports, vue) {
|
|
|
1070
1034
|
"pi-option",
|
|
1071
1035
|
{
|
|
1072
1036
|
"is-focused": idx === vue.unref(focusedIndex),
|
|
1073
|
-
"is-selected": c.id === vue.unref(
|
|
1037
|
+
"is-selected": c.id === vue.unref(country).id
|
|
1074
1038
|
}
|
|
1075
1039
|
]),
|
|
1076
|
-
"aria-selected": c.id === vue.unref(
|
|
1040
|
+
"aria-selected": c.id === vue.unref(country).id,
|
|
1077
1041
|
title: c.name,
|
|
1078
|
-
onClick: ($event) =>
|
|
1079
|
-
onMouseenter: ($event) =>
|
|
1042
|
+
onClick: ($event) => vue.unref(selectCountry)(c.id),
|
|
1043
|
+
onMouseenter: ($event) => vue.unref(setFocusedIndex)(idx)
|
|
1080
1044
|
}, [
|
|
1081
1045
|
vue.createElementVNode("span", {
|
|
1082
1046
|
class: "pi-flag",
|
|
@@ -1086,13 +1050,13 @@ var lib = (function(exports, vue) {
|
|
|
1086
1050
|
vue.renderSlot(_ctx.$slots, "flag", { country: c }, () => [
|
|
1087
1051
|
vue.createTextVNode(vue.toDisplayString(c.flag), 1)
|
|
1088
1052
|
], true)
|
|
1089
|
-
], 8,
|
|
1090
|
-
vue.createElementVNode("span",
|
|
1091
|
-
vue.createElementVNode("span",
|
|
1092
|
-
], 42,
|
|
1053
|
+
], 8, _hoisted_16),
|
|
1054
|
+
vue.createElementVNode("span", _hoisted_17, vue.toDisplayString(c.name), 1),
|
|
1055
|
+
vue.createElementVNode("span", _hoisted_18, vue.toDisplayString(c.code), 1)
|
|
1056
|
+
], 42, _hoisted_15);
|
|
1093
1057
|
}), 128)),
|
|
1094
|
-
vue.unref(filteredCountries).length === 0 ? (vue.openBlock(), vue.createElementBlock("li",
|
|
1095
|
-
], 8,
|
|
1058
|
+
vue.unref(filteredCountries).length === 0 ? (vue.openBlock(), vue.createElementBlock("li", _hoisted_19, vue.toDisplayString(__props.noResultsText), 1)) : vue.createCommentVNode("", true)
|
|
1059
|
+
], 8, _hoisted_14)
|
|
1096
1060
|
], 6)) : vue.createCommentVNode("", true)
|
|
1097
1061
|
]),
|
|
1098
1062
|
_: 3
|
|
@@ -1117,56 +1081,7 @@ var lib = (function(exports, vue) {
|
|
|
1117
1081
|
}
|
|
1118
1082
|
return target;
|
|
1119
1083
|
};
|
|
1120
|
-
const PhoneInput = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
1121
|
-
function getNavigatorLang() {
|
|
1122
|
-
if (typeof navigator !== "undefined") {
|
|
1123
|
-
return navigator.language || "";
|
|
1124
|
-
}
|
|
1125
|
-
return "";
|
|
1126
|
-
}
|
|
1127
|
-
function getCountry(countryCode, locale) {
|
|
1128
|
-
const isEn = locale.toLowerCase().startsWith("en");
|
|
1129
|
-
const countriesMap = isEn ? m : MasksFullMap(locale);
|
|
1130
|
-
const id = countryCode.toUpperCase();
|
|
1131
|
-
const found = countriesMap[id];
|
|
1132
|
-
return found ? { id, ...found } : null;
|
|
1133
|
-
}
|
|
1134
|
-
function getDefaultCountry(locale) {
|
|
1135
|
-
const isEn = locale.toLowerCase().startsWith("en");
|
|
1136
|
-
const countries = isEn ? m : MasksFullMap(locale);
|
|
1137
|
-
return { id: "US", ...countries.US };
|
|
1138
|
-
}
|
|
1139
|
-
async function detectCountryFromGeoIP() {
|
|
1140
|
-
try {
|
|
1141
|
-
const controller = new AbortController();
|
|
1142
|
-
const timeoutId = setTimeout(() => controller.abort(), GEO_IP_TIMEOUT);
|
|
1143
|
-
const res = await fetch(GEO_IP_URL, {
|
|
1144
|
-
signal: controller.signal,
|
|
1145
|
-
headers: { Accept: "application/json" }
|
|
1146
|
-
});
|
|
1147
|
-
clearTimeout(timeoutId);
|
|
1148
|
-
if (!res.ok) return null;
|
|
1149
|
-
const json = await res.json();
|
|
1150
|
-
const code = (json.country || json.country_code || json.countryCode || json.country_code2 || "").toString().toUpperCase();
|
|
1151
|
-
return code || null;
|
|
1152
|
-
} catch {
|
|
1153
|
-
return null;
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
function detectCountryFromLocale() {
|
|
1157
|
-
try {
|
|
1158
|
-
const lang = getNavigatorLang();
|
|
1159
|
-
try {
|
|
1160
|
-
const loc = new Intl.Locale(lang);
|
|
1161
|
-
if (loc.region) return loc.region.toUpperCase();
|
|
1162
|
-
} catch {
|
|
1163
|
-
}
|
|
1164
|
-
const parts = lang.split(/[-_]/);
|
|
1165
|
-
if (parts.length > 1) return parts[1]?.toUpperCase() || null;
|
|
1166
|
-
} catch {
|
|
1167
|
-
}
|
|
1168
|
-
return null;
|
|
1169
|
-
}
|
|
1084
|
+
const PhoneInput = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-33134720"]]);
|
|
1170
1085
|
async function initState(binding) {
|
|
1171
1086
|
const value = binding.value;
|
|
1172
1087
|
let options = {};
|
|
@@ -1175,24 +1090,24 @@ var lib = (function(exports, vue) {
|
|
|
1175
1090
|
} else if (typeof value === "object" && value !== null) {
|
|
1176
1091
|
options = value;
|
|
1177
1092
|
}
|
|
1178
|
-
const locale = options.locale || getNavigatorLang()
|
|
1179
|
-
let country
|
|
1093
|
+
const locale = options.locale || getNavigatorLang();
|
|
1094
|
+
let country;
|
|
1180
1095
|
if (options.country) {
|
|
1181
1096
|
country = getCountry(options.country, locale);
|
|
1182
1097
|
} else if (options.detect) {
|
|
1183
1098
|
const geoCountry = await detectCountryFromGeoIP();
|
|
1184
1099
|
if (geoCountry) {
|
|
1185
1100
|
country = getCountry(geoCountry, locale);
|
|
1186
|
-
}
|
|
1187
|
-
if (!country) {
|
|
1101
|
+
} else {
|
|
1188
1102
|
const localeCountry = detectCountryFromLocale();
|
|
1189
1103
|
if (localeCountry) {
|
|
1190
1104
|
country = getCountry(localeCountry, locale);
|
|
1105
|
+
} else {
|
|
1106
|
+
country = getCountry("US", locale);
|
|
1191
1107
|
}
|
|
1192
1108
|
}
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
|
-
country = getDefaultCountry(locale);
|
|
1109
|
+
} else {
|
|
1110
|
+
country = getCountry("US", locale);
|
|
1196
1111
|
}
|
|
1197
1112
|
return {
|
|
1198
1113
|
country,
|
|
@@ -1214,147 +1129,50 @@ var lib = (function(exports, vue) {
|
|
|
1214
1129
|
});
|
|
1215
1130
|
}
|
|
1216
1131
|
}
|
|
1217
|
-
function createBeforeInputHandler(el) {
|
|
1218
|
-
return (e) => {
|
|
1219
|
-
const data = e.data;
|
|
1220
|
-
if (e.inputType !== "insertText" || !data) return;
|
|
1221
|
-
if (InvalidPattern.test(data) || data === " " && el.value.endsWith(" ")) {
|
|
1222
|
-
e.preventDefault();
|
|
1223
|
-
}
|
|
1224
|
-
};
|
|
1225
|
-
}
|
|
1226
1132
|
function createInputHandler(el, state) {
|
|
1227
|
-
return (
|
|
1228
|
-
const
|
|
1229
|
-
if (!
|
|
1230
|
-
|
|
1231
|
-
const maxDigits = state.formatter.getMaxDigits();
|
|
1232
|
-
state.digits = extractDigits(raw, maxDigits);
|
|
1133
|
+
return (e2) => {
|
|
1134
|
+
const result = processInput(e2, { formatter: state.formatter });
|
|
1135
|
+
if (!result) return;
|
|
1136
|
+
state.digits = result.newDigits;
|
|
1233
1137
|
updateDisplay(el, state);
|
|
1234
1138
|
vue.nextTick(() => {
|
|
1235
|
-
const pos = state.formatter.getCaretPosition(
|
|
1139
|
+
const pos = state.formatter.getCaretPosition(result.caretDigitIndex);
|
|
1236
1140
|
setCaret(el, pos);
|
|
1237
1141
|
});
|
|
1238
1142
|
};
|
|
1239
1143
|
}
|
|
1240
1144
|
function createKeydownHandler(el, state) {
|
|
1241
|
-
return (
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
const pos = state.formatter.getCaretPosition(start);
|
|
1254
|
-
setCaret(el, pos);
|
|
1255
|
-
});
|
|
1256
|
-
}
|
|
1257
|
-
return;
|
|
1258
|
-
}
|
|
1259
|
-
if (selStart > 0) {
|
|
1260
|
-
const displayStr = el.value;
|
|
1261
|
-
let prevPos = selStart - 1;
|
|
1262
|
-
while (prevPos >= 0 && Delimiters.includes(displayStr[prevPos])) {
|
|
1263
|
-
prevPos--;
|
|
1264
|
-
}
|
|
1265
|
-
if (prevPos >= 0) {
|
|
1266
|
-
const range = state.formatter.getDigitRange(state.digits, prevPos, prevPos + 1);
|
|
1267
|
-
if (range) {
|
|
1268
|
-
const [start] = range;
|
|
1269
|
-
state.digits = state.digits.slice(0, start) + state.digits.slice(start + 1);
|
|
1270
|
-
updateDisplay(el, state);
|
|
1271
|
-
vue.nextTick(() => {
|
|
1272
|
-
const pos = state.formatter.getCaretPosition(start);
|
|
1273
|
-
setCaret(el, pos);
|
|
1274
|
-
});
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
return;
|
|
1279
|
-
}
|
|
1280
|
-
if (e.key === "Delete") {
|
|
1281
|
-
e.preventDefault();
|
|
1282
|
-
if (selStart !== selEnd) {
|
|
1283
|
-
const range = state.formatter.getDigitRange(state.digits, selStart, selEnd);
|
|
1284
|
-
if (range) {
|
|
1285
|
-
const [start, end] = range;
|
|
1286
|
-
state.digits = state.digits.slice(0, start) + state.digits.slice(end);
|
|
1287
|
-
updateDisplay(el, state);
|
|
1288
|
-
vue.nextTick(() => {
|
|
1289
|
-
const pos = state.formatter.getCaretPosition(start);
|
|
1290
|
-
setCaret(el, pos);
|
|
1291
|
-
});
|
|
1292
|
-
}
|
|
1293
|
-
return;
|
|
1294
|
-
}
|
|
1295
|
-
if (selStart < el.value.length) {
|
|
1296
|
-
const range = state.formatter.getDigitRange(state.digits, selStart, selStart + 1);
|
|
1297
|
-
if (range) {
|
|
1298
|
-
const [start] = range;
|
|
1299
|
-
state.digits = state.digits.slice(0, start) + state.digits.slice(start + 1);
|
|
1300
|
-
updateDisplay(el, state);
|
|
1301
|
-
vue.nextTick(() => {
|
|
1302
|
-
const pos = state.formatter.getCaretPosition(start);
|
|
1303
|
-
setCaret(el, pos);
|
|
1304
|
-
});
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
return;
|
|
1308
|
-
}
|
|
1309
|
-
if (/^[0-9]$/.test(e.key)) {
|
|
1310
|
-
if (state.digits.length >= state.formatter.getMaxDigits()) {
|
|
1311
|
-
e.preventDefault();
|
|
1312
|
-
}
|
|
1313
|
-
return;
|
|
1314
|
-
}
|
|
1315
|
-
if (e.key.length === 1) {
|
|
1316
|
-
e.preventDefault();
|
|
1317
|
-
}
|
|
1145
|
+
return (e2) => {
|
|
1146
|
+
const result = processKeydown(e2, {
|
|
1147
|
+
digits: state.digits,
|
|
1148
|
+
formatter: state.formatter
|
|
1149
|
+
});
|
|
1150
|
+
if (!result) return;
|
|
1151
|
+
state.digits = result.newDigits;
|
|
1152
|
+
updateDisplay(el, state);
|
|
1153
|
+
vue.nextTick(() => {
|
|
1154
|
+
const pos = state.formatter.getCaretPosition(result.caretDigitIndex);
|
|
1155
|
+
setCaret(el, pos);
|
|
1156
|
+
});
|
|
1318
1157
|
};
|
|
1319
1158
|
}
|
|
1320
1159
|
function createPasteHandler(el, state) {
|
|
1321
|
-
return (
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
if (
|
|
1327
|
-
|
|
1328
|
-
if (selStart !== selEnd) {
|
|
1329
|
-
const range2 = state.formatter.getDigitRange(state.digits, selStart, selEnd);
|
|
1330
|
-
if (range2) {
|
|
1331
|
-
const [start, end] = range2;
|
|
1332
|
-
const left2 = state.digits.slice(0, start);
|
|
1333
|
-
const right2 = state.digits.slice(end);
|
|
1334
|
-
state.digits = extractDigits(left2 + pastedDigits + right2, maxDigits);
|
|
1335
|
-
updateDisplay(el, state);
|
|
1336
|
-
vue.nextTick(() => {
|
|
1337
|
-
const pos = state.formatter.getCaretPosition(start + pastedDigits.length);
|
|
1338
|
-
setCaret(el, pos);
|
|
1339
|
-
});
|
|
1340
|
-
return;
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
const range = state.formatter.getDigitRange(state.digits, selStart, selStart);
|
|
1344
|
-
const insertIndex = range ? range[0] : state.digits.length;
|
|
1345
|
-
const left = state.digits.slice(0, insertIndex);
|
|
1346
|
-
const right = state.digits.slice(insertIndex);
|
|
1347
|
-
state.digits = extractDigits(left + pastedDigits + right, maxDigits);
|
|
1160
|
+
return (e2) => {
|
|
1161
|
+
const result = processPaste(e2, {
|
|
1162
|
+
digits: state.digits,
|
|
1163
|
+
formatter: state.formatter
|
|
1164
|
+
});
|
|
1165
|
+
if (!result) return;
|
|
1166
|
+
state.digits = result.newDigits;
|
|
1348
1167
|
updateDisplay(el, state);
|
|
1349
1168
|
vue.nextTick(() => {
|
|
1350
|
-
const pos = state.formatter.getCaretPosition(
|
|
1169
|
+
const pos = state.formatter.getCaretPosition(result.caretDigitIndex);
|
|
1351
1170
|
setCaret(el, pos);
|
|
1352
1171
|
});
|
|
1353
1172
|
};
|
|
1354
1173
|
}
|
|
1355
1174
|
async function updateCountry(el, state, newCountryCode) {
|
|
1356
1175
|
const newCountry = getCountry(newCountryCode, state.locale);
|
|
1357
|
-
if (!newCountry) return;
|
|
1358
1176
|
state.country = newCountry;
|
|
1359
1177
|
state.formatter = createPhoneFormatter(newCountry);
|
|
1360
1178
|
el.placeholder = state.formatter.getPlaceholder();
|
|
@@ -1380,7 +1198,7 @@ var lib = (function(exports, vue) {
|
|
|
1380
1198
|
state.inputHandler = createInputHandler(el, state);
|
|
1381
1199
|
state.keydownHandler = createKeydownHandler(el, state);
|
|
1382
1200
|
state.pasteHandler = createPasteHandler(el, state);
|
|
1383
|
-
state.beforeInputHandler =
|
|
1201
|
+
state.beforeInputHandler = processBeforeInput;
|
|
1384
1202
|
el.addEventListener("beforeinput", state.beforeInputHandler);
|
|
1385
1203
|
el.addEventListener("input", state.inputHandler);
|
|
1386
1204
|
el.addEventListener("keydown", state.keydownHandler);
|
|
@@ -1411,8 +1229,10 @@ var lib = (function(exports, vue) {
|
|
|
1411
1229
|
if (newCountry && newCountry !== oldCountry) {
|
|
1412
1230
|
await updateCountry(el, state, newCountry);
|
|
1413
1231
|
}
|
|
1414
|
-
const
|
|
1415
|
-
|
|
1232
|
+
const maxDigits = state.formatter.getMaxDigits();
|
|
1233
|
+
const newDigits = extractDigits(el.value, maxDigits);
|
|
1234
|
+
const normalizedDisplay = state.formatter.formatDisplay(newDigits);
|
|
1235
|
+
if (newDigits !== state.digits || el.value !== normalizedDisplay) {
|
|
1416
1236
|
state.digits = newDigits;
|
|
1417
1237
|
updateDisplay(el, state);
|
|
1418
1238
|
}
|
|
@@ -1427,6 +1247,82 @@ var lib = (function(exports, vue) {
|
|
|
1427
1247
|
delete el.__phoneMaskState;
|
|
1428
1248
|
}
|
|
1429
1249
|
};
|
|
1250
|
+
function usePhoneMask(options) {
|
|
1251
|
+
const inputRef = vue.shallowRef(null);
|
|
1252
|
+
const { country, setCountry } = useCountry({
|
|
1253
|
+
country: options.country,
|
|
1254
|
+
locale: options.locale,
|
|
1255
|
+
detect: options.detect,
|
|
1256
|
+
onCountryChange: options.onCountryChange
|
|
1257
|
+
});
|
|
1258
|
+
const {
|
|
1259
|
+
digits,
|
|
1260
|
+
formatter,
|
|
1261
|
+
displayPlaceholder,
|
|
1262
|
+
displayValue,
|
|
1263
|
+
full,
|
|
1264
|
+
fullFormatted,
|
|
1265
|
+
isComplete,
|
|
1266
|
+
isEmpty,
|
|
1267
|
+
shouldShowWarn
|
|
1268
|
+
} = useFormatter({
|
|
1269
|
+
country,
|
|
1270
|
+
value: options.value,
|
|
1271
|
+
onChange: options.onChange,
|
|
1272
|
+
onPhoneChange: options.onPhoneChange
|
|
1273
|
+
});
|
|
1274
|
+
const { handleBeforeInput, handleInput, handleKeydown, handlePaste } = useInputHandlers({
|
|
1275
|
+
formatter,
|
|
1276
|
+
digits,
|
|
1277
|
+
onChange: options.onChange
|
|
1278
|
+
});
|
|
1279
|
+
vue.onMounted(() => {
|
|
1280
|
+
const el = inputRef.value;
|
|
1281
|
+
if (!el) return;
|
|
1282
|
+
el.setAttribute("type", "tel");
|
|
1283
|
+
el.setAttribute("inputmode", "tel");
|
|
1284
|
+
});
|
|
1285
|
+
vue.watchEffect(
|
|
1286
|
+
() => {
|
|
1287
|
+
const el = inputRef.value;
|
|
1288
|
+
if (!el) return;
|
|
1289
|
+
el.value = displayValue.value;
|
|
1290
|
+
el.setAttribute("placeholder", displayPlaceholder.value);
|
|
1291
|
+
},
|
|
1292
|
+
{ flush: "post" }
|
|
1293
|
+
);
|
|
1294
|
+
vue.onMounted(() => {
|
|
1295
|
+
const el = inputRef.value;
|
|
1296
|
+
if (!el) return;
|
|
1297
|
+
el.addEventListener("beforeinput", handleBeforeInput);
|
|
1298
|
+
el.addEventListener("input", handleInput);
|
|
1299
|
+
el.addEventListener("keydown", handleKeydown);
|
|
1300
|
+
el.addEventListener("paste", handlePaste);
|
|
1301
|
+
});
|
|
1302
|
+
vue.onUnmounted(() => {
|
|
1303
|
+
const el = inputRef.value;
|
|
1304
|
+
if (!el) return;
|
|
1305
|
+
el.removeEventListener("beforeinput", handleBeforeInput);
|
|
1306
|
+
el.removeEventListener("input", handleInput);
|
|
1307
|
+
el.removeEventListener("keydown", handleKeydown);
|
|
1308
|
+
el.removeEventListener("paste", handlePaste);
|
|
1309
|
+
});
|
|
1310
|
+
const clear = () => {
|
|
1311
|
+
options.onChange("");
|
|
1312
|
+
};
|
|
1313
|
+
return {
|
|
1314
|
+
inputRef,
|
|
1315
|
+
digits,
|
|
1316
|
+
full,
|
|
1317
|
+
fullFormatted,
|
|
1318
|
+
isComplete,
|
|
1319
|
+
isEmpty,
|
|
1320
|
+
shouldShowWarn,
|
|
1321
|
+
country,
|
|
1322
|
+
setCountry,
|
|
1323
|
+
clear
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1430
1326
|
function install(app) {
|
|
1431
1327
|
app.component("PhoneInput", PhoneInput);
|
|
1432
1328
|
app.directive("phone-mask", vPhoneMask);
|
|
@@ -1435,7 +1331,7 @@ var lib = (function(exports, vue) {
|
|
|
1435
1331
|
install
|
|
1436
1332
|
};
|
|
1437
1333
|
const PMaskHelpers = {
|
|
1438
|
-
getFlagEmoji:
|
|
1334
|
+
getFlagEmoji: k,
|
|
1439
1335
|
countPlaceholders,
|
|
1440
1336
|
formatDigitsWithMap,
|
|
1441
1337
|
pickMaskVariant,
|
|
@@ -1446,6 +1342,7 @@ var lib = (function(exports, vue) {
|
|
|
1446
1342
|
exports.PhoneInput = PhoneInput;
|
|
1447
1343
|
exports.default = index;
|
|
1448
1344
|
exports.install = install;
|
|
1345
|
+
exports.usePhoneMask = usePhoneMask;
|
|
1449
1346
|
exports.vPhoneMask = vPhoneMask;
|
|
1450
1347
|
exports.vPhoneMaskSetCountry = updateCountry;
|
|
1451
1348
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|