npm package: @fenadev/react-native-phone-input
Description: Simplified and optimized Phone Number Input Component for React Native with dark theme support, validation feedback, and SVG icons
Author: fenadev
Latest version: 0.4.1

# react-native-phone-input

[![npm version](https://badge.fury.io/js/@fenadev%2Freact-native-phone-input.svg)](https://badge.fury.io/js/@fenadev/react-native-phone-input)
[![License](https://img.shields.io/badge/license-MIT-blue.svg?&kill_cache=1)](https://github.com/ffigueroa/react-native-phone-input/blob/main/LICENSE)

`react-native-phone-input` is a **simplified and optimized** Phone Number Input Component for React Native that provides an intuitive interface for entering and validating international phone numbers. This fork eliminates redundant API complexity and provides a cleaner, more maintainable solution.

## 🚀 **What's New in This Fork**

- **🎯 Simplified API**: No more redundant `callingCode` - it's automatically derived from `countryCode`
- **⚡ Performance Optimized**: O(1) country code lookups using pre-calculated maps
- **🔧 Better Developer Experience**: Cleaner props with `defaultCountryCode` and `showPrefixCode`
- **🛡️ Enhanced Error Handling**: Better validation and fallback mechanisms
- **📱 Flexible Display**: Control whether to show the calling code prefix or not


<div align="center">
  <h3>Autopick Feature</h3>
  <img src="https://raw.githubusercontent.com/ffigueroa/react-native-phone-input/main/assets/autopick.gif"  />
  <p>A feature that automatically picks the right country while typing the phone number.</p>
  <h3>Masking Feature</h3>
  <img src="https://raw.githubusercontent.com/ffigueroa/react-native-phone-input/main/assets/mask.gif"  />
  <p>A feature that picks a right mask based on the country code.</p>
</div>

## Features

- 🌍 International phone number input with country picker
- 📱 Automatic phone number formatting based on country
- 🔍 Dynamic country and mask adaptation based on typed country code
- ✨ Highly customizable appearance and styling
- 🎯 Phone number validation using Google's libphonenumber
- 🎨 **Dark theme support** with automatic adaptation
- ✅ **Visual validation feedback** with check/X icons
- 🎨 **SVG icons** that adapt to theme automatically
- ♿ Accessibility support
- 💪 Written in TypeScript
- 🚀 **Simplified API** with automatic calling code derivation
- ⚡ **Performance optimized** with O(1) lookups and memoization
- 🎛️ **Flexible prefix display** control

## Installation

```sh
npm install @fenadev/react-native-phone-input

# or

yarn add @fenadev/react-native-phone-input
```

### Peer Dependencies

This library requires `react-native-svg` as a peer dependency. If you don't have it installed:

```sh
npm install react-native-svg

# or

yarn add react-native-svg
```

### Additional Setup

For **react-native-svg**, follow the [installation guide](https://github.com/software-mansion/react-native-svg#installation) for your platform.

For iOS, you may need to run:
```sh
cd ios && pod install
```

## Usage

1. Import the PhoneInput component:

```jsx
import { PhoneInput, isValidNumber } from '@fenadev/react-native-phone-input';
```

2. **NEW Simplified API** (Recommended):

```jsx
export default function App() {
  const [countryCode, setCountryCode] = useState<CountryCode>('US');
  return (
    <PhoneInput
      defaultCountryCode="CL"        // 🎯 Just specify the country
      showPrefixCode={true}          // 🎯 Control prefix display
      onChangeText={(text) =>
        console.log(
          'Phone number:',
          text,
          'isValidNumber:',
          isValidNumber(text, countryCode)
        )
      }
      onChangeCountry={(country) => {
        console.log('Country:', country);
        setCountryCode(country.cca2);
      }}
    />
  );
}
```

3. **Different Countries**:

```jsx
export default function App() {
  const [countryCode, setCountryCode] = useState<CountryCode>('US');
  return (
    <PhoneInput
      defaultCountryCode="MX"        // 🇲🇽 Mexico
      showPrefixCode={true}
      onChangeText={(text) =>
        console.log(
          'Phone number:',
          text,
          'isValidNumber:',
          isValidNumber(text, countryCode)
        )
      }
      onChangeCountry={(country) => {
        console.log('Country:', country);
        setCountryCode(country.cca2);
      }}
    />
  );
}
```

4. Advanced usage with customization:

```jsx
<PhoneInput
  defaultCountryCode="CL"           // 🎯 Simplified country selection
  showPrefixCode={true}              // 🎯 Show/hide calling code prefix
  value="+56 9 1234 5678"
  onChangeText={(text) => console.log('Phone number:', text)}
  onChangeCountry={(country) => console.log('Country:', country)}
  autoFocus={true}
  disabled={false}
  countryPickerProps={{
    withFilter: true,
    withFlag: true,
    withCountryNameButton: true,
  }}
  theme={{
    containerStyle: styles.phoneContainer,
    textInputStyle: styles.input,
    flagButtonStyle: styles.flagButton,
    codeTextStyle: styles.codeText,
    dropDownImageStyle: styles.dropDownImage,
    validationIconStyle: styles.validationIcon,
    enableDarkTheme: false,
  }}
  hideDropdownIcon={false}
  isCallingCodeEditable={false}
  showValidationIcon={true}
  onValidationChange={(isValid) => console.log('Phone number is valid:', isValid)}
/>
```

## 🎯 **New API Examples**

### With Prefix Visible (Default)
```jsx
<PhoneInput defaultCountryCode="CL" showPrefixCode={true} />
// Result: Input shows "+56"
```

### Without Prefix
```jsx
<PhoneInput defaultCountryCode="CL" showPrefixCode={false} />
// Result: Input shows only the local number
```

### Multiple Countries
```jsx
<PhoneInput defaultCountryCode="MX" />  // Automatically uses +52
<PhoneInput defaultCountryCode="ES" />  // Automatically uses +34
<PhoneInput defaultCountryCode="US" />  // Automatically uses +1
```

## Props

### 🚀 **New Simplified Props**

| Prop                    | Type                                                                                           | Description                                                     | Default     |
| ----------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ----------- |
| `defaultCountryCode`    | `CountryCode`                                                                                  | **NEW**: Default country code (e.g., 'CL', 'US', 'MX')          | `'US'`      |
| `showPrefixCode`        | `boolean`                                                                                      | **NEW**: Whether to show the calling code prefix in input       | `true`      |

### 📱 **Core Props**

| Prop                    | Type                                                                                           | Description                                                     | Default     |
| ----------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ----------- |
| `value`                 | `string`                                                                                       | Controlled value for the phone number input                     | `undefined` |
| `onChangeText`          | `(text: string) => void`                                                                       | Callback when phone number changes                              | `undefined` |
| `onChangeCountry`       | `(country: Country) => void`                                                                   | Callback when selected country changes                          | `undefined` |
| `autoFocus`             | `boolean`                                                                                      | Automatically focuses the input when mounted                    | `false`     |
| `disabled`              | `boolean`                                                                                      | Disables the input                                              | `false`     |

### 🎨 **Styling & Customization Props**

| Prop                    | Type                                                                                           | Description                                                     | Default     |
| ----------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ----------- |
| `countryPickerProps`    | [`CountryPickerProps`](https://github.com/xcarpentier/react-native-country-picker-modal#props) | Props for the country picker modal                              | `{}`        |
| `maskInputProps`        | [`MaskInputProps`](https://github.com/CaioQuirinoMedeiros/react-native-mask-input#props)       | Props for the masked input component                            | `{}`        |
| `theme`                 | `Theme`                                                                                        | Theme configuration for styling the component                   | `{}`        |
| `hideDropdownIcon`      | `boolean`                                                                                      | Hides the dropdown arrow icon when set to true                  | `false`     |
| `renderCustomDropdown`  | [`ReactNode`](https://react.dev/reference/react/Children)                                      | Custom component to replace the default dropdown arrow          | `undefined` |
| `flagProps`             | `object`                                                                                       | Props for customizing the country flag                          | `{}`        |
| `dropDownImageProps`    | [`ImageProps`](https://reactnative.dev/docs/image#props)                                       | Props for customizing the dropdown arrow image                  | `{}`        |
| `isCallingCodeEditable` | `boolean`                                                                                      | Controls whether the calling code can be edited                 | `true`      |
| `showValidationIcon`    | `boolean`                                                                                      | Shows validation icon (check/X) next to the input               | `false`     |
| `isValid`              | `boolean`                                                                                      | External validation state (overrides internal validation)      | `undefined` |
| `onValidationChange`   | `(isValid: boolean) => void`                                                                  | Callback when validation state changes                         | `undefined` |


### Theme Properties

| Property             | Type                                                                      | Description                          | Default     |
| -------------------- | ------------------------------------------------------------------------- | ------------------------------------ | ----------- |
| `containerStyle`     | [`StyleProp<ViewStyle>`](https://reactnative.dev/docs/view-style-props)   | Style for the main container         | `undefined` |
| `textInputStyle`     | [`StyleProp<TextStyle>`](https://reactnative.dev/docs/text-style-props)   | Style for the text input             | `undefined` |
| `codeTextStyle`      | [`StyleProp<TextStyle>`](https://reactnative.dev/docs/text-style-props)   | Style for the calling code text      | `undefined` |
| `flagButtonStyle`    | [`StyleProp<ViewStyle>`](https://reactnative.dev/docs/view-style-props)   | Style for the flag button            | `undefined` |
| `dropDownImageStyle` | [`StyleProp<ImageStyle>`](https://reactnative.dev/docs/image-style-props) | Style for the dropdown arrow image   | `undefined` |
| `validationIconStyle`| [`StyleProp<ViewStyle>`](https://reactnative.dev/docs/view-style-props)   | Style for the validation icon         | `undefined` |
| `enableDarkTheme`    | `boolean`                                                                 | Enables dark theme for the component | `false`     |

## Utility Functions

### `isValidNumber(phoneNumber: string, countryCode: string): boolean`

Validates a phone number for a specific country using Google's libphonenumber.

```jsx
import { isValidNumber } from '@fenadev/react-native-phone-input';

const isValid = isValidNumber('+1234567890', 'US');
```

## Dependencies

This library depends on the following packages:

- [react-native-country-picker-modal](https://github.com/xcarpentier/react-native-country-picker-modal)
- [react-native-mask-input](https://github.com/CaioQuirinoMedeiros/react-native-mask-input)
- [google-libphonenumber](https://github.com/ruimarinho/google-libphonenumber)

## Contributing

See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.

## TODO

- [ ] Expose ref of the input
- [ ] Add custom country picker modal

## 🚀 **Performance Improvements**

This fork includes several performance optimizations:

- **O(1) Country Code Lookups**: Pre-calculated maps for instant country code resolution
- **Eliminated Redundant API**: No more manual `callingCode` specification
- **Optimized State Management**: Reduced unnecessary re-renders
- **Better Error Handling**: Graceful fallbacks and validation

## 📊 **Migration Guide**

### From Original react-native-phone-entry to This Fork

```jsx
// ❌ Original library (redundant)
<PhoneInput
  defaultValues={{
    countryCode: 'CL',
    callingCode: '+56',    // Redundant!
    phoneNumber: '+56',    // Redundant!
  }}
/>

// ✅ This fork (simplified)
<PhoneInput
  defaultCountryCode="CL"  // Calling code derived automatically
  showPrefixCode={true}     // Control prefix display
/>
```

### Key Changes
- **Eliminated**: `defaultValues.callingCode` - now automatically derived
- **Eliminated**: `defaultValues.phoneNumber` - use `value` prop instead
- **Added**: `defaultCountryCode` - cleaner country selection
- **Added**: `showPrefixCode` - control prefix visibility

## License

This project is licensed under the [MIT License](https://github.com/ffigueroa/react-native-phone-input/blob/main/LICENSE).

---

**Fork of**: [react-native-phone-entry](https://github.com/anday013/react-native-phone-entry) by [anday013](https://github.com/anday013)

Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)

Inspired by [react-native-phone-number-input](https://github.com/garganurag893/react-native-phone-number-input)