# react-phone-number-input

[![npm version](https://img.shields.io/npm/v/react-phone-number-input.svg?style=flat-square)](https://www.npmjs.com/package/react-phone-number-input)
[![npm downloads](https://img.shields.io/npm/dm/react-phone-number-input.svg?style=flat-square)](https://www.npmjs.com/package/react-phone-number-input)

International phone number `<input/>` for React.

[<img src="https://gitlab.com/catamphetamine/react-phone-number-input/-/raw/master/docs/images/first-glance-local.png" width="270" height="113"/>](https://catamphetamine.gitlab.io/react-phone-number-input/)

[See Demo](https://catamphetamine.gitlab.io/react-phone-number-input/)

<!-- This is a readme for the latest version (`3.x`) of the library. The previous version (`2.x`) readme could be found on [github](https://github.com/catamphetamine/react-phone-number-input/tree/2.x) until they removed it. For migrating from `2.x` to `3.x` see the [changelog](https://gitlab.com/catamphetamine/react-phone-number-input/blob/master/CHANGELOG.md). -->

<!--
## Screenshots

### Phone number input

<img src="https://gitlab.com/catamphetamine/react-phone-number-input/-/raw/master/docs/images/first-glance-local.png" width="270" height="113"/>

<img src="https://gitlab.com/catamphetamine/react-phone-number-input/-/raw/master/docs/images/first-glance.png" width="270" height="113"/>

### Country selection on desktop

<img src="https://gitlab.com/catamphetamine/react-phone-number-input/-/raw/master/docs/images/desktop-native-select.png" width="475" height="223"/>

### Country selection on mobile

<img src="https://gitlab.com/catamphetamine/react-phone-number-input/-/raw/master/docs/images/iphone-native-select.png" width="380" height="443"/>
-->

## Install

```
npm install react-phone-number-input --save
```

Alternatively, one could include it on a web page [directly](#cdn) via a `<script/>` tag.

## Use

This package exports two variants of the input component, depending on what you prefer:
* [With country select](#with-country-select) — A phone number input field with a country select on the left side.
  * This is the most straightforward and easy-to-use one.
  * Provides everything out-of-the-box:
    * CSS styles.
    * Country flags.
    * Country labels in different languages.
* [Without country select](#without-country-select) — Just the phone number input field.
  * This is the "bare-bones" variant.
  * For those who like minimalism or would like to build their own.

## With country select

"With country select" component requires only two properties: `value` and `onChange(value)`.

```js
// CSS styles
import 'react-phone-number-input/style.css'

import PhoneInput from 'react-phone-number-input'

function Example() {
  const [value, setValue] = useState()
  return (
    <PhoneInput
      placeholder="Enter phone number"
      value={value}
      onChange={setValue}
    />
  )
}
```

More on the properties:

* `onChange`
  * When the user types something in the input field, `onChange` function will be called, with its argument being the parsed phone number (in [E.164](https://en.wikipedia.org/wiki/E.164) format). For example, if the user chooses "United States" and enters `(213) 373-4253` in the input field, `onChange` function will be called with the argument `"+12133734253"`.
  * When the user clears the input field, `onChange` function will be called with `undefined` as an argument. Perhaps `null` would've been better, but historically it was decided to be `undefined`.

* `value`
  * The input value (in [E.164](https://en.wikipedia.org/wiki/E.164) format). Example: `"+12133734253"`.
  * Any ["falsy"](https://developer.mozilla.org/en-US/docs/Glossary/Falsy) `value` — for example, `undefined`, `null`, or empty string `""` — will be treated as "no value".

* `defaultCountry` (optional)
  * Specifies the initially-selected country. When provided, it must be a two-letter [country code](#country-code). Example: `"US"` (United States).

* `onCountryChange` (optional)
  * When the user selects a different country, `onCountryChange` function will be called with the new country code as an argument.

* For other supported properties, see the [list of all available `props`](https://catamphetamine.gitlab.io/react-phone-number-input/docs/index.html#phoneinputwithcountry).

* Any unknown properties, such as `placeholder`, will be passed through to the underlying `<input/>` component.

<!--
To format the `value` back to a human-readable phone number, use the exported [`formatPhoneNumber(value)`](#formatphonenumbervalue-string-string) or [`formatPhoneNumberIntl(value)`](#formatphonenumberintlvalue-string-string) functions.

```js
import { formatPhoneNumber, formatPhoneNumberIntl } from 'react-phone-number-input'

formatPhoneNumber('+12133734253') === '(213) 373-4253'
formatPhoneNumberIntl('+12133734253') === '+1 213 373 4253'
```

To recover the country code from a valid phone number, use the exported [`parsePhoneNumber(value)`](#parsephonenumberinput-string-phonenumber) function.

```js
import { parsePhoneNumber } from 'react-phone-number-input'

const phoneNumber = parsePhoneNumber(value)
if (phoneNumber) {
  console.log(phoneNumber.country)
} else {
  // The `value` is not a valid phone number
}
```
-->

<!--
The input is based on [`libphonenumber-js`](https://gitlab.com/catamphetamine/libphonenumber-js) phone number parsing/formatting library. The [`formatPhoneNumber(value, format)`](https://gitlab.com/catamphetamine/libphonenumber-js#formatnumbernumber-format-options) function can be used to output the `value` in `"National"` or `"International"` format.
-->

<!--
The phone number `<input/>` itself is implemented using [`input-format`](https://catamphetamine.gitlab.io/input-format/) (which has an issue with some Samsung Android phones, [see the workaround](#android)).
-->

#### CSS

"With country select" component requires including [`style.css`](https://gitlab.com/catamphetamine/react-phone-number-input/blob/master/style.css) stylesheet on the page.

All CSS class names start with `.PhoneInput` prefix in order to not conflict with the application styles.

The following "status modifier" CSS classes are available:
* `.PhoneInput--focus` for `:focus` state
* `.PhoneInput--disabled` for `:disabled` state
* `.PhoneInput--readOnly` for `[readonly]` state

The stylesheet uses [native CSS variables](https://medium.freecodecamp.org/learn-css-variables-in-5-minutes-80cf63b4025d) for convenience. Native CSS variables have been supported in all modern browsers for a long time now, but ancient ones like Internet Explorer [don't support them](https://caniuse.com/#search=var). If compatibility with such ancient browsers is required, one could use a CSS transformer like [PostCSS](https://postcss.org/) with a "CSS custom properties" [plugin](https://github.com/postcss/postcss-custom-properties).

Some of the CSS variables of interest:

* `--PhoneInputCountryFlag-height` — Flag icon height.
* `--PhoneInputCountryFlag-borderColor` — Flag icon outline color.
* `--PhoneInputCountrySelectArrow-color` — Country select arrow color.
* `--PhoneInputCountrySelectArrow-opacity` — Country select arrow opacity (when not `:focus`ed).
* `--PhoneInput-color--focus` — Flag icon `:focus` outline color, and also country select arrow `:focus` color.
* …

<!--
##### When using Webpack

When using Webpack, include the stylesheet on a page via `import`:

```js
import 'react-phone-number-input/style.css'
```

For supporting old browsers like Internet Explorer, one could
use [`postcss-loader`](https://github.com/postcss/postcss-loader) with a [CSS autoprefixer](https://github.com/postcss/autoprefixer) and [`postcss-custom-properties` transpiler](https://github.com/postcss/postcss-custom-properties).

##### When not using Webpack

Get `style.css` file from this package, optionally process it with a [CSS autoprefixer](https://github.com/postcss/autoprefixer) and [`postcss-custom-properties` transpiler](https://github.com/postcss/postcss-custom-properties) for supporting old web browsers, and then include the CSS file on a page.

```html
<head>
  <link rel="stylesheet" href="/css/react-phone-number-input/style.css"/>
</head>
```

Or include the `style.css` file directly from a [CDN](#cdn) if you don't have to support Internet Explorer.
-->

## Without country select

"Without country select" component is just a minimal "bare-bones" phone number `<input/>`, without any CSS.

```js
import PhoneInput from 'react-phone-number-input/input'

function Example() {
  // `value` holds the parsed phone number (in E.164 format).
  // When the input is empty, or when there's not enough digits, value is `undefined`.
  //
  // Example: "+12133734253".
  //
  const [value, setValue] = useState()

  // Specifying a `country` only allows input of phone numbers belonging to that specific country.
  // Not specifying a `country` only allows input of any phone number in international format
  // (i.e. starting with a "+").
  //
  return (
    <PhoneInput
      country="US"
      value={value}
      onChange={setValue}
    />
  )
}
```

Available properties:

* `country: string?` — If `country` is specified then it only allows input of phone numbers that belong to that specific country. When specified, the value must be a supported [country code](#country-code). Example: `country="US"`.

* `defaultCountry: string?` — If `defaultCountry` is specified then phone numbers can be input either in "international" format for any country or in "national" format for that specific country. Basically, it imposes a `country` restriction but only on phone numbers in "national" format while allowing any phone numbers in "international" format. In other words: "When the country is not specified in the phone number itself, assume it to be ... by default". When specified, the value must be a supported [country code](#country-code). Example: `defaultCountry="US"`.

* `international: boolean?` — Controls which phone number format is allowed: "international" or "national" (or both). Set to `true` to only allow "international" format. Set to `false` to only allow "national" format.
  * When `international` property is not explicitly specified, its default value will be determined based on the values of other properties such as `country` or `defaultCountry`:
    * When `country` is specified, the default value of `international` property is `false`, meaning that the phone number can only be input in "national" format for that `country`.
    * When `defaultCountry` is specified, the phone number could be input either in "international" format or in "national" format for the `defaultCountry`, so the default value of `international` property stays `undefined`.
    * When no `country` or `defaultCountry` are specified, the phone number can only be input in "international" format (without any country restrictions), so the default value of the `international` property is `true`.
  * When `country` is specified and `international` property is explicitly set to `true`, the phone number can only be input in "international" format for that `country`.
    * In that case, by default, the "country calling code" part — for example, `"+1"` when `country` is `"US"` — is not included in the input field.
      * Example: if `country` is `"US"` and `international` property is `true` then the phone number can only be input in "international" format for `US`, without the leading `"+1"` part, so it would look like `"213 373 4253"` rather than `"+1 213 373 4253"`.
      * This is done intentionally so that a developer could build their own multi-country phone number input component where the "country calling code" part like `"+1"` is selectable separately before the main input field.
      * To disable this behavior, set `withCountryCallingCode` property to `true`, and the "country calling code" part like `"+1"` will be part of the input field, but be aware that it still won't be editable because otherwise it would contradict the `country` property.
        * Example: if `country` is `"US"` and `international` property is `true` and `withCountryCallingCode` property is `true` then the phone number can only be input in "international" format for `US`, with the fixed leading `"+1"` part, so it would look like `"+1 213 373 4253"`.

* `withCountryCallingCode: boolean?` — If `country` is specified and `international` property is `true` then the phone number can only be input in "international" format for that `country`. By default, the "country calling code" part — for example, `+1` when `country` is `US` — is not included in the input field. To change that, set `withCountryCallingCode` property to `true`, and it will include the "country calling code" part in the input field, although it will still be non-editable. See the demo for an example.

* `useNationalFormatForDefaultCountryValue: boolean?` — By default, when `defaultCountry` is defined and the initial phone number belongs to the `defaultCountry`, that initial phone number is formatted in "national" format. A developer might rather prefer it to use "international" format for that, in which case set `useNationalFormatForDefaultCountryValue` property value to `false`.

* `value: string?` — Phone number `value`. Examples: `undefined`, `"+12133734253"`.

* `onChange(value: string?)` — Updates the `value` (to `undefined` in case it's empty).

* `inputComponent: component?` — Custom input component.
  * By default, it's a generic DOM `<input/>` component.
  * Any custom input component implementation must use `React.forwardRef()` to "forward" `ref` to the underlying "core" `<input/>` component.
  * Receives properties:
    * `value: string`
    * `onChange(event: Event)`
    * Any other properties that were passed to `<PhoneInput/>` and aren't specifically handled by this library. For example, `type="tel"`, `autoComplete="tel"`, etc.

* `smartCaret: boolean?` — When the user attempts to insert a digit somewhere in the middle of a phone number, the caret position is moved right before the next available digit skipping any punctuation in between. This is called "smart" caret positioning. Another case would be the phone number format changing as a result of the user inserting the digit somewhere in the middle, which would require re-positioning the caret because all digit positions have changed. This "smart" caret positioning feature can be turned off by passing `smartCaret={false}` property: use it in case of any possible issues with caret position during phone number input.

See the [demo](https://catamphetamine.gitlab.io/react-phone-number-input/) for the examples.

If you're an "advanced" user who'd like to pass their [custom](https://www.npmjs.com/package/libphonenumber-js#custom-metadata) `libphonenumber-js` metadata, use `react-phone-number-input/input-core` component instead — it accepts `metadata` property.

This package also exports `getCountries()` and `getCountryCallingCode(country)` functions that a developer could use to construct their own custom country select. Such custom country `<select/>` could be used alongside the "without country select" `<input/>` component.

<details>
<summary>How to create a custom country <code>&lt;select/&gt;</code></summary>

####

```js
import PropTypes from 'prop-types'
import { getCountries, getCountryCallingCode } from 'react-phone-number-input'

const CountrySelect = ({ value, onChange, labels, ...rest }) => (
  <select
    {...rest}
    value={value}
    onChange={event => onChange(event.target.value || undefined)}>
    <option value="">
      {labels['ZZ']}
    </option>
    {getCountries().map((country) => (
      <option key={country} value={country}>
        {labels[country]} +{getCountryCallingCode(country)}
      </option>
    ))}
  </select>
)

CountrySelect.propTypes = {
  value: PropTypes.string,
  onChange: PropTypes.func.isRequired,
  labels: PropTypes.objectOf(PropTypes.string).isRequired
}
```

Use:

```js
import PhoneInput from 'react-phone-number-input/input'
import en from 'react-phone-number-input/locale/en'
import CountrySelect from './CountrySelect'

function Example() {
  const [country, setCountry] = useState('US')
  const [value, setValue] = useState()
  return (
    <div>
      <CountrySelect
        labels={en}
        value={country}
        onChange={setCountry}/>
      <PhoneInput
        country={country}
        value={value}
        onChange={setValue}/>
    </div>
  )
}
```
</details>

## React Native

This package also includes a React Native version of a "without country select" component. Post bug reports and suggestions in the [feedback thread](https://github.com/catamphetamine/react-phone-number-input/issues/296).

```js
import React, { useState } from 'react'
import PhoneInput from 'react-phone-number-input/react-native-input'

function Example() {
  const [value, setValue] = useState()
  return (
    <PhoneInput
      style={...}
      country="US"
      value={value}
      onChange={setValue}
    />
  )
}
```

It accepts the same properties as the web version of "without country select" component, with the following differences:

* `smartCaret: boolean?` property is not supported because "smart caret" positioning feature is not implemented in the React Native component.

* `inputComponent: component?` — By default, it renders a generic `<TextInput/>`. A custom input component can be passed. Such custom input component must `forwardRef()` to the underlying input field. The input component receives properties:
  * `value: string`
  * `onChangeText(value: string)`
  * all the "rest" of the properties that're not handled by this library, like `keyboardType="phone-pad"`, `autoCompleteType="tel"`, etc.

## Validation

To validate the phone number input `value`, use the exported `isPossiblePhoneNumber(value)` function.

```js
import { isPossiblePhoneNumber } from 'react-phone-number-input'

const isValid = (value) => Boolean(value) && isPossiblePhoneNumber(value)
```

What to do next with the returned `boolean` value is up to each different application. Most applications use frameworks like `react-hook-form` or `formik` or a gazillion of other ones. Those frameworks each have their own way of setting up validation.

## Utility

This package exports several utility functions.

### `formatPhoneNumber(value: string): string`

Formats `value` as a "local" phone number.

```js
import { formatPhoneNumber } from 'react-phone-number-input'
formatPhoneNumber('+12133734253') === '(213) 373-4253'
```

### `formatPhoneNumberIntl(value: string): string`

Formats `value` as an "international" phone number.

```js
import { formatPhoneNumberIntl } from 'react-phone-number-input'
formatPhoneNumberIntl('+12133734253') === '+1 213 373 4253'
```

### `isPossiblePhoneNumber(value: string): boolean`

Checks if the `value` could be a "possible" phone number. In other words, it checks if the phone number length is correct. The actual phone number digits themselves aren't validated.

```js
import { isPossiblePhoneNumber } from 'react-phone-number-input'
isPossiblePhoneNumber('+12223333333') === true
isPossiblePhoneNumber('+1222333333') === false
```

### `isValidPhoneNumber(value: string): boolean`

Checks if the `value` represents a "valid" phone number. In other words, it checks if the phone number length is correct, and all digits are correct too.

```js
import { isValidPhoneNumber } from 'react-phone-number-input'
isValidPhoneNumber('+12223333333') === false
isValidPhoneNumber('+12133734253') === true
```

By default this component uses [`min` "metadata"](#min-vs-max-vs-mobile) which results in less strict validation compared to [`max`](#min-vs-max-vs-mobile) or [`mobile`](#min-vs-max-vs-mobile).

[How to choose](https://www.npmjs.com/package/libphonenumber-js#using-phone-number-validation-feature) between `isPossiblePhoneNumber()` and `isValidPhoneNumber()`: I'd personally prefer `isPossiblePhoneNumber()` because its strength is in its weakness. `isValidPhoneNumber()` is a double-edged sword in terms of how strict it is, and when not kept up-to-date, it could get stale over time and start rejecting freshly-assigned phone number ranges.

### `parsePhoneNumber(input: string): PhoneNumber?`

Parses a [`PhoneNumber`](https://gitlab.com/catamphetamine/libphonenumber-js#phonenumber) object from a `string`. This is simply an alias for [`parsePhoneNumber()`](https://gitlab.com/catamphetamine/libphonenumber-js#parsephonenumberstring-options-or-defaultcountry-phonenumber) from [`libphonenumber-js`](https://gitlab.com/catamphetamine/libphonenumber-js). Can be used to get `country` from `value`.

```js
import { parsePhoneNumber } from 'react-phone-number-input'
const phoneNumber = parsePhoneNumber('+12133734253')
if (phoneNumber) {
  phoneNumber.country === 'US'
} else {
  // The argument is not a valid phone number
}
```

### `getCountryCallingCode(country: string): string`

Returns the ["country calling code"](https://gitlab.com/catamphetamine/libphonenumber-js#country-calling-code) of a `country`. The `country` argument must be a supported [country code](#country-code).

This is simply an alias for [`getCountryCallingCode()`](https://gitlab.com/catamphetamine/libphonenumber-js#getcountrycallingcodecountry) from [`libphonenumber-js`](https://gitlab.com/catamphetamine/libphonenumber-js).

```js
import { getCountryCallingCode } from 'react-phone-number-input'
getCountryCallingCode('US') === '1'
```

### `isSupportedCountry(country: string): boolean`

Checks if a given [country code](#country-code) is supported by this library.

This is simply an alias for [`isSupportedCountry()`](https://gitlab.com/catamphetamine/libphonenumber-js#issupportedcountrycountry-string-boolean) from [`libphonenumber-js`](https://gitlab.com/catamphetamine/libphonenumber-js).

```js
import { isSupportedCountry } from 'react-phone-number-input'
isSupportedCountry('US') === true
```

## Flags URL

By default, all flags are linked from [`country-flag-icons`](https://gitlab.com/catamphetamine/country-flag-icons)'s [GitHub pages](https://purecatamphetamine.github.io/country-flag-icons/3x2) website as `<img src="..."/>`s. Any other flag icons could be used instead by passing a custom [`flagUrl`](https://catamphetamine.gitlab.io/react-phone-number-input/docs#phoneinputwithcountry) property (which is `"https://purecatamphetamine.github.io/country-flag-icons/3x2/{XX}.svg"` by default) and specifying their aspect ratio via [`--PhoneInputCountryFlag-aspectRatio`](https://gitlab.com/catamphetamine/react-phone-number-input/blob/master/style.css) CSS variable (which is `1.5` by default, meaning "3x2" aspect ratio).

For example, using custom "4x3" flag icons would be as simple as:

```css
:root {
  --PhoneInputCountryFlag-aspectRatio: 1.333;
}
```

```js
<PhoneInput flagUrl="https://example.com/flags/4x3/{xx}.svg" .../>
```

## Including all flags

Linking flag icons as external `<img/>`s is only done to reduce the overall bundle size, because including all country flags in the code as inline `<svg/>`s would increase the bundle size by 44 kB (after gzip).

If bundle size is not an issue (for example, for a standalone non-web application, or an "intranet" application), then all country flags can be included directly in the code by passing the [`flags`](https://catamphetamine.gitlab.io/react-phone-number-input/docs#phoneinputwithcountry) property:

```js
import PhoneInput from 'react-phone-number-input'
import flags from 'react-phone-number-input/flags'

<PhoneInput flags={flags} .../>
```

<!--
## Android

There have been [reports](https://github.com/catamphetamine/react-phone-number-input/issues/75) of some Samsung Android phones not handling caret positioning properly (e.g. Samsung Galaxy S8+, Samsung Galaxy S7 Edge).

The workaround is to pass `smartCaret={false}` property:

```js
import PhoneInput from 'react-phone-number-input'

<PhoneInput
  smartCaret={false}
  value={this.state.value}
  onChange={value => this.setState(value)}/>
```

`smartCaret={false}` caret is not as "smart" as the default one but still works good enough (and has no issues on Samsung Android phones). When erasing or inserting digits in the middle of a phone number this caret usually jumps to the end: this is the expected behaviour because the "smart" caret positioning has been turned off specifically to fix this Samsung Android phones issue.
-->

## Localization

Language translation can be applied by passing a custom `labels` property value. This component comes pre-packaged with several importable [translations](https://gitlab.com/catamphetamine/react-phone-number-input/tree/master/locale).

```js
import russianLabels from 'react-phone-number-input/locale/ru'

<PhoneInput labels={russianLabels} .../>
```

If labels for a certain language are missing, one could submit a pull request to add those.

<details>
<summary>Where could one get the list of country names for a given language.</summary>

####

There's a myriad sources on the internet. Modern web browsers even have an official [built-in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames/of) list of country names in all languages.

For example, one could copy country names from [`github.com/umpirsky/country-list`](https://github.com/umpirsky/country-list/blob/master/data/).

```js
import countryNamesInRussian from 'country-list/data/ru/country.json'

// Outputs a JSON with the country names.
JSON.stringify(
  Object.keys(countryNamesInRussian).sort()
    .reduce((all, country) => ({
      ...all,
      [country]: countries[country]
    }), {}),
  null,
  '\t'
)
```
</details>

####

Note that this library uses the term ["country code"](#country-code) rather broadly, including both the official and [ISO-3166-1](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country codes and a few of unofficial "country codes", so a translation should include the labels for both official and unofficial "country codes".

Also, a translation should include the following miscellaneous labels:
* `country` — is used as an `aria-label` for the country `<select/>` dropdown. It could also be used as a label for a hypothetical country name autocomplete input field.
* `ZZ` — is used when no country is selected.
* `phone` — could hypothetically be used as a label for the phone number input field.
* `ext` — could hypothetically be used as a label for a phone number extension input field.

####

The final format for a translation file is:

```js
{
  "country": "Phone number country",
  "phone": "Phone",
  "ext": "ext.",
  // The rest are country names, including "unofficial" ones
  // like `AC`, `TA`, `XK`, and `ZZ` for "International".
  ...,
  "RO": "Romania",
  "RS": "Serbia",
  "RU": "Russia",
  ...,
  "ZZ": "International"
}
```

## `min` vs `max` vs `mobile`

This component uses [`libphonenumber-js`](https://gitlab.com/catamphetamine/libphonenumber-js) which lets a developer choose from different "metadata" sets, where a "metadata" set is a complete list of phone number parsing and formatting rules for all possible countries.

As one may guess, the complete list of those rules is huge, so this package provides a way to optimize the bundle size by choosing between `max`, `min`, `mobile` or "custom" metadata, depending on the project's needs.

* `min` — (default) The smallest metadata set
  * Is about `80 kilobytes` in size (`libphonenumber-js/metadata.min.json` file)
  * Choose this when:
    * You don't need to detect phone number type — "fixed line", "mobile", etc — via `libphonenumber-js` functions
    * You're fine with just validating phone number length via `isPossiblePhoneNumber()` and you don't need to strictly validate phone number digits via `isValidPhoneNumber()`

* `max` — The complete metadata set
  * Is about `145 kilobytes` in size (`libphonenumber-js/metadata.max.json` file)
  * Choose this when:
    * The basic `isPossiblePhoneNumber()` phone number length check is not enough for you and you need the strict phone number digits validation via `isValidPhoneNumber()`
    * You need to detect phone number type — "fixed line", "mobile", etc — via `libphonenumber-js` functions

* `mobile` — The complete metadata set for dealing with mobile numbers _only_
  * Is about `95 kilobytes` in size (`libphonenumber-js/metadata.mobile.json` file)
  * Choose this when:
    * You need `max` metadata capabilities and you _only_ accept mobile numbers
      * It will still be able to handle non-mobile numbers just fine, with the only difference that `isValidPhoneNumber()` or `isPossiblePhoneNumber()` might potentially return `false` for them, or it could be unable to determine the phone number type.

* "custom" — (advanced) Create [your own](#custom-metadata) metadata that is even smaller in size by dropping support for most countries
  * The size depends on the number of supported countries and the type of supported phone numbers
  * Choose this when:
    * You only need to support a handful of countries and you're absolutely obsessed with reducing the bundle size

Choose one from the above and then simply `import` the components or functions from the relevant sub-package.

For "with country select" component, the import paths are:

* `min` — `react-phone-number-input`
* `max` — `react-phone-number-input/max`
* `mobile` — `react-phone-number-input/mobile`
* "custom" — `react-phone-number-input/core`

For "without country select" component, the import paths are:

* `min` — `react-phone-number-input/input`
* `max` — `react-phone-number-input/input-max`
* `mobile` — `react-phone-number-input/input-mobile`
* "custom" — `react-phone-number-input/input-core`

As for "custom" metadata, it could be used in those rare cases when not all countries are needed and a developer would really prefer to reduce the bundle size to a minimum. In that case, one could generate their own ["custom"](https://www.npmjs.com/package/libphonenumber-js#custom-metadata) metadata set and then `import` the functions from `react-phone-number-input/core` or `react-phone-number-input/input-core` sub-package which doesn't come pre-packaged with any metadata and instead requires `metadata` property be passed.

## Bug reporting

If you think that the phone number parsing/formatting/validation engine malfunctions for a particular phone number then it could be for several reasons:

* `libphonenumber-js`, which is what this package uses internally, parses/formats/validates phone numbers incorrectly. To test if that's the case, follow the instructions outlined in the [bug reporting section of `libphonenumber-js` readme](https://www.npmjs.com/package/libphonenumber-js#bug-reporting).

* `react-phone-number-input`'s exported `isValidPhoneNumber()` function is a "stripped-down" "min" version of the same function exported from `libphonenumber-js` package, so if you think that the validation is too lax, use the `isValidPhoneNumber()` function from `libphonenumber-js/max` package instead.

* In other cases, report issues in this repo.

## Autocomplete

There's a feature of a web browser when it automatically populates the input with the user's own phone number. It's called ["autocomplete"](https://www.w3schools.com/tags/att_input_autocomplete.asp).

To enable this feature, make sure you're putting `<PhoneInput/>` component inside a `<form/>`, otherwise this feature may not be working: the user will be tapping on their phone number "suggestion" but [nothing would be happening](https://gitlab.com/catamphetamine/react-phone-number-input/issues/101).

## `react-hook-form`

To use this component with [`react-hook-form`](https://react-hook-form.com), use one of the four exported components:

```js
// "Without country select" component.
import PhoneInput from 'react-phone-number-input/react-hook-form-input'

// "Without country select" component (to pass custom `metadata` property).
import PhoneInput from 'react-phone-number-input/react-hook-form-input-core'

// "With country select" component.
import PhoneInputWithCountry from 'react-phone-number-input/react-hook-form'

// "With country select" component (to pass custom `metadata` property).
import PhoneInputWithCountry from 'react-phone-number-input/react-hook-form-core'
```

[Example](https://codesandbox.io/s/recursing-brook-kmtjw):

```js
// "Without country select" component.
import PhoneInput from "react-phone-number-input/react-hook-form-input"

// "With country select" component.
import PhoneInputWithCountry from "react-phone-number-input/react-hook-form"

import { useForm } from "react-hook-form"

export default function Form() {
  const {
    // Either pass a `control` property to the component
    // or wrap it in a `<FormProvider/>`.
    control,
    handleSubmit
  } = useForm()

  return (
    <form onSubmit={handleSubmit(...)}>
      <PhoneInput
        name="phoneInput"
        control={control}
        rules={{ required: true }} />

      <PhoneInputWithCountry
        name="phoneInputWithCountrySelect"
        control={control}
        rules={{ required: true }} />

      <button type="submit">
        Submit
      </button>
    </form>
  )
}
```

Both components accept properties:

* `name` — (required) Form field name.

* `control` — (required) The `control` object returned from `useForm()`.

* `rules` — (optional) Validation rules in the same format as for `register()`. Example: `{{ required: true, validate: isPossiblePhoneNumber }}`.

* `defaultValue` — (optional) A default value could be passed directly to the component, or as part of the `defaultValues` parameter of `useForm()`.

<!-- * `shouldUnregister` — (optional) (advanced) Same as `shouldUnregister` parameter of `register()` (see `react-hook-form` docs for more info). Pass `true` to clear the value from form values on input component unmount: for example, when showing or hiding phone input field. `shouldUnregister` can also be set globally for all fields when passed as a parameter to `useForm()`. -->

## Customization

"With country select" `<PhoneInput/>` component accepts some [customization properties](https://catamphetamine.gitlab.io/react-phone-number-input/docs#phoneinputwithcountry):

<!-- * `containerComponent` — Custom wrapping `<div/>` component. -->

* `metadata` — Custom `libphonenumber-js` ["metadata"](#min-vs-max-vs-mobile). Could be used to supply "metadata" that only contains a small subset of countries.

* `labels` — Custom translation "messages": country names, miscellanous labels. Example for English: [`react-phone-number-input/locale/en.json`](https://gitlab.com/catamphetamine/react-phone-number-input/-/blob/master/locale/en.json)

* [`inputComponent`](#inputcomponent) — Custom phone number `<input/>` component.

* [`countrySelectComponent`](#countryselectcomponent) — Custom country `<select/>` component.

* [`internationalIcon`](#internationalicon) — Custom "International" icon component.

* [`flagComponent`](#flagcomponent) — Custom flag icon component.

* `countrySelectProps.arrowComponent` — Custom "arrow" component of the default country `<select/>`. Renders an "arrow" "dropdown" icon. Doesn't receive any properties.

All those customization properties have their default values which are, therefore, always included in the application bundle, regardless of whether those default property values get overridden by any custom ones.

Those who'd like to exclude the default values just for `metadata` and `labels` properties could `import` the component from `react-phone-number-input/core` subpackage rather than from `react-phone-number-input` package.

#### `countrySelectComponent`

React component for the country select. See [CountrySelect.js](https://gitlab.com/catamphetamine/react-phone-number-input/blob/master/source/CountrySelect.js) for an example.

Receives properties:

* `name: string?` — HTML `name` attribute.
* `value: string?` — The currently selected country code (`undefined` in case of "International").
* `onChange(value: string?)` — Updates the `value` (to `undefined` in case of "International").
* `onFocus()` — Is used to toggle the `--focus` CSS class.
* `onBlur()` — Is used to toggle the `--focus` CSS class.
* `options: object[]` — The list of all selectable countries (including "International") each being an object of shape `{ value: string?, label: string }`.
* `iconComponent: PropTypes.elementType` — React component that renders a country icon: `<Icon country={value}/>`. If `country` is `undefined` then it renders an "International" icon.
* `disabled: boolean?` — HTML `disabled` attribute.
* `readOnly: boolean?` — HTML `readonly` attribute.
* `tabIndex: (number|string)?` — HTML `tabIndex` attribute.
* `className: string` — CSS class name.

#### `inputComponent`

A React component for the phone number input field. Is `"input"` by default, meaning that it renders a standard DOM `<input/>`.

Any custom input component implementation must use `React.forwardRef()` to "forward" `ref` to the underlying "core" `<input/>` component.

Receives properties:

* `value: string` — The formatted `value`.
* `onChange(event: Event)` — Updates the formatted `value` from `event.target.value`.
* `onFocus()` — Is used to toggle the `--focus` CSS class.
* `onBlur(event: Event)` — Is used to toggle the `--focus` CSS class.
* Other properties like `type="tel"` or `autoComplete="tel"` that should be passed through to the DOM `<input/>`.

<!--
#### `inputComponent`

React component for the phone number input field (a higher-order one). See [InputSmart](https://gitlab.com/catamphetamine/react-phone-number-input/blob/master/source/InputSmart.js) and [InputBasic](https://gitlab.com/catamphetamine/react-phone-number-input/blob/master/source/InputBasic.js) for an example.

Receives properties:

* `value : string` — The parsed phone number. E.g.: `""`, `"+"`, `"+123"`, `"123"`.
* `onChange(value : string)` — Updates the `value` (to `undefined` in case it's empty).
* `onFocus()` — Is used to toggle the `--focus` CSS class.
* `onBlur()` — Is used to toggle the `--focus` CSS class.
* `country : string?` — The currently selected country. `undefined` means "International" (no country selected).
* `metadata : object` — `libphonenumber-js` metadata.
* All other properties should be passed through to the underlying `<input/>`.

Must also either use `React.forwardRef()` to "forward" `ref` to the `<input/>` or implement `.focus()` method.
-->

#### `flagComponent`

Renders a country flag icon.

Receives properties:

* `country: string` — A two-letter ISO country code. Example: `"RU"`.
* `countryName: string` — Country name. Example: `"Russia"`.
* `flags?: object` — An object that contains a flag icon component for each country. Same as the [`flags`](https://catamphetamine.gitlab.io/react-phone-number-input/docs/#phoneinputwithcountry) property of the `react-phone-number-input` component.
* `flagUrl?: string` — A template for a country flag icon image URL. Same as the [`flagUrl`](https://catamphetamine.gitlab.io/react-phone-number-input/docs/#phoneinputwithcountry) property of the `react-phone-number-input` component.
* `className: string` — CSS class name.

#### `internationalIcon`

Renders an "International" icon. For example, the default one is a globe icon. The icon is shown instead of a country flag when the phone number is in international format (i.e. starts with a `+` character) but is either incomplete or doesn't belong to any known country.

Receives properties:

* `title: string` — [ARIA](https://developer.mozilla.org/docs/Web/Accessibility/ARIA) label.
* `aspectRatio: number` — Icon aspect ratio: `width / height`.
* `className: string` — CSS class name.

<!--
#### `containerComponent`

React component that contains the country picker and input. Is `"div"` by default meaning that it renders a standard DOM `<div/>`.

Receives properties:

* `style: object` — A component CSS style object.
* `className: string` — Classes to attach to the component, typically changes when component focuses or blurs.
-->

## CDN

To include this library directly via a `<script/>` tag on a page, one can use any npm CDN service, e.g. [unpkg.com](https://unpkg.com) or [jsdelivr.com](https://jsdelivr.com)

```html
<!-- Default ("min" metadata). -->
<script src="https://unpkg.com/react-phone-number-input@3.x/bundle/react-phone-number-input.js"></script>

<!-- Or "max" metadata. -->
<script src="https://unpkg.com/react-phone-number-input@3.x/bundle/react-phone-number-input-max.js"></script>

<!-- Or "mobile" metadata. -->
<script src="https://unpkg.com/react-phone-number-input@3.x/bundle/react-phone-number-input-mobile.js"></script>

<!-- Styles for the component. -->
<!-- Internet Explorer requires transpiling CSS variables. -->
<link rel="stylesheet" href="https://unpkg.com/react-phone-number-input@3.x/bundle/style.css"/>

<script>
  var PhoneInput = window.PhoneInput.default
</script>
```

Without country select:

```html
<!-- Without country `<select/>` ("min" metadata). -->
<script src="https://unpkg.com/react-phone-number-input@3.x/bundle/react-phone-number-input-input.js"></script>

<script>
  var PhoneInput = window.PhoneInput.default
</script>
```

<!--
## Advertisement

[React Responsive UI](https://catamphetamine.gitlab.io/react-responsive-ui/) component library.
-->

## Country code

A "country code" is a two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) like `"US"`, `"CA"`, etc.

However, this library uses `libphonenumber-js`'s [variant](https://www.npmjs.com/package/libphonenumber-js#country-code) of the "country code" term, which is rather broad and includes both the [official](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements) ISO country codes and a few of unofficial "country codes". For that reason, a developer should use a "country code" returned from this library with caution in an application that only expects the official ISO "country codes" to exist. For example, such application will likely not have a label or a flag for such an unofficial "country code". In that case, a developer could manually transform an unofficial "country code" returned from this library to an official ISO country code of the most suitable "parent" country.

To check whether a certain two-letter "country code" is supported by this library, use [`isSupportedCountry()`](#issupportedcountrycountry-string-boolean) function.

## Tests

This component comes with 100% code coverage for the core `./source/helpers` directory.

To run tests:

```
npm test
```

To generate a code coverage report:

```
npm run test-coverage
```

The code coverage report can be viewed by opening `./coverage/lcov-report/index.html`.

If the code coverage report is "empty" then it means that a newer version of `handlebars` was accidentally installed and should be reverted to `handlebars@4.5.3`.

The `handlebars@4.5.3` [work](https://github.com/handlebars-lang/handlebars.js/issues/1646#issuecomment-578306544)[around](https://github.com/facebook/jest/issues/9396#issuecomment-573328488) in `devDependencies` is for the test coverage to not produce empty reports:

```
Handlebars: Access has been denied to resolve the property "statements" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
```

## GitHub

On March 9th, 2020, GitHub, Inc. silently [banned](https://medium.com/@catamphetamine/how-github-blocked-me-and-all-my-libraries-c32c61f061d3) my account (erasing all my repos, issues and comments) without any notice or explanation. Because of that, all source codes had to be promptly moved to [GitLab](https://gitlab.com/catamphetamine/react-phone-number-input). GitHub repo is now deprecated, and the latest source codes can be found on GitLab, which is also the place to report any issues.

## License

[MIT](LICENSE)
