@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.
Files changed (2) hide show
  1. package/README.md +598 -211
  2. 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
- ## Características
5
+ [![npm version](https://img.shields.io/npm/v/@jacksonavila/phone-lib.svg)](https://www.npmjs.com/package/@jacksonavila/phone-lib)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
7
 
7
- - Dropdown con países mostrando nombre, código ISO2, código de marcación y bandera
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
- ## Instalación
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
- ### Desde npm (Después de publicar)
24
+ ## 📦 Instalación
23
25
 
24
26
  ```bash
25
27
  npm install @jacksonavila/phone-lib
26
28
  ```
27
29
 
28
- ### Desarrollo Local
30
+ ### Dependencias
29
31
 
30
32
  ```bash
31
- npm install
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
- ## 🚀 Cómo Probar la Librería
39
+ ## 🚀 Inicio Rápido
35
40
 
36
- ### Opción Rápida (Recomendada)
41
+ ### Vanilla JavaScript
37
42
 
38
- ```bash
39
- # 1. Instalar dependencias
40
- npm install
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
- # 2. Iniciar servidor de desarrollo
43
- npm run serve
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
- Esto abrirá automáticamente tu navegador en `http://localhost:3004` con todos los demos disponibles.
69
+ ### React
47
70
 
48
- ### Archivos de Demo Disponibles
71
+ ```jsx
72
+ import React from 'react';
73
+ import PhoneLibReact from '@jacksonavila/phone-lib/react';
74
+ import '@jacksonavila/phone-lib/css';
49
75
 
50
- Una vez que el servidor esté corriendo, puedes probar:
76
+ function App() {
77
+ return (
78
+ <PhoneLibReact
79
+ initialCountry="CO"
80
+ layout="integrated"
81
+ showDialCode={true}
82
+ />
83
+ );
84
+ }
51
85
 
52
- - **`demo.html`** - Ejemplo básico con layout integrado
53
- - **`demo-separated.html`** - Layout separado
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
- ### Otras Opciones de Servidor
89
+ ## 📖 Guía de Uso Completa
59
90
 
60
- ```bash
61
- # Python 3
62
- python -m http.server 8000
91
+ ### Vanilla JavaScript
63
92
 
64
- # Node.js http-server
65
- npx http-server . -p 8080 -o
93
+ #### Ejemplo Básico
66
94
 
67
- # PHP
68
- php -S localhost:8000
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
- **⚠️ Importante:** No abras los archivos directamente con `file://` - necesitas un servidor HTTP debido a los módulos ES6.
108
+ #### Con Eventos y Callbacks
72
109
 
73
- 📖 **Para más detalles sobre cómo probar**, consulta [`TESTING.md`](./TESTING.md)
110
+ ```javascript
111
+ import PhoneLib from '@jacksonavila/phone-lib';
112
+ import '@jacksonavila/phone-lib/css';
74
113
 
75
- ## Uso Básico
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
- ### HTML
166
+ #### Integración con Formularios
78
167
 
79
168
  ```html
80
- <!DOCTYPE html>
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
- <script type="module">
89
- import PhoneLib from './phone-lib.js';
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 phoneLib = new PhoneLib('#phone-container', {
92
- initialCountry: 'CO',
93
- preferredCountries: ['CO', 'US', 'ES'],
94
- showHint: true
95
- });
96
- </script>
97
- </body>
98
- </html>
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
- ### Opciones de Configuración
205
+ ### React
102
206
 
103
- ```javascript
104
- const phoneLib = new PhoneLib(container, {
105
- initialCountry: 'CO', // País inicial (código ISO2)
106
- preferredCountries: ['CO', 'US'], // Países que aparecen primero en la lista
107
- showHint: true, // Mostrar hint de validación
108
- layout: 'integrated', // 'integrated' o 'separated'
109
- showDialCode: true // Mostrar código de marcación (true/false)
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
- ### Ejemplos de Layouts
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('#phone-container', {
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
- **Layout Integrado sin código:**
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('#phone-container', {
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('#phone-container', {
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
- **Layout Separado sin código:**
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('#phone-container', {
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
- ### Estilos Personalizados
406
+ ## ⚙️ Opciones de Configuración
148
407
 
149
- Puedes personalizar los estilos usando clases CSS o estilos inline:
408
+ ### Opciones Básicas
150
409
 
151
- **Con clases CSS personalizadas:**
152
410
  ```javascript
153
- const phoneLib = new PhoneLib('#phone-container', {
154
- layout: 'integrated',
155
- customClasses: {
156
- wrapper: 'mi-clase-personalizada',
157
- dropdownButton: 'mi-boton-personalizado',
158
- input: 'mi-input-personalizado'
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
- **Con estilos inline:**
420
+ ### Opciones Avanzadas
421
+
164
422
  ```javascript
165
- const phoneLib = new PhoneLib('#phone-container', {
166
- layout: 'integrated',
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
- **Combinando ambos métodos:**
462
+ ### Callbacks y Eventos
463
+
182
464
  ```javascript
183
- const phoneLib = new PhoneLib('#phone-container', {
184
- layout: 'separated',
185
- customClasses: {
186
- wrapper: 'mi-tema-personalizado'
465
+ {
466
+ onCountryChange: (country, dialCode, countryName) => {
467
+ // País cambiado
187
468
  },
188
- customStyles: {
189
- row: {
190
- gap: '20px'
191
- },
192
- input: {
193
- borderColor: '#27ae60'
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
- **Elementos personalizables:**
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
- ## API Pública
486
+ ### Métodos de Lectura
207
487
 
208
- ### `getCountry()`
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
- ### `getDialCode()`
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
- ### `getRaw()`
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
- ### `getE164()`
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
- ### `isValid()`
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
- ### `formatInternational()`
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
- ### `formatNational()`
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
- ### `formatRFC3966()`
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
- ### `getNumberType()`
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
- ### `getInfo()`
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
- ### `getCountryMetadata()`
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
- ### `setCountry(iso2)`
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
- ### `setPhoneNumber(number)`
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
- ### `setValue(country, number)`
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
- ### `enable()` / `disable()`
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
- ### `reset()`
614
+ #### `reset()`
333
615
  Resetea el componente a valores iniciales.
334
616
 
335
617
  ```javascript
336
618
  phoneLib.reset();
337
619
  ```
338
620
 
339
- ### `destroy()`
621
+ #### `destroy()`
340
622
  Destruye la instancia y limpia recursos.
341
623
 
342
624
  ```javascript
343
625
  phoneLib.destroy();
344
626
  ```
345
627
 
346
- ### `updateOptions(newOptions)`
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
- ## Ejemplos Completos
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
- ## Estructura de Archivos
639
+ ### Con Clases CSS
370
640
 
371
- ```
372
- phone-lib/
373
- ├── phone-lib.js # Código principal de la librería (Vanilla JS)
374
- ├── phone-lib.css # Estilos CSS
375
- ├── phone-lib-react.jsx # Componente React wrapper
376
- ├── phone-lib-react.js # Versión CommonJS/ESM del wrapper React
377
- ├── demo.html # Ejemplo básico Vanilla JS
378
- ├── demo-separated.html # Ejemplo layout separado
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
- ## Nuevas Características (v2.0)
651
+ ### Con Estilos Inline
387
652
 
388
- ### Eventos y Callbacks
389
653
  ```javascript
390
- const phoneLib = new PhoneLib('#phone-container', {
391
- onCountryChange: (country, dialCode, countryName) => {
392
- console.log('País cambiado:', country, dialCode);
393
- },
394
- onPhoneChange: (phoneNumber, isValid, country) => {
395
- console.log('Número cambiado:', phoneNumber);
396
- },
397
- onValidationChange: (isValid, phoneNumber) => {
398
- console.log('Validación:', isValid);
399
- },
400
- onFocus: () => console.log('Input enfocado'),
401
- onBlur: () => console.log('Input perdió foco')
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
- ### Métodos de Control Programático
406
- ```javascript
407
- phoneLib.setCountry('ES'); // Establecer país
408
- phoneLib.setPhoneNumber('600123456'); // Establecer número
409
- phoneLib.setValue('ES', '600123456'); // Establecer ambos
410
- phoneLib.enable(); // Habilitar
411
- phoneLib.disable(); // Deshabilitar
412
- phoneLib.reset(); // Resetear
413
- phoneLib.destroy(); // Destruir instancia
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('#phone-container', {
419
- autoDetectCountry: true // Detecta país automáticamente al ingresar +34...
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('#phone-container', {
426
- onlyCountries: ['CO', 'US', 'ES'], // Solo estos países
427
- disabledCountries: ['CU', 'KP'], // Deshabilitar estos
428
- excludeCountries: ['XX'] // Excluir estos
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
- const phoneLib = new PhoneLib('#phone-container', {
435
- readonly: true, // Solo lectura
436
- disabled: false // Deshabilitado
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
- ### Métodos Adicionales
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
- phoneLib.formatNational(); // Formato nacional
443
- phoneLib.formatRFC3966(); // Formato RFC3966
444
- phoneLib.getNumberType(); // Tipo (MOBILE, FIXED_LINE, etc.)
445
- phoneLib.getInfo(); // Objeto completo con toda la info
446
- phoneLib.getCountryMetadata(); // Metadata del país
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
- ## Dependencias
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
- - `libphonenumber-js`: Para validación y formato de números telefónicos
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
- ## Licencia
840
+ ---
454
841
 
455
- MIT
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.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
+ }