react-native-international-phone-number 0.4.12 → 0.4.14
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/README.md +81 -39
- package/lib/index.d.ts +2 -0
- package/lib/index.js +298 -173
- package/lib/interfaces/phoneInputProps.ts +25 -1
- package/lib/interfaces/phoneInputRef.ts +14 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,9 +47,12 @@
|
|
|
47
47
|
- [With Class Component](#class-component)
|
|
48
48
|
- [With Function Component](#function-component)
|
|
49
49
|
- [Custom Default Flag](#custom-default-flag)
|
|
50
|
-
- [
|
|
51
|
-
- [
|
|
52
|
-
- [
|
|
50
|
+
- [Default Phone Number Value](#default-phone-number-value)
|
|
51
|
+
- [Typescript](#typescript)
|
|
52
|
+
- [Intermediate Usage](#intermediate-usage)
|
|
53
|
+
- [Typescript + useRef](#typescript--useref)
|
|
54
|
+
- [Advanced Usage](#advanced-usage)
|
|
55
|
+
- [React-Hook-Form + Typescript + Default Phone Number Value](#react-hook-form--typescript--default-phone-number-value)
|
|
53
56
|
- [Customizing Lib](#customizing-lib)
|
|
54
57
|
- [Dark Mode](#dark-mode)
|
|
55
58
|
- [Custom Lib Styles](#custom-lib-styles)
|
|
@@ -242,35 +245,29 @@ export default function App() {
|
|
|
242
245
|
}
|
|
243
246
|
```
|
|
244
247
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
## Basic Usage - Typescript
|
|
248
|
+
- ### Default Phone Number Value
|
|
248
249
|
|
|
249
250
|
```tsx
|
|
250
251
|
import React, { useState } from 'react';
|
|
251
252
|
import { View, Text } from 'react-native';
|
|
252
|
-
import {
|
|
253
|
-
PhoneInput,
|
|
254
|
-
ICountry,
|
|
255
|
-
} from 'react-native-international-phone-number';
|
|
253
|
+
import { PhoneInput } from 'react-native-international-phone-number';
|
|
256
254
|
|
|
257
255
|
export default function App() {
|
|
258
|
-
const [selectedCountry, setSelectedCountry] = useState
|
|
259
|
-
|
|
260
|
-
>(undefined);
|
|
261
|
-
const [inputValue, setInputValue] = useState<string>('');
|
|
256
|
+
const [selectedCountry, setSelectedCountry] = useState(undefined);
|
|
257
|
+
const [inputValue, setInputValue] = useState('');
|
|
262
258
|
|
|
263
|
-
function handleInputValue(phoneNumber
|
|
259
|
+
function handleInputValue(phoneNumber) {
|
|
264
260
|
setInputValue(phoneNumber);
|
|
265
261
|
}
|
|
266
262
|
|
|
267
|
-
function handleSelectedCountry(country
|
|
263
|
+
function handleSelectedCountry(country) {
|
|
268
264
|
setSelectedCountry(country);
|
|
269
265
|
}
|
|
270
266
|
|
|
271
267
|
return (
|
|
272
268
|
<View style={{ width: '100%', flex: 1, padding: 24 }}>
|
|
273
269
|
<PhoneInput
|
|
270
|
+
defaultValue="+12505550199"
|
|
274
271
|
value={inputValue}
|
|
275
272
|
onChangePhoneNumber={handleInputValue}
|
|
276
273
|
selectedCountry={selectedCountry}
|
|
@@ -291,9 +288,12 @@ export default function App() {
|
|
|
291
288
|
}
|
|
292
289
|
```
|
|
293
290
|
|
|
294
|
-
|
|
291
|
+
> Observations:
|
|
292
|
+
>
|
|
293
|
+
> 1. You need to use a default value with the following format: `+(country callling code)(area code)(number phone)`
|
|
294
|
+
> 2. The lib has the mechanism to set the flag and mask of the supplied `defaultValue`. However, if the supplied `defaultValue` does not match any international standard, the `input mask of the defaultValue` will be set to "BR" (please make sure that the default value is in the format mentioned above).
|
|
295
295
|
|
|
296
|
-
|
|
296
|
+
- ### Typescript
|
|
297
297
|
|
|
298
298
|
```tsx
|
|
299
299
|
import React, { useState } from 'react';
|
|
@@ -320,7 +320,6 @@ export default function App() {
|
|
|
320
320
|
return (
|
|
321
321
|
<View style={{ width: '100%', flex: 1, padding: 24 }}>
|
|
322
322
|
<PhoneInput
|
|
323
|
-
defaultValue="+12505550199"
|
|
324
323
|
value={inputValue}
|
|
325
324
|
onChangePhoneNumber={handleInputValue}
|
|
326
325
|
selectedCountry={selectedCountry}
|
|
@@ -341,14 +340,65 @@ export default function App() {
|
|
|
341
340
|
}
|
|
342
341
|
```
|
|
343
342
|
|
|
344
|
-
> Observations:
|
|
345
|
-
>
|
|
346
|
-
> 1. You need to use a default value with the following format: `+(country callling code)(area code)(number phone)`
|
|
347
|
-
> 2. The lib has the mechanism to set the flag and mask of the supplied `defaultValue`. However, if the supplied `defaultValue` does not match any international standard, the `input mask of the defaultValue` will be set to "BR" (please make sure that the default value is in the format mentioned above).
|
|
348
|
-
|
|
349
343
|
<br>
|
|
350
344
|
|
|
351
|
-
##
|
|
345
|
+
## Intermediate Usage
|
|
346
|
+
|
|
347
|
+
- ### Typescript + useRef
|
|
348
|
+
|
|
349
|
+
```tsx
|
|
350
|
+
import React, { useState, useRef } from 'react';
|
|
351
|
+
import { View, Text } from 'react-native';
|
|
352
|
+
import {
|
|
353
|
+
PhoneInput,
|
|
354
|
+
ICountry,
|
|
355
|
+
IPhoneInputRef,
|
|
356
|
+
} from 'react-native-international-phone-number';
|
|
357
|
+
|
|
358
|
+
export default function App() {
|
|
359
|
+
const phoneInputRef = useRef<IPhoneInputRef>(null);
|
|
360
|
+
|
|
361
|
+
function onSubmitRef() {
|
|
362
|
+
Alert.alert(
|
|
363
|
+
'Intermediate Result',
|
|
364
|
+
`${phoneInputRef.current?.selectedCountry?.callingCode} ${phoneInputRef.current?.value}`
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return (
|
|
369
|
+
<View style={{ width: '100%', flex: 1, padding: 24 }}>
|
|
370
|
+
<PhoneInput ref={phoneInputRef} />
|
|
371
|
+
<TouchableOpacity
|
|
372
|
+
style={{
|
|
373
|
+
width: '100%',
|
|
374
|
+
paddingVertical: 12,
|
|
375
|
+
backgroundColor: '#2196F3',
|
|
376
|
+
borderRadius: 4,
|
|
377
|
+
marginTop: 10,
|
|
378
|
+
}}
|
|
379
|
+
onPress={onSubmit}
|
|
380
|
+
>
|
|
381
|
+
<Text
|
|
382
|
+
style={{
|
|
383
|
+
color: '#F3F3F3',
|
|
384
|
+
textAlign: 'center',
|
|
385
|
+
fontSize: 16,
|
|
386
|
+
fontWeight: 'bold',
|
|
387
|
+
}}
|
|
388
|
+
>
|
|
389
|
+
Submit
|
|
390
|
+
</Text>
|
|
391
|
+
</TouchableOpacity>
|
|
392
|
+
</View>
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
> Observation: Don't use the useRef hook combined with the useState hook to manage the phoneNumber and selectedCountry values. Instead, choose to use just one of them (useRef or useState).
|
|
398
|
+
|
|
399
|
+
## Advanced Usage
|
|
400
|
+
|
|
401
|
+
- ### React-Hook-Form + Typescript + Default Phone Number Value
|
|
352
402
|
|
|
353
403
|
```tsx
|
|
354
404
|
import React, { useState, useEffect } from 'react';
|
|
@@ -357,7 +407,7 @@ import {
|
|
|
357
407
|
PhoneInput,
|
|
358
408
|
ICountry,
|
|
359
409
|
} from 'react-native-international-phone-number';
|
|
360
|
-
import { Controller, FieldValues
|
|
410
|
+
import { Controller, FieldValues } from 'react-hook-form';
|
|
361
411
|
|
|
362
412
|
interface FormProps extends FieldValues {
|
|
363
413
|
phoneNumber: string;
|
|
@@ -368,9 +418,6 @@ export default function App() {
|
|
|
368
418
|
undefined | ICountry
|
|
369
419
|
>(undefined);
|
|
370
420
|
|
|
371
|
-
const { control, handleSubmit, setValue, watch } =
|
|
372
|
-
useForm<FormProps>();
|
|
373
|
-
|
|
374
421
|
function handleSelectedCountry(country: ICountry) {
|
|
375
422
|
setSelectedCountry(country);
|
|
376
423
|
}
|
|
@@ -382,12 +429,6 @@ export default function App() {
|
|
|
382
429
|
);
|
|
383
430
|
}
|
|
384
431
|
|
|
385
|
-
useEffect(() => {
|
|
386
|
-
const watchPhoneNumber = watch('phoneNumber');
|
|
387
|
-
|
|
388
|
-
setValue('phoneNumber', watchPhoneNumber);
|
|
389
|
-
}, []);
|
|
390
|
-
|
|
391
432
|
return (
|
|
392
433
|
<View style={{ width: '100%', flex: 1, padding: 24 }}>
|
|
393
434
|
<Controller
|
|
@@ -511,16 +552,17 @@ export default function App() {
|
|
|
511
552
|
## Component Props ([PhoneInputProps](https://github.com/AstrOOnauta/react-native-international-phone-number/blob/master/lib/interfaces/phoneInputProps.ts))
|
|
512
553
|
|
|
513
554
|
- `defaultValue?:` string;
|
|
514
|
-
- `value
|
|
515
|
-
- `onChangePhoneNumber
|
|
516
|
-
- `selectedCountry
|
|
517
|
-
- `onChangeSelectedCountry
|
|
555
|
+
- `value?:` string;
|
|
556
|
+
- `onChangePhoneNumber?:` (phoneNumber: string) => void;
|
|
557
|
+
- `selectedCountry?:` undefined | [ICountry](https://github.com/AstrOOnauta/react-native-international-phone-number/blob/master/lib/interfaces/country.ts);
|
|
558
|
+
- `onChangeSelectedCountry?:` (country: [ICountry](https://github.com/AstrOOnauta/react-native-international-phone-number/blob/master/lib/interfaces/country.ts)) => void;
|
|
518
559
|
- `disabled?:` boolean;
|
|
519
560
|
- `modalDisabled?:` boolean;
|
|
520
561
|
- `withDarkTheme?:` boolean;
|
|
521
562
|
- `containerStyle?:` StyleProp<[ViewStyle](https://reactnative.dev/docs/view-style-props)>;
|
|
522
563
|
- `flagContainerStyle?:` StyleProp<[ViewStyle](https://reactnative.dev/docs/view-style-props)>;
|
|
523
564
|
- `inputStyle?:` StyleProp<[TextStyle](https://reactnative.dev/docs/text-style-props)>;
|
|
565
|
+
- `ref?:` [Ref](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/663f439d11d78b65f1dfd38d120f3728ea2cc207/types/react/index.d.ts#L100)<[IPhoneInputRef](https://github.com/AstrOOnauta/react-native-international-phone-number/blob/master/lib/interfaces/phoneInputRef.ts)>
|
|
524
566
|
|
|
525
567
|
<br>
|
|
526
568
|
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ICountry } from './interfaces/country';
|
|
2
|
+
import { IPhoneInputRef } from './interfaces/phoneInputRef';
|
|
2
3
|
import { PhoneInputProps } from './interfaces/phoneInputProps';
|
|
3
4
|
|
|
4
5
|
declare function PhoneInput(props: PhoneInputProps): JSX.Element;
|
|
@@ -29,5 +30,6 @@ export {
|
|
|
29
30
|
getCountriesByCallingCode,
|
|
30
31
|
getCountriesByName,
|
|
31
32
|
ICountry,
|
|
33
|
+
IPhoneInputRef,
|
|
32
34
|
PhoneInputProps,
|
|
33
35
|
};
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
useEffect,
|
|
3
|
+
useState,
|
|
4
|
+
useRef,
|
|
5
|
+
forwardRef,
|
|
6
|
+
} from 'react';
|
|
2
7
|
import {
|
|
3
8
|
StyleSheet,
|
|
4
9
|
Dimensions,
|
|
@@ -17,196 +22,316 @@ import getCountryByCca2 from './utils/getCountryByCca2';
|
|
|
17
22
|
import getCountryByPhoneNumber from './utils/getCountryByPhoneNumber';
|
|
18
23
|
import phoneMask from './utils/inputMask';
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
onChangePhoneNumber('');
|
|
43
|
-
if (onChangeSelectedCountry) {
|
|
44
|
-
onChangeSelectedCountry({
|
|
45
|
-
name: country.name,
|
|
46
|
-
cca2: country.cca2,
|
|
47
|
-
flag: country.flag,
|
|
48
|
-
callingCode: `+${country.callingCode[0]}`,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function onChangeText(phoneNumber, callingCode) {
|
|
54
|
-
const res = phoneMask(
|
|
55
|
-
phoneNumber,
|
|
56
|
-
callingCode ? callingCode : selectedCountry?.callingCode,
|
|
57
|
-
selectedCountry?.cca2
|
|
25
|
+
const PhoneInput = forwardRef(
|
|
26
|
+
(
|
|
27
|
+
{
|
|
28
|
+
placeholder,
|
|
29
|
+
placeholderTextColor,
|
|
30
|
+
selectionColor,
|
|
31
|
+
containerStyle,
|
|
32
|
+
flagContainerStyle,
|
|
33
|
+
inputStyle,
|
|
34
|
+
withDarkTheme,
|
|
35
|
+
disabled,
|
|
36
|
+
modalDisabled,
|
|
37
|
+
defaultValue,
|
|
38
|
+
onChangePhoneNumber,
|
|
39
|
+
selectedCountry,
|
|
40
|
+
onChangeSelectedCountry,
|
|
41
|
+
...rest
|
|
42
|
+
},
|
|
43
|
+
ref
|
|
44
|
+
) => {
|
|
45
|
+
const [containerWidth, setContainerWidth] = useState(
|
|
46
|
+
Dimensions.get('window').width
|
|
58
47
|
);
|
|
48
|
+
const [defaultCca2, setDefaultCca2] = useState('');
|
|
49
|
+
const [inputValue, setInputValue] = useState(null);
|
|
50
|
+
const [countryValue, setCountryValue] = useState(null);
|
|
59
51
|
|
|
60
|
-
|
|
61
|
-
}
|
|
52
|
+
const textInputRef = useRef(null);
|
|
62
53
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
const refBase = {
|
|
55
|
+
...textInputRef.current,
|
|
56
|
+
onFocus: textInputRef.current?.focus,
|
|
57
|
+
focus: textInputRef.current?.focus,
|
|
58
|
+
getValue: () => inputValue,
|
|
59
|
+
value: inputValue,
|
|
60
|
+
getSelectedCountry: () => countryValue,
|
|
61
|
+
selectedCountry: countryValue,
|
|
62
|
+
props: {
|
|
63
|
+
placeholder,
|
|
64
|
+
placeholderTextColor,
|
|
65
|
+
selectionColor,
|
|
66
|
+
containerStyle,
|
|
67
|
+
flagContainerStyle,
|
|
68
|
+
inputStyle,
|
|
69
|
+
withDarkTheme,
|
|
70
|
+
disabled,
|
|
71
|
+
modalDisabled,
|
|
72
|
+
defaultValue,
|
|
73
|
+
onChangePhoneNumber,
|
|
74
|
+
selectedCountry,
|
|
75
|
+
onChangeSelectedCountry,
|
|
76
|
+
...rest,
|
|
77
|
+
},
|
|
78
|
+
};
|
|
67
79
|
|
|
68
|
-
|
|
69
|
-
|
|
80
|
+
function updateRef(phoneNumber, country) {
|
|
81
|
+
if (ref) {
|
|
82
|
+
ref.current = {
|
|
83
|
+
...refBase,
|
|
84
|
+
getValue: () => phoneNumber,
|
|
85
|
+
value: phoneNumber,
|
|
86
|
+
getSelectedCountry: () => country,
|
|
87
|
+
selectedCountry: country,
|
|
88
|
+
props: {
|
|
89
|
+
...refBase.props,
|
|
90
|
+
value: phoneNumber,
|
|
91
|
+
selectedCountry: country,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
70
96
|
|
|
71
|
-
|
|
97
|
+
function onSelect(country) {
|
|
98
|
+
if (ref) {
|
|
99
|
+
setInputValue('');
|
|
72
100
|
} else {
|
|
73
|
-
|
|
74
|
-
onChangeSelectedCountry(null);
|
|
75
|
-
onChangeText('', null);
|
|
76
|
-
|
|
77
|
-
console.warn(
|
|
78
|
-
"The default number provided (defaultValue) don't match with anyone country. Please, correct it to be shown in the input. For more information: https://github.com/AstrOOnauta/react-native-international-phone-number#intermediate-usage---typescript--default-phone-number-value"
|
|
79
|
-
);
|
|
101
|
+
onChangePhoneNumber('');
|
|
80
102
|
}
|
|
81
|
-
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
cca2:
|
|
86
|
-
flag:
|
|
87
|
-
|
|
88
|
-
}
|
|
103
|
+
|
|
104
|
+
if (onChangeSelectedCountry || ref) {
|
|
105
|
+
const newValue = {
|
|
106
|
+
name: country.name,
|
|
107
|
+
cca2: country.cca2,
|
|
108
|
+
flag: country.flag,
|
|
109
|
+
callingCode: `+${country.callingCode[0]}`,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
if (ref) {
|
|
113
|
+
setCountryValue(newValue);
|
|
114
|
+
updateRef('', newValue);
|
|
115
|
+
} else {
|
|
116
|
+
onChangeSelectedCountry(newValue);
|
|
117
|
+
}
|
|
89
118
|
}
|
|
90
119
|
}
|
|
91
|
-
}, [defaultValue]);
|
|
92
|
-
|
|
93
|
-
useEffect(() => {
|
|
94
|
-
if (
|
|
95
|
-
defaultValue &&
|
|
96
|
-
selectedCountry &&
|
|
97
|
-
selectedCountry.cca2 === defaultCca2 &&
|
|
98
|
-
!rest.value
|
|
99
|
-
) {
|
|
100
|
-
const callingCode = selectedCountry.callingCode;
|
|
101
120
|
|
|
102
|
-
|
|
121
|
+
function onChangeText(phoneNumber, callingCode) {
|
|
122
|
+
const res = phoneMask(
|
|
123
|
+
phoneNumber,
|
|
124
|
+
callingCode ? callingCode : countryValue?.callingCode,
|
|
125
|
+
countryValue?.cca2
|
|
126
|
+
);
|
|
103
127
|
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
selectedCountry.cca2 !== 'US'
|
|
108
|
-
) {
|
|
109
|
-
phoneNumber = defaultValue
|
|
110
|
-
.replace(/\s/g, '')
|
|
111
|
-
.substring(
|
|
112
|
-
callingCode.length + 3,
|
|
113
|
-
defaultValue.replace(/\D/g, '').length +
|
|
114
|
-
callingCode.length
|
|
115
|
-
);
|
|
116
|
-
} else if (
|
|
117
|
-
callingCode === '+39' &&
|
|
118
|
-
selectedCountry.cca2 === 'VA'
|
|
119
|
-
) {
|
|
120
|
-
phoneNumber = defaultValue
|
|
121
|
-
.replace(/\s/g, '')
|
|
122
|
-
.substring(
|
|
123
|
-
callingCode.length + 5,
|
|
124
|
-
defaultValue.replace(/\D/g, '').length +
|
|
125
|
-
callingCode.length
|
|
126
|
-
);
|
|
128
|
+
if (ref) {
|
|
129
|
+
setInputValue(res);
|
|
130
|
+
updateRef(res, countryValue);
|
|
127
131
|
} else {
|
|
128
|
-
|
|
129
|
-
.replace(/\s/g, '')
|
|
130
|
-
.substring(
|
|
131
|
-
callingCode.length,
|
|
132
|
-
defaultValue.replace(/\D/g, '').length +
|
|
133
|
-
callingCode.length
|
|
134
|
-
);
|
|
132
|
+
onChangePhoneNumber(res);
|
|
135
133
|
}
|
|
136
|
-
onChangeText(phoneNumber, callingCode);
|
|
137
134
|
}
|
|
138
|
-
}, [selectedCountry]);
|
|
139
135
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
modalProps={
|
|
176
|
-
disabled || modalDisabled ? { visible: false } : {}
|
|
177
|
-
}
|
|
178
|
-
/>
|
|
179
|
-
<TextInput
|
|
180
|
-
style={[
|
|
181
|
-
withDarkTheme ? styles.darkInput : styles.lightInput,
|
|
182
|
-
{ width: containerWidth - 100 },
|
|
183
|
-
inputStyle ? inputStyle : {},
|
|
184
|
-
]}
|
|
185
|
-
placeholder={
|
|
186
|
-
placeholder ? placeholder : 'Insert your phone number'
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
if (ref) {
|
|
138
|
+
setInputValue('');
|
|
139
|
+
} else {
|
|
140
|
+
onChangePhoneNumber('');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (defaultValue) {
|
|
144
|
+
const matchingCountry = getCountryByPhoneNumber(defaultValue);
|
|
145
|
+
|
|
146
|
+
if (matchingCountry) {
|
|
147
|
+
setDefaultCca2(matchingCountry.cca2);
|
|
148
|
+
|
|
149
|
+
if (ref) {
|
|
150
|
+
setCountryValue(matchingCountry);
|
|
151
|
+
updateRef('', matchingCountry);
|
|
152
|
+
} else {
|
|
153
|
+
onChangeSelectedCountry(matchingCountry);
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
setDefaultCca2(null);
|
|
157
|
+
|
|
158
|
+
if (ref) {
|
|
159
|
+
setCountryValue(null);
|
|
160
|
+
updateRef('', null);
|
|
161
|
+
} else {
|
|
162
|
+
onChangeSelectedCountry(null);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
onChangeText('', null);
|
|
166
|
+
|
|
167
|
+
console.warn(
|
|
168
|
+
"The default number provided (defaultValue) don't match with anyone country. Please, correct it to be shown in the input. For more information: https://github.com/AstrOOnauta/react-native-international-phone-number#intermediate-usage---typescript--default-phone-number-value"
|
|
169
|
+
);
|
|
187
170
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
:
|
|
192
|
-
|
|
193
|
-
: '
|
|
171
|
+
} else {
|
|
172
|
+
if (!countryValue) {
|
|
173
|
+
const defaultCountry = {
|
|
174
|
+
callingCode: '+55',
|
|
175
|
+
cca2: 'BR',
|
|
176
|
+
flag: 'flag-br',
|
|
177
|
+
name: 'Brazil',
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
if (ref) {
|
|
181
|
+
setCountryValue(defaultCountry);
|
|
182
|
+
updateRef('', defaultCountry);
|
|
183
|
+
} else {
|
|
184
|
+
onChangeSelectedCountry(defaultCountry);
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
if (ref) {
|
|
188
|
+
updateRef('', countryValue);
|
|
189
|
+
}
|
|
194
190
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
191
|
+
}
|
|
192
|
+
}, [defaultValue]);
|
|
193
|
+
|
|
194
|
+
useEffect(() => {
|
|
195
|
+
if (
|
|
196
|
+
defaultValue &&
|
|
197
|
+
countryValue &&
|
|
198
|
+
countryValue.cca2 === defaultCca2 &&
|
|
199
|
+
!inputValue
|
|
200
|
+
) {
|
|
201
|
+
const callingCode = countryValue.callingCode;
|
|
202
|
+
|
|
203
|
+
let phoneNumber = defaultValue;
|
|
204
|
+
|
|
205
|
+
if (
|
|
206
|
+
callingCode === '+1' &&
|
|
207
|
+
countryValue.cca2 !== 'CA' &&
|
|
208
|
+
countryValue.cca2 !== 'US'
|
|
209
|
+
) {
|
|
210
|
+
phoneNumber = defaultValue
|
|
211
|
+
.replace(/\s/g, '')
|
|
212
|
+
.substring(
|
|
213
|
+
callingCode.length + 3,
|
|
214
|
+
defaultValue.replace(/\D/g, '').length +
|
|
215
|
+
callingCode.length
|
|
216
|
+
);
|
|
217
|
+
} else if (
|
|
218
|
+
callingCode === '+39' &&
|
|
219
|
+
countryValue.cca2 === 'VA'
|
|
220
|
+
) {
|
|
221
|
+
phoneNumber = defaultValue
|
|
222
|
+
.replace(/\s/g, '')
|
|
223
|
+
.substring(
|
|
224
|
+
callingCode.length + 5,
|
|
225
|
+
defaultValue.replace(/\D/g, '').length +
|
|
226
|
+
callingCode.length
|
|
227
|
+
);
|
|
228
|
+
} else {
|
|
229
|
+
phoneNumber = defaultValue
|
|
230
|
+
.replace(/\s/g, '')
|
|
231
|
+
.substring(
|
|
232
|
+
callingCode.length,
|
|
233
|
+
defaultValue.replace(/\D/g, '').length +
|
|
234
|
+
callingCode.length
|
|
235
|
+
);
|
|
201
236
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
237
|
+
onChangeText(phoneNumber, callingCode);
|
|
238
|
+
}
|
|
239
|
+
}, [countryValue]);
|
|
240
|
+
|
|
241
|
+
useEffect(() => {
|
|
242
|
+
if (!ref) {
|
|
243
|
+
setInputValue(rest.value);
|
|
244
|
+
setCountryValue(selectedCountry);
|
|
245
|
+
}
|
|
246
|
+
}, [selectedCountry]);
|
|
247
|
+
|
|
248
|
+
if (
|
|
249
|
+
ref &&
|
|
250
|
+
(rest.value ||
|
|
251
|
+
onChangePhoneNumber ||
|
|
252
|
+
selectedCountry ||
|
|
253
|
+
onChangeSelectedCountry)
|
|
254
|
+
) {
|
|
255
|
+
throw new Error(
|
|
256
|
+
"Error: Don't use the useRef hook combined with the useState hook to manage the phoneNumber and selectedCountry values. Instead, choose to use just one of them (useRef or useState)."
|
|
257
|
+
);
|
|
258
|
+
} else {
|
|
259
|
+
return (
|
|
260
|
+
<View
|
|
261
|
+
style={[
|
|
262
|
+
withDarkTheme
|
|
263
|
+
? {
|
|
264
|
+
...styles.darkContainer,
|
|
265
|
+
backgroundColor: disabled
|
|
266
|
+
? '#858585'
|
|
267
|
+
: styles.darkContainer.backgroundColor,
|
|
268
|
+
}
|
|
269
|
+
: {
|
|
270
|
+
...styles.lightContainer,
|
|
271
|
+
backgroundColor: disabled
|
|
272
|
+
? '#E3E3E3'
|
|
273
|
+
: styles.lightContainer.backgroundColor,
|
|
274
|
+
},
|
|
275
|
+
containerStyle ? containerStyle : {},
|
|
276
|
+
]}
|
|
277
|
+
onLayout={(e) =>
|
|
278
|
+
setContainerWidth(e.nativeEvent.layout.width)
|
|
279
|
+
}
|
|
280
|
+
>
|
|
281
|
+
<CountryPicker
|
|
282
|
+
containerButtonStyle={[
|
|
283
|
+
flagContainerBase,
|
|
284
|
+
countryValue?.cca2 === 'VA' ? { width: 140 } : {},
|
|
285
|
+
flagContainerStyle ? flagContainerStyle : {},
|
|
286
|
+
]}
|
|
287
|
+
onSelect={onSelect}
|
|
288
|
+
withFilter
|
|
289
|
+
withAlphaFilter
|
|
290
|
+
withCallingCode
|
|
291
|
+
withCallingCodeButton={countryValue || defaultCca2}
|
|
292
|
+
theme={withDarkTheme ? DARK_THEME : DEFAULT_THEME}
|
|
293
|
+
countryCode={
|
|
294
|
+
countryValue ? countryValue?.cca2 : defaultCca2
|
|
295
|
+
}
|
|
296
|
+
modalProps={
|
|
297
|
+
disabled || modalDisabled ? { visible: false } : {}
|
|
298
|
+
}
|
|
299
|
+
/>
|
|
300
|
+
<TextInput
|
|
301
|
+
style={[
|
|
302
|
+
withDarkTheme ? styles.darkInput : styles.lightInput,
|
|
303
|
+
{ width: containerWidth - 100 },
|
|
304
|
+
inputStyle ? inputStyle : {},
|
|
305
|
+
]}
|
|
306
|
+
placeholder={
|
|
307
|
+
placeholder ? placeholder : 'Insert your phone number'
|
|
308
|
+
}
|
|
309
|
+
placeholderTextColor={
|
|
310
|
+
placeholderTextColor
|
|
311
|
+
? placeholderTextColor
|
|
312
|
+
: withDarkTheme
|
|
313
|
+
? '#CCCCCC'
|
|
314
|
+
: '#DDDDDD'
|
|
315
|
+
}
|
|
316
|
+
selectionColor={
|
|
317
|
+
selectionColor
|
|
318
|
+
? selectionColor
|
|
319
|
+
: withDarkTheme
|
|
320
|
+
? 'rgba(255,255,255, .4)'
|
|
321
|
+
: 'rgba(0 ,0 ,0 , .4)'
|
|
322
|
+
}
|
|
323
|
+
editable={!disabled}
|
|
324
|
+
value={inputValue}
|
|
325
|
+
onChangeText={onChangeText}
|
|
326
|
+
keyboardType="numeric"
|
|
327
|
+
ref={textInputRef}
|
|
328
|
+
{...rest}
|
|
329
|
+
/>
|
|
330
|
+
</View>
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
);
|
|
210
335
|
|
|
211
336
|
const containerBase = {
|
|
212
337
|
flexDirection: 'row',
|
|
@@ -6,8 +6,10 @@ import {
|
|
|
6
6
|
} from 'react-native';
|
|
7
7
|
|
|
8
8
|
import { ICountry } from './country';
|
|
9
|
+
import { Ref } from 'react';
|
|
10
|
+
import { IPhoneInputRef } from './phoneInputRef';
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
interface IPhoneInputPropsWithoutRef extends TextInputProps {
|
|
11
13
|
placeholder?: string;
|
|
12
14
|
placeholderTextColor?: string;
|
|
13
15
|
containerStyle?: StyleProp<ViewStyle>;
|
|
@@ -21,4 +23,26 @@ export interface PhoneInputProps extends TextInputProps {
|
|
|
21
23
|
onChangePhoneNumber: (phoneNumber: string) => void;
|
|
22
24
|
selectedCountry: undefined | ICountry;
|
|
23
25
|
onChangeSelectedCountry: (country: ICountry) => void;
|
|
26
|
+
ref?: never;
|
|
24
27
|
}
|
|
28
|
+
|
|
29
|
+
interface IPhoneInputPropsWithRef extends TextInputProps {
|
|
30
|
+
placeholder?: string;
|
|
31
|
+
placeholderTextColor?: string;
|
|
32
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
33
|
+
flagContainerStyle?: StyleProp<ViewStyle>;
|
|
34
|
+
inputStyle?: StyleProp<TextStyle>;
|
|
35
|
+
withDarkTheme?: boolean;
|
|
36
|
+
disabled?: boolean;
|
|
37
|
+
modalDisabled?: boolean;
|
|
38
|
+
defaultValue?: string;
|
|
39
|
+
value?: never;
|
|
40
|
+
onChangePhoneNumber?: never;
|
|
41
|
+
selectedCountry?: never;
|
|
42
|
+
onChangeSelectedCountry?: never;
|
|
43
|
+
ref: Ref<IPhoneInputRef>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type PhoneInputProps =
|
|
47
|
+
| IPhoneInputPropsWithRef
|
|
48
|
+
| IPhoneInputPropsWithoutRef;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TextInput } from 'react-native';
|
|
2
|
+
|
|
3
|
+
import { ICountry } from './country';
|
|
4
|
+
import { PhoneInputProps } from './phoneInputProps';
|
|
5
|
+
|
|
6
|
+
export interface IPhoneInputRef extends TextInput {
|
|
7
|
+
props: PhoneInputProps;
|
|
8
|
+
onFocus: () => void;
|
|
9
|
+
focus: () => void;
|
|
10
|
+
getValue: () => string;
|
|
11
|
+
value: string;
|
|
12
|
+
getSelectedCountry: () => ICountry;
|
|
13
|
+
selectedCountry: ICountry;
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-international-phone-number",
|
|
3
3
|
"author": "AstrOOnauta (https://github.com/AstrOOnauta)",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.14",
|
|
5
5
|
"description": "International mobile phone input component with mask for React Native",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/index.d.ts",
|