Skip to content

DeSource-Labs/phone-mask

📱 Phone Mask

Always-fresh, extreme small & easy-to-use international phone masking with Google's libphonenumber data

npm version npm downloads bundle size code coverage SonarCloud license code wiki context7 docs

Quick StartPackagesFeaturesDemoContributing


🎯 Why Phone Mask?

🔄 Always Up-to-Date

Phone formats sync automatically from Google's libphonenumber — no stale data, no manual updates. Just upgrade and you're current with global dialing rules.

🪶 Lightest in Class

Real market comparison, segmented by ecosystem and measured for what developers actually ship. Snapshot: 2026-06-15 (Benchmark script, npm Registry API, Bundlephobia package page for independent reference).

Use Total gzip as the primary comparison column. Gzip is measured locally by this repository benchmark pipeline (isolated temp install + minified bundle build). Data overhead is additional phone-data gzip excluded from raw package gzip (e.g. required peer engines). Total gzip = Gzip + Data overhead. Packages without a phone data source are listed after data-backed packages; each bucket is sorted by Total gzip.

Core (TypeScript/JavaScript)

Package Last published Phone data source Data overhead Gzip Total gzip
@desource/phone-mask · Repo 2026-05-08 Included in package 0.0 KB 2.8 KB 2.8 KB
libphonenumber-js · Repo 2026-06-06 Included in package 0.0 KB 43.9 KB 43.9 KB
awesome-phonenumber · Repo 2026-02-18 Included in package 0.0 KB 74.7 KB 74.7 KB
google-libphonenumber · Repo 2026-01-19 Included in package 0.0 KB 115.1 KB 115.1 KB

Best choice in Core (TypeScript/JavaScript): @desource/phone-mask (2.8 KB).

React

Package Last published Phone data source Data overhead Gzip Total gzip
@desource/phone-mask-react · Repo 2026-05-08 @desource/phone-mask (dep) 0.0 KB 9.4 KB 9.4 KB
react-phone-input-2 · Repo 2022-07-01 Included in package 0.0 KB 17.1 KB 17.1 KB
mui-tel-input · Repo 2026-04-24 libphonenumber-js (dep) 0.0 KB 46.7 KB 46.7 KB
react-phone-number-input · Repo 2026-05-29 libphonenumber-js (dep) 0.0 KB 47.4 KB 47.4 KB
react-international-phone · Repo 2026-02-21 None 0.0 KB 9.4 KB 9.4 KB

Best choice in React: @desource/phone-mask-react (9.4 KB).

React ecosystem note: react-international-phone removed built-in validation in v3 and recommends adding google-libphonenumber separately (migration doc). Raw package gzip above does not include that optional validator overhead.

Vue

Package Last published Phone data source Data overhead Gzip Total gzip
@desource/phone-mask-vue · Repo 2026-05-08 @desource/phone-mask (dep) 0.0 KB 10.9 KB 10.9 KB
v-phone-input · Repo 2026-03-11 awesome-phonenumber (dep) 0.0 KB 15.4 KB 15.4 KB
vue-tel-input · Repo 2026-03-19 libphonenumber-js (peer: parsePhoneNumberFromString) 28.5 KB 10.3 KB 38.8 KB
vue-phone-number-input · Repo 2022-09-20 libphonenumber-js (dep) 0.0 KB 96.3 KB 96.3 KB

Best choice in Vue: @desource/phone-mask-vue (10.9 KB).

Svelte

Package Last published Phone data source Data overhead Gzip Total gzip
@desource/phone-mask-svelte · Repo 2026-05-08 @desource/phone-mask (dep) 0.0 KB 11.3 KB 11.3 KB
svelte-tel-input · Repo 2026-04-24 libphonenumber-js (dep) 0.0 KB 78.4 KB 78.4 KB

Best choice in Svelte: @desource/phone-mask-svelte (11.3 KB).

Nuxt

Package Last published Phone data source Data overhead Gzip Total gzip
@desource/phone-mask-nuxt · Repo 2026-05-08 @desource/phone-mask-vue (runtime: install) 10.6 KB 0.8 KB 11.4 KB

Best choice in Nuxt: @desource/phone-mask-nuxt (11.4 KB).

Nuxt ecosystem note: there are currently no widely adopted Nuxt-only phone input modules with stable npm + size signals comparable to React/Vue/Svelte peers; most Nuxt apps use Vue phone input packages directly.

