# @finofo/react-international-phone

> **This is Finofo's fork of [`goveo/react-international-phone`](https://github.com/goveo/react-international-phone).** Published to npm as **`@finofo/react-international-phone`**. The original package is still actively maintained upstream; this fork exists for dependency control, publishing independence, and consumer-coupled patching for Finofo's web app.

🤙 International phone input component for React

![npm-version](https://img.shields.io/npm/v/@finofo/react-international-phone)
![install-size-badge](https://badgen.net/packagephobia/install/@finofo/react-international-phone)
![downloads](https://img.shields.io/npm/dt/@finofo/react-international-phone)

[Live demo: Storybook](https://react-international-phone-storybook.vercel.app) (upstream, same behavior)

![demo-gif](https://user-images.githubusercontent.com/25800848/215350455-0d362e64-d621-4856-a384-ab18d4a0d5fa.gif)

## Why the fork exists

The upstream `react-international-phone` package is maintained by Yurii Brusentsov and is an excellent component. We forked it because:

1. **Dependency staleness.** Upstream `v4.4.0` shipped with `typescript@4.9.4`, `eslint@7.32.0`, `storybook@7.4.1`, `jest@29`, an 18-month-old lockfile, and a long tail of open Dependabot CVE alerts on devDependencies. We needed a current, auditable dependency surface without waiting on upstream's release cadence. The fork is now on `typescript@5.9.3`, `eslint@10` (flat config), `storybook@10` (with `@storybook/addon-vitest`), `jest@30`, `stylelint@17`, `tsup@8`, and actively clears CVE alerts via pnpm overrides where upstream hasn't yet. See `CHANGELOG.finofo.md` for the per-version devDep delta.
2. **Publishing independence.** Upstream publishes via `semantic-release` triggered by push-to-`master`, tied to their npm account. We wanted a manual, OIDC-gated publish workflow tied to Finofo's npm account so we can cut releases on our own timeline.
3. **Consumer coupling.** `@finofo/react-international-phone` is consumed by our flagship product (`finofo-web-app`). Having our own fork lets us backport fixes and coordinate breaking changes with our consumer in the same day, rather than round-tripping through upstream PR review.

Upstream is **not abandoned**. We pull from them regularly (see `CHANGELOG.finofo.md` for sync history). The fork is a thin layer on top, not a divergent rewrite: the public API surface and behavior match upstream version-for-version.

### Fork timeline

- **Forked at:** upstream `v4.4.0`, commit [`1a7a040`](https://github.com/goveo/react-international-phone/commit/1a7a040). First Finofo publish: `@finofo/react-international-phone@4.4.0`.
- **Package scope changed to `@finofo/…`** so both packages can coexist in an npm install if needed and npm can clearly distinguish the fork.
- **Subsequent syncs** are recorded in [`CHANGELOG.finofo.md`](./CHANGELOG.finofo.md). Most recent upstream sync: upstream `v4.8.0` → `@finofo/react-international-phone@4.8.1`, picking up country-data updates (AR / BR / UAE / GCC / French DOM-TOM), the `allowMaskOverflow` prop, and `React.memo` perf work on `CountrySelector`.
- **Latest fork release: `4.8.2`** (2026-04-18) is a pure devDep + tooling sweep with zero source changes and zero runtime-affecting dist changes. Brought eslint, stylelint, jest, storybook, tsup, sass, and postcss to current majors; migrated eslint to flat config; cleared 8 of 10 open CVE alerts by removing unused tooling (`semantic-release`, `@storybook/preset-scss`) and adding `pnpm.overrides` for residual ReDoS transitives; added a post-build bundle-size regression guard. See `CHANGELOG.finofo.md` for the full per-PR breakdown.
- **Dependency modernization is ongoing** in parallel to feature syncs. See [`CLAUDE.md`](./CLAUDE.md) for the current state of dependency groups, ignore rules, and the reasoning.

### What's different from upstream

At the source level, very little. The differences are operational:

| Axis                        | Upstream                               | Finofo fork                                                                                       |
| --------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------- |
| npm package name            | `react-international-phone`            | `@finofo/react-international-phone`                                                               |
| Publish trigger             | `semantic-release` on push to `master` | Manual `workflow_dispatch` with OIDC trusted publishing                                           |
| Dependabot groups           | default / flat                         | Restructured around publish-impact; emitter toolchain pinned to consumer                          |
| Docs site                   | Vercel-hosted by upstream              | `packages/docs/` excluded from workspace; upstream continues to host                              |
| Version scheme              | Semver tracking feature releases       | `{upstream_version}` or `{upstream_version}.{finofo_patch}` to signal fork-level packaging deltas |
| Storybook integration demos | Chakra v1, MUI v5                      | Chakra v2, MUI v9, shadcn/ui (Tailwind v3), Ant v6                                                |
| Test runner                 | `@storybook/test-runner`               | Migrated to `@storybook/addon-vitest` (upstream's recommended path)                               |
| Lint toolchain              | `.eslintrc` (legacy), eslint@7         | `eslint.config.mjs` (flat config), eslint@10, typescript-eslint@8, stylelint@17                   |
| Build-size guard            | none                                   | `scripts/check-bundle-size.mjs` post-build; `tsup.config.ts` pinned to `target: 'es2020'`         |
| Public API                  | stable                                 | identical; we never add or remove exports without upstream doing so first                         |

## Features

- 😎 **Easy to integrate** — Just import and use, no initial setup. Integrate with any UI library via a headless hook.
- 🔍 **Country guessing** — Start typing and the component guesses the country and applies the format. Flags via [Twemoji](https://twemoji.twitter.com/).
- ✨ **Lightweight** — Small bundle, no third-party runtime dependencies.
- 🌈 **Easy to customize** — Props for styles and behavior.
- ⌨ **Caret position handling** — Typing mid-input, selection, deletion all feel natural.
- ✔️ **Validation** — Helper functions for validating entered phone numbers.

## Installation

```sh
$ npm install @finofo/react-international-phone
# or
$ pnpm add @finofo/react-international-phone
# or
$ yarn add @finofo/react-international-phone
```

## Basic usage

```tsx
import { useState } from 'react';
import { PhoneInput } from '@finofo/react-international-phone';
import '@finofo/react-international-phone/style.css';

const App = () => {
  const [phone, setPhone] = useState('');

  return (
    <div>
      <PhoneInput
        defaultCountry="ua"
        value={phone}
        onChange={(phone) => setPhone(phone)}
      />
    </div>
  );
};
```

## Documentation

The upstream [official documentation](https://react-international-phone-docs.vercel.app/) is the API reference. It's accurate for this fork version-for-version; only the package name in the install examples differs (`@finofo/react-international-phone` instead of `react-international-phone`).

Storybook integration demos (Chakra UI v2, Material UI 9, shadcn/ui, Ant Design 6) live under `src/stories/UiLibsExample/` and are visible in the storybook dev server (`pnpm storybook`).

## Migration

Version numbering tracks upstream. Upstream's migration guides apply unchanged:

- [Update from v3 to v4](https://react-international-phone-docs.vercel.app/docs/Migrations/migrate-to-v4)
- [Update from v2 to v3](https://react-international-phone-docs.vercel.app/docs/Migrations/migrate-to-v3)
- [Update from v1 to v2](https://react-international-phone-docs.vercel.app/docs/Migrations/migrate-to-v2)

Fork-specific release notes (dependency bumps, packaging changes, etc. that aren't in upstream) are in [`CHANGELOG.finofo.md`](./CHANGELOG.finofo.md).

## Working on the fork

If you're working on the fork (including AI assistants), [`CLAUDE.md`](./CLAUDE.md) has the operational context: consumer coupling, publish process, tarball-install verification, upstream sync workflow, and the reasoning behind the custom Dependabot setup.

This is an internal Finofo fork; we're not accepting outside contributions. For the upstream project, see [`goveo/react-international-phone`](https://github.com/goveo/react-international-phone).

## License

MIT. Same as upstream.
