npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-native-international-phone-input

v2.0.0

Published

A comprehensive, feature-rich phone number input component for React Native with country picker, validation, theming, and customization options

Downloads

49

Readme

React Native Phone Number Input

A comprehensive, feature-rich phone number input component for React Native with country picker, validation, theming, and customization options.

Demo

Features

Comprehensive Country Support - Built-in support for 250+ countries
Phone Number Validation - Real-time validation using Google LibPhoneNumber
Customizable Theming - Complete theme customization with sensible defaults
Search Functionality - Built-in country search with customizable placeholder
Modern UI Design - Clean, modern interface with rounded flags and inputs
Flexible Layouts - Multiple layout options to fit your design
Custom Render Props - Override any part of the component with custom renders
TypeScript Support - Full TypeScript definitions included
Configurable Labels - Customizable field labels
Custom Modal Support - Implement your own country selection modal
Flag Shape Control - Round or square flag options
Custom Dropdown Icon - Replace the default dropdown with your own icon

Installation

npm install react-native-international-phone-input
# or
yarn add react-native-international-phone-input

Dependencies

npm install google-libphonenumber
# or  
yarn add google-libphonenumber

Basic Usage

import React, { useState, useRef } from 'react';
import PhoneInput from 'react-native-international-phone-input';

export default function App() {
  const [value, setValue] = useState('');
  const [formattedValue, setFormattedValue] = useState('');
  const phoneInput = useRef<PhoneInput>(null);

  return (
    <PhoneInput
      ref={phoneInput}
      defaultValue={value}
      defaultCode="US"
      layout="first"
      onChangeText={(text) => {
        setValue(text);
      }}
      onChangeFormattedText={(text) => {
        setFormattedValue(text);
      }}
      withDarkTheme
      withShadow
      autoFocus
    />
  );
}

Props

Basic Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | defaultCode | string | "US" | Default country code | | value | string | "" | Phone number value | | defaultValue | string | "" | Default phone number value | | placeholder | string | "(415) 555-0132" | Input placeholder text | | disabled | boolean | false | Disable the input | | autoFocus | boolean | false | Auto focus the input | | layout | "first" | "second" | "third" | "first" | Layout style |

Styling Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | withShadow | boolean | false | Add shadow to container | | withDarkTheme | boolean | false | Use dark theme for keyboard | | containerStyle | StyleProp<ViewStyle> | - | Container style | | textContainerStyle | StyleProp<ViewStyle> | - | Text input container style | | textInputStyle | StyleProp<TextStyle> | - | Text input style | | codeTextStyle | StyleProp<TextStyle> | - | Country code text style |

Search & Modal Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | showSearch | boolean | true | Show search in country modal | | searchPlaceholder | string | "Search countries..." | Search input placeholder | | disableArrowIcon | boolean | false | Hide dropdown arrow |

Labels

| Prop | Type | Default | Description | |------|------|---------|-------------| | codeLabel | string | "Code" | Label for country code section | | phoneNumberLabel | string | "Phone Number" | Label for phone number section |

Callbacks

| Prop | Type | Description | |------|------|-------------| | onChangeText | (text: string) => void | Called when phone number changes | | onChangeFormattedText | (text: string) => void | Called with formatted number (includes country code) | | onChangeCountry | (country: Country) => void | Called when country changes |

Theme Customization

The theme prop allows you to customize the entire appearance:

interface PhoneInputTheme {
  // Background colors
  containerBackground?: string;
  inputBackground?: string;
  modalBackground?: string;
  modalOverlay?: string;
  
  // Text colors
  labelTextColor?: string;
  inputTextColor?: string;
  placeholderTextColor?: string;
  codeTextColor?: string;
  dropdownTextColor?: string;
  
  // Border colors
  inputBorderColor?: string;
  modalBorderColor?: string;
  
  // Selection and focus colors
  selectionColor?: string;
  
  // Flag styling
  flagBorderRadius?: number;
  flagSize?: number;
  flagShape?: 'round' | 'square';
  
  // Dropdown arrow
  dropdownArrowColor?: string;
  dropdownArrowOpacity?: number;
}

Theme Example

<PhoneInput
  theme={{
    containerBackground: 'transparent',
    inputBackground: '#F5F5F5',
    modalBackground: '#FFFFFF',
    labelTextColor: '#333333',
    inputTextColor: '#000000',
    flagShape: 'round',
    flagSize: 32,
  }}
/>

Custom Render Props

Override any part of the component with custom implementations:

Custom Flag Renderer

