v1.0.0 · Open Source

react-intl-phone-username-input

A powerful React component for international phone numbers and usernames in one field. Supports 240+ countries, optional country selector, phone formatting, RTL, and is built for performance with lazy loading and code-splitting.

Install with: npm install react-intl-phone-username-input
Live Demo ↗ Quick Start ↓
Capabilities

Powerful Features.

Everything you need for international phone and username input in one reusable component.

🔀

Dual Purpose

Single input for phone or username/email; mode can be fixed or hybrid (auto-detect).

🌍

Multi-Country

240+ countries with flags and dial codes; optional dropdown to choose country.

📱

Phone or Hybrid

Phone mode for numbers only; hybrid accepts text or phone and formats when it looks like a number.

🎛️

Country Selector

Custom dropdown (search + keyboard) or native select; auto choice on mobile vs desktop.

Smart Formatting

Optional as-you-type formatting via libphonenumber-js for proper phone number display.

Performance

Lazy-loaded country list and dynamically imported selectors; memoized components; small initial bundle.

🔒

TypeScript

Full TypeScript support with typed props and options out of the box.

Accessibility

ARIA attributes, keyboard navigation in custom dropdown, semantic markup.

🔄

RTL Support

Built-in right-to-left layout and text direction support for international audiences.

Flexibility

Two Modes, One Component.

Choose the mode that fits your use case. Switch between phone-only and hybrid modes effortlessly.

📞 Phone Mode

Strictly phone number input with formatting. Perfect for forms that only need phone numbers.

  • Numbers-only input validation
  • Always applies phone formatting
  • Country-based dial codes
  • E.164 format support
  • Ideal for contact forms, verification

🔀 Hybrid Mode

Accepts usernames, emails, OR phone numbers. Smart detection formats phones, preserves text.

  • Accepts any text input
  • Auto-detects phone-like patterns
  • Preserves usernames/emails as-is
  • Formats only when it's a phone
  • Perfect for login/signup forms
Getting Started

Simple Integration.

Drop it into your React project and start collecting phone numbers or usernames immediately.

Basic Example – Phone Only

import { IntlPhoneUsernameInput } from "react-intl-phone-username-input";
import "react-intl-phone-username-input/style.css";
import { useState } from "react";

export default function App() {
  const [value, setValue] = useState("");

  return (
    <IntlPhoneUsernameInput
      value={value}
      onChange={setValue}
      options={{
        mode: "phone",
        defaultCountry: "IN",
        multiCountry: true,
        enableFlag: true,
      }}
      placeholder="Enter phone number"
    />
  );
}

Advanced Example – Custom Dropdown with Search

<IntlPhoneUsernameInput
  value={value}
  onChange={setValue}
  options={{
    mode: "phone",
    defaultCountry: "US",
    multiCountry: true,
    enforceCustomSelect: true,
    customSelect: {
      showFlag: true,
      showDialCode: true,
      enableSearch: true,
      searchPlaceholder: "Search countries...",
    },
  }}
  placeholder="Use ↑↓ and Enter in the dropdown"
/>

Hybrid Mode – Username, Email, or Phone

<IntlPhoneUsernameInput
  value={value}
  onChange={setValue}
  options={{
    mode: "hybrid",
    defaultCountry: "US",
    enableFlag: true,
  }}
  placeholder="Enter username, email, or phone"
/>

RTL Support

<IntlPhoneUsernameInput
  value={value}
  onChange={setValue}
  options={{
    mode: "phone",
    direction: "rtl",
    defaultCountry: "AE",
    multiCountry: true,
  }}
  placeholder="أدخل رقم الهاتف"
/>
API Reference

Component Props.

Fully typed props and options for complete control over behavior and appearance.

Main Props

Prop Type Required Description
value string Yes Current input value (controlled)
onChange (value: string) => void Yes Called when the value changes
onChangeSelect (change) => void No Called with {countryCode, dialCode, label, name, source} when country changes
options object No Configuration object; see Options below
className string No Class name for the root wrapper
selectFieldName string No Field name for country selector
placeholder string No Input placeholder

Options Object

Option Type Default Description
mode "phone" | "hybrid" "hybrid" Phone: strictly numbers; Hybrid: accepts text or phone
defaultCountry string "IN" Default country (ISO code, e.g., "US", "IN")
multiCountry boolean false Show country selector dropdown
format boolean true Format phone number as you type
enableFlag boolean true Show flag in single-country mode
hideDialCode boolean false Hide dial code in input
enforceCustomSelect boolean false Always use custom dropdown
enforceHtmlSelect boolean false Always use native select
flagBaseUrl string "https://flagcdn.com" Base URL for flag SVGs
direction "ltr" | "rtl" "ltr" Text/layout direction
preferredCountries string[] [] Countries to show first, e.g., ["US", "CA"]
highlightCountries string[] [] Countries to pin at the top
Customization

Styling & Classes.

Flexible styling options with CSS class overrides and custom theming support.

Root ClassName

<IntlPhoneUsernameInput
  className="my-form-field"
  value={value}
  onChange={setValue}
/>

Per-Part Class Overrides

<IntlPhoneUsernameInput
  value={value}
  onChange={setValue}
  options={{
    defaultCountry: "IN",
    multiCountry: true,
    classes: {
      intlPhoneUsernameInputWrapper: "my-wrapper",
      input_box: "my-input",
      flag_container: "my-flag-container",
      custom_select: {
        select_container: "my-dropdown",
        country_option: "my-option",
        search_input: "my-search",
      },
      html_select: {
        html_select_container: "my-native-select",
        select_overlay: "my-overlay",
      },
    },
  }}
/>

For complete styling documentation and best practices, check out the STYLING.md documentation file.

Bonus

Re-exported Utilities.

Access the same validation and formatting helpers from libphonenumber-js that the component uses internally.

import {
  isValidPhoneNumber,
  isPossiblePhoneNumber,
  parsePhoneNumber,
  parsePhoneNumberWithError,
  formatIncompletePhoneNumber,
  AsYouType,
  getExampleNumber,
  examples,
} from "react-intl-phone-username-input";

// Usage examples
const valid = isValidPhoneNumber('+1 (555) 123-4567');
const parsed = parsePhoneNumber('+91 98765 43210');
const formatted = formatIncompletePhoneNumber('5551234');
Architecture

Built for Performance.

Optimized loading strategy ensures minimal initial bundle size and fast page loads.

⚡ Lazy Loading

Country list and selector components load only when needed, keeping initial bundle small.

  • Minimal entry script loaded first
  • Full country list loads after mount
  • Selectors load only if multiCountry is true
  • Memoized components prevent re-renders

🎯 Smart Defaults

Works immediately with minimal list; full features available asynchronously.

  • Works instantly with default country
  • Async loading doesn't block UX
  • Flags load from CDN (configurable)
  • Code-splitting for optimal performance

For detailed build size analysis and performance metrics:

View Build Size Analysis →