@jacksonavila/phone-lib
v2.0.10
Published
Librería JavaScript para input de teléfono con selector de país y banderas - Compatible con Vanilla JS y React
Maintainers
Readme
PhoneLib 📱
Modern JavaScript library to easily integrate a phone input with country selector, flags, and phone number validation. Compatible with Vanilla JavaScript and React.
Librería JavaScript moderna para integrar fácilmente un input de teléfono con selector de país, banderas y validación de números telefónicos. Compatible con Vanilla JavaScript y React.
✨ Features / Características
- ✅ Country dropdown / Dropdown de países showing name, ISO2 code, dial code, and flag
- ✅ Tel input / Input tipo tel with automatic formatting based on selected country
- ✅ Numbers only input / Input solo números - automatically filters non-numeric characters
- ✅ Phone number validation / Validación de números using
libphonenumber-js - ✅ Complete public API / API pública completa with methods to get number information
- ✅ Vanilla JavaScript and React support / Soporte para Vanilla JavaScript y React
- ✅ Two layouts available / Dos layouts disponibles: integrated and separated
- ✅ Customizable events and callbacks / Eventos y callbacks personalizables
- ✅ Full programmatic control / Control programático completo
- ✅ Automatic country detection / Detección automática de país
- ✅ Country filtering / Filtrado de países (include/exclude/disable)
- ✅ Readonly/disabled mode / Modo readonly/disabled
- ✅ Modern responsive CSS / Estilos CSS modernos y responsivos
- ✅ Improved accessibility / Accesibilidad mejorada (ARIA labels, keyboard navigation)
📦 Installation / Instalación
Option 1: npm / Opción 1: npm
npm install @jacksonavila/phone-libOption 2: CDN (No npm required) / Opción 2: CDN (Sin npm)
Use directly from CDN / Usar directamente desde CDN - see Using from CDN / Usar desde CDN section below / ver sección abajo.
Dependencies / Dependencias
# For React projects / Para proyectos React
npm install react react-dom
# libphonenumber-js is installed automatically
# libphonenumber-js se instala automáticamente🌐 Using from CDN / Usar desde CDN
You can use PhoneLib directly from CDN without npm / Puedes usar PhoneLib directamente desde CDN sin npm.
Method 1: Import Maps (Modern Browsers) / Método 1: Import Maps (Navegadores Modernos)
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jacksonavila/[email protected]/phone-lib.css">
</head>
<body>
<div id="phone-container"></div>
<script type="importmap">
{
"imports": {
"@jacksonavila/phone-lib": "https://cdn.jsdelivr.net/npm/@jacksonavila/[email protected]/phone-lib.js",
"libphonenumber-js": "https://esm.sh/[email protected]"
}
}
</script>
<script type="module">
import PhoneLib from '@jacksonavila/phone-lib';
const phoneLib = new PhoneLib('#phone-container', {
initialCountry: 'CO',
layout: 'integrated',
showDialCode: true
});
</script>
</body>
</html>CDN URLs / URLs de CDN:
- jsDelivr:
https://cdn.jsdelivr.net/npm/@jacksonavila/[email protected]/ - unpkg:
https://unpkg.com/@jacksonavila/[email protected]/
Method 2: Script Tag (All Browsers) / Método 2: Script Tag (Todos los Navegadores)
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jacksonavila/[email protected]/phone-lib.css">
</head>
<body>
<div id="phone-container"></div>
<script src="https://cdn.jsdelivr.net/npm/@jacksonavila/[email protected]/phone-lib.cdn.js"></script>
<script>
let phoneLib = null;
// Wait for PhoneLib to be ready / Esperar a que PhoneLib esté listo
document.addEventListener('phoneLibReady', () => {
phoneLib = new PhoneLib('#phone-container', {
initialCountry: 'CO',
layout: 'integrated',
showDialCode: true
});
});
// Handle errors / Manejar errores
document.addEventListener('phoneLibError', (e) => {
console.error('Error loading PhoneLib:', e.detail.error);
});
</script>
</body>
</html>⚠️ Important / Importante: You need an HTTP server / Necesitas un servidor HTTP (doesn't work with file:// / no funciona con file://)
📖 Complete CDN guide / Guía completa de CDN: See USO-SIN-NPM.md / Ver USO-SIN-NPM.md
🚀 Quick Start / Inicio Rápido
Vanilla JavaScript
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="node_modules/@jacksonavila/phone-lib/phone-lib.css">
</head>
<body>
<div id="phone-container"></div>
<script type="module">
import PhoneLib from '@jacksonavila/phone-lib';
const phoneLib = new PhoneLib('#phone-container', {
initialCountry: 'CO',
layout: 'integrated',
showDialCode: true
});
// Get number information / Obtener información del número
const info = phoneLib.getInfo();
console.log(info);
</script>
</body>
</html>React
import React from 'react';
import PhoneLibReact from '@jacksonavila/phone-lib/react';
import '@jacksonavila/phone-lib/css';
function App() {
return (
<PhoneLibReact
initialCountry="CO"
layout="integrated"
showDialCode={true}
/>
);
}
export default App;📖 Complete Usage Guide / Guía de Uso Completa
Vanilla JavaScript
Basic Example / Ejemplo Básico
import PhoneLib from '@jacksonavila/phone-lib';
import '@jacksonavila/phone-lib/css';
const phoneLib = new PhoneLib('#phone-container', {
initialCountry: 'CO',
initialPhoneNumber: '+573001234567', // Optional: set initial phone number / Opcional: establecer número inicial
preferredCountries: ['CO', 'US', 'ES'],
showHint: true,
layout: 'integrated',
showDialCode: true
});With Events and Callbacks / Con Eventos y Callbacks
import PhoneLib from '@jacksonavila/phone-lib';
import '@jacksonavila/phone-lib/css';
const phoneLib = new PhoneLib('#phone-container', {
initialCountry: 'CO',
// Callbacks
onCountryChange: (country, dialCode, countryName) => {
console.log('Country changed / País cambiado:', country, dialCode, countryName);
},
onPhoneChange: (phoneNumber, isValid, country) => {
console.log('Number / Número:', phoneNumber, 'Valid / Válido:', isValid);
if (isValid) {
const info = phoneLib.getInfo();
console.log('Complete info / Información completa:', info);
}
},
onValidationChange: (isValid, phoneNumber) => {
console.log('Validation / Validación:', isValid ? 'Valid / Válido' : 'Invalid / Inválido');
},
onFocus: () => console.log('Input focused / Input enfocado'),
onBlur: () => console.log('Input blurred / Input perdió foco')
});
// Listen to custom DOM events / Escuchar eventos DOM personalizados
document.getElementById('phone-container').addEventListener('phoneLib:countryChange', (e) => {
console.log('DOM event / Evento DOM:', e.detail);
});Programmatic Control / Control Programático
// Set values / Establecer valores
phoneLib.setCountry('ES');
phoneLib.setPhoneNumber('+34600123456');
phoneLib.setValue('US', '5551234567');
// Control state / Controlar estado
phoneLib.enable();
phoneLib.disable();
phoneLib.reset();
// Get information / Obtener información
const country = phoneLib.getCountry(); // 'CO'
const dialCode = phoneLib.getDialCode(); // '+57'
const raw = phoneLib.getRaw(); // '3001234567'
const e164 = phoneLib.getE164(); // '+573001234567'
const isValid = phoneLib.isValid(); // true/false
const info = phoneLib.getInfo(); // Complete object / Objeto completoForm Integration / Integración con Formularios
<form id="contact-form">
<div id="phone-container"></div>
<button type="submit">Submit / Enviar</button>
</form>
<script type="module">
import PhoneLib from '@jacksonavila/phone-lib';
import '@jacksonavila/phone-lib/css';
const phoneLib = new PhoneLib('#phone-container', {
initialCountry: 'CO',
validateOnInput: true
});
document.getElementById('contact-form').addEventListener('submit', (e) => {
e.preventDefault();
const phoneInfo = phoneLib.getInfo();
if (!phoneInfo.isValid) {
alert('Please enter a valid number / Por favor ingrese un número válido');
return;
}
// Send data / Enviar datos
const formData = {
phone: phoneInfo.e164,
country: phoneInfo.country,
// ... other fields / otros campos
};
console.log('Sending / Enviando:', formData);
});
</script>React
Basic Example / Ejemplo Básico
import React from 'react';
import PhoneLibReact from '@jacksonavila/phone-lib/react';
import '@jacksonavila/phone-lib/css';
function App() {
return (
<PhoneLibReact
initialCountry="CO"
layout="integrated"
showDialCode={true}
/>
);
}
export default App;With Ref and Methods / Con Ref y Métodos
import React, { useRef } from 'react';
import PhoneLibReact from '@jacksonavila/phone-lib/react';
import '@jacksonavila/phone-lib/css';
function App() {
const phoneLibRef = useRef(null);
const handleSubmit = () => {
const info = phoneLibRef.current.getInfo();
if (!info.isValid) {
alert('Invalid number / Número inválido');
return;
}
console.log('Send / Enviar:', info.e164);
};
return (
<div>
<PhoneLibReact
ref={phoneLibRef}
initialCountry="CO"
layout="integrated"
onPhoneChange={(phone, isValid) => {
console.log('Number / Número:', phone, 'Valid / Válido:', isValid);
}}
/>
<button onClick={handleSubmit}>Submit / Enviar</button>
</div>
);
}With React State / Con Estado de React
import React, { useState, useRef } from 'react';
import PhoneLibReact from '@jacksonavila/phone-lib/react';
import '@jacksonavila/phone-lib/css';
function PhoneForm() {
const phoneLibRef = useRef(null);
const [phoneData, setPhoneData] = useState(null);
const handleGetData = () => {
const info = phoneLibRef.current.getInfo();
setPhoneData(info);
};
return (
<div>
<PhoneLibReact
ref={phoneLibRef}
initialCountry="CO"
onPhoneChange={(phone, isValid) => {
if (isValid) {
const info = phoneLibRef.current.getInfo();
setPhoneData(info);
}
}}
/>
{phoneData && (
<div>
<p>Country / País: {phoneData.country}</p>
<p>Number / Número: {phoneData.e164}</p>
<p>Valid / Válido: {phoneData.isValid ? 'Yes / Sí' : 'No'}</p>
</div>
)}
</div>
);
}React Form Integration / Integración con Formularios React
import React, { useRef } from 'react';
import PhoneLibReact from '@jacksonavila/phone-lib/react';
import '@jacksonavila/phone-lib/css';
function ContactForm() {
const phoneLibRef = useRef(null);
const formRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
const phoneInfo = phoneLibRef.current.getInfo();
if (!phoneInfo.isValid) {
alert('Please enter a valid number / Por favor ingrese un número válido');
return;
}
const formData = {
name: formRef.current.name.value,
email: formRef.current.email.value,
phone: phoneInfo.e164,
country: phoneInfo.country
};
// Send data / Enviar datos
fetch('/api/contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
});
};
return (
<form ref={formRef} onSubmit={handleSubmit}>
<input name="name" placeholder="Name / Nombre" required />
<input name="email" type="email" placeholder="Email" required />
<PhoneLibReact
ref={phoneLibRef}
initialCountry="CO"
validateOnInput={true}
/>
<button type="submit">Submit / Enviar</button>
</form>
);
}With Initial Phone Number (React Forms) / Con Número Inicial (Formularios React)
Important / Importante: Use initialPhoneNumber to set an initial value and ensure the phone number persists when the parent component re-renders / Usa initialPhoneNumber para establecer un valor inicial y asegurar que el número persista cuando el componente padre se re-renderiza:
import React, { useState } from 'react';
import PhoneLibReact from '@jacksonavila/phone-lib/react';
import '@jacksonavila/phone-lib/css';
function EditContactForm({ contact }) {
const [name, setName] = useState(contact?.name || '');
const [email, setEmail] = useState(contact?.email || '');
return (
<form>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name / Nombre"
/>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
{/* The phone number value persists even when name/email change /
El valor del teléfono persiste incluso cuando cambian name/email */}
<PhoneLibReact
initialCountry={contact?.country || 'US'}
initialPhoneNumber={contact?.phone || null}
onPhoneChange={(phone, isValid) => {
console.log('Phone / Teléfono:', phone);
}}
/>
<button type="submit">Save / Guardar</button>
</form>
);
}💡 Why initialPhoneNumber is important / Por qué initialPhoneNumber es importante:
- Prevents data loss / Previene pérdida de datos: Without
initialPhoneNumber, the phone value can be lost when the parent component re-renders (e.g., when other form fields change) / SininitialPhoneNumber, el valor del teléfono puede perderse cuando el componente padre se re-renderiza (ej: cuando otros campos del formulario cambian) - Form editing / Edición de formularios: Essential when editing existing data - the phone number is preserved during re-renders / Esencial al editar datos existentes - el número de teléfono se preserva durante re-renders
- Controlled components / Componentes controlados: Works seamlessly with React's controlled component pattern / Funciona perfectamente con el patrón de componentes controlados de React
🎨 Available Layouts / Layouts Disponibles
Integrated Layout / Layout Integrado (Default)
The country selector and input are on the same line / El selector de país y el input están en la misma línea:
const phoneLib = new PhoneLib('#container', {
layout: 'integrated',
showDialCode: true // Shows +57 in button / Muestra +57 en el botón
});With code visible / Con código visible:
- Shows / Muestra:
[🇨🇴 +57 ▼] [300 123 4567]
Without code visible / Sin código visible:
const phoneLib = new PhoneLib('#container', {
layout: 'integrated',
showDialCode: false // Only shows flag / Solo muestra la bandera
});- Shows / Muestra:
[🇨🇴 ▼] [300 123 4567]
Separated Layout / Layout Separado
Fields are separated in a row / Los campos están separados en una fila:
const phoneLib = new PhoneLib('#container', {
layout: 'separated',
showDialCode: true // Shows separate "Code" field / Muestra campo "Código" separado
});With code visible / Con código visible:
- Shows / Muestra:
[Country / País: 🇨🇴 Colombia ▼] [Code / Código: +57] [Number / Número: 300 123 4567]
Without code visible / Sin código visible:
const phoneLib = new PhoneLib('#container', {
layout: 'separated',
showDialCode: false // Only shows Country and Number / Solo muestra País y Número
});- Shows / Muestra:
[Country / País: 🇨🇴 Colombia ▼] [Number / Número: 300 123 4567]
⚙️ Configuration Options / Opciones de Configuración
Basic Options / Opciones Básicas
{
initialCountry: 'CO', // Initial country / País inicial (ISO2)
initialPhoneNumber: '+573001234567', // Initial phone number (optional) / Número inicial (opcional)
preferredCountries: ['CO', 'US'], // Countries that appear first / Países que aparecen primero
showHint: true, // Show validation hint / Mostrar hint de validación
layout: 'integrated', // 'integrated' or 'separated' / 'integrated' o 'separated'
showDialCode: true // Show dial code / Mostrar código de marcación
}📝 Note about initialPhoneNumber / Nota sobre initialPhoneNumber:
- Vanilla JS: Use
initialPhoneNumberin the constructor options to set an initial phone number value / UsainitialPhoneNumberen las opciones del constructor para establecer un valor inicial del teléfono - React: Use the
initialPhoneNumberprop to set an initial value. This prop also ensures the phone number value persists when the parent component re-renders / Usa la propinitialPhoneNumberpara establecer un valor inicial. Esta prop también asegura que el valor del teléfono persista cuando el componente padre se re-renderiza - The value is preserved during re-renders, preventing data loss in React forms / El valor se preserva durante re-renders, previniendo pérdida de datos en formularios React
Advanced Options / Opciones Avanzadas
{
// Initial values / Valores iniciales
initialCountry: 'CO', // Initial country (ISO2) / País inicial (ISO2)
initialPhoneNumber: '+573001234567', // Initial phone number (optional) / Número inicial (opcional)
// In React: ensures value persists during re-renders /
// En React: asegura que el valor persista durante re-renders
// Detection and validation / Detección y validación
autoDetectCountry: true, // Auto-detect country / Detectar país automáticamente
validateOnInput: false, // Validate while typing / Validar mientras se escribe
// Country filtering / Filtrado de países
onlyCountries: ['CO', 'US', 'ES'], // Only these countries / Solo estos países
disabledCountries: ['CU', 'KP'], // Disable these / Deshabilitar estos
excludeCountries: ['XX'], // Exclude these / Excluir estos
// States / Estados
readonly: false, // Read-only mode / Modo solo lectura
disabled: false, // Disabled component / Componente deshabilitado
// Customization / Personalización
placeholder: 'Enter your number', // Custom placeholder / Placeholder personalizado
countryLabel: 'Country', // Label for selector / Label para selector
dialCodeLabel: 'Code', // Label for code / Label para código
phoneLabel: 'Phone number', // Label for number / Label para número
// Messages / Mensajes
messages: {
invalid: 'Invalid number',
valid: '✓ Valid number'
},
// Width control / Control de anchos
width: '500px', // Wrapper width / Ancho del wrapper
maxWidth: '100%', // Max width / Ancho máximo
dropdownWidth: '150px', // Country selector width (integrated) / Ancho selector (integrado)
inputWidth: '350px', // Phone input width (integrated) / Ancho input (integrado)
gridColumns: '3fr 1fr 4fr', // Grid columns (separated) / Columnas grid (separado)
countryWidth: '250px', // Country field width (separated) / Ancho campo país (separado)
dialCodeWidth: '100px', // Dial code width (separated) / Ancho código (separado)
phoneWidth: '350px', // Phone field width (separated) / Ancho campo teléfono (separado)
// Arrow icon / Icono de flecha
arrowIcon: null, // Custom arrow HTML (SVG, emoji, image) / HTML personalizado para flecha
// Styles / Estilos
customClasses: {
wrapper: 'my-class',
input: 'my-input'
},
customStyles: {
input: {
borderColor: '#4a90e2'
}
}
}Callbacks and Events / Callbacks y Eventos
{
onCountryChange: (country, dialCode, countryName) => {
// Country changed / País cambiado
},
onPhoneChange: (phoneNumber, isValid, country) => {
// Number changed / Número cambiado
},
onValidationChange: (isValid, phoneNumber) => {
// Validation changed / Validación cambiada
},
onFocus: () => {
// Input focused / Input enfocado
},
onBlur: () => {
// Input blurred / Input perdió foco
}
}📚 Public API
Reading Methods / Métodos de Lectura
getCountry()
Returns the ISO2 code of the selected country / Devuelve el código ISO2 del país seleccionado.
const country = phoneLib.getCountry(); // 'CO'getDialCode()
Returns the dial code of the selected country / Devuelve el código de marcación del país seleccionado.
const dialCode = phoneLib.getDialCode(); // '+57'getRaw()
Returns the entered number without formatting (digits only) / Devuelve el número ingresado sin formato (solo dígitos).
const raw = phoneLib.getRaw(); // '3001234567'getE164()
Returns the number in E.164 format / Devuelve el número en formato E.164.
const e164 = phoneLib.getE164(); // '+573001234567'isValid()
Returns true if the number is valid, false otherwise / Devuelve true si el número es válido, false en caso contrario.
const isValid = phoneLib.isValid(); // true o falseformatInternational()
Returns the number in international format / Devuelve el número en formato internacional.
const international = phoneLib.formatInternational(); // '+57 300 123 4567'formatNational()
Returns the number in national format / Devuelve el número en formato nacional.
const national = phoneLib.formatNational(); // '300 123 4567'formatRFC3966()
Returns the number in RFC3966 format / Devuelve el número en formato RFC3966.
const rfc3966 = phoneLib.formatRFC3966(); // 'tel:+57-300-123-4567'getNumberType()
Returns the number type (MOBILE, FIXED_LINE, etc.) / Devuelve el tipo de número (MOBILE, FIXED_LINE, etc.).
const type = phoneLib.getNumberType(); // 'MOBILE' o nullgetInfo()
Returns an object with all number information / Devuelve un objeto con toda la información del número.
const info = phoneLib.getInfo();
// {
// country: 'CO',
// dialCode: '+57',
// raw: '3001234567',
// e164: '+573001234567',
// international: '+57 300 123 4567',
// national: '300 123 4567',
// rfc3966: 'tel:+57-300-123-4567',
// isValid: true,
// type: 'MOBILE',
// countryName: 'Colombia'
// }getCountryMetadata()
Returns complete information about the selected country / Devuelve información completa del país seleccionado.
const metadata = phoneLib.getCountryMetadata();
// {
// iso2: 'CO',
// name: 'Colombia',
// dialCode: '+57',
// flag: '<img...>'
// }Control Methods / Métodos de Control
setCountry(iso2)
Sets the country programmatically / Establece el país programáticamente.
phoneLib.setCountry('ES');setPhoneNumber(number)
Sets the phone number programmatically / Establece el número telefónico programáticamente.
phoneLib.setPhoneNumber('+34600123456');setValue(country, number)
Sets both country and number / Establece país y número juntos.
phoneLib.setValue('ES', '600123456');enable() / disable()
Enables or disables the component / Habilita o deshabilita el componente.
phoneLib.enable();
phoneLib.disable();reset()
Resets the component to initial values / Resetea el componente a valores iniciales.
phoneLib.reset();destroy()
Destroys the instance and cleans up resources / Destruye la instancia y limpia recursos.
phoneLib.destroy();updateOptions(newOptions)
Updates options dynamically / Actualiza opciones dinámicamente.
phoneLib.updateOptions({
preferredCountries: ['CO', 'US', 'ES', 'MX']
});🎨 Custom Styling / Estilos Personalizados
With CSS Classes / Con Clases CSS
const phoneLib = new PhoneLib('#container', {
customClasses: {
wrapper: 'my-custom-class',
dropdownButton: 'my-custom-button',
input: 'my-custom-input'
}
});With Inline Styles / Con Estilos Inline
const phoneLib = new PhoneLib('#container', {
customStyles: {
dropdownButton: {
backgroundColor: '#4a90e2',
borderRadius: '20px',
color: 'white'
},
input: {
borderColor: '#4a90e2',
fontSize: '18px'
}
}
});Custom Arrow Icon / Icono de Flecha Personalizado
const phoneLib = new PhoneLib('#container', {
// Opción 1: SVG personalizado
arrowIcon: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
<path d="M3 4.5 L6 7.5 L9 4.5" stroke="#333" stroke-width="2" fill="none"/>
</svg>`,
// Opción 2: Emoji
arrowIcon: '▼',
// Opción 3: Imagen
arrowIcon: '<img src="arrow.png" alt="▼" style="width: 12px; height: 12px;">'
});Nota: Si no se especifica arrowIcon, se usa un chevron SVG por defecto.
Customizable Elements / Elementos Personalizables
wrapper- Main container / Contenedor principaldropdownButton- Country selector button / Botón del selector de paísinput- Phone input field / Campo de entrada de teléfonodialCodeInput- Dial code field (separated layout only) / Campo de código (solo layout separado)row- Grid row (separated layout only) / Fila del grid (solo layout separado)arrowIcon- Dropdown arrow icon / Icono de flecha del dropdown
🔧 Advanced Examples / Ejemplos Avanzados
Automatic Country Detection / Detección Automática de País
const phoneLib = new PhoneLib('#container', {
autoDetectCountry: true // Detects country when entering +34... / Detecta país al ingresar +34...
});
// User types / Usuario escribe: +34 600 123 456
// Automatically changes to Spain / Automáticamente cambia a EspañaCountry Filtering / Filtrado de Países
const phoneLib = new PhoneLib('#container', {
// Only show these countries / Solo mostrar estos países
onlyCountries: ['CO', 'US', 'ES', 'MX'],
// Disable these countries (appear but can't be selected) / Deshabilitar estos países
disabledCountries: ['CU', 'KP'],
// Exclude these countries (don't appear in list) / Excluir estos países
excludeCountries: ['XX']
});Real-time Validation / Validación en Tiempo Real
const phoneLib = new PhoneLib('#container', {
validateOnInput: true, // Validate while user types / Valida mientras el usuario escribe
onValidationChange: (isValid) => {
if (isValid) {
console.log('Valid number! / ¡Número válido!');
}
}
});Readonly/Disabled Mode / Modo Readonly/Disabled
// Read-only / Solo lectura
const phoneLib = new PhoneLib('#container', {
readonly: true
});
// Disabled / Deshabilitado
const phoneLib = new PhoneLib('#container', {
disabled: true
});📱 React Component Props
| Prop | Type | Default | Description / Descripción |
|------|------|---------|--------------------------|
| initialCountry | string | 'US' | Initial country (ISO2) / País inicial (ISO2) |
| initialPhoneNumber | string | null | null | Initial phone number value. Important: This prop ensures the phone value persists during parent component re-renders in React / Valor inicial del teléfono. Importante: Esta prop asegura que el valor del teléfono persista durante re-renders del componente padre en React |
| preferredCountries | array | [] | Preferred countries / Países preferidos |
| showHint | boolean | true | Show validation hint / Mostrar hint de validación |
| layout | string | 'integrated' | 'integrated' or 'separated' / 'integrated' o 'separated' |
| showDialCode | boolean | true | Show dial code / Mostrar código de marcación |
| autoDetectCountry | boolean | false | Auto-detect country / Detectar país automáticamente |
| validateOnInput | boolean | false | Validate while typing / Validar mientras se escribe |
| disabledCountries | array | [] | Disabled countries / Países deshabilitados |
| onlyCountries | array | [] | Only these countries / Solo estos países |
| excludeCountries | array | [] | Exclude these countries / Excluir estos países |
| readonly | boolean | false | Read-only mode / Modo solo lectura |
| disabled | boolean | false | Disabled component / Componente deshabilitado |
| placeholder | string | null | Custom placeholder / Placeholder personalizado |
| countryLabel | string | 'Country' / 'País' | Label for selector / Label para selector |
| dialCodeLabel | string | 'Code' / 'Código' | Label for code / Label para código |
| phoneLabel | string | 'Phone number' / 'Número de teléfono' | Label for number / Label para número |
| arrowIcon | string | null | Custom arrow HTML (SVG, emoji, image) / HTML personalizado para flecha |
| customClasses | object | {} | Custom CSS classes / Clases CSS personalizadas |
| customStyles | object | {} | Inline styles / Estilos inline personalizados |
| width | string | null | Wrapper width (e.g., '500px', '100%') / Ancho del wrapper |
| maxWidth | string | null | Max wrapper width / Ancho máximo del wrapper |
| dropdownWidth | string | null | Country selector width (integrated) / Ancho selector (integrado) |
| inputWidth | string | null | Phone input width (integrated) / Ancho input (integrado) |
| gridColumns | string | null | Grid columns (separated, e.g., '3fr 1fr 4fr') / Columnas grid (separado) |
| countryWidth | string | null | Country field width (separated) / Ancho campo país (separado) |
| dialCodeWidth | string | null | Dial code width (separated) / Ancho código (separado) |
| phoneWidth | string | null | Phone field width (separated) / Ancho campo teléfono (separado) |
| messages | object | {} | Custom messages / Mensajes personalizables |
| ariaLabels | object | {} | ARIA labels / Labels ARIA personalizables |
| onCountryChange | function | null | Callback when country changes / Callback cuando cambia el país |
| onPhoneChange | function | null | Callback when number changes / Callback cuando cambia el número |
| onValidationChange | function | null | Callback when validation changes / Callback cuando cambia la validación |
| onFocus | function | null | Callback when focused / Callback cuando se enfoca |
| onBlur | function | null | Callback when blurred / Callback cuando pierde foco |
🧪 Development and Testing / Desarrollo y Pruebas
Run Demos Locally / Ejecutar Demos Localmente
# Install dependencies / Instalar dependencias
npm install
# Start development server / Iniciar servidor de desarrollo
npm run serveThis will open http://localhost:3004 with all available demos / Esto abrirá http://localhost:3004 con todos los demos disponibles.
Demo Files / Archivos de Demo
demo.html- Basic integrated layout / Layout integrado básicodemo-separated.html- Separated layout / Layout separadodemo-all-layouts.html- All layouts comparison / Comparación de todos los layoutsdemo-features.html- All features / Todas las característicasdemo-react.html- React example / Ejemplo con Reactdemo-cdn-importmap.html- CDN with Import Maps / CDN con Import Mapsdemo-cdn-script.html- CDN with Script Tag / CDN con Script Tagdemo-widths.html- Width control examples / Ejemplos de control de anchos
📦 Package Structure / Estructura del Paquete
@jacksonavila/phone-lib/
├── phone-lib.js # Main code (Vanilla JS) / Código principal (Vanilla JS)
├── phone-lib.css # CSS styles / Estilos CSS
├── phone-lib-react.jsx # React component / Componente React
├── phone-lib-react.js # CommonJS/ESM React version / Versión CommonJS/ESM React
└── README.md # Documentation / DocumentaciónImport Paths / Rutas de Importación
// Main library (Vanilla JS) / Librería principal (Vanilla JS)
import PhoneLib from '@jacksonavila/phone-lib';
// React component / Componente React
import PhoneLibReact from '@jacksonavila/phone-lib/react';
// CSS styles / Estilos CSS
import '@jacksonavila/phone-lib/css';
// Or with full paths / O con rutas completas
import PhoneLib from '@jacksonavila/phone-lib/phone-lib.js';
import PhoneLibReact from '@jacksonavila/phone-lib/phone-lib-react.jsx';
import '@jacksonavila/phone-lib/phone-lib.css';🤝 Contributing / Contribuir
Contributions are welcome / Las contribuciones son bienvenidas. Please / Por favor:
- Fork the project / Haz fork del proyecto
- Create a feature branch / Crea una rama para tu feature (
git checkout -b feature/AmazingFeature) - Commit your changes / Commit tus cambios (
git commit -m 'Add some AmazingFeature') - Push to the branch / Push a la rama (
git push origin feature/AmazingFeature) - Open a Pull Request / Abre un Pull Request
📄 License / Licencia
This project is licensed under the MIT License / Este proyecto está bajo la Licencia MIT - see the LICENSE file for details / ver el archivo LICENSE para más detalles.
🙏 Acknowledgments / Agradecimientos
- libphonenumber-js - For phone number validation and formatting / Para validación y formato de números telefónicos
📞 Support / Soporte
If you have questions or find any issues / Si tienes preguntas o encuentras algún problema:
- Open an issue on GitHub
- Check the complete documentation / Consulta la documentación completa
- Review the examples / Revisa los ejemplos
Made with ❤️ for the developer community / Hecho con ❤️ para la comunidad de desarrolladores
