PhoneInput

A phone number input built on react-phone-input-2, wrapped with FlxUI’s Input.Wrapper for consistent label/description/error styling. The country dropdown selector is disabled — this component is designed for a fixed-country context (e.g. a form where the country is already known or chosen elsewhere), not a general international phone picker.

Import

import { PhoneInput } from '@flxui/uikit/business'

Basic Usage

import { PhoneInput } from '@flxui/uikit/business'
 
function Demo() {
  return <PhoneInput country="us" placeholder="Phone number" />
}

The country dropdown is always disabled (disableDropdown is hardcoded internally) — country sets the parsing/mask context, it isn’t a selectable dropdown option.

With label, description, and error

Since PhoneInput wraps Input.Wrapper, it accepts the same label/description/error props as any other FlxUI input:

<PhoneInput
  country="us"
  label="Phone number"
  description="We'll only use this for account recovery"
  error={touched && !isValid ? 'Enter a valid phone number' : undefined}
/>

Showing the country code only after focus

By default the dial code isn’t shown. Set showContryCodeAfterFocus to reveal it once the field is focused for the first time:

<PhoneInput country="us" showContryCodeAfterFocus />
⚠️

Note the prop name is showContryCodeAfterFocus (missing the “u” in “Country”) — this matches the actual exported prop name in the current package version, not a typo in this doc.

Custom input masks

PhoneInput accepts react-phone-input-2’s masks prop to override the digit mask per country. If you don’t pass masks, only China (cn) gets a hardcoded default mask ('...........', 11 digits) — every other country falls back to react-phone-input-2’s own defaults.

For full, real per-country mask coverage, pass the exported phoneMasks constant — see phoneMasks below.

import { PhoneInput, phoneMasks } from '@flxui/uikit/business'
 
;<PhoneInput country="cn" masks={phoneMasks} />

Styling the underlying react-phone-input-2 elements

react-phone-input-2’s own class-name props are forwarded — useful for targeting specific parts of the rendered widget:

<PhoneInput inputClass="my-input-class" buttonClass="my-button-class" containerClass="my-container-class" />

Wrapping the outer container

rootProps forwards to the outermost Box, separate from the input wrapper itself — useful for layout concerns like width or margin on the whole component:

<PhoneInput rootProps={{ w: 320, mb: 16 }} />

Props

PhoneInput extends react-phone-input-2’s PhoneInputProps, plus Input.Wrapper props (label, description, error, etc. — excluding onBlur, onChange, onClick, onFocus, onKeyDown, which come from react-phone-input-2 instead).

PropTypeDefaultDescription
countrystring''Country code used for parsing/masking (dropdown is disabled, so this isn’t user-selectable)
showContryCodeAfterFocusboolean-Reveals the dial code once the field has been focused for the first time
rootPropsBoxProps-Props forwarded to the outermost Box, separate from the input wrapper itself
valuestring-Phone value
placeholderstring''Input placeholder
inputClass / buttonClass / containerClass / dropdownClass / searchClassstring-Forwarded to react-phone-input-2 for styling specific internal elements
masksobject{ cn: '...........' }Per-country digit masks. Only cn has a built-in default — pass the exported phoneMasks constant for full per-country coverage
onFocus(e, data) => void-Called after the component’s internal focus-tracking state updates (used for showContryCodeAfterFocus)

Plus any other react-phone-input-2 prop (onChange, onBlur, disabled, etc.) and any Input.Wrapper prop (label, description, error, required, etc.) are accepted and forwarded.


FormPhoneInput

A react-hook-form-connected wrapper around PhoneInput. Must be used inside a react-hook-form FormProvider (or FlxUI’s Form wrapper, if you’re using it) — it reads form context via useFormContext internally.

Import

import { FormPhoneInput } from '@flxui/uikit/business'

Basic Usage

import { useForm, FormProvider } from 'react-hook-form'
import { FormPhoneInput } from '@flxui/uikit/business'
 
function Demo() {
  const methods = useForm()
  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit((data) => console.log(data))}>
        <FormPhoneInput name="phone" label="Phone Number" rules={{ required: 'Phone number is required' }} />
      </form>
    </FormProvider>
  )
}

