react-native-international-phone-number 0.3.1 → 0.4.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/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ ISC License
2
+
3
+ Copyright 2022-present Willian Barbosa Lima do Nascimento & Collaborators
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -11,19 +11,45 @@
11
11
  <img src="https://img.shields.io/npm/v/react-native-international-phone-number.svg?style=flat-square">
12
12
  </a>
13
13
  <a href="https://www.npmjs.com/package/react-native-international-phone-number">
14
- <img src="https://img.shields.io/npm/dm/react-native-international-phone-number.svg?style=flat-square">
14
+ <img src="https://img.shields.io/npm/dm/react-native-international-phone-number.svg?style=flat-square&color=success">
15
15
  </a>
16
16
  <a href="https://github.com/AstrOOnauta/react-native-international-phone-number">
17
- <img src="https://img.shields.io/github/stars/AstrOOnauta/react-native-international-phone-number"/>
17
+ <img src="https://img.shields.io/github/stars/AstrOOnauta/react-native-international-phone-number?style=flat-square&color=success"/>
18
18
  </a>
19
19
  <a href="https://github.com/AstrOOnauta/react-native-international-phone-number/issues">
20
- <img src="https://img.shields.io/github/issues/AstrOOnauta/react-native-international-phone-number"/>
20
+ <img src="https://img.shields.io/github/issues/AstrOOnauta/react-native-international-phone-number?style=flat-square&color=blue"/>
21
21
  </a>
22
22
  <a href="https://github.com/AstrOOnauta/react-native-international-phone-number/pulls">
23
- <img src="https://img.shields.io/github/issues-pr/AstrOOnauta/react-native-international-phone-number"/>
23
+ <img src="https://img.shields.io/github/issues-pr/AstrOOnauta/react-native-international-phone-number?style=flat-square&color=blue"/>
24
+ </a>
25
+ <a href="https://github.com/AstrOOnauta/react-native-international-phone-number/blob/master/LICENSE.md">
26
+ <img src="https://img.shields.io/:license-isc-yellow.svg?style=flat-square"/>
24
27
  </a>
25
28
  </p>
26
29
 