<PhoneInput
  renderFlag={(country) => (
    <View style={{ flexDirection: 'row', alignItems: 'center' }}>
      <Text style={{ fontSize: 20 }}>{country.code}</Text>
    </View>
  )}
/>

Custom Input Renderer

<PhoneInput
  renderInput={(props) => (
    <TextInput
      {...props}
      style={[props.style, { borderWidth: 1, borderColor: 'blue' }]}
    />
  )}
/>

Custom Dropdown Icon

<PhoneInput
  renderDropdownIcon={() => (
    <Icon name="chevron-down" size={16} color="#666" />
  )}
/>

Custom Country Modal

Implement your own country selection modal (e.g., for bottom sheets):

<PhoneInput
  renderCountryModal={({ visible, onClose, onSelectCountry, countries, searchText, onSearchChange }) => (
    <Modal visible={visible} onRequestClose={onClose}>
      <View style={{ flex: 1, backgroundColor: 'white' }}>
        <TextInput
          value={searchText}
          onChangeText={onSearchChange}
          placeholder="Search countries..."
        />
        <FlatList
          data={countries}
          renderItem={({ item }) => (
            <TouchableOpacity onPress={() => onSelectCountry(item)}>
              <Text>{item.name} (+{item.callingCode})</Text>
            </TouchableOpacity>
          )}
        />
      </View>
    </Modal>
  )}
/>

Custom Country Item

<PhoneInput
  renderCountryItem={(country, onSelect) => (
    <TouchableOpacity onPress={() => onSelect(country)}>
      <Text>{country.name} - {country.code}</Text>
    </TouchableOpacity>
  )}
/>

Layouts

Layout "first" (default)

Country flag + Country code in main input + Phone number

Layout "second"

Country flag + Country code in picker + Phone number

Layout "third"

Country flag + Country code in picker + Phone number

Methods

Access component methods via ref:

const phoneInput = useRef<PhoneInput>(null);

// Get country code
const countryCode = phoneInput.current?.getCountryCode();

// Get calling code  
const callingCode = phoneInput.current?.getCurrentCallingCode();

// Validate number
const isValid = phoneInput.current?.isValidNumber(phoneNumber);

// Get formatted number
const { formattedNumber } = phoneInput.current?.getNumberAfterPossiblyEliminatingZero();

Validation

Use the built-in validation or the standalone function:

import { isValidNumber } from 'react-native-international-phone-input';

// Using component method
const isValid = phoneInput.current?.isValidNumber(phoneNumber);

// Using standalone function  
const isValid = isValidNumber(phoneNumber, countryCode);

TypeScript

Full TypeScript support with comprehensive type definitions:

import PhoneInput, { Country, PhoneInputTheme } from 'react-native-international-phone-input';

const customTheme: PhoneInputTheme = {
  flagShape: 'round',
  inputBackground: '#F0F0F0',
};

const handleCountryChange = (country: Country) => {
  console.log(country.name, country.code, country.callingCode);
};

Complete Example

import React, { useState, useRef } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import PhoneInput from 'react-native-international-phone-input';

export default function App() {
  const [value, setValue] = useState('');
  const [formattedValue, setFormattedValue] = useState('');
  const [valid, setValid] = useState(false);
  const [showMessage, setShowMessage] = useState(false);
  const phoneInput = useRef<PhoneInput>(null);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Phone Number Input</Text>
      
      <PhoneInput
        ref={phoneInput}
        defaultValue={value}
        defaultCode="US"
        layout="first"
        onChangeText={(text) => {
          setValue(text);
        }}
        onChangeFormattedText={(text) => {
          setFormattedValue(text);
          setValid(phoneInput.current?.isValidNumber(text) || false);
        }}
        onChangeCountry={(country) => {
          console.log('Country changed:', country);
        }}
        withDarkTheme
        withShadow
        autoFocus
        theme={{
          flagShape: 'round',
          inputBackground: '#F8F9FA',
          containerBackground: 'transparent',
        }}
        codeLabel="Country Code"
        phoneNumberLabel="Mobile Number"
        placeholder="Enter your phone number"
        searchPlaceholder="Search for country..."
      />
      
      {showMessage && (
        <View style={styles.message}>
          <Text>Value: {value}</Text>
          <Text>Formatted: {formattedValue}</Text>
          <Text>Valid: {valid ? 'true' : 'false'}</Text>
        </View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  message: {
    marginTop: 20,
    padding: 15,
    backgroundColor: '#f0f0f0',
    borderRadius: 8,
  },
});

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.