@jacksonavila/phone-lib 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +598 -211
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,274 +1,554 @@
|
|
|
1
1
|
# PhoneLib 📱
|
|
2
2
|
|
|
3
|
-
Librería JavaScript 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**.
|
|
3
|
+
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**.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@jacksonavila/phone-lib)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
- ✅ Input de tipo "tel" con formato automático según el país seleccionado
|
|
9
|
-
- ✅ Validación de números telefónicos usando `libphonenumber-js`
|
|
10
|
-
- ✅ API pública completa con métodos para obtener información del número
|
|
11
|
-
- ✅ Opciones de configuración flexibles
|
|
12
|
-
- ✅ Estilos CSS modernos y responsivos
|
|
13
|
-
- ✅ **Soporte para Vanilla JavaScript y React**
|
|
14
|
-
- ✅ Eventos y callbacks personalizables
|
|
15
|
-
- ✅ Control programático completo
|
|
16
|
-
- ✅ Detección automática de país
|
|
17
|
-
- ✅ Filtrado de países
|
|
18
|
-
- ✅ Modo readonly/disabled
|
|
8
|
+
## ✨ Características
|
|
19
9
|
|
|
20
|
-
|
|
10
|
+
- ✅ **Dropdown con países** mostrando nombre, código ISO2, código de marcación y bandera
|
|
11
|
+
- ✅ **Input de tipo "tel"** con formato automático según el país seleccionado
|
|
12
|
+
- ✅ **Validación de números** telefónicos usando `libphonenumber-js`
|
|
13
|
+
- ✅ **API pública completa** con métodos para obtener información del número
|
|
14
|
+
- ✅ **Soporte para Vanilla JavaScript y React**
|
|
15
|
+
- ✅ **Dos layouts disponibles**: integrado y separado
|
|
16
|
+
- ✅ **Eventos y callbacks** personalizables
|
|
17
|
+
- ✅ **Control programático** completo
|
|
18
|
+
- ✅ **Detección automática** de país
|
|
19
|
+
- ✅ **Filtrado de países** (incluir/excluir/deshabilitar)
|
|
20
|
+
- ✅ **Modo readonly/disabled**
|
|
21
|
+
- ✅ **Estilos CSS modernos** y responsivos
|
|
22
|
+
- ✅ **Accesibilidad** mejorada (ARIA labels, navegación por teclado)
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
## 📦 Instalación
|
|
23
25
|
|
|
24
26
|
```bash
|
|
25
27
|
npm install @jacksonavila/phone-lib
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
###
|
|
30
|
+
### Dependencias
|
|
29
31
|
|
|
30
32
|
```bash
|
|
31
|
-
|
|
33
|
+
# Para proyectos React
|
|
34
|
+
npm install react react-dom
|
|
35
|
+
|
|
36
|
+
# La dependencia libphonenumber-js se instala automáticamente
|
|
32
37
|
```
|
|
33
38
|
|
|
34
|
-
## 🚀
|
|
39
|
+
## 🚀 Inicio Rápido
|
|
35
40
|
|
|
36
|
-
###
|
|
41
|
+
### Vanilla JavaScript
|
|
37
42
|
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
```html
|
|
44
|
+
<!DOCTYPE html>
|
|
45
|
+
<html>
|
|
46
|
+
<head>
|
|
47
|
+
<link rel="stylesheet" href="node_modules/@jacksonavila/phone-lib/phone-lib.css">
|
|
48
|
+
</head>
|
|
49
|
+
<body>
|
|
50
|
+
<div id="phone-container"></div>
|
|
41
51
|
|
|
42
|
-
|
|
43
|
-
|
|
52
|
+
<script type="module">
|
|
53
|
+
import PhoneLib from '@jacksonavila/phone-lib';
|
|
54
|
+
|
|
55
|
+
const phoneLib = new PhoneLib('#phone-container', {
|
|
56
|
+
initialCountry: 'CO',
|
|
57
|
+
layout: 'integrated',
|
|
58
|
+
showDialCode: true
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Obtener información del número
|
|
62
|
+
const info = phoneLib.getInfo();
|
|
63
|
+
console.log(info);
|
|
64
|
+
</script>
|
|
65
|
+
</body>
|
|
66
|
+
</html>
|
|
44
67
|
```
|
|
45
68
|
|
|
46
|
-
|
|
69
|
+
### React
|
|
47
70
|
|
|
48
|
-
|
|
71
|
+
```jsx
|
|
72
|
+
import React from 'react';
|
|
73
|
+
import PhoneLibReact from '@jacksonavila/phone-lib/react';
|
|
74
|
+
import '@jacksonavila/phone-lib/css';
|
|
49
75
|
|
|
50
|
-
|
|
76
|
+
function App() {
|
|
77
|
+
return (
|
|
78
|
+
<PhoneLibReact
|
|
79
|
+
initialCountry="CO"
|
|
80
|
+
layout="integrated"
|
|
81
|
+
showDialCode={true}
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
51
85
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
- **`demo-all-layouts.html`** - Comparación de todos los layouts
|
|
55
|
-
- **`demo-features.html`** - Todas las nuevas características (eventos, control programático, etc.)
|
|
56
|
-
- **`demo-react.html`** - Ejemplo con React
|
|
86
|
+
export default App;
|
|
87
|
+
```
|
|
57
88
|
|
|
58
|
-
|
|
89
|
+
## 📖 Guía de Uso Completa
|
|
59
90
|
|
|
60
|
-
|
|
61
|
-
# Python 3
|
|
62
|
-
python -m http.server 8000
|
|
91
|
+
### Vanilla JavaScript
|
|
63
92
|
|
|
64
|
-
|
|
65
|
-
npx http-server . -p 8080 -o
|
|
93
|
+
#### Ejemplo Básico
|
|
66
94
|
|
|
67
|
-
|
|
68
|
-
|
|
95
|
+
```javascript
|
|
96
|
+
import PhoneLib from '@jacksonavila/phone-lib';
|
|
97
|
+
import '@jacksonavila/phone-lib/css';
|
|
98
|
+
|
|
99
|
+
const phoneLib = new PhoneLib('#phone-container', {
|
|
100
|
+
initialCountry: 'CO',
|
|
101
|
+
preferredCountries: ['CO', 'US', 'ES'],
|
|
102
|
+
showHint: true,
|
|
103
|
+
layout: 'integrated',
|
|
104
|
+
showDialCode: true
|
|
105
|
+
});
|
|
69
106
|
```
|
|
70
107
|
|
|
71
|
-
|
|
108
|
+
#### Con Eventos y Callbacks
|
|
72
109
|
|
|
73
|
-
|
|
110
|
+
```javascript
|
|
111
|
+
import PhoneLib from '@jacksonavila/phone-lib';
|
|
112
|
+
import '@jacksonavila/phone-lib/css';
|
|
74
113
|
|
|
75
|
-
|
|
114
|
+
const phoneLib = new PhoneLib('#phone-container', {
|
|
115
|
+
initialCountry: 'CO',
|
|
116
|
+
|
|
117
|
+
// Callbacks
|
|
118
|
+
onCountryChange: (country, dialCode, countryName) => {
|
|
119
|
+
console.log('País cambiado:', country, dialCode, countryName);
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
onPhoneChange: (phoneNumber, isValid, country) => {
|
|
123
|
+
console.log('Número:', phoneNumber, 'Válido:', isValid);
|
|
124
|
+
if (isValid) {
|
|
125
|
+
const info = phoneLib.getInfo();
|
|
126
|
+
console.log('Información completa:', info);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
onValidationChange: (isValid, phoneNumber) => {
|
|
131
|
+
console.log('Validación:', isValid ? 'Válido' : 'Inválido');
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
onFocus: () => console.log('Input enfocado'),
|
|
135
|
+
onBlur: () => console.log('Input perdió foco')
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Escuchar eventos DOM personalizados
|
|
139
|
+
document.getElementById('phone-container').addEventListener('phoneLib:countryChange', (e) => {
|
|
140
|
+
console.log('Evento DOM:', e.detail);
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### Control Programático
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
// Establecer valores
|
|
148
|
+
phoneLib.setCountry('ES');
|
|
149
|
+
phoneLib.setPhoneNumber('+34600123456');
|
|
150
|
+
phoneLib.setValue('US', '5551234567');
|
|
151
|
+
|
|
152
|
+
// Controlar estado
|
|
153
|
+
phoneLib.enable();
|
|
154
|
+
phoneLib.disable();
|
|
155
|
+
phoneLib.reset();
|
|
156
|
+
|
|
157
|
+
// Obtener información
|
|
158
|
+
const country = phoneLib.getCountry(); // 'CO'
|
|
159
|
+
const dialCode = phoneLib.getDialCode(); // '+57'
|
|
160
|
+
const raw = phoneLib.getRaw(); // '3001234567'
|
|
161
|
+
const e164 = phoneLib.getE164(); // '+573001234567'
|
|
162
|
+
const isValid = phoneLib.isValid(); // true/false
|
|
163
|
+
const info = phoneLib.getInfo(); // Objeto completo
|
|
164
|
+
```
|
|
76
165
|
|
|
77
|
-
|
|
166
|
+
#### Integración con Formularios
|
|
78
167
|
|
|
79
168
|
```html
|
|
80
|
-
|
|
81
|
-
<html>
|
|
82
|
-
<head>
|
|
83
|
-
<link rel="stylesheet" href="phone-lib.css">
|
|
84
|
-
</head>
|
|
85
|
-
<body>
|
|
169
|
+
<form id="contact-form">
|
|
86
170
|
<div id="phone-container"></div>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
171
|
+
<button type="submit">Enviar</button>
|
|
172
|
+
</form>
|
|
173
|
+
|
|
174
|
+
<script type="module">
|
|
175
|
+
import PhoneLib from '@jacksonavila/phone-lib';
|
|
176
|
+
import '@jacksonavila/phone-lib/css';
|
|
177
|
+
|
|
178
|
+
const phoneLib = new PhoneLib('#phone-container', {
|
|
179
|
+
initialCountry: 'CO',
|
|
180
|
+
validateOnInput: true
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
document.getElementById('contact-form').addEventListener('submit', (e) => {
|
|
184
|
+
e.preventDefault();
|
|
90
185
|
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
186
|
+
const phoneInfo = phoneLib.getInfo();
|
|
187
|
+
|
|
188
|
+
if (!phoneInfo.isValid) {
|
|
189
|
+
alert('Por favor ingrese un número válido');
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Enviar datos
|
|
194
|
+
const formData = {
|
|
195
|
+
phone: phoneInfo.e164,
|
|
196
|
+
country: phoneInfo.country,
|
|
197
|
+
// ... otros campos
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
console.log('Enviando:', formData);
|
|
201
|
+
});
|
|
202
|
+
</script>
|
|
99
203
|
```
|
|
100
204
|
|
|
101
|
-
###
|
|
205
|
+
### React
|
|
102
206
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
207
|
+
#### Ejemplo Básico
|
|
208
|
+
|
|
209
|
+
```jsx
|
|
210
|
+
import React from 'react';
|
|
211
|
+
import PhoneLibReact from '@jacksonavila/phone-lib/react';
|
|
212
|
+
import '@jacksonavila/phone-lib/css';
|
|
213
|
+
|
|
214
|
+
function App() {
|
|
215
|
+
return (
|
|
216
|
+
<PhoneLibReact
|
|
217
|
+
initialCountry="CO"
|
|
218
|
+
layout="integrated"
|
|
219
|
+
showDialCode={true}
|
|
220
|
+
/>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export default App;
|
|
111
225
|
```
|
|
112
226
|
|
|
113
|
-
|
|
227
|
+
#### Con Ref y Métodos
|
|
228
|
+
|
|
229
|
+
```jsx
|
|
230
|
+
import React, { useRef } from 'react';
|
|
231
|
+
import PhoneLibReact from '@jacksonavila/phone-lib/react';
|
|
232
|
+
import '@jacksonavila/phone-lib/css';
|
|
233
|
+
|
|
234
|
+
function App() {
|
|
235
|
+
const phoneLibRef = useRef(null);
|
|
236
|
+
|
|
237
|
+
const handleSubmit = () => {
|
|
238
|
+
const info = phoneLibRef.current.getInfo();
|
|
239
|
+
|
|
240
|
+
if (!info.isValid) {
|
|
241
|
+
alert('Número inválido');
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
console.log('Enviar:', info.e164);
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
return (
|
|
249
|
+
<div>
|
|
250
|
+
<PhoneLibReact
|
|
251
|
+
ref={phoneLibRef}
|
|
252
|
+
initialCountry="CO"
|
|
253
|
+
layout="integrated"
|
|
254
|
+
onPhoneChange={(phone, isValid) => {
|
|
255
|
+
console.log('Número:', phone, 'Válido:', isValid);
|
|
256
|
+
}}
|
|
257
|
+
/>
|
|
258
|
+
<button onClick={handleSubmit}>Enviar</button>
|
|
259
|
+
</div>
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Con Estado de React
|
|
265
|
+
|
|
266
|
+
```jsx
|
|
267
|
+
import React, { useState, useRef } from 'react';
|
|
268
|
+
import PhoneLibReact from '@jacksonavila/phone-lib/react';
|
|
269
|
+
import '@jacksonavila/phone-lib/css';
|
|
270
|
+
|
|
271
|
+
function PhoneForm() {
|
|
272
|
+
const phoneLibRef = useRef(null);
|
|
273
|
+
const [phoneData, setPhoneData] = useState(null);
|
|
274
|
+
|
|
275
|
+
const handleGetData = () => {
|
|
276
|
+
const info = phoneLibRef.current.getInfo();
|
|
277
|
+
setPhoneData(info);
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
return (
|
|
281
|
+
<div>
|
|
282
|
+
<PhoneLibReact
|
|
283
|
+
ref={phoneLibRef}
|
|
284
|
+
initialCountry="CO"
|
|
285
|
+
onPhoneChange={(phone, isValid) => {
|
|
286
|
+
if (isValid) {
|
|
287
|
+
const info = phoneLibRef.current.getInfo();
|
|
288
|
+
setPhoneData(info);
|
|
289
|
+
}
|
|
290
|
+
}}
|
|
291
|
+
/>
|
|
292
|
+
|
|
293
|
+
{phoneData && (
|
|
294
|
+
<div>
|
|
295
|
+
<p>País: {phoneData.country}</p>
|
|
296
|
+
<p>Número: {phoneData.e164}</p>
|
|
297
|
+
<p>Válido: {phoneData.isValid ? 'Sí' : 'No'}</p>
|
|
298
|
+
</div>
|
|
299
|
+
)}
|
|
300
|
+
</div>
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### Integración con Formularios React
|
|
306
|
+
|
|
307
|
+
```jsx
|
|
308
|
+
import React, { useRef } from 'react';
|
|
309
|
+
import PhoneLibReact from '@jacksonavila/phone-lib/react';
|
|
310
|
+
import '@jacksonavila/phone-lib/css';
|
|
311
|
+
|
|
312
|
+
function ContactForm() {
|
|
313
|
+
const phoneLibRef = useRef(null);
|
|
314
|
+
const formRef = useRef(null);
|
|
315
|
+
|
|
316
|
+
const handleSubmit = (e) => {
|
|
317
|
+
e.preventDefault();
|
|
318
|
+
|
|
319
|
+
const phoneInfo = phoneLibRef.current.getInfo();
|
|
320
|
+
|
|
321
|
+
if (!phoneInfo.isValid) {
|
|
322
|
+
alert('Por favor ingrese un número válido');
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const formData = {
|
|
327
|
+
name: formRef.current.name.value,
|
|
328
|
+
email: formRef.current.email.value,
|
|
329
|
+
phone: phoneInfo.e164,
|
|
330
|
+
country: phoneInfo.country
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
// Enviar datos
|
|
334
|
+
fetch('/api/contact', {
|
|
335
|
+
method: 'POST',
|
|
336
|
+
headers: { 'Content-Type': 'application/json' },
|
|
337
|
+
body: JSON.stringify(formData)
|
|
338
|
+
});
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
return (
|
|
342
|
+
<form ref={formRef} onSubmit={handleSubmit}>
|
|
343
|
+
<input name="name" placeholder="Nombre" required />
|
|
344
|
+
<input name="email" type="email" placeholder="Email" required />
|
|
345
|
+
|
|
346
|
+
<PhoneLibReact
|
|
347
|
+
ref={phoneLibRef}
|
|
348
|
+
initialCountry="CO"
|
|
349
|
+
validateOnInput={true}
|
|
350
|
+
/>
|
|
351
|
+
|
|
352
|
+
<button type="submit">Enviar</button>
|
|
353
|
+
</form>
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## 🎨 Layouts Disponibles
|
|
359
|
+
|
|
360
|
+
### Layout Integrado (Default)
|
|
361
|
+
|
|
362
|
+
El selector de país y el input están en la misma línea:
|
|
114
363
|
|
|
115
|
-
**Layout Integrado con código:**
|
|
116
364
|
```javascript
|
|
117
|
-
const phoneLib = new PhoneLib('#
|
|
365
|
+
const phoneLib = new PhoneLib('#container', {
|
|
118
366
|
layout: 'integrated',
|
|
119
367
|
showDialCode: true // Muestra +57 en el botón
|
|
120
368
|
});
|
|
121
369
|
```
|
|
122
370
|
|
|
123
|
-
**
|
|
371
|
+
**Con código visible:**
|
|
372
|
+
- Muestra: `[🇨🇴 +57 ▼] [300 123 4567]`
|
|
373
|
+
|
|
374
|
+
**Sin código visible:**
|
|
124
375
|
```javascript
|
|
125
|
-
const phoneLib = new PhoneLib('#
|
|
376
|
+
const phoneLib = new PhoneLib('#container', {
|
|
126
377
|
layout: 'integrated',
|
|
127
378
|
showDialCode: false // Solo muestra la bandera
|
|
128
379
|
});
|
|
129
380
|
```
|
|
381
|
+
- Muestra: `[🇨🇴 ▼] [300 123 4567]`
|
|
382
|
+
|
|
383
|
+
### Layout Separado
|
|
384
|
+
|
|
385
|
+
Los campos están separados en una fila:
|
|
130
386
|
|
|
131
|
-
**Layout Separado con código:**
|
|
132
387
|
```javascript
|
|
133
|
-
const phoneLib = new PhoneLib('#
|
|
388
|
+
const phoneLib = new PhoneLib('#container', {
|
|
134
389
|
layout: 'separated',
|
|
135
390
|
showDialCode: true // Muestra campo "Código" separado
|
|
136
391
|
});
|
|
137
392
|
```
|
|
138
393
|
|
|
139
|
-
**
|
|
394
|
+
**Con código visible:**
|
|
395
|
+
- Muestra: `[País: 🇨🇴 Colombia ▼] [Código: +57] [Número: 300 123 4567]`
|
|
396
|
+
|
|
397
|
+
**Sin código visible:**
|
|
140
398
|
```javascript
|
|
141
|
-
const phoneLib = new PhoneLib('#
|
|
399
|
+
const phoneLib = new PhoneLib('#container', {
|
|
142
400
|
layout: 'separated',
|
|
143
401
|
showDialCode: false // Solo muestra País y Número
|
|
144
402
|
});
|
|
145
403
|
```
|
|
404
|
+
- Muestra: `[País: 🇨🇴 Colombia ▼] [Número: 300 123 4567]`
|
|
146
405
|
|
|
147
|
-
|
|
406
|
+
## ⚙️ Opciones de Configuración
|
|
148
407
|
|
|
149
|
-
|
|
408
|
+
### Opciones Básicas
|
|
150
409
|
|
|
151
|
-
**Con clases CSS personalizadas:**
|
|
152
410
|
```javascript
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
});
|
|
411
|
+
{
|
|
412
|
+
initialCountry: 'CO', // País inicial (ISO2)
|
|
413
|
+
preferredCountries: ['CO', 'US'], // Países que aparecen primero
|
|
414
|
+
showHint: true, // Mostrar hint de validación
|
|
415
|
+
layout: 'integrated', // 'integrated' o 'separated'
|
|
416
|
+
showDialCode: true // Mostrar código de marcación
|
|
417
|
+
}
|
|
161
418
|
```
|
|
162
419
|
|
|
163
|
-
|
|
420
|
+
### Opciones Avanzadas
|
|
421
|
+
|
|
164
422
|
```javascript
|
|
165
|
-
|
|
166
|
-
|
|
423
|
+
{
|
|
424
|
+
// Detección y validación
|
|
425
|
+
autoDetectCountry: true, // Detectar país automáticamente
|
|
426
|
+
validateOnInput: false, // Validar mientras se escribe
|
|
427
|
+
|
|
428
|
+
// Filtrado de países
|
|
429
|
+
onlyCountries: ['CO', 'US', 'ES'], // Solo estos países
|
|
430
|
+
disabledCountries: ['CU', 'KP'], // Deshabilitar estos
|
|
431
|
+
excludeCountries: ['XX'], // Excluir estos
|
|
432
|
+
|
|
433
|
+
// Estados
|
|
434
|
+
readonly: false, // Modo solo lectura
|
|
435
|
+
disabled: false, // Componente deshabilitado
|
|
436
|
+
|
|
437
|
+
// Personalización
|
|
438
|
+
placeholder: 'Ingrese su número', // Placeholder personalizado
|
|
439
|
+
countryLabel: 'País', // Label para selector
|
|
440
|
+
dialCodeLabel: 'Código', // Label para código
|
|
441
|
+
phoneLabel: 'Número de teléfono', // Label para número
|
|
442
|
+
|
|
443
|
+
// Mensajes
|
|
444
|
+
messages: {
|
|
445
|
+
invalid: 'Número inválido',
|
|
446
|
+
valid: '✓ Número válido'
|
|
447
|
+
},
|
|
448
|
+
|
|
449
|
+
// Estilos
|
|
450
|
+
customClasses: {
|
|
451
|
+
wrapper: 'mi-clase',
|
|
452
|
+
input: 'mi-input'
|
|
453
|
+
},
|
|
167
454
|
customStyles: {
|
|
168
|
-
dropdownButton: {
|
|
169
|
-
backgroundColor: '#4a90e2',
|
|
170
|
-
borderRadius: '20px',
|
|
171
|
-
color: 'white'
|
|
172
|
-
},
|
|
173
455
|
input: {
|
|
174
|
-
borderColor: '#4a90e2'
|
|
175
|
-
fontSize: '18px'
|
|
456
|
+
borderColor: '#4a90e2'
|
|
176
457
|
}
|
|
177
458
|
}
|
|
178
|
-
}
|
|
459
|
+
}
|
|
179
460
|
```
|
|
180
461
|
|
|
181
|
-
|
|
462
|
+
### Callbacks y Eventos
|
|
463
|
+
|
|
182
464
|
```javascript
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
wrapper: 'mi-tema-personalizado'
|
|
465
|
+
{
|
|
466
|
+
onCountryChange: (country, dialCode, countryName) => {
|
|
467
|
+
// País cambiado
|
|
187
468
|
},
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
469
|
+
onPhoneChange: (phoneNumber, isValid, country) => {
|
|
470
|
+
// Número cambiado
|
|
471
|
+
},
|
|
472
|
+
onValidationChange: (isValid, phoneNumber) => {
|
|
473
|
+
// Validación cambiada
|
|
474
|
+
},
|
|
475
|
+
onFocus: () => {
|
|
476
|
+
// Input enfocado
|
|
477
|
+
},
|
|
478
|
+
onBlur: () => {
|
|
479
|
+
// Input perdió foco
|
|
195
480
|
}
|
|
196
|
-
}
|
|
481
|
+
}
|
|
197
482
|
```
|
|
198
483
|
|
|
199
|
-
|
|
200
|
-
- `wrapper` - Contenedor principal
|
|
201
|
-
- `dropdownButton` - Botón del selector de país
|
|
202
|
-
- `input` - Campo de entrada de teléfono
|
|
203
|
-
- `dialCodeInput` - Campo de código (solo layout separado)
|
|
204
|
-
- `row` - Fila del grid (solo layout separado)
|
|
484
|
+
## 📚 API Pública
|
|
205
485
|
|
|
206
|
-
|
|
486
|
+
### Métodos de Lectura
|
|
207
487
|
|
|
208
|
-
|
|
488
|
+
#### `getCountry()`
|
|
209
489
|
Devuelve el código ISO2 del país seleccionado.
|
|
210
490
|
|
|
211
491
|
```javascript
|
|
212
492
|
const country = phoneLib.getCountry(); // 'CO'
|
|
213
493
|
```
|
|
214
494
|
|
|
215
|
-
|
|
495
|
+
#### `getDialCode()`
|
|
216
496
|
Devuelve el código de marcación del país seleccionado.
|
|
217
497
|
|
|
218
498
|
```javascript
|
|
219
499
|
const dialCode = phoneLib.getDialCode(); // '+57'
|
|
220
500
|
```
|
|
221
501
|
|
|
222
|
-
|
|
223
|
-
Devuelve el número ingresado sin formato.
|
|
502
|
+
#### `getRaw()`
|
|
503
|
+
Devuelve el número ingresado sin formato (solo dígitos).
|
|
224
504
|
|
|
225
505
|
```javascript
|
|
226
506
|
const raw = phoneLib.getRaw(); // '3001234567'
|
|
227
507
|
```
|
|
228
508
|
|
|
229
|
-
|
|
509
|
+
#### `getE164()`
|
|
230
510
|
Devuelve el número en formato E.164.
|
|
231
511
|
|
|
232
512
|
```javascript
|
|
233
513
|
const e164 = phoneLib.getE164(); // '+573001234567'
|
|
234
514
|
```
|
|
235
515
|
|
|
236
|
-
|
|
516
|
+
#### `isValid()`
|
|
237
517
|
Devuelve `true` si el número es válido, `false` en caso contrario.
|
|
238
518
|
|
|
239
519
|
```javascript
|
|
240
520
|
const isValid = phoneLib.isValid(); // true o false
|
|
241
521
|
```
|
|
242
522
|
|
|
243
|
-
|
|
523
|
+
#### `formatInternational()`
|
|
244
524
|
Devuelve el número en formato internacional.
|
|
245
525
|
|
|
246
526
|
```javascript
|
|
247
527
|
const international = phoneLib.formatInternational(); // '+57 300 123 4567'
|
|
248
528
|
```
|
|
249
529
|
|
|
250
|
-
|
|
530
|
+
#### `formatNational()`
|
|
251
531
|
Devuelve el número en formato nacional.
|
|
252
532
|
|
|
253
533
|
```javascript
|
|
254
534
|
const national = phoneLib.formatNational(); // '300 123 4567'
|
|
255
535
|
```
|
|
256
536
|
|
|
257
|
-
|
|
537
|
+
#### `formatRFC3966()`
|
|
258
538
|
Devuelve el número en formato RFC3966.
|
|
259
539
|
|
|
260
540
|
```javascript
|
|
261
541
|
const rfc3966 = phoneLib.formatRFC3966(); // 'tel:+57-300-123-4567'
|
|
262
542
|
```
|
|
263
543
|
|
|
264
|
-
|
|
544
|
+
#### `getNumberType()`
|
|
265
545
|
Devuelve el tipo de número (MOBILE, FIXED_LINE, etc.).
|
|
266
546
|
|
|
267
547
|
```javascript
|
|
268
548
|
const type = phoneLib.getNumberType(); // 'MOBILE' o null
|
|
269
549
|
```
|
|
270
550
|
|
|
271
|
-
|
|
551
|
+
#### `getInfo()`
|
|
272
552
|
Devuelve un objeto con toda la información del número.
|
|
273
553
|
|
|
274
554
|
```javascript
|
|
@@ -287,7 +567,7 @@ const info = phoneLib.getInfo();
|
|
|
287
567
|
// }
|
|
288
568
|
```
|
|
289
569
|
|
|
290
|
-
|
|
570
|
+
#### `getCountryMetadata()`
|
|
291
571
|
Devuelve información completa del país seleccionado.
|
|
292
572
|
|
|
293
573
|
```javascript
|
|
@@ -300,28 +580,30 @@ const metadata = phoneLib.getCountryMetadata();
|
|
|
300
580
|
// }
|
|
301
581
|
```
|
|
302
582
|
|
|
303
|
-
###
|
|
583
|
+
### Métodos de Control
|
|
584
|
+
|
|
585
|
+
#### `setCountry(iso2)`
|
|
304
586
|
Establece el país programáticamente.
|
|
305
587
|
|
|
306
588
|
```javascript
|
|
307
589
|
phoneLib.setCountry('ES');
|
|
308
590
|
```
|
|
309
591
|
|
|
310
|
-
|
|
592
|
+
#### `setPhoneNumber(number)`
|
|
311
593
|
Establece el número telefónico programáticamente.
|
|
312
594
|
|
|
313
595
|
```javascript
|
|
314
596
|
phoneLib.setPhoneNumber('+34600123456');
|
|
315
597
|
```
|
|
316
598
|
|
|
317
|
-
|
|
599
|
+
#### `setValue(country, number)`
|
|
318
600
|
Establece país y número juntos.
|
|
319
601
|
|
|
320
602
|
```javascript
|
|
321
603
|
phoneLib.setValue('ES', '600123456');
|
|
322
604
|
```
|
|
323
605
|
|
|
324
|
-
|
|
606
|
+
#### `enable()` / `disable()`
|
|
325
607
|
Habilita o deshabilita el componente.
|
|
326
608
|
|
|
327
609
|
```javascript
|
|
@@ -329,21 +611,21 @@ phoneLib.enable();
|
|
|
329
611
|
phoneLib.disable();
|
|
330
612
|
```
|
|
331
613
|
|
|
332
|
-
|
|
614
|
+
#### `reset()`
|
|
333
615
|
Resetea el componente a valores iniciales.
|
|
334
616
|
|
|
335
617
|
```javascript
|
|
336
618
|
phoneLib.reset();
|
|
337
619
|
```
|
|
338
620
|
|
|
339
|
-
|
|
621
|
+
#### `destroy()`
|
|
340
622
|
Destruye la instancia y limpia recursos.
|
|
341
623
|
|
|
342
624
|
```javascript
|
|
343
625
|
phoneLib.destroy();
|
|
344
626
|
```
|
|
345
627
|
|
|
346
|
-
|
|
628
|
+
#### `updateOptions(newOptions)`
|
|
347
629
|
Actualiza opciones dinámicamente.
|
|
348
630
|
|
|
349
631
|
```javascript
|
|
@@ -352,104 +634,209 @@ phoneLib.updateOptions({
|
|
|
352
634
|
});
|
|
353
635
|
```
|
|
354
636
|
|
|
355
|
-
##
|
|
356
|
-
|
|
357
|
-
### Vanilla JavaScript
|
|
358
|
-
- `demo.html` - Layout integrado con código
|
|
359
|
-
- `demo-separated.html` - Layout separado con código
|
|
360
|
-
- `demo-all-layouts.html` - Comparación de todos los layouts disponibles
|
|
361
|
-
- `demo-features.html` - Demostración de todas las nuevas características
|
|
362
|
-
|
|
363
|
-
### React
|
|
364
|
-
- `demo-react.html` - Ejemplo básico con React (usando Babel Standalone para demo)
|
|
365
|
-
- `phone-lib-react.jsx` - Componente React completo para usar en tu proyecto
|
|
366
|
-
|
|
367
|
-
Ver estos archivos para ejemplos completos de integración con actualización en tiempo real de la información del número.
|
|
637
|
+
## 🎨 Estilos Personalizados
|
|
368
638
|
|
|
369
|
-
|
|
639
|
+
### Con Clases CSS
|
|
370
640
|
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
├── demo-all-layouts.html # Comparación de layouts
|
|
380
|
-
├── demo-features.html # Nuevas características
|
|
381
|
-
├── demo-react.html # Ejemplo React (demo)
|
|
382
|
-
├── package.json # Dependencias
|
|
383
|
-
└── README.md # Documentación
|
|
641
|
+
```javascript
|
|
642
|
+
const phoneLib = new PhoneLib('#container', {
|
|
643
|
+
customClasses: {
|
|
644
|
+
wrapper: 'mi-clase-personalizada',
|
|
645
|
+
dropdownButton: 'mi-boton-personalizado',
|
|
646
|
+
input: 'mi-input-personalizado'
|
|
647
|
+
}
|
|
648
|
+
});
|
|
384
649
|
```
|
|
385
650
|
|
|
386
|
-
|
|
651
|
+
### Con Estilos Inline
|
|
387
652
|
|
|
388
|
-
### Eventos y Callbacks
|
|
389
653
|
```javascript
|
|
390
|
-
const phoneLib = new PhoneLib('#
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
654
|
+
const phoneLib = new PhoneLib('#container', {
|
|
655
|
+
customStyles: {
|
|
656
|
+
dropdownButton: {
|
|
657
|
+
backgroundColor: '#4a90e2',
|
|
658
|
+
borderRadius: '20px',
|
|
659
|
+
color: 'white'
|
|
660
|
+
},
|
|
661
|
+
input: {
|
|
662
|
+
borderColor: '#4a90e2',
|
|
663
|
+
fontSize: '18px'
|
|
664
|
+
}
|
|
665
|
+
}
|
|
402
666
|
});
|
|
403
667
|
```
|
|
404
668
|
|
|
405
|
-
###
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
```
|
|
669
|
+
### Elementos Personalizables
|
|
670
|
+
|
|
671
|
+
- `wrapper` - Contenedor principal
|
|
672
|
+
- `dropdownButton` - Botón del selector de país
|
|
673
|
+
- `input` - Campo de entrada de teléfono
|
|
674
|
+
- `dialCodeInput` - Campo de código (solo layout separado)
|
|
675
|
+
- `row` - Fila del grid (solo layout separado)
|
|
676
|
+
|
|
677
|
+
## 🔧 Ejemplos Avanzados
|
|
415
678
|
|
|
416
679
|
### Detección Automática de País
|
|
680
|
+
|
|
417
681
|
```javascript
|
|
418
|
-
const phoneLib = new PhoneLib('#
|
|
419
|
-
autoDetectCountry: true // Detecta país
|
|
682
|
+
const phoneLib = new PhoneLib('#container', {
|
|
683
|
+
autoDetectCountry: true // Detecta país al ingresar +34...
|
|
420
684
|
});
|
|
685
|
+
|
|
686
|
+
// El usuario escribe: +34 600 123 456
|
|
687
|
+
// Automáticamente cambia a España
|
|
421
688
|
```
|
|
422
689
|
|
|
423
690
|
### Filtrado de Países
|
|
691
|
+
|
|
424
692
|
```javascript
|
|
425
|
-
const phoneLib = new PhoneLib('#
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
693
|
+
const phoneLib = new PhoneLib('#container', {
|
|
694
|
+
// Solo mostrar estos países
|
|
695
|
+
onlyCountries: ['CO', 'US', 'ES', 'MX'],
|
|
696
|
+
|
|
697
|
+
// Deshabilitar estos países (aparecen pero no se pueden seleccionar)
|
|
698
|
+
disabledCountries: ['CU', 'KP'],
|
|
699
|
+
|
|
700
|
+
// Excluir estos países (no aparecen en la lista)
|
|
701
|
+
excludeCountries: ['XX']
|
|
702
|
+
});
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
### Validación en Tiempo Real
|
|
706
|
+
|
|
707
|
+
```javascript
|
|
708
|
+
const phoneLib = new PhoneLib('#container', {
|
|
709
|
+
validateOnInput: true, // Valida mientras el usuario escribe
|
|
710
|
+
|
|
711
|
+
onValidationChange: (isValid) => {
|
|
712
|
+
if (isValid) {
|
|
713
|
+
console.log('Número válido!');
|
|
714
|
+
}
|
|
715
|
+
}
|
|
429
716
|
});
|
|
430
717
|
```
|
|
431
718
|
|
|
432
719
|
### Modo Readonly/Disabled
|
|
720
|
+
|
|
433
721
|
```javascript
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
722
|
+
// Solo lectura
|
|
723
|
+
const phoneLib = new PhoneLib('#container', {
|
|
724
|
+
readonly: true
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
// Deshabilitado
|
|
728
|
+
const phoneLib = new PhoneLib('#container', {
|
|
729
|
+
disabled: true
|
|
437
730
|
});
|
|
438
731
|
```
|
|
439
732
|
|
|
440
|
-
|
|
733
|
+
## 📱 Props del Componente React
|
|
734
|
+
|
|
735
|
+
| Prop | Tipo | Default | Descripción |
|
|
736
|
+
|------|------|---------|-------------|
|
|
737
|
+
| `initialCountry` | string | `'US'` | País inicial (ISO2) |
|
|
738
|
+
| `preferredCountries` | array | `[]` | Países preferidos |
|
|
739
|
+
| `showHint` | boolean | `true` | Mostrar hint de validación |
|
|
740
|
+
| `layout` | string | `'integrated'` | `'integrated'` o `'separated'` |
|
|
741
|
+
| `showDialCode` | boolean | `true` | Mostrar código de marcación |
|
|
742
|
+
| `autoDetectCountry` | boolean | `false` | Detectar país automáticamente |
|
|
743
|
+
| `validateOnInput` | boolean | `false` | Validar mientras se escribe |
|
|
744
|
+
| `disabledCountries` | array | `[]` | Países deshabilitados |
|
|
745
|
+
| `onlyCountries` | array | `[]` | Solo estos países |
|
|
746
|
+
| `excludeCountries` | array | `[]` | Excluir estos países |
|
|
747
|
+
| `readonly` | boolean | `false` | Modo solo lectura |
|
|
748
|
+
| `disabled` | boolean | `false` | Componente deshabilitado |
|
|
749
|
+
| `placeholder` | string | `null` | Placeholder personalizado |
|
|
750
|
+
| `countryLabel` | string | `'País'` | Label para selector |
|
|
751
|
+
| `dialCodeLabel` | string | `'Código'` | Label para código |
|
|
752
|
+
| `phoneLabel` | string | `'Número de teléfono'` | Label para número |
|
|
753
|
+
| `customClasses` | object | `{}` | Clases CSS personalizadas |
|
|
754
|
+
| `customStyles` | object | `{}` | Estilos inline personalizados |
|
|
755
|
+
| `messages` | object | `{}` | Mensajes personalizables |
|
|
756
|
+
| `ariaLabels` | object | `{}` | Labels ARIA personalizables |
|
|
757
|
+
| `onCountryChange` | function | `null` | Callback cuando cambia el país |
|
|
758
|
+
| `onPhoneChange` | function | `null` | Callback cuando cambia el número |
|
|
759
|
+
| `onValidationChange` | function | `null` | Callback cuando cambia la validación |
|
|
760
|
+
| `onFocus` | function | `null` | Callback cuando se enfoca |
|
|
761
|
+
| `onBlur` | function | `null` | Callback cuando pierde foco |
|
|
762
|
+
|
|
763
|
+
## 🧪 Desarrollo y Pruebas
|
|
764
|
+
|
|
765
|
+
### Ejecutar Demos Localmente
|
|
766
|
+
|
|
767
|
+
```bash
|
|
768
|
+
# Instalar dependencias
|
|
769
|
+
npm install
|
|
770
|
+
|
|
771
|
+
# Iniciar servidor de desarrollo
|
|
772
|
+
npm run serve
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
Esto abrirá `http://localhost:3004` con todos los demos disponibles.
|
|
776
|
+
|
|
777
|
+
### Archivos de Demo
|
|
778
|
+
|
|
779
|
+
- `demo.html` - Layout integrado básico
|
|
780
|
+
- `demo-separated.html` - Layout separado
|
|
781
|
+
- `demo-all-layouts.html` - Comparación de todos los layouts
|
|
782
|
+
- `demo-features.html` - Todas las características
|
|
783
|
+
- `demo-react.html` - Ejemplo con React
|
|
784
|
+
|
|
785
|
+
## 📦 Estructura del Paquete
|
|
786
|
+
|
|
787
|
+
```
|
|
788
|
+
@jacksonavila/phone-lib/
|
|
789
|
+
├── phone-lib.js # Código principal (Vanilla JS)
|
|
790
|
+
├── phone-lib.css # Estilos CSS
|
|
791
|
+
├── phone-lib-react.jsx # Componente React
|
|
792
|
+
├── phone-lib-react.js # Versión CommonJS/ESM React
|
|
793
|
+
└── README.md # Documentación
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
### Rutas de Importación
|
|
797
|
+
|
|
441
798
|
```javascript
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
799
|
+
// Librería principal (Vanilla JS)
|
|
800
|
+
import PhoneLib from '@jacksonavila/phone-lib';
|
|
801
|
+
|
|
802
|
+
// Componente React
|
|
803
|
+
import PhoneLibReact from '@jacksonavila/phone-lib/react';
|
|
804
|
+
|
|
805
|
+
// Estilos CSS
|
|
806
|
+
import '@jacksonavila/phone-lib/css';
|
|
807
|
+
|
|
808
|
+
// O con rutas completas
|
|
809
|
+
import PhoneLib from '@jacksonavila/phone-lib/phone-lib.js';
|
|
810
|
+
import PhoneLibReact from '@jacksonavila/phone-lib/phone-lib-react.jsx';
|
|
811
|
+
import '@jacksonavila/phone-lib/phone-lib.css';
|
|
447
812
|
```
|
|
448
813
|
|
|
449
|
-
##
|
|
814
|
+
## 🤝 Contribuir
|
|
815
|
+
|
|
816
|
+
Las contribuciones son bienvenidas. Por favor:
|
|
817
|
+
|
|
818
|
+
1. Fork el proyecto
|
|
819
|
+
2. Crea una rama para tu feature (`git checkout -b feature/AmazingFeature`)
|
|
820
|
+
3. Commit tus cambios (`git commit -m 'Add some AmazingFeature'`)
|
|
821
|
+
4. Push a la rama (`git push origin feature/AmazingFeature`)
|
|
822
|
+
5. Abre un Pull Request
|
|
823
|
+
|
|
824
|
+
## 📄 Licencia
|
|
825
|
+
|
|
826
|
+
Este proyecto está bajo la Licencia MIT - ver el archivo [LICENSE](LICENSE) para más detalles.
|
|
827
|
+
|
|
828
|
+
## 🙏 Agradecimientos
|
|
829
|
+
|
|
830
|
+
- [libphonenumber-js](https://github.com/catamphetamine/libphonenumber-js) - Para validación y formato de números telefónicos
|
|
831
|
+
|
|
832
|
+
## 📞 Soporte
|
|
833
|
+
|
|
834
|
+
Si tienes preguntas o encuentras algún problema:
|
|
450
835
|
|
|
451
|
-
-
|
|
836
|
+
- Abre un [issue](https://github.com/tu-usuario/phone-lib/issues) en GitHub
|
|
837
|
+
- Consulta la [documentación completa](./USAGE.md)
|
|
838
|
+
- Revisa los [ejemplos](./demo.html)
|
|
452
839
|
|
|
453
|
-
|
|
840
|
+
---
|
|
454
841
|
|
|
455
|
-
|
|
842
|
+
**Hecho con ❤️ para la comunidad de desarrolladores**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jacksonavila/phone-lib",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Librería JavaScript para input de teléfono con selector de país y banderas - Compatible con Vanilla JS y React",
|
|
5
5
|
"main": "phone-lib.js",
|
|
6
6
|
"module": "phone-lib.js",
|
|
@@ -71,4 +71,4 @@
|
|
|
71
71
|
"engines": {
|
|
72
72
|
"node": ">=14.0.0"
|
|
73
73
|
}
|
|
74
|
-
}
|
|
74
|
+
}
|