svelte-tel-input 3.5.2 → 3.6.1
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/components/input/TelInput.svelte +56 -11
- package/dist/types/index.d.ts +5 -0
- package/dist/utils/directives/telInputAction.d.ts +2 -1
- package/dist/utils/directives/telInputAction.js +3 -2
- package/dist/utils/helpers.d.ts +4 -3
- package/dist/utils/helpers.js +9 -9
- package/package.json +1 -1
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
<script>import { createEventDispatcher, onMount } from "svelte";
|
|
1
|
+
<script>import { createEventDispatcher, onMount, tick } from "svelte";
|
|
2
2
|
import { parsePhoneNumberWithError, ParseError } from "libphonenumber-js/max";
|
|
3
3
|
import {
|
|
4
4
|
normalizeTelInput,
|
|
5
5
|
getCountryForPartialE164Number,
|
|
6
6
|
generatePlaceholder,
|
|
7
|
-
telInputAction
|
|
7
|
+
telInputAction,
|
|
8
|
+
allowedCharacters
|
|
8
9
|
} from "../../utils/index.js";
|
|
9
10
|
const dispatch = createEventDispatcher();
|
|
10
11
|
const defaultOptions = {
|
|
11
12
|
autoPlaceholder: true,
|
|
12
13
|
spaces: true,
|
|
13
14
|
invalidateOnCountryChange: false,
|
|
14
|
-
format: "national"
|
|
15
|
+
format: "national",
|
|
16
|
+
strictCountry: false
|
|
15
17
|
};
|
|
16
18
|
export let autocomplete = null;
|
|
17
19
|
let classes = "";
|
|
@@ -44,19 +46,37 @@ const updateCountry = (countryCode) => {
|
|
|
44
46
|
country = countryCode;
|
|
45
47
|
prevCountry = country;
|
|
46
48
|
dispatch("updateCountry", country);
|
|
49
|
+
dispatch("updateDetailedValue", detailedValue);
|
|
47
50
|
}
|
|
48
51
|
return country;
|
|
49
52
|
};
|
|
50
|
-
const
|
|
53
|
+
const findNewCursorPosition = (newValue, formattedValue, initialCursorPosition) => {
|
|
54
|
+
if (initialCursorPosition >= newValue.length) {
|
|
55
|
+
return formattedValue.length;
|
|
56
|
+
}
|
|
57
|
+
let fvIndex = 0;
|
|
58
|
+
for (let nvIndex = 0; nvIndex < initialCursorPosition; nvIndex++) {
|
|
59
|
+
const nvChar = allowedCharacters(newValue[nvIndex], { spaces: false });
|
|
60
|
+
if (nvChar >= "0" && nvChar <= "9") {
|
|
61
|
+
while (!(formattedValue[fvIndex] >= "0" && formattedValue[fvIndex] <= "9") && fvIndex < formattedValue.length) {
|
|
62
|
+
fvIndex++;
|
|
63
|
+
}
|
|
64
|
+
fvIndex++;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return fvIndex;
|
|
68
|
+
};
|
|
69
|
+
const handleParsePhoneNumber = async (rawInput, currCountry = null) => {
|
|
51
70
|
const input = rawInput;
|
|
52
71
|
if (input !== null) {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
const detectedCountry = getCountryForPartialE164Number(input);
|
|
73
|
+
const useCountry = options?.strictCountry ? currCountry : detectedCountry ?? currCountry;
|
|
74
|
+
if (!options?.strictCountry && detectedCountry && detectedCountry !== prevCountry) {
|
|
75
|
+
updateCountry(detectedCountry);
|
|
56
76
|
}
|
|
57
77
|
try {
|
|
58
78
|
detailedValue = normalizeTelInput(
|
|
59
|
-
parsePhoneNumberWithError(input,
|
|
79
|
+
parsePhoneNumberWithError(input, useCountry ?? void 0)
|
|
60
80
|
);
|
|
61
81
|
} catch (err) {
|
|
62
82
|
if (err instanceof ParseError) {
|
|
@@ -71,10 +91,31 @@ const handleParsePhoneNumber = (rawInput, currCountry = null) => {
|
|
|
71
91
|
}
|
|
72
92
|
const formatOption = combinedOptions.format === "national" ? "nationalNumber" : "e164";
|
|
73
93
|
const formattedValue = combinedOptions.format === "national" ? "formatOriginal" : "formatInternational";
|
|
94
|
+
const initialCursorPosition = el?.selectionStart || 0;
|
|
74
95
|
if (combinedOptions.spaces && detailedValue?.[formattedValue]) {
|
|
75
96
|
inputValue = detailedValue[formattedValue] ?? null;
|
|
97
|
+
await tick();
|
|
98
|
+
if (el) {
|
|
99
|
+
const newCursorPosition = findNewCursorPosition(
|
|
100
|
+
input,
|
|
101
|
+
inputValue,
|
|
102
|
+
initialCursorPosition
|
|
103
|
+
);
|
|
104
|
+
el.selectionStart = newCursorPosition;
|
|
105
|
+
el.selectionEnd = newCursorPosition;
|
|
106
|
+
}
|
|
76
107
|
} else if (detailedValue?.[formatOption]) {
|
|
77
108
|
inputValue = detailedValue[formatOption] ?? null;
|
|
109
|
+
await tick();
|
|
110
|
+
if (el) {
|
|
111
|
+
const newCursorPosition = findNewCursorPosition(
|
|
112
|
+
input,
|
|
113
|
+
inputValue,
|
|
114
|
+
initialCursorPosition
|
|
115
|
+
);
|
|
116
|
+
el.selectionStart = newCursorPosition;
|
|
117
|
+
el.selectionEnd = newCursorPosition;
|
|
118
|
+
}
|
|
78
119
|
}
|
|
79
120
|
value = detailedValue?.e164 ?? input ?? null;
|
|
80
121
|
valid = detailedValue?.isValid ?? false;
|
|
@@ -124,13 +165,16 @@ export const updateValue = (newValue, newCountry) => {
|
|
|
124
165
|
if (castedValue) {
|
|
125
166
|
handleParsePhoneNumber(
|
|
126
167
|
castedValue,
|
|
127
|
-
getCountryForPartialE164Number(castedValue) || newCountry
|
|
168
|
+
options?.strictCountry ? country : getCountryForPartialE164Number(castedValue) || newCountry
|
|
128
169
|
);
|
|
129
170
|
}
|
|
130
171
|
};
|
|
131
172
|
onMount(() => {
|
|
132
173
|
if (value) {
|
|
133
|
-
handleParsePhoneNumber(
|
|
174
|
+
handleParsePhoneNumber(
|
|
175
|
+
value,
|
|
176
|
+
options?.strictCountry ? country : getCountryForPartialE164Number(value) || country
|
|
177
|
+
);
|
|
134
178
|
}
|
|
135
179
|
});
|
|
136
180
|
</script>
|
|
@@ -162,6 +206,7 @@ onMount(() => {
|
|
|
162
206
|
use:telInputAction={{
|
|
163
207
|
handler: handleInputAction,
|
|
164
208
|
spaces: combinedOptions.spaces,
|
|
165
|
-
value
|
|
209
|
+
value,
|
|
210
|
+
strictCountryCode: combinedOptions.strictCountry
|
|
166
211
|
}}
|
|
167
212
|
/>
|
package/dist/types/index.d.ts
CHANGED
|
@@ -75,6 +75,11 @@ export interface TelInputOptions {
|
|
|
75
75
|
* @default false
|
|
76
76
|
*/
|
|
77
77
|
invalidateOnCountryChange?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Prevent automatic country parsing from the input value. It validates via the passed `country` property value.
|
|
80
|
+
* @default false
|
|
81
|
+
*/
|
|
82
|
+
strictCountry?: boolean;
|
|
78
83
|
/**
|
|
79
84
|
* "international": `+36 20 123 4567`,
|
|
80
85
|
* "default": `20 123 4567`
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { E164Number } from 'libphonenumber-js';
|
|
2
|
-
export declare const telInputAction: (node: HTMLInputElement, { handler, spaces }: {
|
|
2
|
+
export declare const telInputAction: (node: HTMLInputElement, { handler, spaces, strictCountryCode }: {
|
|
3
3
|
handler: (val: string) => void;
|
|
4
4
|
spaces: boolean;
|
|
5
5
|
value: E164Number | null;
|
|
6
|
+
strictCountryCode: boolean;
|
|
6
7
|
}) => {
|
|
7
8
|
update(params: {
|
|
8
9
|
handler: (val: string) => void;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { inspectAllowedChars, inputParser } from '../../index.js';
|
|
2
|
-
export const telInputAction = (node, { handler, spaces }) => {
|
|
2
|
+
export const telInputAction = (node, { handler, spaces, strictCountryCode }) => {
|
|
3
3
|
const onInput = (event) => {
|
|
4
4
|
if (node && node.contains(event.target)) {
|
|
5
5
|
const currentValue = event.target.value;
|
|
6
6
|
const formattedInput = inputParser(currentValue, {
|
|
7
7
|
parseCharacter: inspectAllowedChars,
|
|
8
|
-
allowSpaces: spaces
|
|
8
|
+
allowSpaces: spaces,
|
|
9
|
+
disallowPlusSign: strictCountryCode
|
|
9
10
|
});
|
|
10
11
|
node.value = formattedInput;
|
|
11
12
|
handler(formattedInput);
|
package/dist/utils/helpers.d.ts
CHANGED
|
@@ -69,8 +69,9 @@ export declare const isSupportedCountry: (country: CountryCode, metadata: Metada
|
|
|
69
69
|
export declare const allowedCharacters: (character: string, { spaces }?: {
|
|
70
70
|
spaces?: boolean;
|
|
71
71
|
}) => string;
|
|
72
|
-
export declare const inputParser: (text: string, { allowSpaces, parseCharacter }: {
|
|
72
|
+
export declare const inputParser: (text: string, { allowSpaces, parseCharacter, disallowPlusSign }: {
|
|
73
73
|
allowSpaces: boolean;
|
|
74
|
-
|
|
74
|
+
disallowPlusSign: boolean;
|
|
75
|
+
parseCharacter: (char: string, val: string, allowSpaces: boolean, disallowPlusSign: boolean) => string | undefined;
|
|
75
76
|
}) => string;
|
|
76
|
-
export declare const inspectAllowedChars: (character: string, value: string, allowSpaces
|
|
77
|
+
export declare const inspectAllowedChars: (character: string, value: string, allowSpaces: boolean, disallowPlusSign: boolean) => string;
|
package/dist/utils/helpers.js
CHANGED
|
@@ -31,16 +31,16 @@ export const normalizeTelInput = (input) => {
|
|
|
31
31
|
isPossible: input ? input.isPossible() : false,
|
|
32
32
|
phoneNumber: input ? input.number : null,
|
|
33
33
|
countryCallingCode: input ? input.countryCallingCode : null,
|
|
34
|
-
formattedNumber: input ? input.
|
|
34
|
+
formattedNumber: input ? new AsYouType().input(input.number) : null,
|
|
35
35
|
nationalNumber: input ? input.nationalNumber : null,
|
|
36
|
-
formatInternational: input ? input.
|
|
36
|
+
formatInternational: input ? new AsYouType().input(input.number) : null,
|
|
37
37
|
formatOriginal: input
|
|
38
|
-
?
|
|
39
|
-
.
|
|
38
|
+
? new AsYouType()
|
|
39
|
+
.input(input.number)
|
|
40
40
|
.slice(input.countryCallingCode.length + 1)
|
|
41
41
|
.trim()
|
|
42
42
|
: null,
|
|
43
|
-
formatNational: input ? input.
|
|
43
|
+
formatNational: input ? new AsYouType(input.country).input(input.number) : null,
|
|
44
44
|
uri: input ? input.getURI() : null,
|
|
45
45
|
e164: input ? input.number : null
|
|
46
46
|
}).filter(([, value]) => value !== null));
|
|
@@ -265,19 +265,19 @@ export const allowedCharacters = (character, { spaces } = {
|
|
|
265
265
|
// Allow digits
|
|
266
266
|
return DIGITS[character];
|
|
267
267
|
};
|
|
268
|
-
export const inputParser = (text, { allowSpaces, parseCharacter }) => {
|
|
268
|
+
export const inputParser = (text, { allowSpaces, parseCharacter, disallowPlusSign }) => {
|
|
269
269
|
let value = '';
|
|
270
270
|
for (let index = 0; index < text.length; index++) {
|
|
271
|
-
const character = parseCharacter(text[index], value, allowSpaces);
|
|
271
|
+
const character = parseCharacter(text[index], value, allowSpaces, disallowPlusSign);
|
|
272
272
|
if (character !== undefined) {
|
|
273
273
|
value += character;
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
return value;
|
|
277
277
|
};
|
|
278
|
-
export const inspectAllowedChars = (character, value, allowSpaces) => {
|
|
278
|
+
export const inspectAllowedChars = (character, value, allowSpaces, disallowPlusSign) => {
|
|
279
279
|
// Leading plus is allowed
|
|
280
|
-
if (character === '+') {
|
|
280
|
+
if (!disallowPlusSign && character === '+') {
|
|
281
281
|
if (!value) {
|
|
282
282
|
return character;
|
|
283
283
|
}
|