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