🎨 Framework-Ready

Ready-made plugins for your stack:

  • Vue 3 — Component, composable, and directive
  • Nuxt — Auto-imported, SSR-compatible
  • React — Component & hook with modern React patterns
  • Svelte — Component, composable, action, and attachment for Svelte 5
  • TypeScript/Vanilla JS — Framework-agnostic core

📦 Packages

Package Version Description
@desource/phone-mask npm Core library — TypeScript/JS
@desource/phone-mask-react npm React component + hook
@desource/phone-mask-vue npm Vue 3 component + composable + directive
@desource/phone-mask-svelte npm Svelte 5 component + composable + action + attachment
@desource/phone-mask-nuxt npm Nuxt module

⚡ Quick Start

React

npm install @desource/phone-mask-react
import { useState } from 'react';
import { PhoneInput } from '@desource/phone-mask-react';
import '@desource/phone-mask-react/assets/lib.css';

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

  return <PhoneInput value={phone} onChange={setPhone} country="US" />;
}

Vue 3

npm install @desource/phone-mask-vue
<script setup>
import { ref } from 'vue';
import { PhoneInput } from '@desource/phone-mask-vue';
import '@desource/phone-mask-vue/assets/lib.css';

const phone = ref('');
</script>

<template>
  <PhoneInput v-model="phone" country="US" />
</template>

Svelte 5

npm install @desource/phone-mask-svelte
<script lang="ts">
  import { PhoneInput } from '@desource/phone-mask-svelte';
  import '@desource/phone-mask-svelte/assets/lib.css';

  let phone = $state('');
</script>

<PhoneInput bind:value={phone} country="US" />

Nuxt

npm install @desource/phone-mask-nuxt
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@desource/phone-mask-nuxt']
});
<script setup>
import { ref } from 'vue';

const phone = ref('');
</script>

<template>
  <PhoneInput v-model="phone" country="US" />
</template>

TypeScript/Vanilla JS

npm install @desource/phone-mask
import { MasksFullMapEn } from '@desource/phone-mask';
import { formatDigitsWithMap } from '@desource/phone-mask/kit';

const mask = MasksFullMapEn.US.mask[0]; // "###-###-####"
const formatted = formatDigitsWithMap(mask, '2025551234').display;
// Result: "202-555-1234"

✨ Features

  • 🌍 240+ countries with accurate dialing codes and formats
  • 🎭 Auto-formatting as you type with smart cursor positioning
  • 🔍 Country search with fuzzy matching and keyboard navigation
  • 🌐 Auto-detection via GeoIP and browser locale
  • 📋 Copy to clipboard with one click
  • Validation with visual feedback
  • 🎨 Themeable (light/dark) with custom styling
  • Accessible with ARIA labels and keyboard support
  • 📱 Mobile-optimized with proper input modes
  • 🌳 Tree-shakeable — only import what you use
  • 🔧 TypeScript — full type safety
  • 🧩 Directive mode for custom input styling

🎮 Demo

Live Demo →

Try the interactive playground with:

  • Real-time formatting preview
  • Country switching
  • Theme toggle
  • Code examples

📚 Documentation


🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Quick Contribution Flow

  1. Fork the repository
  2. Clone your fork: git clone https://github.com/YOUR_USERNAME/phone-mask.git
  3. Install dependencies: pnpm install
  4. Create a branch: git checkout -b feature/my-feature
  5. Make your changes
  6. Commit: git commit -m "feat: add awesome feature"
  7. Push: git push origin feature/my-feature
  8. Open a Pull Request

For package changes intended for release, add a changeset in your PR: pnpm changeset

Development

# Install dependencies
pnpm install

# Build all packages
pnpm build

# Run unit tests with coverage report
pnpm test:unit:coverage

# Start demo dev server
pnpm dev:prepare
pnpm dev:demo

# Generate fresh data from Google's library
pnpm gen

# Refresh README benchmark section (optional, if needed)
pnpm readme:benchmarks

# Lint & format code (if you made changes)
pnpm lint
pnpm lint:fix
pnpm format

🌟 Sponsors

Developed and maintained by DeSource Labs.

Created by Stefan Popov


📄 License

MIT © 2026 DeSource Labs


🔗 Links


Built with ❤️ by the DeSource Labs team