@desource/phone-mask-vue 1.1.1 → 1.2.0

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