Full per-country masking via phoneMasks is applied automatically — you don’t need to pass masks yourself.

Props

Extends PhoneInput props (minus onSelect, redefined below with a country-data callback), plus:

PropTypeDefaultDescription
namestring-Required. Field name registered with react-hook-form
defaultCountrystring-Initial country context
rulesRegisterOptions-react-hook-form validation rules (e.g. { required: '...' })
onSelect(value: string, country: CountryData | {}) => void-Called alongside the form’s own onChange, with the parsed country data

Validation errors are automatically read from form state and rendered via @hookform/error-message’s ErrorMessage — no manual error prop needed.


FormPhoneInputV2

A combined country-select + phone-number pair, for forms where the country needs to be its own selectable field (rather than fixed/known ahead of time, as with PhoneInput/FormPhoneInput). Renders a FormSelect for the country and a FormPhoneInput for the number side by side, with a single consolidated error message under both.

Import

import { FormPhoneInputV2 } from '@flxui/uikit/business'

Basic Usage

import { useForm, FormProvider } from 'react-hook-form'
import { FormPhoneInputV2 } from '@flxui/uikit/business'
 
function Demo() {
  const methods = useForm()
  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit((data) => console.log(data))}>
        <FormPhoneInputV2
          countryKey="country"
          phoneKey="phone"
          rules={{ required: 'Phone number is required' }}
          countryRules={{ required: 'Country is required' }}
          selectProps={{ placeholder: 'Select country' }}
        />
      </form>
    </FormProvider>
  )
}

The phone field’s country is driven live by the country field’s value (via watch) — selecting a country immediately updates the phone input’s parsing/mask context.

Filtering the country list

<FormPhoneInputV2
  countryKey="country"
  phoneKey="phone"
  selectProps={{
    placeholder: 'Select country',
    filterData: (option) => ['us', 'ca', 'gb'].includes(option.value)
  }}
/>

Props

PropTypeDefaultDescription
countryKeystring-Required. Form field name for the country select
phoneKeystring-Required. Form field name for the phone number
defaultCountrystring-Initial country context
rulesRegisterOptions-Validation rules for the phone field
countryRulesRegisterOptions-Validation rules for the country field
onSelect(value: string, country: CountryData | {}) => void-Called on phone change, with parsed country data
selectPropsobject-Props for the country FormSelect, plus an optional filterData to restrict the list
rootPropsBoxProps-Props forwarded to the outer wrapping Box

showContryCodeAfterFocus is forced to false internally on the phone side — since the country is already visible in its own select field, showing the dial code inside the phone input as well would be redundant.


phoneMasks

A full per-country digit mask map, generated from real country format data. Includes a forced override for China (cn) to match PhoneInput’s expected 11-digit format.

Import

import { phoneMasks } from '@flxui/uikit/business'

Usage

<PhoneInput masks={phoneMasks} />

FormPhoneInput and FormPhoneInputV2 already apply phoneMasks internally — you only need to import it directly when using the plain PhoneInput component outside a form context.


validPhoneNumber

An async helper for validating a phone number against a specific country/region, using google-libphonenumber. The validation library is lazy-loaded on first call (dynamic import()), so it doesn’t add to your initial bundle unless you actually validate a number.

Import

import { validPhoneNumber } from '@flxui/uikit/business'

Usage

import { validPhoneNumber } from '@flxui/uikit/business'
 
async function handleSubmit(country: string, phoneNumber: string) {
  const isValid = await validPhoneNumber(country, phoneNumber)
  if (!isValid) {
    // show a validation error
  }
}

Signature

function validPhoneNumber(country: string, phoneNum: string): Promise<boolean>
ParamTypeDescription
countrystringTwo-letter region code (e.g. 'US', 'CN') to validate the number against
phoneNumstringThe raw phone number string to validate
⚠️

Throws if the underlying google-libphonenumber parse fails unexpectedly (not just “invalid number” — a genuine parse error). Wrap calls in a try/catch if you need to distinguish “invalid” from “couldn’t be parsed at all”.