30
+ <br>
31
+
32
+ ## Table of Contents
33
+
34
+ - [Installation](#installation)
35
+ - [Features](#features)
36
+ - [Basic Usage](#basic-usage)
37
+ - With Function Component
38
+ - With Class Component
39
+ - [Basic Usage - Typescript](#basic-usage---typescript)
40
+ - [Intermediate Usage - Typescrypt + Default Phone Number Value](#intermediate-usage---typescript--default-phone-number-value)
41
+ - [Advanced Usage - React Hook Form + Typescript + Default Phone Number Value](#advanced-usage---react-hook-form--typescript--default-phone-number-value)
42
+ - [Customizing Lib](#customizing-lib)
43
+ - Theme Mode: Light (default) and Dark
44
+ - Custom Lib Styles
45
+ - Disabled Mode
46
+ - Custom Disabled Mode Style
47
+ - [Lib Props](#props)
48
+ - [Contributing](#contributing)
49
+ - [License](#license)
50
+
51
+ <br>
52
+
27
53
  ## Installation
28
54
 
29
55
  ```bash
@@ -49,37 +75,146 @@ AND
49
75
  > };
50
76
  > ```
51
77
 
78
+ <br>
79
+
52
80
  ## Features
53
81
 
54
82
  - 📱 Works with iOS, Android (Cross-platform) and Expo;
55
83
  - 🎨 Lib with UI customizable;
56
- - 🌎 Phone Input Mask according to the selected country.
84
+ - 🌎 Phone Input Mask according to the selected country;
85
+ - 👨‍💻 Functional and class component support.
86
+
87
+ <br>
57
88
 
58
89
  ## Basic Usage
59
90
 
91
+ - Function Component:
92
+
60
93
  ```jsx
61
94
  import React, { useState } from 'react';
62
95
  import { View, Text } from 'react-native';
96
+ import { PhoneInput } from 'react-native-international-phone-number';
97
+
98
+ export default function App() {
99
+ const [selectedCountry, setSelectedCountry] = useState(undefined);
100
+ const [inputValue, setInputValue] = useState('');
101
+
102
+ function handleInputValue(phoneNumber) {
103
+ setInputValue(phoneNumber);
104
+ }
105
+
106
+ function handleSelectedCountry(country) {
107
+ setSelectedCountry(country);
108
+ }
109
+
110
+ return (
111
+ <View style={{ width: '100%', flex: 1, padding: 24 }}>
112
+ <PhoneInput
113
+ value={inputValue}
114
+ onChangePhoneNumber={handleInputValue}
115
+ selectedCountry={selectedCountry}
116
+ onChangeSelectedCountry={handleSelectedCountry}
117
+ />
118
+ <View style={{ marginTop: 10 }}>
119
+ <Text>
120
+ Country:{' '}
121
+ {`${selectedCountry?.name} (${selectedCountry?.cca2})`}
122
+ </Text>
123
+ <Text>
124
+ Phone Number:{' '}
125
+ {`${selectedCountry?.callingCode} ${inputValue}`}
126
+ </Text>
127
+ </View>
128
+ </View>
129
+ );
130
+ }
131
+ ```
132
+
133
+ - Class Component:
134
+
135
+ ```jsx
136
+ import React from 'react';
137
+ import { View, Text } from 'react-native';
138
+ import { PhoneInput } from 'react-native-international-phone-number';
139
+
140
+ export class App extends React.Component {
141
+ constructor(props) {
142
+ super(props)
143
+ this.state = {
144
+ selectedCountry: undefined,
145
+ inputValue: ''
146
+ }
147
+ }
148
+
149
+ function handleSelectedCountry(country) {
150
+ this.setState({
151
+ selectedCountry: country
152
+ })
153
+ }
154
+
155
+ function handleInputValue(phoneNumber) {
156
+ this.setState({
157
+ inputValue: phoneNumber
158
+ })
159
+ }
160
+
161
+ render(){
162
+ return (
163
+ <View style={{ width: '100%', flex: 1, padding: 24 }}>
164
+ <PhoneInput
165
+ value={this.inputValue}
166
+ onChangePhoneNumber={this.handleInputValue}
167
+ selectedCountry={this.selectedCountry}
168
+ onChangeSelectedCountry={this.handleSelectedCountry}
169
+ />
170
+ <View style={{ marginTop: 10 }}>
171
+ <Text>
172
+ Country:{' '}
173
+ {`${this.selectedCountry?.name} (${this.selectedCountry?.cca2})`}
174
+ </Text>
175
+ <Text>
176
+ Phone Number: {`${this.selectedCountry?.callingCode} ${this.inputValue}`}
177
+ </Text>
178
+ </View>
179
+ </View>
180
+ );
181
+ }
182
+ }
183
+ ```
184
+
185
+ <br>
186
+
187
+ ## Basic Usage - Typescript
188
+
189
+ ```tsx
190
+ import React, { useState } from 'react';
191
+ import { View, Text } from 'react-native';
63
192
  import {
64
- phoneMask,
65
193
  PhoneInput,
194
+ ICountry,
66
195
  } from 'react-native-international-phone-number';
67
196
 
68
197
  export default function App() {
69
- const [selectedCountry, setSelectedCountry] = useState(undefined);
70
- const [phoneInput, setPhoneInput] = useState('');
198
+ const [selectedCountry, setSelectedCountry] = useState<
199
+ undefined | ICountry
200
+ >(undefined);
201
+ const [inputValue, setInputValue] = useState<string>('');
202
+
203
+ function handleInputValue(phoneNumber: string) {
204
+ setInputValue(phoneNumber);
205
+ }
206
+
207
+ function handleSelectedCountry(country: ICountry) {
208
+ setSelectedCountry(country);
209
+ }
71
210
 
72
211
  return (
73
212
  <View style={{ width: '100%', flex: 1, padding: 24 }}>
74
213
  <PhoneInput
214
+ value={inputValue}
215
+ onChangePhoneNumber={handleInputValue}
75
216
  selectedCountry={selectedCountry}
76
- setSelectedCountry={setSelectedCountry}
77
- value={phoneInput}
78
- onChangeText={(newValue) =>
79
- setPhoneInput(
80
- phoneMask(newValue, selectedCountry.callingCode[0])
81
- )
82
- }
217
+ onChangeSelectedCountry={handleSelectedCountry}
83
218
  />
84
219
  <View style={{ marginTop: 10 }}>
85
220
  <Text>
@@ -87,7 +222,8 @@ export default function App() {
87
222
  {`${selectedCountry?.name} (${selectedCountry?.cca2})`}
88
223
  </Text>
89
224
  <Text>
90
- Phone: {`${selectedCountry?.callingCode[0]} ${phoneInput}`}
225
+ Phone Number:{' '}
226
+ {`${selectedCountry?.callingCode} ${inputValue}`}
91
227
  </Text>
92
228
  </View>
93
229
  </View>
@@ -95,34 +231,40 @@ export default function App() {
95
231
  }
96
232
  ```
97
233
 
98
- ## Basic Usage - Typescript
234
+ <br>
235
+
236
+ ## Intermediate Usage - Typescript + Default Phone Number Value
99
237
 
100
238
  ```tsx
101
239
  import React, { useState } from 'react';
102
240
  import { View, Text } from 'react-native';
103
241
  import {
104
- phoneMask,
105
242
  PhoneInput,
243
+ ICountry,
106
244
  } from 'react-native-international-phone-number';
107
- import { Country } from 'react-native-country-picker-modal';
108
245
 
109
246
  export default function App() {
110
247
  const [selectedCountry, setSelectedCountry] = useState<
111
- undefined | Country
248
+ undefined | ICountry
112
249
  >(undefined);
113
- const [phoneInput, setPhoneInput] = useState<string>('');
250
+ const [inputValue, setInputValue] = useState<string>('');
251
+
252
+ function handleInputValue(phoneNumber: string) {
253
+ setInputValue(phoneNumber);
254
+ }
255
+
256
+ function handleSelectedCountry(country: ICountry) {
257
+ setSelectedCountry(country);
258
+ }
114
259
 
115
260
  return (
116
261
  <View style={{ width: '100%', flex: 1, padding: 24 }}>
117
262
  <PhoneInput
263
+ defaultValue="+12505550199"
264
+ value={inputValue}
265
+ onChangePhoneNumber={handleInputValue}
118
266
  selectedCountry={selectedCountry}
119
- setSelectedCountry={setSelectedCountry}
120
- value={phoneInput}
121
- onChangeText={(newValue) =>
122
- setPhoneInput(
123
- phoneMask(newValue, selectedCountry?.callingCode[0])
124
- )
125
- }
267
+ onChangeSelectedCountry={handleSelectedCountry}
126
268
  />
127
269
  <View style={{ marginTop: 10 }}>
128
270
  <Text>
@@ -130,7 +272,8 @@ export default function App() {
130
272
  {`${selectedCountry?.name} (${selectedCountry?.cca2})`}
131
273
  </Text>
132
274
  <Text>
133
- Phone: {`${selectedCountry?.callingCode[0]} ${phoneInput}`}
275
+ Phone Number:{' '}
276
+ {`${selectedCountry?.callingCode} ${inputValue}`}
134
277
  </Text>
135
278
  </View>
136
279
  </View>
@@ -138,16 +281,22 @@ export default function App() {
138
281
  }
139
282
  ```
140
283
 
141
- ## Advanced Usage - React-Hook-Form and Typescript
284
+ > Observations:
285
+ >
286
+ > 1. You need to use a default value with the following format: `+(country callling code)(area code)(number phone)`
287
+ > 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).
288
+
289
+ <br>
290
+
291
+ ## Advanced Usage - React-Hook-Form + Typescript + Default Phone Number Value
142
292
 
143
293
  ```tsx
144
294
  import React, { useState, useEffect } from 'react';
145
- import { View, Text, Alert } from 'react-native';
295
+ import { View, Text, TouchableOpacity, Alert } from 'react-native';
146
296
  import {
147
- phoneMask,
148
297
  PhoneInput,
298
+ ICountry,
149
299
  } from 'react-native-international-phone-number';
150
- import { Country } from 'react-native-country-picker-modal';
151
300
  import { Controller, FieldValues, useForm } from 'react-hook-form';
152
301
 
153
302
  interface FormProps extends FieldValues {
@@ -155,21 +304,29 @@ interface FormProps extends FieldValues {
155
304
  }
156
305
 
157
306
  export default function App() {
158
- const [selectedCountry, setSelectedCountry] = useState<undefined | Country>(undefined);
307
+ const [selectedCountry, setSelectedCountry] = useState<
308
+ undefined | ICountry
309
+ >(undefined);
159
310
 
160
- const { control, handleSubmit, resetField } = useForm<FormProps>();
311
+ const { control, handleSubmit, setValue, watch } =
312
+ useForm<FormProps>();
313
+
314
+ function handleSelectedCountry(country: ICountry) {
315
+ setSelectedCountry(country);
316
+ }
161
317
 
162
318
  function onSubmit(form: FormProps) {
163
319
  Alert.alert(
164
320
  'Advanced Result',
165
- `${selectedCountry?.callingCode[0]} ${form.phoneNumber}`
321
+ `${selectedCountry?.callingCode} ${form.phoneNumber}`
166
322
  );
167
- resetField('phoneNumber');
168
323
  }
169
324
 
170
- useEffect(()=>{
171
- resetField('phoneNumber')
172
- },[selectedCountry])
325
+ useEffect(() => {
326
+ const watchPhoneNumber = watch('phoneNumber');
327
+
328
+ setValue('phoneNumber', watchPhoneNumber);
329
+ }, []);
173
330
 
174
331
  return (
175
332
  <View style={{ width: '100%', flex: 1, padding: 24 }}>
@@ -178,35 +335,49 @@ export default function App() {
178
335
  control={control}
179
336
  render={({ field: { onChange, value } }) => (
180
337
  <PhoneInput
181
- selectedCountry={selectedCountry}
182
- setSelectedCountry={setSelectedCountry}
338
+ defaultValue="+12505550199"
183
339
  value={value}
184
- onChangeText={(newValue) =>
185
- onChange(
186
- phoneMask(newValue, selectedCountry?.callingCode[0])
187
- )
188
- }
340
+ onChangePhoneNumber={onChange}
341
+ selectedCountry={selectedCountry}
342
+ onChangeSelectedCountry={handleSelectedCountry}
189
343
  />
190
344
  )}
191
345
  />
192
- <Button
346
+ <TouchableOpacity
193
347
  style={{
194
348
  width: '100%',
195
- marginTop: 10,
196
- backgroundColor: '#90d7ff',
349
+ paddingVertical: 12,
350
+ backgroundColor: '#2196F3',
351
+ borderRadius: 4,
197
352
  }}
198
353
  onPress={handleSubmit(onSubmit)}
199
- />
200
- <Text>Submit</Text>
201
- </Button>
354
+ >
355
+ <Text
356
+ style={{
357
+ color: '#F3F3F3',
358
+ textAlign: 'center',
359
+ fontSize: 16,
360
+ fontWeight: 'bold',
361
+ }}
362
+ >
363
+ Submit
364
+ </Text>
365
+ </TouchableOpacity>
202
366
  </View>
203
367
  );
204
368
  }
205
369
  ```
206
370
 
371
+ > Observations:
372
+ >
373
+ > 1. You need to use a default value with the following format: `+(country callling code)(area code)(number phone)`
374
+ > 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).
375
+
376
+ <br>
377
+
207
378
  ## Customizing lib
208
379
 
209
- ### Dark mode:
380
+ - Dark Mode:
210
381
 
211
382
  ```jsx
212
383
  <PhoneInput
@@ -215,7 +386,7 @@ export default function App() {
215
386
  />
216
387
  ```
217
388
 
218
- ### Custom Lib Styles:
389
+ - Custom Lib Styles:
219
390
 
220
391
  <div>
221
392
  <img src="https://github.com/AstrOOnauta/react-native-international-phone-number/blob/master/images/custom-styles.png">
@@ -243,21 +414,45 @@ export default function App() {
243
414
  />
244
415
  ```
245
416
 
246
- ## Props
417
+ - Disabled Mode:
247
418
 
248
- - `value?`: string
249
- - `onChangeText?`: (text: string) => void
250
- - `containerStyle?`: StyleProp<ViewStyle>
251
- - `flagContainerStyle?`: StyleProp<ViewStyle>
252
- - `inputStyle?`: StyleProp<InputStyle>
253
- - `withDarkTheme?`: boolean
254
- - `disabled?`: boolean
255
- - `placeholder?`: string
256
- - `placeholderTextColor?`: string
419
+ ```jsx
420
+ <PhoneInput
421
+ ...
422
+ disabled
423
+ />
424
+ ```
257
425
 
258
- ## Methods
426
+ - Custom Disabled Mode Style:
259
427
 
260
- - `phoneMask`: (phoneNumber: string, callingCode: string) => string
428
+ ```jsx
429
+ ...
430
+ const [isDisabled, setIsDisabled] = useState<boolean>(true)
431
+ ...
432
+ <PhoneInput
433
+ ...
434
+ containerStyle={ isDisabled ? { backgroundColor: 'yellow' } : {} }
435
+ disabled={isDisabled}
436
+ />
437
+ ...
438
+ ```
439
+
440
+ </br>
441
+
442
+ ## Props
443
+
444
+ - `defaultValue?:` string;
445
+ - `value:` string;
446
+ - `onChangePhoneNumber:` (phoneNumber: string) => void;
447
+ - `selectedCountry:` undefined | ICountry;
448
+ - `onChangeSelectedCountry:` (country: ICountry) => void;
449
+ - `disabled?:` boolean;
450
+ - `withDarkTheme?:` boolean;
451
+ - `containerStyle?:` StyleProp<[ViewStyle](https://reactnative.dev/docs/view-style-props)>;
452
+ - `flagContainerStyle?:` StyleProp<[ViewStyle](https://reactnative.dev/docs/view-style-props)>;
453
+ - `inputStyle?:` StyleProp<[TextStyle](https://reactnative.dev/docs/text-style-props)>;
454
+
455
+ </br>
261
456
 
262
457
  ## Contributing
263
458
 
@@ -273,6 +468,12 @@ export default function App() {
273
468
 
274
469
  <br>
275
470
 
471
+ ## License
472
+
473
+ [ISC](https://github.com/AstrOOnauta/react-native-international-phone-number/blob/master/LICENSE.md)
474
+
475
+ <br>
476
+
276
477
  <div align = "center">
277
478
  <br>
278
479
  Thanks for stopping by! 😁
package/lib/index.d.ts CHANGED
@@ -1,11 +1,16 @@
1
- import { Dispatch, SetStateAction } from 'react';
2
1
  import {
3
2
  StyleProp,
4
3
  TextInputProps,
5
4
  TextStyle,
6
5
  ViewStyle,
7
6
  } from 'react-native';
8
- import { Country } from 'react-native-country-picker-modal';
7
+
8
+ export interface ICountry {
9
+ callingCode: string;
10
+ cca2: string;
11
+ flag: string;
12
+ name: string;
13
+ }
9
14
 
10
15
  interface PhoneInputProps extends TextInputProps {
11
16
  placeholder?: string;
@@ -15,15 +20,13 @@ interface PhoneInputProps extends TextInputProps {
15
20
  inputStyle?: StyleProp<TextStyle>;
16
21
  withDarkTheme?: boolean;
17
22
  disabled?: boolean;
18
- selectedCountry: undefined | Country;
19
- setSelectedCountry: Dispatch<SetStateAction<undefined | Country>>;
23
+ defaultValue?: string;
24
+ value: string;
25
+ onChangePhoneNumber: (phoneNumber: string) => void;
26
+ selectedCountry: undefined | ICountry;
27
+ onChangeSelectedCountry: (country: ICountry) => void;
20
28
  }
21
29
 
22
- declare function PhoneInput(props: PhoneInputProps): JSX.Element;
23
-
24
- declare function phoneMask(
25
- value: string,
26
- countryCode?: string
27
- ): string;
28
-
29
- export { PhoneInput, phoneMask };
30
+ export declare function PhoneInput(
31
+ props: PhoneInputProps
32
+ ): JSX.Element;