Changelog
Upgrading across a rename or a major version? Start with the Migration guide.
Unreleasedβ
Fixed
internationalPhoneNumberis now a real E.164 string. It was built by concatenating the calling code with the typed digits, which kept the national trunk prefix that the example-number placeholder invites users to type β GB07400 123456produced+4407400123456instead of+447400123456. Same fix fornationalPhoneNumberandgetInternationalPhoneNumberLength(). Countries where a leading zero is significant (Italy) keep it.isValidPhoneNumber()now validates against the selected country instead of the whole calling code. A Kazakh number no longer passes with Russia selected, and a Bahamian number no longer passes with the United States selected β both share a calling code (+7,+1). Territories without a numbering plan of their own (Γ land, Isle of Man, Svalbardβ¦) keep validating under their parent country's plan.isValidPhoneNumber()returns abooleanin every case; it previously returnedundefinedfor input it could not parse, and for a full E.164 string passed together with its country (isValidPhoneNumber('+12025550123', us)).languagenow accepts ISO 639-1 codes ("pt","en","ar") as documented. Only the ISO 639-2 spelling ("por") used to resolve β the 2-letter form left the input with no placeholder and no accessibility label at all. An unknown or missing code now falls back to English instead ofundefined.- Every
TextInputPropsthe component does not own reaches the underlyingTextInput.keyboardType,testID,style,editable,placeholderTextColorandselectionColorwere typed as accepted but silently dropped.stylemerges with the component's own styles;disabledstill wins overeditable.valueandonChangeTextremain owned by the component. internationalPhoneNumberFormattedis formatted from the corrected E.164, so it no longer shows a trunk prefix thatinternationalPhoneNumberhas already dropped (+44 07400 123456β+44 7400 123456). Unchanged for input typed without one.- The calling code now comes from libphonenumber rather than the country data's
idd.root, which is stored as a root plus suffixes and left three territories with a truncated value: Saint Helena showed+2instead of+290, Western Sahara+2instead of+212, Vatican City+3instead of+39. - An international
defaultPhoneNumber(or pasted value) carrying digits past the end of the number now has them trimmed, so the country is still detected and the value lands in the input as something editable.+1250553456550199selects Canada and fills250 553 4565, the same as passing+12505534565. Numbers that already resolve are never shortened. Previously nothing happened at all: the selected country's calling code was prefixed onto a string that already carried its own+, building+55+1250β¦, which libphonenumber gave up on β it returned just+55, which was then stripped back off, leaving"". - A value the component still cannot format is no longer dropped either. Overflowing the
country's plan makes formatting return "rejected", which is right while typing β the
keystroke is ignored and the previous value stands β but a programmatic set has no
previous value to stand on, so under a controlled
valuethe parent was never notified and the prop did nothing at all. Programmatic sets now keep the raw value; only typing still rejects. Controlled and uncontrolled inputs now agree. ref.clear()now empties the input. The underlyingTextInputis controlled, so the nativeclear()it used to call was undone by the next render.showModalScrollIndicatorreaches the modal. It was accepted and documented but never forwarded.onValidationChangeandonPhoneNumberTypeChangereport the initial state when the input starts pre-filled (defaultPhoneNumberor a controlledvalue). A form opening on a valid number was never told about it. An input that starts empty stays silent, so a pristine form is still not told it is invalid before the user types.- Territories libphonenumber has no numbering plan for (
BV,GS,PN,TF,UM) are hidden from the modal alongsideAQandHM. Picking one left the input with no mask, no length limit and no validation. customFlagandcustomCaretcan hide the element by returningnull. Both results were run through a falsy check, sonullfell back to the default flag or caret. Returningundefinedstill means "keep the default".phoneInputStyles.caretis no longer also spread raw onto the caret's wrapperView. It is aTextStyle(color,fontSize,display), and those are not validViewstyle keys.- The country button reports its disabled state to screen readers when
disabledormodalDisabledis set. It used to announce a plain button that silently did nothing.
Changed
- The
placeholderType="number"placeholder is now formatted the way the input formats what you type. It used the national format, which groups digits differently ((201) 555-0123vs201 555 0123) and prints the national trunk prefix (07400 123456for the UK) β teaching users to type a leading zero the number should not carry. - The library now loads a single libphonenumber metadata set (
max) instead of pulling in bothminandmaxβ roughly 84 KB less metadata in the bundle. Validation is stricter as a result: numbers that merely matched a length pattern no longer pass. react-native-safe-area-contextis declared as a peer dependency. It was always required β the country modal renders with it β but only mentioned in the install docs.
Internal
npm testrunstsc --noEmitover the shipped types plus a dependency-free self-check (scripts/check.mjs) covering E.164 derivation, validation, translations, placeholders and calling codes across every country libphonenumber knows.- Dropped the unused (and deprecated)
metro-react-native-babel-presetdev dependency. - Bumped
libphonenumber-jsto 1.13.12. No country or calling code changed; the only validation difference across the example-number sweep is a Somali range that upstream now recognizes as valid.
v0.14.0β
Added
usePhoneInputβ headless hook exposing the whole state machine (values, country, validity, line type, setters) for fully custom UIs.onValidationChangeβ fires when validity flips, with the detected line type and country.onPhoneNumberTypeChangeand the exportedgetPhoneNumberType()βMOBILE,FIXED_LINE,TOLL_FREE,VOIPand more.placeholderType="number"β uses a real example number for the current country as the placeholder instead of translated text. Now the default.
Fixed
- Smart paste fills the input correctly, and
customMaskclears properly on an empty input. onChangeCountrynow fires on mount when thecountryprop is left undefined.- The input clears when
defaultCountrychanges after mount.
Internal
PhoneInputis now a thin view overusePhoneInput;lib/index.jswas split into utils, subcomponents and a ref hook.- npm package ships via a
fileswhitelist β smaller install.
v0.13.2β
- Streamlined RTL styling for the flag container.
v0.13.1β
- Improved RTL support.
peerDependenciesrelaxed to minimum versions instead of pinned ranges (thanks @Shasikhan).
v0.13.0β
Breaking
- Package renamed to
rn-international-phone-number. - The country selector modal now comes from
rn-country-select, addingreact-native-safe-area-contextas a required peer dependency β and moving the flag font tonode_modules/rn-country-select/lib/assets/fonts. - Props renamed:
selectedCountryβcountry,onChangeSelectedCountryβonChangeCountry,defaultValueβdefaultPhoneNumber(old name deprecated). - Ref renamed:
valueβnationalPhoneNumber,fullPhoneNumberβinternationalPhoneNumberFormatted,isValidβisValidPhoneNumber,selectedCountryβcountry. getPhoneNumberLength()βgetInternationalPhoneNumberLength().
Added
internationalPhoneNumberβ unformatted E.164 output.- Bottom sheet and popup modal types, alphabet filter, popular countries section, custom country item / section title / close button components.
- ISO 639-1 language codes accepted alongside ISO 639-2 β 33 languages.
Full diff for every step in the migration guide.
Older releasesβ
Release notes for v0.12 and earlier live on GitHub: