react-native-international-phone-number 0.10.8 → 0.11.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/README.md CHANGED
@@ -69,11 +69,11 @@
69
69
  - [Basic Usage](#basic-usage)
70
70
  - [With Class Component](#class-component)
71
71
  - [With Function Component](#function-component)
72
- - [With Typescript](#typescript)
72
+ - [With Typescript + defaultValue](#typescript)
73
73
  - [Intermediate Usage](#intermediate-usage)
74
- - [Typescript + useRef](#typescript--useref)
74
+ - [Typescript + useRef + defaultValue](#typescript--useref)
75
75
  - [Advanced Usage](#advanced-usage)
76
- - [React-Hook-Form + Typescript + Default Phone Number Value](#react-hook-form--typescript--default-phone-number-value)
76
+ - [React-Hook-Form + Typescript + defaultValue](#react-hook-form--typescript--default-phone-number-value)
77
77
  - [Customizing Lib](#customizing-lib)
78
78
  - [Lib Props](#component-props-phoneinputprops)
79
79
  - [Lib Functions](#functions)
@@ -87,6 +87,7 @@
87
87
 
88
88
  ## Old Versions
89
89
 
90
+ - [Version 0.10.x](https://github.com/AstrOOnauta/react-native-international-phone-number/tree/v0.10.x)
90
91
  - [Version 0.9.x](https://github.com/AstrOOnauta/react-native-international-phone-number/tree/v0.9.x)
91
92
  - [Version 0.8.x](https://github.com/AstrOOnauta/react-native-international-phone-number/tree/v0.8.x)
92
93
  - [Version 0.7.x](https://github.com/AstrOOnauta/react-native-international-phone-number/tree/v0.7.x)
@@ -260,7 +261,7 @@ export default function App() {
260
261
  }
261
262
  ```
262
263
 
263
- - ### Typescript
264
+ - ### Typescript + DefaultValue
264
265
 
265
266
  ```tsx
266
267
  import React, {useState} from 'react';
@@ -285,6 +286,7 @@ export default function App() {
285
286
  return (
286
287
  <View style={{width: '100%', flex: 1, padding: 24}}>
287
288
  <PhoneInput
289
+ defaultValue="+12505550199"
288
290
  value={inputValue}
289
291
  onChangePhoneNumber={handleInputValue}
290
292
  selectedCountry={selectedCountry}
@@ -312,7 +314,7 @@ export default function App() {
312
314
 
313
315
  ## Intermediate Usage
314
316
 
315
- - ### Typescript + useRef
317
+ - ### Typescript + useRef + defaultValue
316
318
 
317
319
  ```tsx
318
320
  import React, {useRef} from 'react';
@@ -334,7 +336,7 @@ export default function App() {
334
336
 
335
337
  return (
336
338
  <View style={{width: '100%', flex: 1, padding: 24}}>
337
- <PhoneInput ref={phoneInputRef} />
339
+ <PhoneInput ref={phoneInputRef} defaultValue="+12505550199" />
338
340
  <TouchableOpacity
339
341
  style={{
340
342
  width: '100%',
@@ -359,13 +361,11 @@ export default function App() {
359
361
  }
360
362
  ```
361
363
 
362
- > 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).
363
-
364
364
  <br>
365
365
 
366
366
  ## Advanced Usage
367
367
 
368
- - ### React-Hook-Form + Typescript + Default Phone Number Value
368
+ - ### React-Hook-Form + Typescript + defaultValue
369
369
 
370
370
  ```tsx
371
371
  import React, {useState, useEffect} from 'react';
@@ -463,26 +463,33 @@ export default function App() {
463
463
 
464
464
  ### Modal Styles ([modalStyles](https://github.com/AstrOOnauta/react-native-country-select/blob/main/lib/interface/countrySelectStyles.ts))
465
465
 
466
- | Property | Type | Description |
467
- | -------------------------- | --------- | ------------------------- |
468
- | `backdrop` | ViewStyle | Modal background overlay |
469
- | `container` | ViewStyle | Modal main container |
470
- | `content` | ViewStyle | Modal content area |
471
- | `dragHandleContainer` | ViewStyle | Drag Handle area |
472
- | `dragHandleIndicator` | ViewStyle | Drag Handle Indicator |
473
- | `searchContainer` | ViewStyle | Search input wrapper |
474
- | `searchInput` | TextStyle | Search input field |
475
- | `list` | ViewStyle | Countries list container |
476
- | `countryItem` | ViewStyle | Individual country row |
477
- | `flag` | TextStyle | Country flag in list |
478
- | `countryInfo` | ViewStyle | Country details container |
479
- | `callingCode` | TextStyle | Calling code in list |
480
- | `countryName` | TextStyle | Country name in list |
481
- | `sectionTitle` | TextStyle | Section headers |
482
- | `closeButton` | ViewStyle | Close button container |
483
- | `closeButtonText` | TextStyle | Close button text |
484
- | `countryNotFoundContainer` | ViewStyle | No results container |
485
- | `countryNotFoundMessage` | TextStyle | No results message |
466
+ | Property | Type | Description |
467
+ | ---------------------------- | --------- | ------------------------- |
468
+ | `backdrop` | ViewStyle | Modal background overlay |
469
+ | `container` | ViewStyle | Modal main container |
470
+ | `content` | ViewStyle | Modal content area |
471
+ | `dragHandleContainer` | ViewStyle | Drag Handle area |
472
+ | `dragHandleIndicator` | ViewStyle | Drag Handle Indicator |
473
+ | `searchContainer` | ViewStyle | Search input wrapper |
474
+ | `searchInput` | TextStyle | Search input field |
475
+ | `list` | ViewStyle | Countries list container |
476
+ | `countryItem` | ViewStyle | Individual country row |
477
+ | `flag` | TextStyle | Country flag in list |
478
+ | `countryInfo` | ViewStyle | Country details container |
479
+ | `callingCode` | TextStyle | Calling code in list |
480
+ | `countryName` | TextStyle | Country name in list |
481
+ | `sectionTitle` | TextStyle | Section headers |
482
+ | `closeButton` | ViewStyle | Close button container |
483
+ | `closeButtonText` | TextStyle | Close button text |
484
+ | `countryNotFoundContainer` | ViewStyle | No results container |
485
+ | `countryNotFoundMessage` | TextStyle | No results message |
486
+ | `alphabetContainer` | ViewStyle | Alphabet filter container |
487
+ | `alphabetLetter` | ViewStyle | Alphabet letter item |
488
+ | `alphabetLetterText` | TextStyle | Alphabet letter text |
489
+ | `alphabetLetterActive` | ViewStyle | Active letter state |
490
+ | `alphabetLetterDisabled` | ViewStyle | Disabled letter state |
491
+ | `alphabetLetterTextActive` | TextStyle | Active letter text |
492
+ | `alphabetLetterTextDisabled` | TextStyle | Disabled letter text |
486
493
 
487
494
  <br>
488
495
 
@@ -528,6 +535,7 @@ export default function App() {
528
535
  | `removedModalBackdrop` | `boolean` | Remove modal backdrop entirely |
529
536
  | `onModalBackdropPress` | `() => void` | Callback when modal backdrop is pressed |
530
537
  | `onModalRequestClose` | `() => void` | Callback when modal close is requested |
538
+ | `showModalAlphabetFilter` | `boolean` | Show alphabet filter in modal |
531
539
  | `showModalSearchInput` | `boolean` | Show search input in modal |
532
540
  | `showModalCloseButton` | `boolean` | Show close button in modal |
533
541
  | `showModalScrollIndicator` | `boolean` | Show scroll indicator in modal |
@@ -545,6 +553,7 @@ export default function App() {
545
553
  | `getCountriesByName` | `(name: string, language: ILanguage)` | `ICountry[] \| undefined` | Returns countries that match the given name in the specified language |
546
554
  | `getCountryByPhoneNumber` | `(phoneNumber: string)` | `ICountry \| undefined` | Returns the country that matches the given phone number |
547
555
  | `isValidPhoneNumber` | `(phoneNumber: string, country: ICountry)` | `boolean` | Validates if a phone number is valid for the given country |
556
+ | `getPhoneNumberLength` | `(country: ICountry, phoneNumber: string)` | `number` | Returns total digits of calling code + phone number |
548
557
 
549
558
  </br>
550
559
 
@@ -604,6 +613,7 @@ const countrySelectList = getByTestId('countrySelectList');
604
613
  const countrySelectSearchInput = getByTestId('countrySelectSearchInput');
605
614
  const countrySelectItem = getByTestId('countrySelectItem');
606
615
  const countrySelectCloseButton = getByTestId('countrySelectCloseButton');
616
+ const countrySelectAlphabetFilter = getByTestId('countrySelectAlphabetFilter');
607
617
  ```
608
618
 
609
619
  <br>
@@ -627,7 +637,11 @@ Ensure your app is inclusive and usable by everyone by leveraging built-in React
627
637
  - `accessibilityLabelCountriesList`: Accessibility label for the countries list;
628
638
  - `accessibilityHintCountriesList`: Accessibility hint for the countries list;
629
639
  - `accessibilityLabelCountryItem`: Accessibility label for individual country items;
630
- - `accessibilityHintCountryItem`: Accessibility hint for individual country.
640
+ - `accessibilityHintCountryItem`: Accessibility hint for individual country;
641
+ - `accessibilityLabelAlphabetFilter`: Accessibility label for alphabet filter list;
642
+ - `accessibilityHintAlphabetFilter`: Accessibility hint for alphabet filter list;
643
+ - `accessibilityLabelAlphabetLetter`: Accessibility label for individual alphabet filter letter;
644
+ - `accessibilityHintAlphabetLetter`: Accessibility hint for individual alphabet filter letter.
631
645
 
632
646
  <br>
633
647
 
Binary file
package/lib/index.d.ts CHANGED
@@ -29,6 +29,11 @@ declare function isValidPhoneNumber(
29
29
  country: ICountry,
30
30
  ): boolean;
31
31
 
32
+ declare function getPhoneNumberLength(
33
+ selectedCountry: ICountry,
34
+ phoneNumber: string,
35
+ ): number;
36
+
32
37
  export default PhoneInput;
33
38
 
34
39
  export {
@@ -38,6 +43,7 @@ export {
38
43
  getCountriesByCallingCode,
39
44
  getCountriesByName,
40
45
  isValidPhoneNumber,
46
+ getPhoneNumberLength,
41
47
  ITheme,
42
48
  ICountrySelectLanguages,
43
49
  ICountry,
package/lib/index.js CHANGED
@@ -14,6 +14,7 @@ import parsePhoneNumber, {
14
14
  } from 'libphonenumber-js';
15
15
 
16
16
  import getCountryByPhoneNumber from './utils/getCountryByPhoneNumber';
17
+ import {getPhoneNumberLength} from './utils/getPhoneNumberLength';
17
18
  import isValidPhoneNumber from './utils/isValidPhoneNumber';
18
19
  import {
19
20
  getCountriesButtonAccessibilityHint,
@@ -72,6 +73,7 @@ const PhoneInput = forwardRef(
72
73
  removedModalBackdrop,
73
74
  onModalBackdropPress,
74
75
  onModalRequestClose,
76
+ showModalAlphabetFilter = true,
75
77
  showModalSearchInput,
76
78
  showModalCloseButton,
77
79
  showModalScrollIndicator,
@@ -89,6 +91,10 @@ const PhoneInput = forwardRef(
89
91
  accessibilityHintCountriesList,
90
92
  accessibilityLabelCountryItem,
91
93
  accessibilityHintCountryItem,
94
+ accessibilityLabelAlphabetFilter,
95
+ accessibilityHintAlphabetFilter,
96
+ accessibilityLabelAlphabetLetter,
97
+ accessibilityHintAlphabetLetter,
92
98
  ...rest
93
99
  },
94
100
  ref,
@@ -110,6 +116,7 @@ const PhoneInput = forwardRef(
110
116
  value: inputValue,
111
117
  getFullPhoneNumber: () => `${countryValue?.idd?.root} ${inputValue}`,
112
118
  fullPhoneNumber: `${countryValue?.idd?.root} ${inputValue}`,
119
+ phoneNumberLength: getPhoneNumberLength(countryValue, inputValue),
113
120
  getSelectedCountry: () => countryValue,
114
121
  selectedCountry: countryValue,
115
122
  isValid: isValidPhoneNumber(inputValue, selectedCountry),
@@ -195,21 +202,15 @@ const PhoneInput = forwardRef(
195
202
 
196
203
  function onSelect(country) {
197
204
  setShow(false);
198
-
199
- if (ref) {
200
- setInputValue('');
201
- } else {
205
+ setInputValue('');
206
+ setCountryValue(country);
207
+ if (onChangePhoneNumber) {
202
208
  onChangePhoneNumber('');
203
209
  }
204
-
205
- if (onChangeSelectedCountry || ref) {
206
- if (ref) {
207
- setCountryValue(country);
208
- updateRef('', country);
209
- } else {
210
- onChangeSelectedCountry(country);
211
- }
210
+ if (onChangeSelectedCountry) {
211
+ onChangeSelectedCountry(country);
212
212
  }
213
+ updateRef('', country);
213
214
  }
214
215
 
215
216
  function formatPhoneNumberWithCustomMask(phoneNumber) {
@@ -235,12 +236,11 @@ const PhoneInput = forwardRef(
235
236
  }
236
237
  }
237
238
 
238
- if (ref) {
239
- setInputValue(result);
240
- updateRef(result, countryValue);
241
- } else {
239
+ setInputValue(result);
240
+ if (onChangePhoneNumber) {
242
241
  onChangePhoneNumber(result);
243
242
  }
243
+ updateRef(result, countryValue);
244
244
  }
245
245
 
246
246
  function formatPhoneNumber(phoneNumber, callingCode) {
@@ -277,12 +277,11 @@ const PhoneInput = forwardRef(
277
277
  return;
278
278
  }
279
279
 
280
- if (ref) {
281
- setInputValue(formattedNumber);
282
- updateRef(formattedNumber, countryValue);
283
- } else {
280
+ setInputValue(formattedNumber);
281
+ if (onChangePhoneNumber) {
284
282
  onChangePhoneNumber(formattedNumber);
285
283
  }
284
+ updateRef(formattedNumber, countryValue);
286
285
  }
287
286
 
288
287
  function onChangeText(phoneNumber, callingCode) {
@@ -292,12 +291,11 @@ const PhoneInput = forwardRef(
292
291
  if (matchingCountry) {
293
292
  setDefaultCca2(matchingCountry.cca2);
294
293
 
295
- if (ref) {
296
- setCountryValue(matchingCountry);
297
- updateRef('', matchingCountry);
298
- } else {
294
+ setCountryValue(matchingCountry);
295
+ if (onChangeSelectedCountry) {
299
296
  onChangeSelectedCountry(matchingCountry);
300
297
  }
298
+ updateRef('', matchingCountry);
301
299
 
302
300
  onChangeText(
303
301
  phoneNumber.replace(matchingCountry?.idd?.root, ''),
@@ -317,28 +315,24 @@ const PhoneInput = forwardRef(
317
315
  useEffect(() => {
318
316
  if (!countryValue && !defaultCountry) {
319
317
  const country = getCountryByCca2('BR');
320
-
321
- if (ref) {
322
- setCountryValue(country);
323
- updateRef('', country);
324
- } else {
318
+ setCountryValue(country);
319
+ if (onChangeSelectedCountry) {
325
320
  onChangeSelectedCountry(country);
326
321
  }
327
- } else {
328
- if (ref) {
329
- updateRef('', countryValue);
330
- }
322
+ updateRef('', country);
323
+ } else if (countryValue) {
324
+ updateRef(inputValue, countryValue);
331
325
  }
332
326
  }, []);
333
327
 
334
328
  useEffect(() => {
335
329
  if (defaultCountry) {
336
- if (ref) {
337
- setCountryValue(getCountryByCca2(defaultCountry));
338
- updateRef('', getCountryByCca2(defaultCountry));
339
- } else {
340
- onChangeSelectedCountry(getCountryByCca2(defaultCountry));
330
+ const c = getCountryByCca2(defaultCountry);
331
+ setCountryValue(c);
332
+ if (onChangeSelectedCountry) {
333
+ onChangeSelectedCountry(c);
341
334
  }
335
+ updateRef('', c);
342
336
  }
343
337
  }, [defaultCountry]);
344
338
 
@@ -349,12 +343,11 @@ const PhoneInput = forwardRef(
349
343
  if (matchingCountry) {
350
344
  setDefaultCca2(matchingCountry.cca2);
351
345
 
352
- if (ref) {
353
- setCountryValue(matchingCountry);
354
- updateRef('', matchingCountry);
355
- } else {
346
+ setCountryValue(matchingCountry);
347
+ if (onChangeSelectedCountry) {
356
348
  onChangeSelectedCountry(matchingCountry);
357
349
  }
350
+ updateRef('', matchingCountry);
358
351
  } else {
359
352
  // console.warn(
360
353
  // "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",
@@ -374,23 +367,15 @@ const PhoneInput = forwardRef(
374
367
  }, [countryValue]);
375
368
 
376
369
  useEffect(() => {
377
- if (!ref) {
370
+ if (typeof rest.value === 'string') {
378
371
  setInputValue(rest.value);
372
+ }
373
+ if (selectedCountry) {
379
374
  setCountryValue(selectedCountry);
380
375
  }
381
- }, [selectedCountry]);
382
-
383
- if (
384
- ref &&
385
- (rest.value ||
386
- onChangePhoneNumber ||
387
- selectedCountry ||
388
- onChangeSelectedCountry)
389
- ) {
390
- throw new Error(
391
- "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).",
392
- );
393
- } else {
376
+ }, [selectedCountry, rest.value]);
377
+
378
+ {
394
379
  // Create a separate constant for each part of the component
395
380
  const touchableStart = (
396
381
  <>
@@ -540,6 +525,7 @@ const PhoneInput = forwardRef(
540
525
  disabledBackdropPress={disabledModalBackdropPress}
541
526
  removedBackdrop={removedModalBackdrop}
542
527
  showSearchInput={showModalSearchInput}
528
+ showAlphabetFilter={showModalAlphabetFilter}
543
529
  countryNotFoundMessage={modalNotFoundCountryMessage}
544
530
  accessibilityLabelBackdrop={accessibilityLabelBackdrop}
545
531
  accessibilityHintBackdrop={accessibilityHintBackdrop}
@@ -553,6 +539,18 @@ const PhoneInput = forwardRef(
553
539
  accessibilityHintCountriesList={accessibilityHintCountriesList}
554
540
  accessibilityLabelCountryItem={accessibilityLabelCountryItem}
555
541
  accessibilityHintCountryItem={accessibilityHintCountryItem}
542
+ accessibilityLabelAlphabetFilter={
543
+ accessibilityLabelAlphabetFilter
544
+ }
545
+ accessibilityHintAlphabetFilter={
546
+ accessibilityHintAlphabetFilter
547
+ }
548
+ accessibilityLabelAlphabetLetter={
549
+ accessibilityLabelAlphabetLetter
550
+ }
551
+ accessibilityHintAlphabetLetter={
552
+ accessibilityHintAlphabetLetter
553
+ }
556
554
  />
557
555
  </>
558
556
  ) : null}
@@ -571,4 +569,5 @@ export {
571
569
  getCountriesByCallingCode,
572
570
  getCountriesByName,
573
571
  isValidPhoneNumber,
572
+ getPhoneNumberLength,
574
573
  };
@@ -46,6 +46,7 @@ interface BasePhoneInput extends TextInputProps {
46
46
  removedModalBackdrop?: boolean;
47
47
  onModalBackdropPress?: () => void;
48
48
  onModalRequestClose?: () => void;
49
+ showModalAlphabetFilter?: boolean;
49
50
  showModalSearchInput?: boolean;
50
51
  showModalCloseButton?: boolean;
51
52
  showModalScrollIndicator?: boolean;
@@ -63,24 +64,28 @@ interface BasePhoneInput extends TextInputProps {
63
64
  accessibilityHintCountriesList?: string;
64
65
  accessibilityLabelCountryItem?: string;
65
66
  accessibilityHintCountryItem?: string;
67
+ accessibilityLabelAlphabetFilter?: string;
68
+ accessibilityHintAlphabetFilter?: string;
69
+ accessibilityLabelAlphabetLetter?: string;
70
+ accessibilityHintAlphabetLetter?: string;
66
71
  }
67
72
 
68
- interface IPhoneInputPropsWithoutRef extends BasePhoneInput {
73
+ interface PhoneInputPropsWithoutRef extends BasePhoneInput {
69
74
  value: string;
70
75
  onChangePhoneNumber: (phoneNumber: string) => void;
71
76
  selectedCountry: ICountry | undefined | null;
72
77
  onChangeSelectedCountry: (country: ICountry) => void;
73
- ref?: never;
78
+ ref?: Ref<IPhoneInputRef>;
74
79
  }
75
80
 
76
- interface IPhoneInputPropsWithRef extends BasePhoneInput {
77
- value?: never;
78
- onChangePhoneNumber?: never;
79
- selectedCountry?: never;
80
- onChangeSelectedCountry?: never;
81
+ interface PhoneInputPropsWithRef extends BasePhoneInput {
81
82
  ref: Ref<IPhoneInputRef>;
83
+ value?: string;
84
+ onChangePhoneNumber?: (phoneNumber: string) => void;
85
+ selectedCountry?: ICountry | undefined | null;
86
+ onChangeSelectedCountry?: (country: ICountry) => void;
82
87
  }
83
88
 
84
89
  export type PhoneInputProps =
85
- | IPhoneInputPropsWithRef
86
- | IPhoneInputPropsWithoutRef;
90
+ | PhoneInputPropsWithoutRef
91
+ | PhoneInputPropsWithRef;
@@ -13,6 +13,7 @@ export interface IPhoneInputRef extends TextInput {
13
13
  valueFormatted: string;
14
14
  getFullPhoneNumber: () => string;
15
15
  fullPhoneNumber: string;
16
+ phoneNumberLength: number;
16
17
  getSelectedCountry: () => ICountry;
17
18
  selectedCountry: ICountry;
18
19
  isValid: boolean;
@@ -0,0 +1,4 @@
1
+ export function getPhoneNumberLength(selectedCountry, phoneNumber) {
2
+ return `${selectedCountry?.idd?.root}${phoneNumber}`.replace(/\D/g, '')
3
+ .length;
4
+ }
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.10.8",
4
+ "version": "0.11.0",
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",
@@ -44,8 +44,8 @@
44
44
  "react-native": "*"
45
45
  },
46
46
  "dependencies": {
47
- "react-native-country-select": "0.2.6",
48
- "libphonenumber-js": "1.12.17"
47
+ "react-native-country-select": "0.3.1",
48
+ "libphonenumber-js": "1.12.23"
49
49
  },
50
50
  "devDependencies": {
51
51
  "metro-react-native-babel-preset": "^0.61.0"