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