@votodigital-onpeui/react 0.1.0 → 0.1.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 +542 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,542 @@
1
+ # @votodigital-onpeui/react
2
+
3
+ Librería de componentes de interfaz de usuario para aplicaciones de la Oficina Nacional de Procesos Electorales (ONPE) del Perú, construida con React, TypeScript y Tailwind CSS v4.
4
+
5
+ ## Características
6
+
7
+ - **Colores oficiales ONPE** — Paleta de colores institucional completa
8
+ - **Tailwind CSS v4** — Framework CSS moderno, sin conflictos con proyectos existentes
9
+ - **TypeScript** — Tipado completo en todos los componentes e iconos
10
+ - **Responsive** — Diseño adaptable a todos los dispositivos
11
+ - **Accesible** — Componentes con soporte de focus trap, ARIA y navegación por teclado
12
+ - **Tree-shakable** — Solo se incluye en el bundle lo que se importa
13
+ - **Sin framer-motion** — Animaciones con CSS transitions nativas, sin dependencias pesadas
14
+
15
+ ---
16
+
17
+ ## Instalación
18
+
19
+ ```bash
20
+ npm install @votodigital-onpeui/react
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Configuración inicial
26
+
27
+ Importar los estilos **una sola vez** en el entry point de tu aplicación:
28
+
29
+ ```tsx
30
+ // main.tsx o index.tsx
31
+ import "@votodigital-onpeui/react/styles.css";
32
+ ```
33
+
34
+ Para componentes que usan `Portal` (Modal y derivados), agregar el elemento `#portal` en el HTML:
35
+
36
+ ```html
37
+ <!-- index.html -->
38
+ <body>
39
+ <div id="root"></div>
40
+ <div id="portal"></div>
41
+ </body>
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Imports
47
+
48
+ Todo se importa desde el paquete. Hay tres entradas disponibles:
49
+
50
+ ```tsx
51
+ // Todo junto
52
+ import { Button, ModalConfirm, IconLogoONPE } from "@votodigital-onpeui/react";
53
+
54
+ // Solo componentes
55
+ import { Button, ModalConfirm } from "@votodigital-onpeui/react/components";
56
+
57
+ // Solo iconos
58
+ import { IconLogoONPE, IconChrome } from "@votodigital-onpeui/react/icons";
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Componentes
64
+
65
+ ### Button
66
+
67
+ Botón con múltiples colores y tamaños.
68
+
69
+ ```tsx
70
+ import { Button } from "@votodigital-onpeui/react";
71
+
72
+ // Colores
73
+ <Button color="primary" title="Primario" />
74
+ <Button color="blue" title="Azul" />
75
+ <Button color="skyblue" title="Sky Blue" />
76
+ <Button color="red" title="Rojo" />
77
+ <Button color="green" title="Verde" />
78
+ <Button color="yellow" title="Amarillo" />
79
+
80
+ // Tamaños
81
+ <Button color="primary" title="Pequeño" size="small" />
82
+ <Button color="primary" title="Normal" size="normal" />
83
+ <Button color="primary" title="Grande" size="large" />
84
+
85
+ // Estado deshabilitado
86
+ <Button color="primary" title="Deshabilitado" disabled />
87
+ ```
88
+
89
+ #### Props
90
+
91
+ | Prop | Tipo | Default | Descripción |
92
+ |------|------|---------|-------------|
93
+ | `title` | `string` | — | Texto del botón **(requerido)** |
94
+ | `color` | `'primary' \| 'blue' \| 'skyblue' \| 'skyblue-light' \| 'yellow' \| 'light-skyblue' \| 'gray' \| 'gray-light' \| 'gray-extra-light' \| 'red' \| 'dark-gray' \| 'green' \| 'yellow-light'` | `'primary'` | Color del botón |
95
+ | `size` | `'small' \| 'normal' \| 'large'` | `'normal'` | Tamaño del botón |
96
+ | `disabled` | `boolean` | `false` | Estado deshabilitado |
97
+ | `className` | `string` | — | Clases adicionales |
98
+ | `onClick` | `() => void` | — | Handler de click |
99
+
100
+ ---
101
+
102
+ ### Modal
103
+
104
+ Modal base con animación de entrada/salida, focus trap, scroll lock y soporte de navegación por teclado.
105
+
106
+ ```tsx
107
+ import { Modal } from "@votodigital-onpeui/react";
108
+ import { useState } from "react";
109
+
110
+ function App() {
111
+ const [isOpen, setIsOpen] = useState(false);
112
+
113
+ return (
114
+ <>
115
+ <button onClick={() => setIsOpen(true)}>Abrir Modal</button>
116
+
117
+ <Modal isOpen={isOpen} onClose={() => setIsOpen(false)} closeButton>
118
+ <h2>Título del Modal</h2>
119
+ <p>Contenido del modal.</p>
120
+ </Modal>
121
+ </>
122
+ );
123
+ }
124
+ ```
125
+
126
+ #### Props principales
127
+
128
+ | Prop | Tipo | Default | Descripción |
129
+ |------|------|---------|-------------|
130
+ | `isOpen` | `boolean` | — | Estado de apertura **(requerido)** |
131
+ | `onClose` | `() => void` | — | Función para cerrar **(requerida)** |
132
+ | `children` | `ReactNode` | — | Contenido del modal **(requerido)** |
133
+ | `closeButton` | `boolean` | `false` | Muestra botón X para cerrar |
134
+ | `closeDisabled` | `boolean` | `false` | Deshabilita el cierre por click fuera y Escape |
135
+ | `escapeToClose` | `boolean` | `true` | Permite cerrar con tecla Escape |
136
+ | `whitoutBackground` | `boolean` | `false` | Modal sin fondo blanco (transparente) |
137
+ | `zIndexLevel` | `number` | `100` | Nivel de z-index del modal |
138
+ | `onCloseComplete` | `() => void` | — | Callback que se ejecuta cuando termina la animación de salida |
139
+ | `className` | `string` | — | Clases adicionales para el contenedor del contenido |
140
+
141
+ > **Nota sobre estado global:** El Modal cachea internamente el último contenido mientras realiza la animación de salida. Si usás Zustand, Redux u otro estado global y limpiás los datos al cerrar, el modal seguirá mostrando el contenido durante la animación de salida sin que se vea en blanco.
142
+
143
+ ---
144
+
145
+ ### ModalConfirm
146
+
147
+ Modal de confirmación con icono, título, mensaje y botones de acción.
148
+
149
+ ```tsx
150
+ import { ModalConfirm } from "@votodigital-onpeui/react";
151
+ import { useState } from "react";
152
+
153
+ function App() {
154
+ const [isOpen, setIsOpen] = useState(false);
155
+
156
+ return (
157
+ <>
158
+ <button onClick={() => setIsOpen(true)}>Eliminar</button>
159
+
160
+ <ModalConfirm
161
+ isOpen={isOpen}
162
+ onClose={() => setIsOpen(false)}
163
+ title="¿Estás seguro?"
164
+ message="Esta acción no se puede deshacer."
165
+ icon="warning"
166
+ color="red"
167
+ textButtonConfirm="Eliminar"
168
+ textButtonCancel="Cancelar"
169
+ onConfirm={() => console.log("confirmado")}
170
+ onCancel={() => setIsOpen(false)}
171
+ />
172
+ </>
173
+ );
174
+ }
175
+ ```
176
+
177
+ #### Props
178
+
179
+ | Prop | Tipo | Default | Descripción |
180
+ |------|------|---------|-------------|
181
+ | `isOpen` | `boolean` | — | **(requerido)** |
182
+ | `onClose` | `() => void` | — | **(requerido)** |
183
+ | `title` | `string` | — | Título del modal **(requerido)** |
184
+ | `message` | `ReactNode` | — | Mensaje descriptivo **(requerido)** |
185
+ | `icon` | `'warning' \| 'success'` | `'warning'` | Icono a mostrar |
186
+ | `color` | `'blue' \| 'red'` | `'blue'` | Color del icono y título |
187
+ | `twoButtons` | `boolean` | `true` | Muestra dos botones (confirmar + cancelar) |
188
+ | `textButtonConfirm` | `string` | `'Confirmar'` | Texto del botón de confirmación |
189
+ | `textButtonCancel` | `string` | `'Cancelar'` | Texto del botón de cancelación |
190
+ | `onConfirm` | `() => void` | — | Acción al confirmar |
191
+ | `onCancel` | `() => void` | — | Acción al cancelar |
192
+ | `withoutAutoClose` | `boolean` | `false` | Evita que el modal se cierre automáticamente al confirmar/cancelar |
193
+ | `zIndexLevel` | `number` | `100` | Nivel de z-index |
194
+
195
+ ---
196
+
197
+ ### ModalLoading
198
+
199
+ Modal de carga con spinner animado y mensaje.
200
+
201
+ ```tsx
202
+ import { ModalLoading } from "@votodigital-onpeui/react";
203
+
204
+ <ModalLoading
205
+ isOpen={loading}
206
+ message="Procesando información..."
207
+ />
208
+ ```
209
+
210
+ #### Props
211
+
212
+ | Prop | Tipo | Default | Descripción |
213
+ |------|------|---------|-------------|
214
+ | `isOpen` | `boolean` | — | **(requerido)** |
215
+ | `message` | `string` | `'Cargando...'` | Mensaje de carga |
216
+ | `zIndexLevel` | `number` | `100` | Nivel de z-index |
217
+
218
+ ---
219
+
220
+ ### ModalBrowserIncompatible
221
+
222
+ Modal que informa al usuario que está usando un navegador no recomendado.
223
+
224
+ ```tsx
225
+ import { ModalBrowserIncompatible } from "@votodigital-onpeui/react";
226
+
227
+ <ModalBrowserIncompatible
228
+ isOpen={showBrowserModal}
229
+ onClose={() => setShowBrowserModal(false)}
230
+ />
231
+ ```
232
+
233
+ ---
234
+
235
+ ### ModalSystemIncompatible
236
+
237
+ Modal que informa al usuario que su sistema operativo no es compatible con ONPE ID.
238
+
239
+ ```tsx
240
+ import { ModalSystemIncompatible } from "@votodigital-onpeui/react";
241
+
242
+ <ModalSystemIncompatible
243
+ isOpen={showSystemModal}
244
+ onClose={() => setShowSystemModal(false)}
245
+ />
246
+ ```
247
+
248
+ ---
249
+
250
+ ### ModalDnieVersions
251
+
252
+ Modal informativo sobre las versiones del DNI electrónico. Recibe las imágenes de cada versión como props (ReactNode).
253
+
254
+ ```tsx
255
+ import { ModalDnieVersions } from "@votodigital-onpeui/react";
256
+
257
+ <ModalDnieVersions
258
+ isOpen={isOpen}
259
+ onClose={() => setIsOpen(false)}
260
+ iconDnie1={<img src="/dnie-v1.png" alt="DNIe versión 1" />}
261
+ iconDnie2={<img src="/dnie-v2.png" alt="DNIe versión 2" />}
262
+ iconDnie3={<img src="/dnie-v3.png" alt="DNIe versión 3" />}
263
+ />
264
+ ```
265
+
266
+ ---
267
+
268
+ ### ModalNfc
269
+
270
+ Modal informativo sobre cómo usar NFC para leer el DNIe. Recibe las imágenes de ejemplo como props (ReactNode).
271
+
272
+ ```tsx
273
+ import { ModalNfc } from "@votodigital-onpeui/react";
274
+
275
+ <ModalNfc
276
+ isOpen={isOpen}
277
+ onClose={() => setIsOpen(false)}
278
+ iconNfc1={<img src="/nfc-android.png" alt="NFC Android" />}
279
+ iconNfc2={<img src="/nfc-iphone.png" alt="NFC iPhone" />}
280
+ />
281
+ ```
282
+
283
+ ---
284
+
285
+ ### NotRecommended
286
+
287
+ Widget flotante que advierte sobre navegador o sistema operativo no recomendado. Se puede minimizar/maximizar.
288
+
289
+ ```tsx
290
+ import { NotRecommended } from "@votodigital-onpeui/react";
291
+
292
+ // Advertencia de navegador
293
+ <NotRecommended isOpenBrowserError={true} />
294
+
295
+ // Advertencia de sistema operativo
296
+ <NotRecommended isOpenDeviceError={true} />
297
+
298
+ // Posición personalizada
299
+ <NotRecommended
300
+ isOpenBrowserError={true}
301
+ bottom={40}
302
+ right={20}
303
+ />
304
+ ```
305
+
306
+ ---
307
+
308
+ ### Footer
309
+
310
+ Footer institucional ONPE con información de contacto y navegadores recomendados.
311
+
312
+ ```tsx
313
+ import { Footer } from "@votodigital-onpeui/react";
314
+
315
+ <Footer
316
+ showBrowserInfo={true}
317
+ showContactInfo={true}
318
+ isDevelopment={false}
319
+ />
320
+ ```
321
+
322
+ ---
323
+
324
+ ### BrowserRecommended
325
+
326
+ Banner que muestra los navegadores recomendados (Chrome, Safari, Edge).
327
+
328
+ ```tsx
329
+ import { BrowserRecommended } from "@votodigital-onpeui/react";
330
+
331
+ <BrowserRecommended />
332
+ ```
333
+
334
+ ---
335
+
336
+ ### Show
337
+
338
+ Componente de renderizado condicional. Muestra un componente de carga mientras `condition` es `true`, y el contenido cuando es `false`.
339
+
340
+ ```tsx
341
+ import { Show } from "@votodigital-onpeui/react";
342
+
343
+ <Show
344
+ condition={isLoading}
345
+ loadingComponent={<div>Cargando...</div>}
346
+ >
347
+ <div>Contenido cargado</div>
348
+ </Show>
349
+ ```
350
+
351
+ ---
352
+
353
+ ### Overlay
354
+
355
+ Overlay de fondo para superposiciones personalizadas.
356
+
357
+ ```tsx
358
+ import { Overlay } from "@votodigital-onpeui/react";
359
+
360
+ <div className="relative">
361
+ <Overlay show={isOpen} color="blue" onClick={() => setIsOpen(false)} />
362
+ </div>
363
+ ```
364
+
365
+ ---
366
+
367
+ ### Portal
368
+
369
+ Renderiza contenido fuera del árbol DOM del componente padre, usando `document.querySelector('#portal')` o `document.body` como fallback.
370
+
371
+ ```tsx
372
+ import { Portal } from "@votodigital-onpeui/react";
373
+
374
+ <Portal>
375
+ <div>Contenido renderizado fuera del árbol DOM</div>
376
+ </Portal>
377
+ ```
378
+
379
+ ---
380
+
381
+ ## Iconos
382
+
383
+ Los iconos son componentes SVG que aceptan `className` y demás props de `<svg>`.
384
+
385
+ ### Acciones
386
+
387
+ ```tsx
388
+ import {
389
+ IconCheck,
390
+ IconClose,
391
+ IconCloseRadius,
392
+ IconHome,
393
+ IconInfo,
394
+ IconPhone,
395
+ IconSpinnerDesktop,
396
+ IconSpinnerMobile,
397
+ IconWarning,
398
+ IconWarningNotRecommended,
399
+ } from "@votodigital-onpeui/react/icons";
400
+
401
+ <IconCheck className="w-6 h-6 text-onpe-green" />
402
+ <IconWarning className="w-8 h-8 text-onpe-yellow" />
403
+ <IconSpinnerDesktop className="w-12 h-12 text-white animate-spin" />
404
+ ```
405
+
406
+ ### Navegadores
407
+
408
+ ```tsx
409
+ import {
410
+ IconChrome, IconChromeColor,
411
+ IconEdge, IconEdgeColor,
412
+ IconSafari, IconSafariColor,
413
+ IconMozilla, IconMozillaColor,
414
+ } from "@votodigital-onpeui/react/icons";
415
+
416
+ // Monocromos (color via className)
417
+ <IconChrome className="w-6 h-6 text-onpe-blue" />
418
+
419
+ // A color (colores fijos propios del ícono)
420
+ <IconChromeColor className="w-8 h-8" />
421
+ ```
422
+
423
+ ### Sistemas Operativos
424
+
425
+ ```tsx
426
+ import {
427
+ IconAndroid,
428
+ IconApple,
429
+ IconHuawei,
430
+ IconWindow,
431
+ } from "@votodigital-onpeui/react/icons";
432
+
433
+ <IconAndroid className="w-6 h-6 text-onpe-skyblue" />
434
+ <IconApple className="w-6 h-6 text-onpe-skyblue" />
435
+ ```
436
+
437
+ ### Redes Sociales
438
+
439
+ ```tsx
440
+ import {
441
+ FaceBookIcon,
442
+ InstagramIcon,
443
+ TikTokIcon,
444
+ WhatsappIcon,
445
+ XIcon,
446
+ YoutubeIcon,
447
+ } from "@votodigital-onpeui/react/icons";
448
+
449
+ <FaceBookIcon className="w-6 h-6 text-onpe-blue" />
450
+ <YoutubeIcon className="w-6 h-6 text-onpe-red" />
451
+ ```
452
+
453
+ ### ONPE
454
+
455
+ ```tsx
456
+ import {
457
+ IconLogoONPE,
458
+ IconVotoDigital,
459
+ IconElectionsGeneral,
460
+ IconElectionsRegionalesYMunicipales,
461
+ } from "@votodigital-onpeui/react/icons";
462
+
463
+ <IconLogoONPE className="w-24 h-24 text-onpe-blue" />
464
+ <IconVotoDigital className="w-16 h-16 text-onpe-skyblue" />
465
+ ```
466
+
467
+ ---
468
+
469
+ ## Paleta de colores ONPE
470
+
471
+ Los colores se acceden via clases Tailwind con el prefijo `onpe-`:
472
+
473
+ | Token | Clase Tailwind | Hex |
474
+ |-------|---------------|-----|
475
+ | Azul principal | `text-onpe-blue` / `bg-onpe-blue` | `#003770` |
476
+ | Sky Blue | `text-onpe-skyblue` / `bg-onpe-skyblue` | `#0073cf` |
477
+ | Sky Blue Light | `text-onpe-skyblue-light` / `bg-onpe-skyblue-light` | `#69b2e8` |
478
+ | Light Sky Blue | `text-onpe-light-skyblue` / `bg-onpe-light-skyblue` | `#aaeff6` |
479
+ | Amarillo | `text-onpe-yellow` / `bg-onpe-yellow` | `#ffb81c` |
480
+ | Amarillo Light | `text-onpe-yellow-light` / `bg-onpe-yellow-light` | `#fff1d2` |
481
+ | Verde | `text-onpe-green` / `bg-onpe-green` | `#76bd43` |
482
+ | Rojo | `text-onpe-red` / `bg-onpe-red` | `#e3002b` |
483
+ | Dark Gray | `text-onpe-dark-gray` / `bg-onpe-dark-gray` | `#4f4f4f` |
484
+ | Gray | `text-onpe-gray` / `bg-onpe-gray` | `#bcbcbc` |
485
+ | Gray Light | `text-onpe-gray-light` / `bg-onpe-gray-light` | `#bdbdbd` |
486
+ | Gray Extra Light | `text-onpe-gray-extra-light` / `bg-onpe-gray-extra-light` | `#f2f2f2` |
487
+
488
+ ---
489
+
490
+ ## Dependencias de componentes
491
+
492
+ ```
493
+ Modal
494
+ ├── Portal
495
+ └── IconCloseRadius
496
+
497
+ ModalConfirm → Modal
498
+ ModalLoading → Modal
499
+ ModalBrowserIncompatible → Modal + IconWarning + IconChromeColor + IconSafariColor + IconEdgeColor
500
+ ModalSystemIncompatible → Modal + IconWarning + IconWindow + IconAndroid + IconApple
501
+ ModalDnieVersions → Modal
502
+ ModalNfc → Modal + IconAndroid + IconApple
503
+
504
+ Footer → BrowserRecommended + iconos de redes sociales
505
+ NotRecommended → IconWarningNotRecommended + IconCloseRadius
506
+ ```
507
+
508
+ ---
509
+
510
+ ## Desarrollo
511
+
512
+ ### Requisitos
513
+
514
+ - Node.js 18+
515
+ - npm 9+
516
+
517
+ ### Scripts
518
+
519
+ ```bash
520
+ npm run build # Build para producción
521
+ npm run dev # Build en modo watch
522
+ npm run storybook # Servidor de Storybook en localhost:6006
523
+ npm run lint # Verificar código con ESLint
524
+ ```
525
+
526
+ ### Build
527
+
528
+ El build genera tres entradas en `dist/`:
529
+
530
+ ```
531
+ dist/
532
+ ├── index.js / index.mjs / index.d.ts → @votodigital-onpeui/react
533
+ ├── components.js / components.mjs / ... → @votodigital-onpeui/react/components
534
+ ├── icons.js / icons.mjs / icons.d.ts → @votodigital-onpeui/react/icons
535
+ └── styles.css → @votodigital-onpeui/react/styles.css
536
+ ```
537
+
538
+ ---
539
+
540
+ ## Licencia
541
+
542
+ MIT © ONPE — Oficina Nacional de Procesos Electorales
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@votodigital-onpeui/react",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Librería de componentes UI para proyectos ONPE",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",