anteriority-ui 1.0.0
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/.github/workflows/ci.yml +31 -0
- package/.github/workflows/publish.yml +45 -0
- package/.npmrc.bak +1 -0
- package/.storybook/main.js +15 -0
- package/.storybook/preview.jsx +26 -0
- package/AnteriorityUI.md +2400 -0
- package/CLAUDE.md +91 -0
- package/README.md +182 -0
- package/assets/anteriorityUI/AnteriorityUI.logo.jpeg +0 -0
- package/assets/favicon/anteriorityUI.ico +0 -0
- package/common/api/client.js +43 -0
- package/common/storage/LocalStorage.js +13 -0
- package/common/styles/typography.css +5 -0
- package/common/styles/variables.css +192 -0
- package/common/theme/muiTheme.js +9 -0
- package/features/password-reset/api.js +39 -0
- package/features/user-profile/api.js +5 -0
- package/hooks/useAdminPasswordReset.js +133 -0
- package/index.js +57 -0
- package/package.json +57 -0
- package/pnpm-workspace.yaml +3 -0
- package/screens/components/AlertModal/AlertModal.jsx +259 -0
- package/screens/components/AlertModal/AlertModal.module.css +185 -0
- package/screens/components/AlertModal/AlertModal.stories.jsx +87 -0
- package/screens/components/Avatar/index.jsx +0 -0
- package/screens/components/Avatar/index.module.css +0 -0
- package/screens/components/Avatar/utils.js +0 -0
- package/screens/components/Badge/index.jsx +33 -0
- package/screens/components/Badge/index.module.css +18 -0
- package/screens/components/Badge/index.stories.jsx +40 -0
- package/screens/components/Barnner/index.jsx +21 -0
- package/screens/components/Barnner/index.module.css +33 -0
- package/screens/components/Barnner/index.stories.jsx +39 -0
- package/screens/components/Barnner/utils.js +0 -0
- package/screens/components/BlueLink/index.jsx +27 -0
- package/screens/components/BlueLink/index.module.css +11 -0
- package/screens/components/BlueLink/index.stories.jsx +29 -0
- package/screens/components/Breadcrumbs/index.jsx +62 -0
- package/screens/components/Breadcrumbs/index.module.css +158 -0
- package/screens/components/Breadcrumbs/index.stories.jsx +37 -0
- package/screens/components/Button/index.jsx +169 -0
- package/screens/components/Button/index.module.css +168 -0
- package/screens/components/Button/index.stories.jsx +71 -0
- package/screens/components/Button/utils.js +28 -0
- package/screens/components/CalendarComponent/CustomDatePicker.jsx +248 -0
- package/screens/components/CalendarComponent/CustomDatePicker.module.css +323 -0
- package/screens/components/CalendarComponent/CustomDatePicker.stories.jsx +45 -0
- package/screens/components/CalendarPicker/Constants.js +12 -0
- package/screens/components/CalendarPicker/index.jsx +263 -0
- package/screens/components/CalendarPicker/index.module.css +147 -0
- package/screens/components/CalendarPicker/index.stories.jsx +45 -0
- package/screens/components/CalendarPicker/utils.js +42 -0
- package/screens/components/CardV1/index.jsx +165 -0
- package/screens/components/CardV1/index.module.css +232 -0
- package/screens/components/CardV1/index.stories.jsx +62 -0
- package/screens/components/CardV1/utils.js +49 -0
- package/screens/components/ChatWindow/index.jsx +251 -0
- package/screens/components/ChatWindow/index.module.css +311 -0
- package/screens/components/ChatWindow/index.stories.jsx +62 -0
- package/screens/components/Checks/index.jsx +31 -0
- package/screens/components/Checks/index.module.css +32 -0
- package/screens/components/Checks/index.stories.jsx +32 -0
- package/screens/components/Container/index.jsx +36 -0
- package/screens/components/Container/index.module.css +24 -0
- package/screens/components/Container/index.stories.jsx +32 -0
- package/screens/components/CopyText/index.jsx +42 -0
- package/screens/components/CopyText/index.module.css +52 -0
- package/screens/components/CopyText/index.stories.jsx +24 -0
- package/screens/components/CountdownBar/constants.js +3 -0
- package/screens/components/CountdownBar/index.jsx +81 -0
- package/screens/components/CountdownBar/index.module.css +45 -0
- package/screens/components/CountdownBar/index.stories.jsx +43 -0
- package/screens/components/CountdownBar/utils.js +119 -0
- package/screens/components/DateTag/index.jsx +33 -0
- package/screens/components/DateTag/index.module.css +12 -0
- package/screens/components/DateTag/index.stories.jsx +29 -0
- package/screens/components/DesplegablePanel/constants.js +0 -0
- package/screens/components/DesplegablePanel/index.jsx +61 -0
- package/screens/components/DesplegablePanel/index.module.css +120 -0
- package/screens/components/DesplegablePanel/index.stories.jsx +44 -0
- package/screens/components/DesplegablePanel/utils.js +0 -0
- package/screens/components/DrawPanel/index.jsx +217 -0
- package/screens/components/DrawPanel/index.module.css +252 -0
- package/screens/components/DrawPanel/index.stories.jsx +66 -0
- package/screens/components/DrawPanel/utils.js +0 -0
- package/screens/components/Filter/index.jsx +105 -0
- package/screens/components/Filter/index.module.css +91 -0
- package/screens/components/Filter/index.stories.jsx +46 -0
- package/screens/components/Filter/utils.js +0 -0
- package/screens/components/FormControls/FormControls.module.css +86 -0
- package/screens/components/FormControls/index.jsx +51 -0
- package/screens/components/FormControls/index.stories.jsx +36 -0
- package/screens/components/Frame/index.jsx +54 -0
- package/screens/components/Frame/index.module.css +102 -0
- package/screens/components/Frame/index.stories.jsx +37 -0
- package/screens/components/Frame/utils.js +0 -0
- package/screens/components/GreenHighlight/index.jsx +11 -0
- package/screens/components/GreenHighlight/index.module.css +7 -0
- package/screens/components/GreenHighlight/index.stories.jsx +26 -0
- package/screens/components/GreenHighlight/utils.jsx +45 -0
- package/screens/components/HoursPicker/Constants.js +26 -0
- package/screens/components/HoursPicker/index.jsx +350 -0
- package/screens/components/HoursPicker/index.module.css +99 -0
- package/screens/components/HoursPicker/index.stories.jsx +44 -0
- package/screens/components/HoursPicker/utils.js +48 -0
- package/screens/components/InfoTooltip/index.jsx +59 -0
- package/screens/components/InfoTooltip/index.module.css +98 -0
- package/screens/components/InfoTooltip/index.stories.jsx +35 -0
- package/screens/components/Input/index.jsx +36 -0
- package/screens/components/Input/index.module.css +49 -0
- package/screens/components/Input/index.stories.jsx +37 -0
- package/screens/components/Input/utils.js +0 -0
- package/screens/components/Loading/index.jsx +76 -0
- package/screens/components/Loading/index.module.css +193 -0
- package/screens/components/Loading/index.stories.jsx +38 -0
- package/screens/components/Loading/utils.js +0 -0
- package/screens/components/MarkdownContent/index.jsx +16 -0
- package/screens/components/MarkdownContent/index.module.css +149 -0
- package/screens/components/MarkdownContent/index.stories.jsx +30 -0
- package/screens/components/MarkdownEditor/index.jsx +430 -0
- package/screens/components/MarkdownEditor/index.module.css +192 -0
- package/screens/components/MarkdownEditor/index.stories.jsx +50 -0
- package/screens/components/Material-UI/Components/InputWithIcon/index.jsx +87 -0
- package/screens/components/Material-UI/Components/InputWithIcon/index.stories.jsx +49 -0
- package/screens/components/Material-UI/Components/MenuPopover/index.jsx +117 -0
- package/screens/components/Material-UI/Components/MenuPopover/index.stories.jsx +36 -0
- package/screens/components/Material-UI/Components/MultilinePlaceholder/index.jsx +44 -0
- package/screens/components/Material-UI/Components/MultilinePlaceholder/index.stories.jsx +45 -0
- package/screens/components/Material-UI/Components/Paginador/index.jsx +79 -0
- package/screens/components/Material-UI/Components/Paginador/index.stories.jsx +49 -0
- package/screens/components/Material-UI/Components/Search/index.jsx +81 -0
- package/screens/components/Material-UI/Components/Search/index.stories.jsx +68 -0
- package/screens/components/Material-UI/Components/Selector/index.jsx +100 -0
- package/screens/components/Material-UI/Components/Selector/index.module.css +0 -0
- package/screens/components/Material-UI/Components/Selector/index.stories.jsx +52 -0
- package/screens/components/Material-UI/Components/Selector/utils.js +0 -0
- package/screens/components/Material-UI/Components/TextField/index.jsx +61 -0
- package/screens/components/Material-UI/Components/TextField/index.stories.jsx +53 -0
- package/screens/components/ModalTooltip/ModalTooltip.jsx +122 -0
- package/screens/components/ModalTooltip/ModalTooltip.module.css +65 -0
- package/screens/components/ModalTooltip/ModalTooltip.stories.jsx +39 -0
- package/screens/components/Notification/Error/ErrorMessage.jsx +30 -0
- package/screens/components/Notification/Error/ErrorMessage.module.css +57 -0
- package/screens/components/Notification/Error/ErrorMessage.stories.jsx +37 -0
- package/screens/components/PasswordResetPanel/index.jsx +325 -0
- package/screens/components/PasswordResetPanel/index.stories.jsx +26 -0
- package/screens/components/PlaceholderButton/index.jsx +169 -0
- package/screens/components/PlaceholderButton/index.module.css +162 -0
- package/screens/components/PlaceholderButton/index.stories.jsx +69 -0
- package/screens/components/PlaceholderButton/utils.js +42 -0
- package/screens/components/Profile/Avatar/index.jsx +125 -0
- package/screens/components/Profile/Avatar/index.module.css +86 -0
- package/screens/components/Profile/Avatar/index.stories.jsx +48 -0
- package/screens/components/Profile/Avatar/utils.js +18 -0
- package/screens/components/Profile/index.jsx +58 -0
- package/screens/components/Profile/index.module.css +0 -0
- package/screens/components/Profile/index.stories.jsx +38 -0
- package/screens/components/Profile/utils.js +0 -0
- package/screens/components/ScrollBar/index.jsx +62 -0
- package/screens/components/ScrollBar/index.module.css +78 -0
- package/screens/components/ScrollBar/index.stories.jsx +64 -0
- package/screens/components/ScrollBar/utils.js +127 -0
- package/screens/components/Sidebar/constants.js +16 -0
- package/screens/components/Sidebar/index.jsx +399 -0
- package/screens/components/Sidebar/index.module.css +405 -0
- package/screens/components/Sidebar/index.stories.jsx +86 -0
- package/screens/components/Sidebar/utils.js +75 -0
- package/screens/components/Skeleton/index.jsx +11 -0
- package/screens/components/Skeleton/index.module.css +26 -0
- package/screens/components/Skeleton/index.stories.jsx +42 -0
- package/screens/components/SubSidebarLayout/index.jsx +44 -0
- package/screens/components/SubSidebarLayout/index.module.css +80 -0
- package/screens/components/SubSidebarLayout/index.stories.jsx +51 -0
- package/screens/components/SummaryCard/index.jsx +50 -0
- package/screens/components/SummaryCard/index.module.css +30 -0
- package/screens/components/SummaryCard/index.stories.jsx +29 -0
- package/screens/components/Swich/constants.js +4 -0
- package/screens/components/Swich/index.jsx +85 -0
- package/screens/components/Swich/index.module.css +68 -0
- package/screens/components/Swich/index.stories.jsx +44 -0
- package/screens/components/Swich/utils.js +0 -0
- package/screens/components/TableA/index.jsx +156 -0
- package/screens/components/TableA/index.module.css +105 -0
- package/screens/components/TableA/index.stories.jsx +116 -0
- package/screens/components/TableA/utils.js +11 -0
- package/screens/components/TableB/index.jsx +222 -0
- package/screens/components/TableB/index.module.css +295 -0
- package/screens/components/TableB/index.stories.jsx +110 -0
- package/screens/components/TableB/utils.js +11 -0
- package/screens/components/ToggleCard/index.jsx +64 -0
- package/screens/components/ToggleCard/index.module.css +111 -0
- package/screens/components/ToggleCard/index.stories.jsx +49 -0
- package/screens/components/UserEditPopover/index.jsx +102 -0
- package/screens/components/UserEditPopover/index.module.css +97 -0
- package/screens/components/UserEditPopover/index.stories.jsx +49 -0
- package/scripts/build.mjs +129 -0
- package/scripts/check-case.mjs +127 -0
- package/scripts/verify-dist.mjs +45 -0
- package/vitest.config.js +36 -0
package/AnteriorityUI.md
ADDED
|
@@ -0,0 +1,2400 @@
|
|
|
1
|
+
# Documentación de componentes — anteriority-ui
|
|
2
|
+
|
|
3
|
+
Referencia detallada de uso de cada componente de la librería (props, ejemplos, notas). Para instalación y setup del proyecto, ver [README.md](README.md). Para convenciones internas (patrón de colores, estructura de carpetas), ver [CLAUDE.md](CLAUDE.md).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
### AlertModal
|
|
8
|
+
|
|
9
|
+
Modal de alerta/confirmación genérico que se renderiza vía portal sobre `document.body`. Traduce y formatea automáticamente mensajes de error (string, array u objeto con `errors`/`details`) al español, y puede incluir un input de texto o select embebido.
|
|
10
|
+
|
|
11
|
+
**Import:**
|
|
12
|
+
```jsx
|
|
13
|
+
import AlertModal from '../AlertModal/AlertModal'; // export default
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Uso básico:**
|
|
17
|
+
```jsx
|
|
18
|
+
<AlertModal
|
|
19
|
+
open={true}
|
|
20
|
+
title="Alerta"
|
|
21
|
+
message="¿Estás seguro de que deseas continuar con esta acción?"
|
|
22
|
+
confirmText="Ok"
|
|
23
|
+
cancelText="Cancelar"
|
|
24
|
+
onClose={() => setOpen(false)}
|
|
25
|
+
onConfirm={handleConfirm}
|
|
26
|
+
/>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Props:**
|
|
30
|
+
|
|
31
|
+
| Prop | Tipo | Default | Descripción |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| `open` | boolean | — | Controla si el modal se renderiza (si es falsy, retorna `null`) |
|
|
34
|
+
| `title` | string | `'Alerta'` | Título del modal |
|
|
35
|
+
| `message` | string \| array \| object | `''` | Mensaje o error a mostrar; se parsea automáticamente (soporta objetos de error tipo API con `errors`/`details`) |
|
|
36
|
+
| `onClose` | function | — | Handler del botón cancelar / click en overlay; si no es función, no se renderiza el botón cancelar |
|
|
37
|
+
| `onConfirm` | function | — | Handler del botón confirmar; si no se pasa, el botón confirmar actúa como `onClose` |
|
|
38
|
+
| `confirmText` | string | `'Ok'` | Texto del botón de confirmación |
|
|
39
|
+
| `cancelText` | string | `'Cancelar'` | Texto del botón de cancelar |
|
|
40
|
+
| `hideActions` | boolean | `false` | Oculta la fila de botones de acción |
|
|
41
|
+
| `children` | node | — | Contenido adicional (ej. un formulario) renderizado dentro del cuerpo |
|
|
42
|
+
| `showInput` | boolean | `false` | Muestra un input (`TextField` o `Selector`) dentro del modal |
|
|
43
|
+
| `inputType` | string | `'text'` | Tipo de input; `'select'` renderiza un `Selector`, cualquier otro valor un `TextField` |
|
|
44
|
+
| `inputLabel` | string | `''` | Label del input |
|
|
45
|
+
| `inputPlaceholder` | string | `''` | Placeholder del input |
|
|
46
|
+
| `inputValue` | string | `''` | Valor controlado del input |
|
|
47
|
+
| `onInputChange` | function | — | Handler de cambio del input |
|
|
48
|
+
| `inputOptions` | array | `[]` | Opciones para el `Selector` (`{ value, label }`) |
|
|
49
|
+
| `inputError` | string | `''` | Mensaje de error mostrado bajo el `TextField` |
|
|
50
|
+
| `imageUrl` | string | `''` | Si se define, muestra una imagen de vista previa |
|
|
51
|
+
| `showWarningIcon` | boolean | `true` | Muestra el ícono de alerta triangular junto al título |
|
|
52
|
+
| `bgColor` | string | — | Sobrescribe el color de fondo del modal (`--alertmodal-bg`) |
|
|
53
|
+
| `titleBorderColor` | string | — | Sobrescribe el borde bajo el título (`--alertmodal-title-border`) |
|
|
54
|
+
| `errorTextColor` | string | — | Color del texto de errores (`--alertmodal-error-text`) |
|
|
55
|
+
| `errorBgColor` | string | — | Color de fondo/borde de la lista de errores (`--alertmodal-error-bg`/`--alertmodal-error-border`) |
|
|
56
|
+
|
|
57
|
+
**Ejemplos:**
|
|
58
|
+
```jsx
|
|
59
|
+
// Con input de texto controlado
|
|
60
|
+
<AlertModal
|
|
61
|
+
open
|
|
62
|
+
title="Renombrar elemento"
|
|
63
|
+
showInput
|
|
64
|
+
inputType="text"
|
|
65
|
+
inputLabel="Nombre"
|
|
66
|
+
inputValue={value}
|
|
67
|
+
onInputChange={(e) => setValue(e.target.value)}
|
|
68
|
+
onConfirm={handleSave}
|
|
69
|
+
onClose={handleClose}
|
|
70
|
+
/>
|
|
71
|
+
|
|
72
|
+
// Con imagen y sin botón cancelar
|
|
73
|
+
<AlertModal
|
|
74
|
+
open
|
|
75
|
+
title="Foto de Perfil"
|
|
76
|
+
imageUrl="https://i.pravatar.cc/300?img=12"
|
|
77
|
+
confirmText="Cerrar"
|
|
78
|
+
showWarningIcon={false}
|
|
79
|
+
onClose={handleClose}
|
|
80
|
+
/>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Notas:** Se renderiza con `createPortal` en `document.body`, por lo que puede colocarse en cualquier parte del árbol. Depende de `Button`, `TextField` y `Selector` (Material-UI) internos del sistema de diseño.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
### Badge
|
|
88
|
+
|
|
89
|
+
Etiqueta pequeña e inline para mostrar un par label/valor, opcionalmente con ícono, usada para indicadores de estado o métricas cortas.
|
|
90
|
+
|
|
91
|
+
**Import:**
|
|
92
|
+
```jsx
|
|
93
|
+
import Badge from '../Badge'; // export default (index.jsx)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Uso básico:**
|
|
97
|
+
```jsx
|
|
98
|
+
<Badge label="Estado" value="Activo" />
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Props:**
|
|
102
|
+
|
|
103
|
+
| Prop | Tipo | Default | Descripción |
|
|
104
|
+
|---|---|---|---|
|
|
105
|
+
| `icon` | componente (lucide-react) | — | Ícono a mostrar antes del texto (prop interna `Icon`) |
|
|
106
|
+
| `label` | string | — | Etiqueta opcional antes del valor (se renderiza como `label:`) |
|
|
107
|
+
| `value` | node | — | Valor principal mostrado |
|
|
108
|
+
| `iconColor` | string | `'#000000ff'` | Color del ícono |
|
|
109
|
+
| `bgColor` | string | — | Color de fondo (`--badge-bg`) |
|
|
110
|
+
| `borderColor` | string | — | Color de borde (`--badge-border`) |
|
|
111
|
+
| `labelColor` | string | — | Color del texto de la etiqueta (`--badge-label`) |
|
|
112
|
+
| `valueColor` | string | — | Color del texto del valor (`--badge-value`) |
|
|
113
|
+
| `style` | object | `{}` | Estilos inline adicionales fusionados con las variables CSS |
|
|
114
|
+
|
|
115
|
+
**Ejemplos:**
|
|
116
|
+
```jsx
|
|
117
|
+
<Badge icon={Star} label="Puntaje" value="4.8" iconColor="#f59e0b" />
|
|
118
|
+
|
|
119
|
+
<Badge icon={Clock} value="12:30" />
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### Barnner
|
|
125
|
+
|
|
126
|
+
Chip/etiqueta de estado con variantes de color predefinidas (default, success, warning, danger) y un ícono opcional.
|
|
127
|
+
|
|
128
|
+
**Import:**
|
|
129
|
+
```jsx
|
|
130
|
+
import Barnner from '../Barnner'; // export default (index.jsx)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Uso básico:**
|
|
134
|
+
```jsx
|
|
135
|
+
<Barnner type="default">Default</Barnner>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Props:**
|
|
139
|
+
|
|
140
|
+
| Prop | Tipo | Default | Descripción |
|
|
141
|
+
|---|---|---|---|
|
|
142
|
+
| `children` | node | — | Contenido del banner |
|
|
143
|
+
| `icon` | componente (lucide-react) | — | Ícono opcional mostrado antes del texto |
|
|
144
|
+
| `type` | string: `'default' \| 'success' \| 'warning' \| 'danger'` (o cualquier variante definida en el CSS) | `'default'` | Determina la clase de color (`badge{Type}`); si no existe, cae a `badgeDefault` |
|
|
145
|
+
| `className` | string | `''` | Clase CSS adicional |
|
|
146
|
+
| `bgColor` | string | — | Sobrescribe el color de fondo inline |
|
|
147
|
+
| `textColor` | string | — | Sobrescribe el color de texto inline |
|
|
148
|
+
| `borderColor` | string | — | Sobrescribe el borde inline (agrega `1px solid`) |
|
|
149
|
+
|
|
150
|
+
**Ejemplos:**
|
|
151
|
+
```jsx
|
|
152
|
+
<Barnner type="success" icon={CheckCircle}>Completado</Barnner>
|
|
153
|
+
|
|
154
|
+
<Barnner type="danger" icon={XCircle}>Cancelado</Barnner>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
> `screens/components/Barnner/utils.js` existe pero está vacío; no exporta nada actualmente usado por el componente.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
### BlueLink
|
|
162
|
+
|
|
163
|
+
Enlace de texto con estilo de "link azul" que abre URLs externas en una nueva pestaña o navega internamente vía una función `navigate`, envuelto en un tooltip.
|
|
164
|
+
|
|
165
|
+
**Import:**
|
|
166
|
+
```jsx
|
|
167
|
+
import BlueLink from '../BlueLink/index'; // export default
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Uso básico:**
|
|
171
|
+
```jsx
|
|
172
|
+
<BlueLink label="Visitar sitio web" url="https://example.com" />
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Props:**
|
|
176
|
+
|
|
177
|
+
| Prop | Tipo | Default | Descripción |
|
|
178
|
+
|---|---|---|---|
|
|
179
|
+
| `label` | string | — | Texto visible del enlace |
|
|
180
|
+
| `url` | string | — | URL destino; si empieza con `http://` o `https://` se abre en nueva pestaña, si no, se usa `navigate(url)` |
|
|
181
|
+
| `navigate` | function | — | Función de navegación interna (ej. router) usada para URLs no absolutas |
|
|
182
|
+
| `color` | string | — | Sobrescribe el color del enlace (`--bluelink-color`) |
|
|
183
|
+
|
|
184
|
+
**Ejemplos:**
|
|
185
|
+
```jsx
|
|
186
|
+
<BlueLink
|
|
187
|
+
label="Ir al perfil"
|
|
188
|
+
url="/profile/123"
|
|
189
|
+
navigate={(path) => router.push(path)}
|
|
190
|
+
/>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Notas:** Envuelve el link en `ModalTooltip` (muestra "Ir a {label}"); si `url` no está definido, `url.startsWith` lanzará un error, así que `url` es efectivamente requerido.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### Breadcrumbs
|
|
198
|
+
|
|
199
|
+
Rastro de navegación (breadcrumb trail) animado; el último elemento de `items` siempre se muestra como página actual (no clicable), y los anteriores con `onClick` se renderizan como botones.
|
|
200
|
+
|
|
201
|
+
**Import:**
|
|
202
|
+
```jsx
|
|
203
|
+
import { Breadcrumbs } from '../Breadcrumbs/index'; // named export (también default export)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Uso básico:**
|
|
207
|
+
```jsx
|
|
208
|
+
<Breadcrumbs
|
|
209
|
+
items={[
|
|
210
|
+
{ label: 'Inicio', onClick: goHome },
|
|
211
|
+
{ label: 'Pacientes', onClick: goPatients },
|
|
212
|
+
{ label: 'Juan Pérez' },
|
|
213
|
+
]}
|
|
214
|
+
/>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Props:**
|
|
218
|
+
|
|
219
|
+
| Prop | Tipo | Default | Descripción |
|
|
220
|
+
|---|---|---|---|
|
|
221
|
+
| `items` | array de `{ id?, label, onClick? }` | `[]` | Ruta completa de migas de pan en orden; si está vacío no renderiza nada |
|
|
222
|
+
| `className` | string | `''` | Clase CSS adicional en el `<nav>` |
|
|
223
|
+
| `iconColor` | string | — | Color del ícono de "home" (`--crumb-icon-color`) |
|
|
224
|
+
| `activeBgColor` | string | — | Fondo del crumb activo/actual (`--crumb-active-bg`) |
|
|
225
|
+
| `linkColor` | string | — | Color de los crumbs clicables (`--crumb-link-color`) |
|
|
226
|
+
|
|
227
|
+
**Ejemplos:**
|
|
228
|
+
```jsx
|
|
229
|
+
<Breadcrumbs
|
|
230
|
+
items={[
|
|
231
|
+
{ label: 'Inicio', onClick: goHome },
|
|
232
|
+
{ label: 'Sesiones', onClick: goSessions },
|
|
233
|
+
{ label: '2024-05-10', onClick: goDate },
|
|
234
|
+
{ label: 'Detalle' },
|
|
235
|
+
]}
|
|
236
|
+
/>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Notas:** El primer ítem siempre muestra un ícono de casa; las animaciones de entrada usan `--crumb-index` y respetan `prefers-reduced-motion`. Se puede importar tanto como named export (`{ Breadcrumbs }`) o default.
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
### Button
|
|
244
|
+
|
|
245
|
+
Botón estándar del sistema, construido sobre `MuiButton` de Material-UI, con variantes, tamaños, colores, estado de carga, forma circular y tooltip integrado.
|
|
246
|
+
|
|
247
|
+
**Import:**
|
|
248
|
+
```jsx
|
|
249
|
+
import Button, { VARIANTS, SIZES, COLORS } from '../Button'; // export default + named exports
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Uso básico:**
|
|
253
|
+
```jsx
|
|
254
|
+
<Button variant={VARIANTS.PRIMARY} size={SIZES.MEDIUM} onClick={handleSave}>
|
|
255
|
+
Guardar
|
|
256
|
+
</Button>
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**Props:**
|
|
260
|
+
|
|
261
|
+
| Prop | Tipo | Default | Descripción |
|
|
262
|
+
|---|---|---|---|
|
|
263
|
+
| `children` | node | — | Contenido del botón |
|
|
264
|
+
| `variant` | `'primary' \| 'secondary' \| 'ghost' \| 'danger' \| 'outline' \| 'tab' \| 'list-item'` (`VARIANTS`) | `'primary'` | Estilo visual; mapea a `variant`/`color` de MUI |
|
|
265
|
+
| `size` | `'small' \| 'medium' \| 'large'` (`SIZES`) | `'medium'` | Tamaño del botón e ícono |
|
|
266
|
+
| `active` | boolean | `false` | Aplica un fondo levemente oscurecido (estado activo/seleccionado) |
|
|
267
|
+
| `fullWidth` | boolean | `false` | Ancho completo del contenedor |
|
|
268
|
+
| `icon` | componente (lucide-react) | — | Ícono inicial (`startIcon`) o único contenido si `circle` |
|
|
269
|
+
| `onClick` | function | — | Handler de click (no se dispara si está deshabilitado/loading) |
|
|
270
|
+
| `disabled` | boolean | `false` | Deshabilita el botón |
|
|
271
|
+
| `type` | string | `'button'` | Tipo HTML del botón (`'submit'`, etc.) |
|
|
272
|
+
| `className` | string | `''` | Clase CSS adicional |
|
|
273
|
+
| `color` | string (valor CSS o de `COLORS`) | — | Color custom o uno de los colores estándar MUI/`COLORS` |
|
|
274
|
+
| `border` | string | — | Color de borde (fuerza variante `outlined`) |
|
|
275
|
+
| `borderColor` | string | — | Igual que `border` |
|
|
276
|
+
| `style` | object | `{}` | Estilos `sx` adicionales, se aplican al final (mayor prioridad) |
|
|
277
|
+
| `loading` | boolean | `false` | Muestra un `CircularProgress` en lugar del contenido y deshabilita el botón |
|
|
278
|
+
| `success` | boolean \| undefined | `undefined` | Si es `false`, deshabilita el botón |
|
|
279
|
+
| `circle` | boolean | `false` | Botón circular que muestra solo el ícono como children |
|
|
280
|
+
| `ToolTip` | boolean \| string | `false` | Si es truthy, envuelve el botón en `ModalTooltip` (usa el string como texto, o `title` si es `true`) |
|
|
281
|
+
| `title` | string | — | Texto de tooltip cuando `ToolTip={true}` |
|
|
282
|
+
| `...props` | — | — | Cualquier otra prop se pasa directo a `MuiButton` |
|
|
283
|
+
|
|
284
|
+
**Ejemplos:**
|
|
285
|
+
```jsx
|
|
286
|
+
<Button variant={VARIANTS.PRIMARY} loading>Guardando...</Button>
|
|
287
|
+
|
|
288
|
+
<Button
|
|
289
|
+
variant={VARIANTS.GHOST}
|
|
290
|
+
circle
|
|
291
|
+
icon={Star}
|
|
292
|
+
color={COLORS.GREEN}
|
|
293
|
+
ToolTip
|
|
294
|
+
title="Marcar como favorito"
|
|
295
|
+
onClick={handleFavorite}
|
|
296
|
+
/>
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Notas:** Es un `React.forwardRef`. Expone `Button.VARIANTS`, `Button.SIZES` y `Button.COLORS` como propiedades estáticas además de los named exports.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
### CalendarComponent
|
|
304
|
+
|
|
305
|
+
Selector de fecha con `TextField` (Material-UI) como disparador y un calendario propio en un modal/backdrop, con selectores rápidos de mes/año.
|
|
306
|
+
|
|
307
|
+
**Import:**
|
|
308
|
+
```jsx
|
|
309
|
+
import CustomDatePicker from '../CalendarComponent/CustomDatePicker'; // export default
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Uso básico:**
|
|
313
|
+
```jsx
|
|
314
|
+
<CustomDatePicker
|
|
315
|
+
label="Fecha de nacimiento"
|
|
316
|
+
name="birthDate"
|
|
317
|
+
value={birthDate}
|
|
318
|
+
onChange={(e) => setBirthDate(e.target.value)}
|
|
319
|
+
/>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Props:**
|
|
323
|
+
|
|
324
|
+
| Prop | Tipo | Default | Descripción |
|
|
325
|
+
|---|---|---|---|
|
|
326
|
+
| `label` | string | — | Label del `TextField` |
|
|
327
|
+
| `name` | string | — | Nombre usado en el evento sintético `onChange` |
|
|
328
|
+
| `value` | string (`YYYY-MM-DD`) \| Date | — | Fecha seleccionada |
|
|
329
|
+
| `onChange` | function | — | Recibe un evento `{ target: { name, value, type: 'date' } }` |
|
|
330
|
+
| `required` | boolean | `false` | Marca el campo como requerido |
|
|
331
|
+
| `disabled` | boolean | `false` | Deshabilita la apertura del calendario |
|
|
332
|
+
| `selectedColor` | string | — | Color del día seleccionado (`--cdp-selected`) |
|
|
333
|
+
| `accentColor` | string | — | Color de acento del calendario (`--cdp-accent`) |
|
|
334
|
+
|
|
335
|
+
**Ejemplos:**
|
|
336
|
+
```jsx
|
|
337
|
+
<CustomDatePicker
|
|
338
|
+
label="Fecha de la cita"
|
|
339
|
+
name="appointmentDate"
|
|
340
|
+
value="2024-06-15"
|
|
341
|
+
onChange={handleChange}
|
|
342
|
+
/>
|
|
343
|
+
|
|
344
|
+
<CustomDatePicker label="Fecha bloqueada" name="disabledDate" value="2024-01-01" disabled onChange={handleChange} />
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**Notas:** El valor se emite siempre como string `YYYY-MM-DD`. Incluye botones internos "Borrar" y "Hoy". Depende de `date-fns` (locale `es`) y del `TextField` de Material-UI del sistema.
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
### CalendarPicker
|
|
352
|
+
|
|
353
|
+
Variante de selector de fecha equivalente a `CalendarComponent`, pero el calendario se renderiza dentro de un `Frame` (modal reutilizable) y usa los `Button`/`Selector` del sistema de diseño en vez de controles nativos.
|
|
354
|
+
|
|
355
|
+
**Import:**
|
|
356
|
+
```jsx
|
|
357
|
+
import CalendarPicker from '../CalendarPicker/index'; // export default
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**Uso básico:**
|
|
361
|
+
```jsx
|
|
362
|
+
<CalendarPicker
|
|
363
|
+
label="Fecha de nacimiento"
|
|
364
|
+
name="birthDate"
|
|
365
|
+
value={birthDate}
|
|
366
|
+
onChange={(e) => setBirthDate(e.target.value)}
|
|
367
|
+
/>
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
**Props:**
|
|
371
|
+
|
|
372
|
+
| Prop | Tipo | Default | Descripción |
|
|
373
|
+
|---|---|---|---|
|
|
374
|
+
| `label` | string | — | Label del `TextField` |
|
|
375
|
+
| `name` | string | — | Nombre usado en el evento sintético `onChange` |
|
|
376
|
+
| `value` | string (`YYYY-MM-DD`) \| Date | — | Fecha seleccionada |
|
|
377
|
+
| `onChange` | function | — | Recibe un evento `{ target: { name, value, type: 'date' } }` |
|
|
378
|
+
| `required` | boolean | `false` | Marca el campo como requerido |
|
|
379
|
+
| `disabled` | boolean | `false` | Deshabilita la apertura del calendario |
|
|
380
|
+
| `inputSx` | object | — | `sx` custom pasado al `TextField` interno |
|
|
381
|
+
| `selectedColor` | string | — | Color del día seleccionado / botón confirmar (`--cp-selected`) |
|
|
382
|
+
| `accentColor` | string | — | Color de acento / botón "Hoy" (`--cp-accent`) |
|
|
383
|
+
|
|
384
|
+
**Ejemplos:**
|
|
385
|
+
```jsx
|
|
386
|
+
<CalendarPicker label="Fecha requerida" name="requiredDate" value="" required onChange={handleChange} />
|
|
387
|
+
|
|
388
|
+
<CalendarPicker label="Fecha bloqueada" name="disabledDate" value="2024-01-01" disabled onChange={handleChange} />
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Notas:** El calendario se abre dentro de `Frame` (`isModal`), a diferencia de `CalendarComponent` que usa su propio backdrop; ambos componentes son intercambiables en su API pero difieren en la implementación visual del modal.
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
### CardV1
|
|
396
|
+
|
|
397
|
+
Tarjeta de métrica/KPI con badge superior, botón de acción (ej. refrescar), estados de carga/error/vacío, un valor principal grande y un footer opcional con ícono de tendencia.
|
|
398
|
+
|
|
399
|
+
**Import:**
|
|
400
|
+
```jsx
|
|
401
|
+
import CardV1 from '../CardV1'; // export default (index.jsx)
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
**Uso básico:**
|
|
405
|
+
```jsx
|
|
406
|
+
<CardV1
|
|
407
|
+
badgeIcon={DollarSign}
|
|
408
|
+
badgeText="Ingresos"
|
|
409
|
+
primaryText="Total del mes"
|
|
410
|
+
secondaryText="$12,450"
|
|
411
|
+
footerIcon={TrendingUp}
|
|
412
|
+
footerContent="+12% vs mes anterior"
|
|
413
|
+
/>
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**Props:**
|
|
417
|
+
|
|
418
|
+
| Prop | Tipo | Default | Descripción |
|
|
419
|
+
|---|---|---|---|
|
|
420
|
+
| `badgeIcon` | componente (lucide-react) | — | Ícono del badge principal |
|
|
421
|
+
| `badgeText` | string | — | Texto del badge principal |
|
|
422
|
+
| `badgeBgColor` | string | `'#f1f5f9'` | Fondo del badge principal |
|
|
423
|
+
| `badgeTextColor` | string | `'#475569'` | Color de texto del badge principal |
|
|
424
|
+
| `extraBadges` | array de `{ text, bgColor, textColor }` | `[]` | Badges adicionales junto al principal |
|
|
425
|
+
| `actionIcon` | componente (lucide-react) | — | Ícono del botón de acción (esquina superior derecha) |
|
|
426
|
+
| `onActionClick` | function | — | Handler del botón de acción |
|
|
427
|
+
| `actionDisabled` | boolean | `false` | Deshabilita el botón de acción |
|
|
428
|
+
| `actionTooltip` | string | — | Si se define, envuelve el botón de acción en `ModalTooltip` |
|
|
429
|
+
| `isSpinning` | boolean | `false` | Pasa `loading` al botón de acción (para íconos de refresco) |
|
|
430
|
+
| `actionCustomClass` | string | — | Clase custom para el botón de acción (declarada pero no aplicada en el JSX actual) |
|
|
431
|
+
| `isLoading` | boolean | `false` | Muestra un skeleton en el contenido principal |
|
|
432
|
+
| `isError` | boolean | `false` | Muestra `errorText` en vez del contenido |
|
|
433
|
+
| `isEmpty` | boolean | `false` | Muestra `emptyText` en vez del contenido |
|
|
434
|
+
| `errorText` | string | `'Error'` | Texto mostrado en estado de error |
|
|
435
|
+
| `emptyText` | string | `'Vacío'` | Texto mostrado en estado vacío |
|
|
436
|
+
| `primaryText` | node | — | Subtítulo/label sobre el valor principal |
|
|
437
|
+
| `secondaryText` | node | — | Valor principal grande |
|
|
438
|
+
| `secondaryTextStyle` | object | `{}` | Estilos inline para el valor principal |
|
|
439
|
+
| `footerIcon` | componente (lucide-react) | — | Ícono del footer |
|
|
440
|
+
| `footerIconColor` | string | — | Color del ícono del footer |
|
|
441
|
+
| `footerContent` | node | — | Contenido del footer (si no se define, el footer no se renderiza) |
|
|
442
|
+
| `className` | string | `''` | Clase CSS adicional en la tarjeta |
|
|
443
|
+
| `variant` | `'default' \| 'glass-pink-green'` | `'default'` | Variante visual de la tarjeta |
|
|
444
|
+
| `children` | node | — | Contenido adicional insertado después de `secondaryText` |
|
|
445
|
+
|
|
446
|
+
**Ejemplos:**
|
|
447
|
+
```jsx
|
|
448
|
+
<CardV1
|
|
449
|
+
badgeText="Ingresos"
|
|
450
|
+
extraBadges={[{ text: 'Nuevo', bgColor: '#fef3c7', textColor: '#92400e' }]}
|
|
451
|
+
primaryText="Total del mes"
|
|
452
|
+
secondaryText="$8,920"
|
|
453
|
+
footerIcon={TrendingDown}
|
|
454
|
+
footerIconColor="#ef4444"
|
|
455
|
+
footerContent="-5% vs mes anterior"
|
|
456
|
+
/>
|
|
457
|
+
|
|
458
|
+
<CardV1 badgeText="Ingresos" isLoading primaryText="Total del mes" />
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
**Notas:** El archivo `utils.js` del componente exporta helpers (`getPriorityData`, `getAppointmentColorByTime`) que no son usados directamente dentro de `CardV1`; están pensados para que el consumidor calcule colores/badges antes de pasarlos como props.
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
### ChatWindow
|
|
466
|
+
|
|
467
|
+
Ventana de chat completa (header de contacto, lista de mensajes con auto-scroll, indicador de "escribiendo" y composer) con un mini-lenguaje de formato propio que se traduce a Markdown.
|
|
468
|
+
|
|
469
|
+
**Import:**
|
|
470
|
+
```jsx
|
|
471
|
+
import ChatWindow from '../ChatWindow/index'; // export default
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
**Uso básico:**
|
|
475
|
+
```jsx
|
|
476
|
+
<ChatWindow
|
|
477
|
+
messages={messages}
|
|
478
|
+
currentUser={{ id: 'user-1' }}
|
|
479
|
+
selectedContact={selectedContact}
|
|
480
|
+
onSend={(text) => sendMessage(text)}
|
|
481
|
+
/>
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
**Props:**
|
|
485
|
+
|
|
486
|
+
| Prop | Tipo | Default | Descripción |
|
|
487
|
+
|---|---|---|---|
|
|
488
|
+
| `messages` | array de `{ id, from, content, createdAt }` | `[]` | Lista de mensajes; `content` puede ser string (parseado con el mini-formato) o un nodo React |
|
|
489
|
+
| `currentUser` | object `{ id }` | `{}` | Usuario actual, usado para alinear mensajes propios |
|
|
490
|
+
| `selectedContact` | object `{ id, name, avatarUrl, raw }` | `{}` | Contacto activo mostrado en el header |
|
|
491
|
+
| `isTyping` | boolean | `false` | Muestra el indicador de "escribiendo" |
|
|
492
|
+
| `onSend` | function(text) | — | Handler al enviar un mensaje (Enter o botón enviar) |
|
|
493
|
+
| `showHeader` | boolean | `true` | Muestra/oculta el header del hilo |
|
|
494
|
+
| `isMobile` | boolean | `false` | Muestra botón "Volver" en el header (para layout móvil) |
|
|
495
|
+
| `showContactsList` | boolean | `false` | Declarado pero no usado en el render actual |
|
|
496
|
+
| `handleBackToList` | function | — | Handler del botón "Volver" en modo móvil |
|
|
497
|
+
| `isLoading` | boolean | `false` | Muestra el componente `Loading` en el área de mensajes |
|
|
498
|
+
| `placeholder` | string | `'Escribe tu mensaje aquí...'` | Placeholder del textarea de composición |
|
|
499
|
+
| `accentColor` | string | — | Color de acento (`--chat-accent`) |
|
|
500
|
+
| `accentColorDark` | string | — | Color de acento oscuro (`--chat-accent-dark`) |
|
|
501
|
+
|
|
502
|
+
**Ejemplos:**
|
|
503
|
+
```jsx
|
|
504
|
+
<ChatWindow messages={messages} currentUser={currentUser} selectedContact={selectedContact} isTyping onSend={handleSend} />
|
|
505
|
+
|
|
506
|
+
<ChatWindow
|
|
507
|
+
messages={messages}
|
|
508
|
+
currentUser={currentUser}
|
|
509
|
+
selectedContact={selectedContact}
|
|
510
|
+
isMobile
|
|
511
|
+
handleBackToList={() => setSelected(null)}
|
|
512
|
+
onSend={handleSend}
|
|
513
|
+
/>
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
**Notas:** El texto de cada mensaje soporta un mini-formato propio: `**texto**` para resaltado (vía `GreenHighlight`), `$Label|url$` para enlaces (`BlueLink`) y `(texto)` para bloques copiables (`CopyText`); todo se convierte a Markdown y se renderiza con `MarkdownContent`. Depende de `UserAvatar`, `Loading`, `CopyText`, `GreenHighlight`, `BlueLink` y `MarkdownContent`, además de `Popover` de Material-UI para el menú de ayuda de formato.
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
### Checks
|
|
521
|
+
|
|
522
|
+
Ítem de checkbox de permisos: fila completa clicable con un `Checkbox` de Material-UI y una etiqueta, pensado para listas de permisos/opciones.
|
|
523
|
+
|
|
524
|
+
**Import:**
|
|
525
|
+
```jsx
|
|
526
|
+
import PermissionCheckboxItem from '../Checks/index'; // export default
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
**Uso básico:**
|
|
530
|
+
```jsx
|
|
531
|
+
<PermissionCheckboxItem
|
|
532
|
+
label="Ver historial clínico"
|
|
533
|
+
checked={checked}
|
|
534
|
+
onChange={() => setChecked(!checked)}
|
|
535
|
+
/>
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
**Props:**
|
|
539
|
+
|
|
540
|
+
| Prop | Tipo | Default | Descripción |
|
|
541
|
+
|---|---|---|---|
|
|
542
|
+
| `label` | string | — | Texto de la opción (también usado como texto del tooltip sobre el checkbox) |
|
|
543
|
+
| `checked` | boolean | — | Estado marcado/desmarcado |
|
|
544
|
+
| `onChange` | function | — | Handler al hacer click en toda la fila (no solo en el checkbox) |
|
|
545
|
+
| `disabled` | boolean | — | Deshabilita la fila y el checkbox |
|
|
546
|
+
| `checkedBgColor` | string | — | Color de fondo cuando está marcado (`--checks-checked-bg`) |
|
|
547
|
+
|
|
548
|
+
**Ejemplos:**
|
|
549
|
+
```jsx
|
|
550
|
+
<PermissionCheckboxItem label="Editar información de pacientes" checked onChange={toggle} />
|
|
551
|
+
|
|
552
|
+
<PermissionCheckboxItem label="Eliminar registros (bloqueado)" checked={false} disabled onChange={toggle} />
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
**Notas:** Todo el `ButtonBase` es clicable (no solo el checkbox visual), y el checkbox interno tiene `tabIndex={-1}` para que el foco recaiga en el contenedor.
|
|
556
|
+
|
|
557
|
+
---
|
|
558
|
+
|
|
559
|
+
### Container
|
|
560
|
+
|
|
561
|
+
Envoltorio de tarjeta genérico para secciones de contenido, con soporte opcional de paginación integrada (`Paginador` de Material-UI).
|
|
562
|
+
|
|
563
|
+
**Import:**
|
|
564
|
+
```jsx
|
|
565
|
+
import Container from '../Container'; // export default (index.jsx)
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
**Uso básico:**
|
|
569
|
+
```jsx
|
|
570
|
+
<Container>
|
|
571
|
+
<p>Contenido de ejemplo dentro del contenedor.</p>
|
|
572
|
+
</Container>
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
**Props:**
|
|
576
|
+
|
|
577
|
+
| Prop | Tipo | Default | Descripción |
|
|
578
|
+
|---|---|---|---|
|
|
579
|
+
| `children` | node | — | Contenido del contenedor |
|
|
580
|
+
| `className` | string | `''` | Clase CSS adicional |
|
|
581
|
+
| `showPagination` | boolean | `false` | Muestra el bloque de paginación al pie |
|
|
582
|
+
| `paginationCount` | number | `10` | Total de elementos/páginas para el `Paginador` |
|
|
583
|
+
| `paginationPage` | number | `1` | Página actual |
|
|
584
|
+
| `onPaginationChange` | function | — | Handler de cambio de página |
|
|
585
|
+
| `paginationProps` | object | `{}` | Props adicionales pasadas directo al `Paginador` |
|
|
586
|
+
| `pageSize` | number | `10` | Tamaño de página actual |
|
|
587
|
+
| `pageSizeOptions` | array | `[5, 10, 20, 50]` | Opciones de tamaño de página |
|
|
588
|
+
| `onPageSizeChange` | function | — | Handler de cambio de tamaño de página |
|
|
589
|
+
| `...props` | — | — | Cualquier otra prop (ej. `onClick`, `id`) se pasa al `div` raíz |
|
|
590
|
+
|
|
591
|
+
**Ejemplos:**
|
|
592
|
+
```jsx
|
|
593
|
+
<Container
|
|
594
|
+
showPagination
|
|
595
|
+
paginationCount={50}
|
|
596
|
+
paginationPage={1}
|
|
597
|
+
pageSize={10}
|
|
598
|
+
onPaginationChange={handlePageChange}
|
|
599
|
+
onPageSizeChange={handlePageSizeChange}
|
|
600
|
+
>
|
|
601
|
+
<p>Lista de resultados paginados.</p>
|
|
602
|
+
</Container>
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
---
|
|
606
|
+
|
|
607
|
+
### CopyText
|
|
608
|
+
|
|
609
|
+
Texto/código con click-to-copy: al hacer click copia el valor al portapapeles vía `navigator.clipboard` y muestra feedback visual (ícono de check) durante 2 segundos.
|
|
610
|
+
|
|
611
|
+
**Import:**
|
|
612
|
+
```jsx
|
|
613
|
+
import CopyableText from '../CopyText/index'; // export default
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
**Uso básico:**
|
|
617
|
+
```jsx
|
|
618
|
+
<CopyableText text="ABC-12345-XYZ" />
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
**Props:**
|
|
622
|
+
|
|
623
|
+
| Prop | Tipo | Default | Descripción |
|
|
624
|
+
|---|---|---|---|
|
|
625
|
+
| `text` | string | — | Texto a mostrar y copiar al portapapeles |
|
|
626
|
+
| `bgColor` | string | — | Color de fondo (`--copytext-bg`) |
|
|
627
|
+
| `borderColor` | string | — | Color de borde (`--copytext-border`) |
|
|
628
|
+
| `textColor` | string | — | Color de texto (`--copytext-text`) |
|
|
629
|
+
|
|
630
|
+
**Ejemplos:**
|
|
631
|
+
```jsx
|
|
632
|
+
<CopyableText text="f47ac10b-58cc-4372-a567-0e02b2c3d479" />
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
**Notas:** Muestra un `ModalTooltip` con "Haga clic para copiar" / "¡Copiado!" según el estado; requiere un contexto de navegador con `navigator.clipboard` disponible (HTTPS o localhost).
|
|
636
|
+
|
|
637
|
+
---
|
|
638
|
+
|
|
639
|
+
### CountdownBar
|
|
640
|
+
|
|
641
|
+
Barra de progreso/cuenta regresiva animada, con color interpolado dinámicamente según el progreso; soporta modo temporizador automático (por duración o fecha de expiración) o modo de valor controlado externamente, y una variante "overlay" a pantalla completa.
|
|
642
|
+
|
|
643
|
+
**Import:**
|
|
644
|
+
```jsx
|
|
645
|
+
import CountdownBar from '../CountdownBar'; // export default (index.jsx)
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
**Uso básico:**
|
|
649
|
+
```jsx
|
|
650
|
+
<CountdownBar active duration={10000} onComplete={() => console.log('listo')} />
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
**Props:**
|
|
654
|
+
|
|
655
|
+
| Prop | Tipo | Default | Descripción |
|
|
656
|
+
|---|---|---|---|
|
|
657
|
+
| `active` | boolean | — | Si es `false`, el componente no renderiza nada |
|
|
658
|
+
| `duration` | number (ms) | `10000` | Duración del temporizador cuando no se usa `value`/`expiresAt` |
|
|
659
|
+
| `onComplete` | function | — | Callback al llegar a 0 |
|
|
660
|
+
| `height` | string | `'6px'` | Alto de la barra |
|
|
661
|
+
| `width` | string | `'100%'` | Ancho del wrapper |
|
|
662
|
+
| `colors` | array de strings hex | `['#ef4444', '#f59e0b', '#10b981', '#3b82f6']` | Gradiente de colores interpolado según el progreso (rojo→azul de fin a inicio) |
|
|
663
|
+
| `expiresAt` | string/Date | — | Fecha/hora de expiración absoluta, alternativa a `duration` |
|
|
664
|
+
| `totalDuration` | number (ms) | `900000` | Duración total usada para calcular el % cuando se usa `expiresAt` |
|
|
665
|
+
| `value` | number (0-100) | — | Si se define, el progreso es controlado externamente (ignora el temporizador interno) |
|
|
666
|
+
| `increment` | boolean | `false` | Cuando se usa `value`, invierte la barra para que se vea "creciente" en vez de "decreciente" |
|
|
667
|
+
| `isOverlay` | boolean | `false` | Renderiza la barra centrada como overlay de pantalla, con `overlayMessage` |
|
|
668
|
+
| `overlayMessage` | string | — | Mensaje mostrado sobre la barra en modo overlay |
|
|
669
|
+
|
|
670
|
+
**Ejemplos:**
|
|
671
|
+
```jsx
|
|
672
|
+
<CountdownBar active duration={15000} height="10px" colors={['#ef4444', '#f97316', '#22c55e']} onComplete={handleDone} />
|
|
673
|
+
|
|
674
|
+
<CountdownBar active value={65} increment height="8px" />
|
|
675
|
+
|
|
676
|
+
<CountdownBar active duration={8000} isOverlay overlayMessage="Guardando cambios, no cierres esta ventana..." onComplete={handleDone} />
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
**Notas:** Envuelve la barra en `ModalTooltip` mostrando el porcentaje o segundos restantes. El hook interno `useCountdown` (en `utils.js`) captura `expiresAt`/`totalDuration` solo la primera vez que se activa.
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
### DateTag
|
|
684
|
+
|
|
685
|
+
Etiqueta/chip que muestra una fecha (y hora) formateada en español con un ícono de calendario.
|
|
686
|
+
|
|
687
|
+
**Import:**
|
|
688
|
+
```jsx
|
|
689
|
+
import DateTag from '../DateTag'; // export default (index.jsx)
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
**Uso básico:**
|
|
693
|
+
```jsx
|
|
694
|
+
<DateTag date="2026-09-12T10:30:00" />
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
**Props:**
|
|
698
|
+
|
|
699
|
+
| Prop | Tipo | Default | Descripción |
|
|
700
|
+
|---|---|---|---|
|
|
701
|
+
| `date` | string \| Date | — | Fecha a mostrar; si es falsy, el componente no renderiza nada |
|
|
702
|
+
| `bgColor` | string | `'var(--tag-bg, #f1f5f9)'` | Color de fondo |
|
|
703
|
+
| `textColor` | string | `'var(--tag-text, #475569)'` | Color de texto |
|
|
704
|
+
| `iconColor` | string | usa `textColor` como fallback | Color del ícono de calendario |
|
|
705
|
+
| `style` | object | `{}` | Estilos inline adicionales (tienen prioridad sobre `bgColor`/`textColor`) |
|
|
706
|
+
|
|
707
|
+
**Ejemplos:**
|
|
708
|
+
```jsx
|
|
709
|
+
<DateTag date="2026-01-05T08:00:00" bgColor="#fee2e2" textColor="#b91c1c" />
|
|
710
|
+
|
|
711
|
+
<DateTag date="2026-12-25T00:00:00" bgColor="#dcfce7" textColor="#166534" iconColor="#16a34a" />
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
**Notas:** El formato de fecha es fijo: `dd/MM/yyyy HH:mm` en locale `es-ES` (vía `toLocaleString`), no configurable por props.
|
|
715
|
+
|
|
716
|
+
---
|
|
717
|
+
|
|
718
|
+
### DesplegablePanel
|
|
719
|
+
|
|
720
|
+
Panel/fila expandible tipo "settings" (acordeón de un solo ítem): muestra un ícono, título y descripción, y al hacer click alterna la visibilidad de su contenido (controlado externamente vía `isOpen`/`onToggle`).
|
|
721
|
+
|
|
722
|
+
**Import:**
|
|
723
|
+
```jsx
|
|
724
|
+
import DesplegablePanel from '../DesplegablePanel'; // export default (index.jsx)
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
**Uso básico:**
|
|
728
|
+
```jsx
|
|
729
|
+
<DesplegablePanel
|
|
730
|
+
title="Notificaciones"
|
|
731
|
+
description="Administra cómo recibes las alertas del sistema"
|
|
732
|
+
icon={Bell}
|
|
733
|
+
isOpen={open}
|
|
734
|
+
onToggle={() => setOpen(!open)}
|
|
735
|
+
/>
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
**Props:**
|
|
739
|
+
|
|
740
|
+
| Prop | Tipo | Default | Descripción |
|
|
741
|
+
|---|---|---|---|
|
|
742
|
+
| `title` | string | — | Título de la fila |
|
|
743
|
+
| `description` | string | — | Descripción secundaria (opcional) |
|
|
744
|
+
| `icon` | componente (lucide-react) | — | Ícono a la izquierda |
|
|
745
|
+
| `iconColorVariant` | `'blue' \| 'green' \| 'purple' \| 'red' \| 'green2'` | — | Variante de color predefinida del contenedor del ícono |
|
|
746
|
+
| `iconColor` | string | — | Sobrescribe el color del ícono (`--dp-icon-color`) |
|
|
747
|
+
| `iconBgColor` | string | — | Sobrescribe el fondo del ícono (`--dp-icon-bg`) |
|
|
748
|
+
| `isOpen` | boolean | `false` | Controla si el contenido (`children`) está expandido |
|
|
749
|
+
| `onToggle` | function | — | Handler al hacer click en la fila |
|
|
750
|
+
| `action` | node | — | Si se define, reemplaza la flecha (chevron) por este contenido a la derecha |
|
|
751
|
+
| `children` | node | — | Contenido expandible, solo se renderiza si `isOpen` es `true` |
|
|
752
|
+
|
|
753
|
+
**Ejemplos:**
|
|
754
|
+
```jsx
|
|
755
|
+
<DesplegablePanel
|
|
756
|
+
title="Seguridad"
|
|
757
|
+
description="Configura las opciones de seguridad de tu cuenta"
|
|
758
|
+
icon={Shield}
|
|
759
|
+
iconColorVariant="green"
|
|
760
|
+
isOpen
|
|
761
|
+
onToggle={toggle}
|
|
762
|
+
>
|
|
763
|
+
<p>Aquí puedes activar la autenticación en dos pasos.</p>
|
|
764
|
+
</DesplegablePanel>
|
|
765
|
+
|
|
766
|
+
<DesplegablePanel
|
|
767
|
+
title="Perfil"
|
|
768
|
+
icon={User}
|
|
769
|
+
action={<span style={{ fontSize: '0.8rem', color: '#64748b' }}>Editar</span>}
|
|
770
|
+
onToggle={toggle}
|
|
771
|
+
/>
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
**Notas:** El componente es totalmente controlado: no maneja estado interno de apertura, depende de que el consumidor guarde `isOpen` y actualice en `onToggle`.
|
|
775
|
+
|
|
776
|
+
---
|
|
777
|
+
|
|
778
|
+
### DrawPanel
|
|
779
|
+
|
|
780
|
+
Panel lateral (drawer) deslizante renderizado vía portal, con header, footer de acciones opcional, barra de progreso (`CountdownBar`) opcional y protección contra cierre accidental cuando hay cambios sin guardar.
|
|
781
|
+
|
|
782
|
+
**Import:**
|
|
783
|
+
```jsx
|
|
784
|
+
import DrawPanel from '../DrawPanel'; // export default (index.jsx)
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
**Uso básico:**
|
|
788
|
+
```jsx
|
|
789
|
+
<DrawPanel
|
|
790
|
+
isOpen={open}
|
|
791
|
+
onClose={() => setOpen(false)}
|
|
792
|
+
title="Detalle del registro"
|
|
793
|
+
description="Revisa la información antes de continuar"
|
|
794
|
+
width="420px"
|
|
795
|
+
>
|
|
796
|
+
<p>Contenido del panel lateral.</p>
|
|
797
|
+
</DrawPanel>
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
**Props:**
|
|
801
|
+
|
|
802
|
+
| Prop | Tipo | Default | Descripción |
|
|
803
|
+
|---|---|---|---|
|
|
804
|
+
| `isOpen` | boolean | — | Controla apertura/cierre (anima entrada/salida antes de desmontar) |
|
|
805
|
+
| `onClose` | function | — | Handler de cierre (click en overlay, botón X o cancelar) |
|
|
806
|
+
| `title` | string | — | Título del panel |
|
|
807
|
+
| `description` | string | — | Texto descriptivo, ubicado según `descriptionPosition` |
|
|
808
|
+
| `descriptionPosition` | `'top' \| 'bottom'` | `'top'` | Dónde se muestra la descripción |
|
|
809
|
+
| `children` | node | — | Contenido principal del panel |
|
|
810
|
+
| `width` | string | `'400px'` | Ancho máximo del panel |
|
|
811
|
+
| `showActions` | boolean | `false` | Muestra footer con botones cancelar/confirmar |
|
|
812
|
+
| `onConfirm` | function | — | Handler del botón confirmar |
|
|
813
|
+
| `confirmText` | string | `'Confirmar'` | Texto del botón confirmar |
|
|
814
|
+
| `cancelText` | string | `'Cancelar'` | Texto del botón cancelar |
|
|
815
|
+
| `formId` | string | — | Si se define, el botón confirmar es `type="submit"` con `form={formId}` |
|
|
816
|
+
| `loading` | boolean | `false` | Estado de carga de los botones del footer |
|
|
817
|
+
| `success` | boolean \| undefined | `undefined` | Pasado al `Button` de confirmar |
|
|
818
|
+
| `className` | string | `''` | Clase adicional en el panel |
|
|
819
|
+
| `showCountdown` | boolean | `false` | Muestra una `CountdownBar` bajo el header |
|
|
820
|
+
| `countdownActive` | boolean | `true` | Activa el temporizador de la `CountdownBar` |
|
|
821
|
+
| `countdownDuration` | number | — | Duración pasada a `CountdownBar` |
|
|
822
|
+
| `countdownOnComplete` | function | — | Callback al completar el countdown |
|
|
823
|
+
| `countdownExpiresAt` | string/Date | — | Fecha de expiración para `CountdownBar` |
|
|
824
|
+
| `countdownTotalDuration` | number | — | Duración total para `CountdownBar` |
|
|
825
|
+
| `countdownValue` | number | — | Valor manual de progreso (ver `calculatedProgress`) |
|
|
826
|
+
| `countdownHeight` | string | — | Alto de la `CountdownBar` |
|
|
827
|
+
| `countdownColors` | array | — | Colores de la `CountdownBar` |
|
|
828
|
+
| `countdownIncrement` | boolean | `true` | Modo incremental de la `CountdownBar` |
|
|
829
|
+
| `progressMode` | `'count' \| 'selection' \| 'form'` | `'count'` | Cómo se calcula el progreso automáticamente |
|
|
830
|
+
| `totalFields` | number | `0` | Total de campos (modo `'count'`) |
|
|
831
|
+
| `filledFields` | number | `0` | Campos completados (modo `'count'`) |
|
|
832
|
+
| `totalItems` | array | `[]` | Ítems totales (modo `'selection'`) |
|
|
833
|
+
| `selectedItems` | array | `[]` | Ítems seleccionados (modo `'selection'`) |
|
|
834
|
+
| `formData` | object | — | Datos del formulario (modo `'form'`, y para detectar cambios sin guardar) |
|
|
835
|
+
| `requiredFields` | array | `[]` | Campos requeridos a validar (modo `'form'`) |
|
|
836
|
+
| `panelColor` | string | `'#ffffff'` | Color de fondo del panel/header/footer |
|
|
837
|
+
| `textColor` | string | `'#0f172a'` | Color del texto del título |
|
|
838
|
+
| `mutedTextColor` | string | `'#64748b'` | Color de textos secundarios/íconos |
|
|
839
|
+
| `borderColor` | string | `'#e2e8f0'` | Color de bordes del header/footer |
|
|
840
|
+
| `hasUnsavedChanges` | boolean | — | Fuerza el estado "sucio"; si no se define, se infiere de `formData` |
|
|
841
|
+
| `closeConfirmMessage` | string | `'Vuelve a hacer clic fuera para cerrar sin guardar'` | Mensaje mostrado al intentar cerrar con cambios sin guardar |
|
|
842
|
+
| `anchor` | `'right' \| 'top'` | `'right'` | Lado desde el que se desliza el panel |
|
|
843
|
+
|
|
844
|
+
**Ejemplos:**
|
|
845
|
+
```jsx
|
|
846
|
+
<DrawPanel
|
|
847
|
+
isOpen
|
|
848
|
+
onClose={handleClose}
|
|
849
|
+
onConfirm={handleConfirm}
|
|
850
|
+
title="Confirmar acción"
|
|
851
|
+
description="Esta acción no se puede deshacer"
|
|
852
|
+
descriptionPosition="bottom"
|
|
853
|
+
showActions
|
|
854
|
+
confirmText="Guardar"
|
|
855
|
+
>
|
|
856
|
+
<p>Formulario o resumen de la acción a confirmar.</p>
|
|
857
|
+
</DrawPanel>
|
|
858
|
+
|
|
859
|
+
<DrawPanel
|
|
860
|
+
isOpen
|
|
861
|
+
onClose={handleClose}
|
|
862
|
+
title="Selecciona elementos"
|
|
863
|
+
showCountdown
|
|
864
|
+
progressMode="selection"
|
|
865
|
+
totalItems={['a', 'b', 'c', 'd']}
|
|
866
|
+
selectedItems={['a', 'b']}
|
|
867
|
+
>
|
|
868
|
+
<p>2 de 4 elementos seleccionados.</p>
|
|
869
|
+
</DrawPanel>
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
**Notas:** Se renderiza con `createPortal` en `document.body`. Si hay `formData` con valores (o `hasUnsavedChanges` es `true`), el primer click fuera del panel o en el botón cerrar solo muestra un aviso (`closeConfirmMessage`); un segundo click sí cierra. Compone `Button` y `CountdownBar` internos del sistema.
|
|
873
|
+
|
|
874
|
+
---
|
|
875
|
+
|
|
876
|
+
### Filter
|
|
877
|
+
|
|
878
|
+
Barra de acciones para filtros de una tabla/listado: botón "Filtrar" que abre un panel lateral (drawer) con los campos de filtro, badge con el conteo de filtros activos, botón "Limpiar" e indicador del término de búsqueda actual.
|
|
879
|
+
|
|
880
|
+
**Import:**
|
|
881
|
+
```jsx
|
|
882
|
+
import Filter from '../Filter/index'; // export default, archivo index.jsx
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
**Uso básico:**
|
|
886
|
+
```jsx
|
|
887
|
+
<Filter title="Filtros" onApply={handleApply} onClear={handleClear}>
|
|
888
|
+
<TextField label="Nombre" placeholder="Buscar por nombre" />
|
|
889
|
+
</Filter>
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
**Props:**
|
|
893
|
+
|
|
894
|
+
| Prop | Tipo | Default | Descripción |
|
|
895
|
+
|---|---|---|---|
|
|
896
|
+
| children | node | — | Campos de filtro que se renderizan dentro del panel lateral. |
|
|
897
|
+
| onClear | function | — | Se ejecuta al pulsar "Limpiar". Si no se pasa, ese botón no se muestra. |
|
|
898
|
+
| onApply | function | — | Se ejecuta al pulsar "Aplicar"; además cierra el panel. |
|
|
899
|
+
| searchTerm | string | `''` | Si tiene valor, muestra un indicador "Buscar: {searchTerm}" en la barra. |
|
|
900
|
+
| width | string | `'350px'` | Ancho del panel lateral (DrawPanel). |
|
|
901
|
+
| title | string | `'Filtros'` | Título del panel lateral. |
|
|
902
|
+
| activeFiltersCount | number | `0` | Si es mayor a 0, muestra un badge numérico sobre el botón "Filtrar". |
|
|
903
|
+
| badgeColor | string | — | Color de fondo del badge (`--filter-badge-bg`). |
|
|
904
|
+
|
|
905
|
+
**Ejemplos:**
|
|
906
|
+
```jsx
|
|
907
|
+
<Filter
|
|
908
|
+
title="Filtros avanzados"
|
|
909
|
+
activeFiltersCount={3}
|
|
910
|
+
searchTerm="reporte mensual"
|
|
911
|
+
onApply={handleApply}
|
|
912
|
+
onClear={handleClear}
|
|
913
|
+
>
|
|
914
|
+
<TextField label="Nombre" placeholder="Buscar por nombre" />
|
|
915
|
+
<TextField label="Estado" placeholder="Activo, inactivo..." />
|
|
916
|
+
</Filter>
|
|
917
|
+
```
|
|
918
|
+
```jsx
|
|
919
|
+
<Filter title="Filtros" width="480px" onApply={handleApply} onClear={handleClear}>
|
|
920
|
+
<TextField label="Fecha desde" type="date" />
|
|
921
|
+
</Filter>
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
**Notas:** Compone internamente `DrawPanel`, `Button` y `ModalTooltip` (el badge muestra un tooltip "Filtros aplicados"). El botón "Limpiar" solo aparece si se pasa `onClear`.
|
|
925
|
+
|
|
926
|
+
---
|
|
927
|
+
|
|
928
|
+
### FormControls
|
|
929
|
+
|
|
930
|
+
Conjunto de tres componentes para armar formularios en tarjeta: `FormCard` (contenedor con encabezado e ícono), `FormInput` (campo de texto) y `FormTextArea` (área de texto multilínea).
|
|
931
|
+
|
|
932
|
+
**Import:**
|
|
933
|
+
```jsx
|
|
934
|
+
import { FormCard, FormInput, FormTextArea } from '../FormControls/index'; // named exports, archivo index.jsx
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
**Uso básico:**
|
|
938
|
+
```jsx
|
|
939
|
+
<FormCard icon={Settings} title="Preferencias">
|
|
940
|
+
<FormInput label="Nombre completo" placeholder="Juan Pérez" />
|
|
941
|
+
<FormTextArea label="Descripción" placeholder="Cuéntanos más detalles" rows={5} />
|
|
942
|
+
</FormCard>
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
**Props:**
|
|
946
|
+
|
|
947
|
+
#### FormCard
|
|
948
|
+
|
|
949
|
+
| Prop | Tipo | Default | Descripción |
|
|
950
|
+
|---|---|---|---|
|
|
951
|
+
| icon | componente (ícono) | — | Ícono (ej. de lucide-react) mostrado junto al título. |
|
|
952
|
+
| title | string | — | Título de la tarjeta. |
|
|
953
|
+
| children | node | — | Contenido del cuerpo de la tarjeta. |
|
|
954
|
+
| headerActions | node | — | Elemento(s) alineados a la derecha del header (ej. un botón "Editar"). |
|
|
955
|
+
| iconColor | string | — | Color del ícono (`--form-card-icon`). |
|
|
956
|
+
|
|
957
|
+
#### FormInput
|
|
958
|
+
|
|
959
|
+
| Prop | Tipo | Default | Descripción |
|
|
960
|
+
|---|---|---|---|
|
|
961
|
+
| label | string | — | Etiqueta del campo, pasada a `TextField`. |
|
|
962
|
+
| icon | componente | — | Se recibe pero actualmente no se renderiza (no tiene efecto visual). |
|
|
963
|
+
| ...props | any | — | Cualquier otra prop válida de `TextField` (placeholder, value, onChange, error, helperText, etc.). |
|
|
964
|
+
|
|
965
|
+
#### FormTextArea
|
|
966
|
+
|
|
967
|
+
| Prop | Tipo | Default | Descripción |
|
|
968
|
+
|---|---|---|---|
|
|
969
|
+
| label | string | — | Etiqueta del campo, pasada a `MultilinePlaceholder`. |
|
|
970
|
+
| icon | componente | — | Se recibe pero actualmente no se renderiza (no tiene efecto visual). |
|
|
971
|
+
| ...props | any | — | Cualquier otra prop válida de `MultilinePlaceholder` (rows, placeholder, value, onChange, error, etc.). |
|
|
972
|
+
|
|
973
|
+
**Ejemplos:**
|
|
974
|
+
```jsx
|
|
975
|
+
<FormCard icon={FileText} title="Datos del contacto" headerActions={<button type="button">Editar</button>}>
|
|
976
|
+
<FormInput label="Nombre completo" placeholder="Juan Pérez" />
|
|
977
|
+
</FormCard>
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
**Notas:** `FormInput` y `FormTextArea` son wrappers delgados de `TextField` y `MultilinePlaceholder` respectivamente: heredan todas sus props.
|
|
981
|
+
|
|
982
|
+
---
|
|
983
|
+
|
|
984
|
+
### Frame
|
|
985
|
+
|
|
986
|
+
Contenedor tipo "card" con título, ícono, descripción y estado de error/carga opcionales. Puede renderizarse inline o como modal (overlay + portal).
|
|
987
|
+
|
|
988
|
+
**Import:**
|
|
989
|
+
```jsx
|
|
990
|
+
import Frame from '../Frame/index'; // export default, archivo index.jsx
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
**Uso básico:**
|
|
994
|
+
```jsx
|
|
995
|
+
<Frame title="Información general" content="Este es un panel de contenido simple con título y descripción." />
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
**Props:**
|
|
999
|
+
|
|
1000
|
+
| Prop | Tipo | Default | Descripción |
|
|
1001
|
+
|---|---|---|---|
|
|
1002
|
+
| title | string | — | Título en el header del frame. |
|
|
1003
|
+
| icon | node | — | Ícono mostrado junto al título. |
|
|
1004
|
+
| content | string | — | Texto descriptivo debajo del header. |
|
|
1005
|
+
| error | string | — | Mensaje de error mostrado en rojo. |
|
|
1006
|
+
| children | node | — | Contenido principal del frame. |
|
|
1007
|
+
| className | string | `''` | Clase(s) CSS adicionales. |
|
|
1008
|
+
| isModal | boolean | `false` | Si es `true`, renderiza el frame como overlay modal vía `createPortal` a `document.body`. |
|
|
1009
|
+
| onClose | function | — | Se ejecuta al hacer click en el overlay (solo aplica con `isModal`). |
|
|
1010
|
+
| isLoading | boolean | `false` | Muestra un overlay con `Loading` (`size="giant"`) y oculta el contenido. |
|
|
1011
|
+
| bgColor | string | — | Color de fondo del frame (`--frame-bg`). |
|
|
1012
|
+
| iconColor | string | — | Color del contenedor del ícono (`--frame-icon`). |
|
|
1013
|
+
| descriptionBgColor | string | — | Color de fondo del texto de descripción (`--frame-description-bg`). |
|
|
1014
|
+
|
|
1015
|
+
**Ejemplos:**
|
|
1016
|
+
```jsx
|
|
1017
|
+
<Frame title="Error al cargar" error="No se pudo obtener la información solicitada." />
|
|
1018
|
+
```
|
|
1019
|
+
```jsx
|
|
1020
|
+
<Frame title="Cargando datos" isLoading={true}>
|
|
1021
|
+
<p>Este contenido queda oculto mientras carga.</p>
|
|
1022
|
+
</Frame>
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
**Notas:** `isModal` renderiza vía `createPortal` sobre `document.body` con un overlay que cierra al hacer click fuera (así lo usa internamente `HoursPicker`). Depende del componente `Loading` para el estado `isLoading`.
|
|
1026
|
+
|
|
1027
|
+
---
|
|
1028
|
+
|
|
1029
|
+
### GreenHighlight
|
|
1030
|
+
|
|
1031
|
+
Envoltorio `<strong>` para resaltar texto (por ejemplo montos o palabras clave) con color de texto/fondo personalizables.
|
|
1032
|
+
|
|
1033
|
+
**Import:**
|
|
1034
|
+
```jsx
|
|
1035
|
+
import GreenHighlight from '../GreenHighlight/index'; // export default, archivo index.jsx
|
|
1036
|
+
```
|
|
1037
|
+
|
|
1038
|
+
**Uso básico:**
|
|
1039
|
+
```jsx
|
|
1040
|
+
<GreenHighlight>texto destacado</GreenHighlight>
|
|
1041
|
+
```
|
|
1042
|
+
|
|
1043
|
+
**Props:**
|
|
1044
|
+
|
|
1045
|
+
| Prop | Tipo | Default | Descripción |
|
|
1046
|
+
|---|---|---|---|
|
|
1047
|
+
| children | node | — | Contenido a resaltar. |
|
|
1048
|
+
| textColor | string | — | Color del texto (`--green-highlight-text`). |
|
|
1049
|
+
| bgColor | string | — | Color de fondo (`--green-highlight-bg`). |
|
|
1050
|
+
| style | object | — | Estilos inline adicionales; se combinan con las variables de color. |
|
|
1051
|
+
|
|
1052
|
+
**Ejemplos:**
|
|
1053
|
+
```jsx
|
|
1054
|
+
<p>
|
|
1055
|
+
El pedido fue <GreenHighlight>aprobado exitosamente</GreenHighlight> y está listo para su envío.
|
|
1056
|
+
</p>
|
|
1057
|
+
```
|
|
1058
|
+
```jsx
|
|
1059
|
+
<GreenHighlight>$1,250.00</GreenHighlight>
|
|
1060
|
+
```
|
|
1061
|
+
|
|
1062
|
+
**Notas:** Existe un helper `formatHighlightedText` (`GreenHighlight/utils.jsx`) que convierte automáticamente segmentos `**texto**` dentro de un string en `<GreenHighlight>`; lo usan internamente `TextField` y `MultilinePlaceholder` para sus props `label`/`helperText`.
|
|
1063
|
+
|
|
1064
|
+
---
|
|
1065
|
+
|
|
1066
|
+
### HoursPicker
|
|
1067
|
+
|
|
1068
|
+
Selector de hora (formato 12h AM/PM en la UI, valor en formato 24h) implementado como un `TextField` de solo lectura que abre un modal con ruedas de hora/minuto y accesos rápidos.
|
|
1069
|
+
|
|
1070
|
+
**Import:**
|
|
1071
|
+
```jsx
|
|
1072
|
+
import HoursPicker from '../HoursPicker/index'; // export default, archivo index.jsx
|
|
1073
|
+
```
|
|
1074
|
+
|
|
1075
|
+
**Uso básico:**
|
|
1076
|
+
```jsx
|
|
1077
|
+
<HoursPicker
|
|
1078
|
+
label="Hora de inicio"
|
|
1079
|
+
name="startTime"
|
|
1080
|
+
value={value}
|
|
1081
|
+
onChange={(e) => setValue(e.target.value)}
|
|
1082
|
+
/>
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1085
|
+
**Props:**
|
|
1086
|
+
|
|
1087
|
+
| Prop | Tipo | Default | Descripción |
|
|
1088
|
+
|---|---|---|---|
|
|
1089
|
+
| label | string | — | Etiqueta del `TextField` que dispara el selector. |
|
|
1090
|
+
| name | string | — | Nombre devuelto en `event.target.name`. |
|
|
1091
|
+
| value | string | — | Hora en formato 24h `"HH:MM"` (ej. `"14:30"`). |
|
|
1092
|
+
| onChange | function | — | Se llama con un evento simulado `{ target: { name, value, type: 'time' } }` al confirmar, limpiar o al usar "Hora Actual". |
|
|
1093
|
+
| required | boolean | `false` | Marca el campo como obligatorio (asterisco en el `TextField`). |
|
|
1094
|
+
| disabled | boolean | `false` | Deshabilita la apertura del selector. |
|
|
1095
|
+
| selectedColor | string | `'#10b981'` | Color de la columna hora/minuto activa y de los presets seleccionados. |
|
|
1096
|
+
| accentColor | string | `'#0f172a'` | Color de acento del botón "Confirmar" y de selecciones por defecto. |
|
|
1097
|
+
|
|
1098
|
+
**Ejemplos:**
|
|
1099
|
+
```jsx
|
|
1100
|
+
<HoursPicker label="Hora límite" name="deadlineTime" value="09:00" required onChange={handleChange} />
|
|
1101
|
+
```
|
|
1102
|
+
```jsx
|
|
1103
|
+
<HoursPicker label="Hora de cierre" name="closeTime" value="18:00" disabled onChange={handleChange} />
|
|
1104
|
+
```
|
|
1105
|
+
|
|
1106
|
+
**Notas:** Al abrirse renderiza un `Frame` en modo modal (`isModal`) con selector numérico, presets rápidos (`QUICK_TIMES` en `Constants.js`) y botones "Hora Actual" / "Confirmar" / "Borrar". Depende de `TextField`, `Frame` y `Button`.
|
|
1107
|
+
|
|
1108
|
+
---
|
|
1109
|
+
|
|
1110
|
+
### InfoTooltip
|
|
1111
|
+
|
|
1112
|
+
Botón de ayuda (ícono) que al hacer click abre un popover con un título y contenido explicativo; se cierra al hacer click fuera.
|
|
1113
|
+
|
|
1114
|
+
**Import:**
|
|
1115
|
+
```jsx
|
|
1116
|
+
import InfoTooltip from '../InfoTooltip/index'; // export default, archivo index.jsx
|
|
1117
|
+
```
|
|
1118
|
+
|
|
1119
|
+
**Uso básico:**
|
|
1120
|
+
```jsx
|
|
1121
|
+
<InfoTooltip
|
|
1122
|
+
title="¿Qué es esto?"
|
|
1123
|
+
content="Este campo se utiliza para identificar de forma única cada registro en el sistema."
|
|
1124
|
+
/>
|
|
1125
|
+
```
|
|
1126
|
+
|
|
1127
|
+
**Props:**
|
|
1128
|
+
|
|
1129
|
+
| Prop | Tipo | Default | Descripción |
|
|
1130
|
+
|---|---|---|---|
|
|
1131
|
+
| content | string \| string[] | — | Contenido del popover; si es un arreglo de strings, se renderiza un párrafo por elemento. |
|
|
1132
|
+
| title | string | — | Título del popover (también se usa como `aria-label` del botón disparador). |
|
|
1133
|
+
| icon | componente | `HelpCircle` (lucide-react) | Ícono del botón disparador. |
|
|
1134
|
+
| iconSize | number | `18` | Tamaño del ícono. |
|
|
1135
|
+
| iconColor | string | `'#94a3b8'` | Color del ícono. |
|
|
1136
|
+
| width | string | `'280px'` | Ancho del popover. |
|
|
1137
|
+
|
|
1138
|
+
**Ejemplos:**
|
|
1139
|
+
```jsx
|
|
1140
|
+
<InfoTooltip
|
|
1141
|
+
title="Detalles del cálculo"
|
|
1142
|
+
content={[
|
|
1143
|
+
'El total se calcula sumando todos los conceptos activos.',
|
|
1144
|
+
'Los descuentos se aplican antes de los impuestos.',
|
|
1145
|
+
]}
|
|
1146
|
+
/>
|
|
1147
|
+
```
|
|
1148
|
+
```jsx
|
|
1149
|
+
<InfoTooltip title="Información adicional" content="..." icon={Info} iconSize={22} iconColor="#3b82f6" width="320px" />
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
---
|
|
1153
|
+
|
|
1154
|
+
### Input
|
|
1155
|
+
|
|
1156
|
+
Wrapper de `TextField` que agrega manejo simplificado de `required` (asterisco `**`) y de `error`/`helperText`.
|
|
1157
|
+
|
|
1158
|
+
**Import:**
|
|
1159
|
+
```jsx
|
|
1160
|
+
import Input from '../Input/index'; // export default, forwardRef, archivo index.jsx
|
|
1161
|
+
```
|
|
1162
|
+
|
|
1163
|
+
**Uso básico:**
|
|
1164
|
+
```jsx
|
|
1165
|
+
<Input label="Nombre" placeholder="Escribe tu nombre" />
|
|
1166
|
+
```
|
|
1167
|
+
|
|
1168
|
+
**Props:**
|
|
1169
|
+
|
|
1170
|
+
| Prop | Tipo | Default | Descripción |
|
|
1171
|
+
|---|---|---|---|
|
|
1172
|
+
| label | string | — | Etiqueta del campo; si `required` es `true` se le agrega `**` en el color de `requiredColor`. |
|
|
1173
|
+
| id | string | — | id del input. |
|
|
1174
|
+
| className | string | `''` | Clase CSS adicional. |
|
|
1175
|
+
| error | string | — | Mensaje de error; si existe, reemplaza a `helperText` y activa el estado de error. |
|
|
1176
|
+
| helperText | string | — | Texto de ayuda bajo el campo (se ignora si hay `error`). |
|
|
1177
|
+
| required | boolean | — | Muestra el indicador `**` junto a la etiqueta. |
|
|
1178
|
+
| requiredColor | string | `'red'` | Color del indicador de requerido. |
|
|
1179
|
+
| ...props | any | — | Cualquier otra prop de `TextField` (`type`, `placeholder`, `value`, `onChange`, `disabled`, etc.). |
|
|
1180
|
+
|
|
1181
|
+
**Ejemplos:**
|
|
1182
|
+
```jsx
|
|
1183
|
+
<Input label="Teléfono" placeholder="555-555-5555" error="El número de teléfono no es válido" />
|
|
1184
|
+
```
|
|
1185
|
+
```jsx
|
|
1186
|
+
<Input label="Contraseña" type="password" helperText="Debe tener al menos 8 caracteres" />
|
|
1187
|
+
```
|
|
1188
|
+
|
|
1189
|
+
**Notas:** Es un wrapper de `TextField` con `forwardRef`, por lo que la `ref` se reenvía al input nativo.
|
|
1190
|
+
|
|
1191
|
+
---
|
|
1192
|
+
|
|
1193
|
+
### Loading
|
|
1194
|
+
|
|
1195
|
+
Indicador de carga con varias variantes visuales (spinner, barras, rebote, caja) y texto opcional, incluyendo rotación automática entre varias frases.
|
|
1196
|
+
|
|
1197
|
+
**Import:**
|
|
1198
|
+
```jsx
|
|
1199
|
+
import Loading from '../Loading/index'; // export default, archivo index.jsx
|
|
1200
|
+
```
|
|
1201
|
+
|
|
1202
|
+
**Uso básico:**
|
|
1203
|
+
```jsx
|
|
1204
|
+
<Loading text="Cargando..." />
|
|
1205
|
+
```
|
|
1206
|
+
|
|
1207
|
+
**Props:**
|
|
1208
|
+
|
|
1209
|
+
| Prop | Tipo | Default | Descripción |
|
|
1210
|
+
|---|---|---|---|
|
|
1211
|
+
| text | string | `''` | Texto fijo mostrado junto al loader (se ignora si se pasa `phrases`). |
|
|
1212
|
+
| phrases | string[] | `[]` | Frases que rotan automáticamente cada 3.5s con transición de fundido. |
|
|
1213
|
+
| size | `'small'` \| `'medium'` \| `'large'` \| `'giant'` | `'medium'` | Tamaño del loader. |
|
|
1214
|
+
| variant | `'default'` \| `'bars'` \| `'bounce'` \| `'box'` | `'default'` | Estilo visual del loader (`'default'` es el spinner circular). |
|
|
1215
|
+
| className | string | `''` | Clase(s) CSS adicionales. |
|
|
1216
|
+
| color | string | — | Color personalizado del loader (`--loading-color`). |
|
|
1217
|
+
|
|
1218
|
+
**Ejemplos:**
|
|
1219
|
+
```jsx
|
|
1220
|
+
<Loading phrases={['Cargando datos...', 'Procesando información...', 'Casi listo...']} />
|
|
1221
|
+
```
|
|
1222
|
+
```jsx
|
|
1223
|
+
<Loading text="Un momento..." size="large" variant="bars" />
|
|
1224
|
+
```
|
|
1225
|
+
|
|
1226
|
+
**Notas:** Es usado internamente por `Frame` (prop `isLoading`) con `size="giant"`.
|
|
1227
|
+
|
|
1228
|
+
---
|
|
1229
|
+
|
|
1230
|
+
### MarkdownContent
|
|
1231
|
+
|
|
1232
|
+
Renderiza una cadena markdown como HTML, con soporte GFM (tablas, listas de tareas, etc.) vía `react-markdown` + `remark-gfm`.
|
|
1233
|
+
|
|
1234
|
+
**Import:**
|
|
1235
|
+
```jsx
|
|
1236
|
+
import { MarkdownContent } from '../MarkdownContent/index'; // named export (también default export)
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
**Uso básico:**
|
|
1240
|
+
```jsx
|
|
1241
|
+
<MarkdownContent>{'# Heading\n\nThis is a **bold** paragraph.'}</MarkdownContent>
|
|
1242
|
+
```
|
|
1243
|
+
|
|
1244
|
+
**Props:**
|
|
1245
|
+
|
|
1246
|
+
| Prop | Tipo | Default | Descripción |
|
|
1247
|
+
|---|---|---|---|
|
|
1248
|
+
| children | string | — | Contenido markdown a renderizar. |
|
|
1249
|
+
| className | string | `''` | Clase(s) CSS adicionales. |
|
|
1250
|
+
| style | object | — | Estilos inline adicionales. |
|
|
1251
|
+
| components | object | — | Mapa de renderers personalizados de `react-markdown`. |
|
|
1252
|
+
| linkColor | string | — | Color de los enlaces (`--markdown-link`). |
|
|
1253
|
+
|
|
1254
|
+
**Ejemplos:**
|
|
1255
|
+
```jsx
|
|
1256
|
+
<MarkdownContent>{'| Col 1 | Col 2 |\n| --- | --- |\n| A | B |'}</MarkdownContent>
|
|
1257
|
+
```
|
|
1258
|
+
```jsx
|
|
1259
|
+
<MarkdownContent>{'```js\nfunction greet(name) {\n return `Hello, ${name}!`;\n}\n```'}</MarkdownContent>
|
|
1260
|
+
```
|
|
1261
|
+
|
|
1262
|
+
---
|
|
1263
|
+
|
|
1264
|
+
### MarkdownEditor
|
|
1265
|
+
|
|
1266
|
+
Editor de texto markdown con barra de herramientas (negrita, cursiva, encabezados, listas, cita, código, enlace, tabla), atajos de teclado, modos Editor/Dividido/Vista previa y altura ajustable con arrastre.
|
|
1267
|
+
|
|
1268
|
+
**Import:**
|
|
1269
|
+
```jsx
|
|
1270
|
+
import { MarkdownEditor } from '../MarkdownEditor/index'; // named export (también default export)
|
|
1271
|
+
```
|
|
1272
|
+
|
|
1273
|
+
**Uso básico:**
|
|
1274
|
+
```jsx
|
|
1275
|
+
const [value, setValue] = useState('# Hello world');
|
|
1276
|
+
|
|
1277
|
+
<MarkdownEditor
|
|
1278
|
+
value={value}
|
|
1279
|
+
onChange={(e) => setValue(e.target.value)}
|
|
1280
|
+
placeholder="Write your markdown here..."
|
|
1281
|
+
/>
|
|
1282
|
+
```
|
|
1283
|
+
|
|
1284
|
+
**Props:**
|
|
1285
|
+
|
|
1286
|
+
| Prop | Tipo | Default | Descripción |
|
|
1287
|
+
|---|---|---|---|
|
|
1288
|
+
| value | string | `''` | Contenido markdown controlado. |
|
|
1289
|
+
| onChange | function | — | Se llama con un evento simulado `{ target: { value } }`. |
|
|
1290
|
+
| placeholder | string | `''` | Placeholder del textarea. |
|
|
1291
|
+
| defaultHeight | number | `320` | Alto inicial (px) del área de contenido; ajustable arrastrando el handle inferior (entre 180 y 1200px). |
|
|
1292
|
+
| labels | object | `{}` | Textos personalizables: `editorTab`, `splitTab`, `previewTab`, tooltips de cada botón, textos por defecto al insertar formato, encabezados de la tabla de ejemplo. |
|
|
1293
|
+
| activeColor | string | — | Color de acento del modo/pestaña activa (`--markdown-editor-active`). |
|
|
1294
|
+
|
|
1295
|
+
**Ejemplos:**
|
|
1296
|
+
```jsx
|
|
1297
|
+
<MarkdownEditor
|
|
1298
|
+
value={value}
|
|
1299
|
+
onChange={(e) => setValue(e.target.value)}
|
|
1300
|
+
defaultHeight={260}
|
|
1301
|
+
placeholder="Type something..."
|
|
1302
|
+
/>
|
|
1303
|
+
```
|
|
1304
|
+
```jsx
|
|
1305
|
+
<MarkdownEditor
|
|
1306
|
+
value={value}
|
|
1307
|
+
onChange={(e) => setValue(e.target.value)}
|
|
1308
|
+
labels={{ editorTab: 'Editar', splitTab: 'Dividido', previewTab: 'Vista previa' }}
|
|
1309
|
+
/>
|
|
1310
|
+
```
|
|
1311
|
+
|
|
1312
|
+
**Notas:** Es un componente controlado (`value`/`onChange` obligatorios); el modo de vista es estado interno. Soporta atajos `Ctrl+B`, `Ctrl+I`, `Ctrl+K` y continuación automática de listas al presionar Enter. Usa `MarkdownContent` para la vista previa.
|
|
1313
|
+
|
|
1314
|
+
---
|
|
1315
|
+
|
|
1316
|
+
### InputWithIcon
|
|
1317
|
+
|
|
1318
|
+
Campo de texto de Material-UI con un ícono (lucide-react) como adorno, con tres presentaciones distintas: `outlined`/`filled` (adorno dentro del campo), `standard` y `row` (ícono al costado, fuera del campo).
|
|
1319
|
+
|
|
1320
|
+
**Import:**
|
|
1321
|
+
```jsx
|
|
1322
|
+
import InputWithIcon from '../Material-UI/Components/InputWithIcon/index'; // export default, archivo index.jsx
|
|
1323
|
+
```
|
|
1324
|
+
|
|
1325
|
+
**Uso básico:**
|
|
1326
|
+
```jsx
|
|
1327
|
+
<InputWithIcon label="Correo electrónico" icon={Mail} value={value} onChange={(e) => setValue(e.target.value)} />
|
|
1328
|
+
```
|
|
1329
|
+
|
|
1330
|
+
**Props:**
|
|
1331
|
+
|
|
1332
|
+
| Prop | Tipo | Default | Descripción |
|
|
1333
|
+
|---|---|---|---|
|
|
1334
|
+
| label | string | — | Etiqueta del campo. |
|
|
1335
|
+
| value | string | — | Valor controlado. |
|
|
1336
|
+
| onChange | function | — | Handler estándar de evento de input. |
|
|
1337
|
+
| icon | componente (ícono) | — | Ícono mostrado como adorno. |
|
|
1338
|
+
| placeholder | string | — | Placeholder del campo. |
|
|
1339
|
+
| type | string | `'text'` | Tipo de input HTML. |
|
|
1340
|
+
| variant | `'standard'` \| `'outlined'` \| `'row'` \| `'filled'` | `'outlined'` | Presentación visual; `'row'` coloca el ícono fuera del campo. |
|
|
1341
|
+
| fullWidth | boolean | `true` | Si ocupa el 100% del ancho disponible. |
|
|
1342
|
+
| iconColor | string | `'black'` | Color del ícono (solo aplica en `standard` y `row`; en `outlined`/`filled` usa `currentColor`). |
|
|
1343
|
+
| ...props | any | — | Cualquier otra prop de `TextField`/`Input` de Material-UI. |
|
|
1344
|
+
|
|
1345
|
+
**Ejemplos:**
|
|
1346
|
+
```jsx
|
|
1347
|
+
<InputWithIcon label="Usuario" icon={User} variant="standard" value={value} onChange={onChange} />
|
|
1348
|
+
```
|
|
1349
|
+
```jsx
|
|
1350
|
+
<InputWithIcon label="Buscar" icon={SearchIcon} variant="row" value={value} onChange={onChange} />
|
|
1351
|
+
```
|
|
1352
|
+
|
|
1353
|
+
---
|
|
1354
|
+
|
|
1355
|
+
### MenuPopover
|
|
1356
|
+
|
|
1357
|
+
Botón de navegación que al hacer click abre un menú desplegable de Material-UI (`Menu`/`MenuItem`), pensado para ítems de un sidebar con sub-opciones.
|
|
1358
|
+
|
|
1359
|
+
**Import:**
|
|
1360
|
+
```jsx
|
|
1361
|
+
import MenuPopover from '../Material-UI/Components/MenuPopover/index'; // export default, archivo index.jsx
|
|
1362
|
+
```
|
|
1363
|
+
|
|
1364
|
+
**Uso básico:**
|
|
1365
|
+
```jsx
|
|
1366
|
+
<MenuPopover
|
|
1367
|
+
item={{ label: 'Opciones', icon: Settings, subItems: [{ label: 'Editar' }, { label: 'Eliminar', isDanger: true }] }}
|
|
1368
|
+
renderIcon={(Icon) => (Icon ? <Icon size={18} /> : null)}
|
|
1369
|
+
onNavigate={(subItem) => console.log('navigate to', subItem)}
|
|
1370
|
+
isCollapsed={false}
|
|
1371
|
+
/>
|
|
1372
|
+
```
|
|
1373
|
+
|
|
1374
|
+
**Props:**
|
|
1375
|
+
|
|
1376
|
+
| Prop | Tipo | Default | Descripción |
|
|
1377
|
+
|---|---|---|---|
|
|
1378
|
+
| item | object | — | `{ label, icon, subItems: [{ label, isDanger? }] }`. Requerido. |
|
|
1379
|
+
| styles | object | `{}` | Objeto de clases CSS externas (ej. `{ navItem, icon }`) aplicadas al botón disparador. |
|
|
1380
|
+
| renderIcon | function | — | `(icon, className) => node`; renderiza el ícono de `item.icon`. |
|
|
1381
|
+
| onNavigate | function | — | Se llama con el `subItem` clickeado. |
|
|
1382
|
+
| isCollapsed | boolean | — | Si es `true`, oculta el texto del label y la flecha. |
|
|
1383
|
+
| children | node \| function | — | Contenido personalizado del menú; si es función, recibe `{ handleClose }` (render prop). |
|
|
1384
|
+
| triggerProps | object | `{}` | Props adicionales que se mezclan en el botón disparador. |
|
|
1385
|
+
| bgColor | string | `'#ffffffff'` | Color de fondo del panel del menú. |
|
|
1386
|
+
| textColor | string | `'#000000ff'` | Color de texto de las opciones. |
|
|
1387
|
+
| dangerColor | string | `'#ef4444'` | Color de las opciones marcadas como peligrosas. |
|
|
1388
|
+
|
|
1389
|
+
**Ejemplos:**
|
|
1390
|
+
```jsx
|
|
1391
|
+
<MenuPopover item={item} renderIcon={renderIcon} onNavigate={onNavigate} isCollapsed={true} />
|
|
1392
|
+
```
|
|
1393
|
+
|
|
1394
|
+
**Notas:** Un `subItem` se resalta con `dangerColor` si tiene `isDanger: true`, o si su `label` contiene "eliminar" o "cancelar".
|
|
1395
|
+
|
|
1396
|
+
---
|
|
1397
|
+
|
|
1398
|
+
### MultilinePlaceholder
|
|
1399
|
+
|
|
1400
|
+
`TextField` multilínea (textarea), hermano de `TextField` de este mismo kit, con el mismo soporte de resaltado `**texto**` en `label`/`helperText`.
|
|
1401
|
+
|
|
1402
|
+
**Import:**
|
|
1403
|
+
```jsx
|
|
1404
|
+
import MultilinePlaceholder from '../Material-UI/Components/MultilinePlaceholder/index'; // export default, forwardRef, archivo index.jsx
|
|
1405
|
+
```
|
|
1406
|
+
|
|
1407
|
+
**Uso básico:**
|
|
1408
|
+
```jsx
|
|
1409
|
+
<MultilinePlaceholder label="Descripción" placeholder="Escribe una descripción..." rows={4} value={value} onChange={onChange} />
|
|
1410
|
+
```
|
|
1411
|
+
|
|
1412
|
+
**Props:**
|
|
1413
|
+
|
|
1414
|
+
| Prop | Tipo | Default | Descripción |
|
|
1415
|
+
|---|---|---|---|
|
|
1416
|
+
| label | string \| node | — | Etiqueta del campo; admite `**texto**` para resaltar con `GreenHighlight`. |
|
|
1417
|
+
| value | string | — | Valor controlado. |
|
|
1418
|
+
| onChange | function | — | Handler de evento de input. |
|
|
1419
|
+
| error | string | — | Mensaje de error; si existe, activa el estado de error y reemplaza a `helperText`. |
|
|
1420
|
+
| helperText | string \| node | — | Texto de ayuda (admite `**texto**` como el `label`). |
|
|
1421
|
+
| rows | number | `4` | Número de filas visibles. |
|
|
1422
|
+
| maxRows | number | — | Límite de filas al auto-crecer. |
|
|
1423
|
+
| variant | string | `'outlined'` | Variant de `TextField`. |
|
|
1424
|
+
| size | string | `'small'` | Tamaño de `TextField`. |
|
|
1425
|
+
| fullWidth | boolean | `true` | Si ocupa el 100% del ancho disponible. |
|
|
1426
|
+
| placeholder | string | — | Placeholder del campo. |
|
|
1427
|
+
| bgColor | string | `'#fff'` | Color de fondo del input. |
|
|
1428
|
+
| ...props | any | — | Cualquier otra prop de `TextField` de Material-UI. |
|
|
1429
|
+
|
|
1430
|
+
**Ejemplos:**
|
|
1431
|
+
```jsx
|
|
1432
|
+
<MultilinePlaceholder label="Notas" helperText="Opcional, máximo 500 caracteres." rows={3} value={value} onChange={onChange} />
|
|
1433
|
+
```
|
|
1434
|
+
```jsx
|
|
1435
|
+
<MultilinePlaceholder label="Comentarios" error="Este campo es obligatorio" rows={3} value={value} onChange={onChange} />
|
|
1436
|
+
```
|
|
1437
|
+
|
|
1438
|
+
---
|
|
1439
|
+
|
|
1440
|
+
### Paginador
|
|
1441
|
+
|
|
1442
|
+
Barra de paginación de Material-UI con selector opcional de "filas por página".
|
|
1443
|
+
|
|
1444
|
+
**Import:**
|
|
1445
|
+
```jsx
|
|
1446
|
+
import Paginador from '../Material-UI/Components/Paginador/index'; // export default, archivo index.jsx
|
|
1447
|
+
```
|
|
1448
|
+
|
|
1449
|
+
**Uso básico:**
|
|
1450
|
+
```jsx
|
|
1451
|
+
<Paginador count={10} page={page} onChange={(e, value) => setPage(value)} />
|
|
1452
|
+
```
|
|
1453
|
+
|
|
1454
|
+
**Props:**
|
|
1455
|
+
|
|
1456
|
+
| Prop | Tipo | Default | Descripción |
|
|
1457
|
+
|---|---|---|---|
|
|
1458
|
+
| count | number | `10` | Número total de páginas. |
|
|
1459
|
+
| page | number | `1` | Página actual. |
|
|
1460
|
+
| onChange | function | — | Handler estándar de `Pagination` de MUI: `(event, page) => void`. |
|
|
1461
|
+
| color | string | `'primary'` | Color de `Pagination`. |
|
|
1462
|
+
| size | string | `'medium'` | Tamaño de `Pagination`. |
|
|
1463
|
+
| disabled | boolean | `false` | Deshabilita la paginación (y el selector de filas, si está presente). |
|
|
1464
|
+
| variant | string | `'outlined'` | Variant de `Pagination`. |
|
|
1465
|
+
| shape | string | `'rounded'` | Forma de los botones de `Pagination`. |
|
|
1466
|
+
| pageSize | number | — | Valor actual del selector de "Filas". Si se pasa junto con `onPageSizeChange`, se muestra el `Select` a la izquierda. |
|
|
1467
|
+
| pageSizeOptions | number[] | `[5, 10, 20, 50]` | Opciones del selector de filas por página. |
|
|
1468
|
+
| onPageSizeChange | function | — | `(newPageSize: number) => void`. |
|
|
1469
|
+
| ...props | any | — | Cualquier otra prop de `Pagination` de Material-UI. |
|
|
1470
|
+
|
|
1471
|
+
**Ejemplos:**
|
|
1472
|
+
```jsx
|
|
1473
|
+
<Paginador
|
|
1474
|
+
count={15}
|
|
1475
|
+
page={page}
|
|
1476
|
+
onChange={(e, value) => setPage(value)}
|
|
1477
|
+
pageSize={pageSize}
|
|
1478
|
+
pageSizeOptions={[5, 10, 20, 50]}
|
|
1479
|
+
onPageSizeChange={setPageSize}
|
|
1480
|
+
/>
|
|
1481
|
+
```
|
|
1482
|
+
```jsx
|
|
1483
|
+
<Paginador count={10} page={3} disabled onChange={onChange} />
|
|
1484
|
+
```
|
|
1485
|
+
|
|
1486
|
+
**Notas:** El selector de "Filas" solo se renderiza si se pasan **ambos** `pageSize` y `onPageSizeChange`.
|
|
1487
|
+
|
|
1488
|
+
---
|
|
1489
|
+
|
|
1490
|
+
### Search
|
|
1491
|
+
|
|
1492
|
+
Campo de búsqueda basado en `Autocomplete` de Material-UI, con estado de carga y modo `freeSolo` (texto libre sin opciones).
|
|
1493
|
+
|
|
1494
|
+
**Import:**
|
|
1495
|
+
```jsx
|
|
1496
|
+
import Search from '../Material-UI/Components/Search/index'; // export default, archivo index.jsx
|
|
1497
|
+
```
|
|
1498
|
+
|
|
1499
|
+
**Uso básico:**
|
|
1500
|
+
```jsx
|
|
1501
|
+
<Search
|
|
1502
|
+
options={options}
|
|
1503
|
+
value={value}
|
|
1504
|
+
onChange={setValue}
|
|
1505
|
+
inputValue={inputValue}
|
|
1506
|
+
onInputChange={setInputValue}
|
|
1507
|
+
label="Buscar usuario"
|
|
1508
|
+
/>
|
|
1509
|
+
```
|
|
1510
|
+
|
|
1511
|
+
**Props:**
|
|
1512
|
+
|
|
1513
|
+
| Prop | Tipo | Default | Descripción |
|
|
1514
|
+
|---|---|---|---|
|
|
1515
|
+
| open | boolean | — | Controla si el desplegable está abierto. |
|
|
1516
|
+
| onOpen | function | — | Callback al abrirse el desplegable. |
|
|
1517
|
+
| onClose | function | — | Callback al cerrarse el desplegable. |
|
|
1518
|
+
| options | array | `[]` | Lista de opciones (objetos, ej. `{ label, value }`). |
|
|
1519
|
+
| loading | boolean | `false` | Muestra un `CircularProgress` como adorno final. |
|
|
1520
|
+
| value | any | — | Opción seleccionada (controlado). |
|
|
1521
|
+
| onChange | function | — | `(newValue) => void` — recibe el valor directamente, no el evento de MUI. |
|
|
1522
|
+
| inputValue | string | — | Texto actual del input (controlado). |
|
|
1523
|
+
| onInputChange | function | — | `(newInputValue) => void`. |
|
|
1524
|
+
| getOptionLabel | function | `option => option?.label \|\| ''` | Cómo obtener el texto de cada opción. |
|
|
1525
|
+
| isOptionEqualToValue | function | `(option, val) => option?.value === val?.value` | Comparador de igualdad de opciones. |
|
|
1526
|
+
| label | string | `'Buscar'` | Etiqueta del `TextField` interno. |
|
|
1527
|
+
| placeholder | string | `'Buscar...'` | Placeholder del `TextField` interno. |
|
|
1528
|
+
| freeSolo | boolean | `false` | Si es `true` y `options` está vacío, renderiza un `TextField` simple (texto libre) en vez de `Autocomplete`. |
|
|
1529
|
+
| ...props | any | — | Cualquier otra prop de `Autocomplete` de Material-UI. |
|
|
1530
|
+
|
|
1531
|
+
**Ejemplos:**
|
|
1532
|
+
```jsx
|
|
1533
|
+
<Search options={[]} loading={true} label="Buscar usuario" value={value} onChange={setValue} inputValue={inputValue} onInputChange={setInputValue} />
|
|
1534
|
+
```
|
|
1535
|
+
```jsx
|
|
1536
|
+
<Search freeSolo options={[]} label="Buscar" placeholder="Escribe texto libre..." value={value} onChange={setValue} />
|
|
1537
|
+
```
|
|
1538
|
+
|
|
1539
|
+
**Notas:** A diferencia del `Autocomplete` nativo de MUI, `onChange` y `onInputChange` reciben directamente el valor (no `(event, value)`).
|
|
1540
|
+
|
|
1541
|
+
---
|
|
1542
|
+
|
|
1543
|
+
### Selector
|
|
1544
|
+
|
|
1545
|
+
`Autocomplete` de Material-UI configurado como un select de opciones fijas, con matching flexible de valores (por `value` exacto o normalizado).
|
|
1546
|
+
|
|
1547
|
+
**Import:**
|
|
1548
|
+
```jsx
|
|
1549
|
+
import Selector from '../Material-UI/Components/Selector/index'; // export default, archivo index.jsx
|
|
1550
|
+
```
|
|
1551
|
+
|
|
1552
|
+
**Uso básico:**
|
|
1553
|
+
```jsx
|
|
1554
|
+
<Selector
|
|
1555
|
+
label="Especie"
|
|
1556
|
+
options={[{ value: 'perro', label: 'Perro' }, { value: 'gato', label: 'Gato' }]}
|
|
1557
|
+
value={value}
|
|
1558
|
+
onChange={(e) => setValue(e.target.value)}
|
|
1559
|
+
/>
|
|
1560
|
+
```
|
|
1561
|
+
`
|
|
1562
|
+
**Props:**
|
|
1563
|
+
|
|
1564
|
+
| Prop | Tipo | Default | Descripción |
|
|
1565
|
+
|---|---|---|---|
|
|
1566
|
+
| label | string | — | Etiqueta del campo. |
|
|
1567
|
+
| value | string | — | Valor seleccionado (se busca en `options` por `value` o, si no matchea, de forma normalizada). |
|
|
1568
|
+
| onChange | function | — | Se llama con un evento simulado `{ target: { value } }`, no con `(event, newValue)` de MUI. |
|
|
1569
|
+
| options | array | `[]` | Lista de opciones `{ value, label, icon? }` (`icon` es una URL de imagen mostrada en el listado). |
|
|
1570
|
+
| id | string | `'custom-autocomplete'` | id del `Autocomplete`. |
|
|
1571
|
+
| style | object | `{}` | Estilos adicionales (`sx`) del contenedor. |
|
|
1572
|
+
| className | string | `''` | Clase CSS adicional. |
|
|
1573
|
+
| fullWidth | boolean | `true` | Si ocupa el 100% del ancho (si `false`, ancho fijo de 300px). |
|
|
1574
|
+
| placeholder | string | — | Placeholder del campo. |
|
|
1575
|
+
| required | boolean | — | Muestra un indicador `**` junto a la etiqueta. |
|
|
1576
|
+
| requiredColor | string | `'red'` | Color del indicador de requerido. |
|
|
1577
|
+
| disableClearable | boolean | `false` | Si es `true`, oculta el botón de limpiar selección. |
|
|
1578
|
+
|
|
1579
|
+
**Ejemplos:**
|
|
1580
|
+
```jsx
|
|
1581
|
+
<Selector label="Especie" options={options} required value={value} onChange={onChange} />
|
|
1582
|
+
```
|
|
1583
|
+
```jsx
|
|
1584
|
+
<Selector label="Especie" options={options} value="gato" onChange={onChange} />
|
|
1585
|
+
```
|
|
1586
|
+
|
|
1587
|
+
**Notas:** El matching de `value` contra `options` ignora mayúsculas, espacios, guiones y guiones bajos si no hay coincidencia exacta por `value`.
|
|
1588
|
+
|
|
1589
|
+
---
|
|
1590
|
+
|
|
1591
|
+
### TextField
|
|
1592
|
+
|
|
1593
|
+
Wrapper del `TextField` de Material-UI usado como base de varios otros componentes del kit (`Input`, `Filter`, `FormInput`, `HoursPicker`), con manejo de `required` y resaltado `**texto**` en `label`/`helperText`.
|
|
1594
|
+
|
|
1595
|
+
**Import:**
|
|
1596
|
+
```jsx
|
|
1597
|
+
import TextField from '../Material-UI/Components/TextField/index'; // export default, forwardRef, archivo index.jsx
|
|
1598
|
+
```
|
|
1599
|
+
|
|
1600
|
+
**Uso básico:**
|
|
1601
|
+
```jsx
|
|
1602
|
+
<TextField label="Nombre" placeholder="Escribe tu nombre..." value={value} onChange={onChange} />
|
|
1603
|
+
```
|
|
1604
|
+
|
|
1605
|
+
**Props:**
|
|
1606
|
+
|
|
1607
|
+
| Prop | Tipo | Default | Descripción |
|
|
1608
|
+
|---|---|---|---|
|
|
1609
|
+
| label | string \| node | — | Etiqueta del campo; admite `**texto**` para resaltar con `GreenHighlight`. |
|
|
1610
|
+
| value | string | — | Valor controlado. |
|
|
1611
|
+
| onChange | function | — | Handler de evento de input. |
|
|
1612
|
+
| error | boolean \| string | — | Estado/mensaje de error; si es un string, reemplaza a `helperText`. |
|
|
1613
|
+
| helperText | string \| node | — | Texto de ayuda (admite `**texto**` como el `label`). |
|
|
1614
|
+
| type | string | `'text'` | Tipo de input HTML. |
|
|
1615
|
+
| variant | string | `'outlined'` | Variant de `TextField`. |
|
|
1616
|
+
| size | string | `'small'` | Tamaño de `TextField`. |
|
|
1617
|
+
| fullWidth | boolean | `true` | Si ocupa el 100% del ancho disponible. |
|
|
1618
|
+
| placeholder | string | — | Placeholder del campo. |
|
|
1619
|
+
| required | boolean | — | Muestra un indicador `**` junto a la etiqueta. |
|
|
1620
|
+
| requiredColor | string | `'red'` | Color del indicador de requerido. |
|
|
1621
|
+
| bgColor | string | `'#fff'` | Color de fondo del input (incluye fix de autofill de Chrome). |
|
|
1622
|
+
| textColor | string | `'#0f172a'` | Color de texto usado en el fix de autofill. |
|
|
1623
|
+
| ...props | any | — | Cualquier otra prop de `TextField` de Material-UI. |
|
|
1624
|
+
|
|
1625
|
+
**Ejemplos:**
|
|
1626
|
+
```jsx
|
|
1627
|
+
<TextField label="Contraseña" type="password" error helperText="La contraseña debe tener al menos 6 caracteres" />
|
|
1628
|
+
```
|
|
1629
|
+
```jsx
|
|
1630
|
+
<TextField label="Correo electrónico (Autocompletado)" value="usuario@correo.com" disabled />
|
|
1631
|
+
```
|
|
1632
|
+
|
|
1633
|
+
**Notas:** El `ref` se reenvía al input interno de Material-UI (`inputRef`). Es el componente base que usan internamente `Input`, `Filter`, `FormInput` y `HoursPicker`.
|
|
1634
|
+
|
|
1635
|
+
---
|
|
1636
|
+
|
|
1637
|
+
### ModalTooltip
|
|
1638
|
+
|
|
1639
|
+
Tooltip flotante que se muestra al pasar el mouse sobre su contenido, renderizado en un portal para evitar problemas de overflow/z-index, con reposicionamiento automático para no salirse del viewport.
|
|
1640
|
+
|
|
1641
|
+
**Import:**
|
|
1642
|
+
```jsx
|
|
1643
|
+
import ModalTooltip from 'screens/components/ModalTooltip/ModalTooltip';
|
|
1644
|
+
```
|
|
1645
|
+
|
|
1646
|
+
**Uso básico:**
|
|
1647
|
+
```jsx
|
|
1648
|
+
<ModalTooltip text="Más información" position="top">
|
|
1649
|
+
<button type="button">Hover me</button>
|
|
1650
|
+
</ModalTooltip>
|
|
1651
|
+
```
|
|
1652
|
+
|
|
1653
|
+
**Props:**
|
|
1654
|
+
|
|
1655
|
+
| Prop | Tipo | Default | Descripción |
|
|
1656
|
+
|---|---|---|---|
|
|
1657
|
+
| `text` | `string` | — | Texto mostrado dentro del tooltip. |
|
|
1658
|
+
| `children` | `node` | — | Elemento(s) que disparan el tooltip al hacer hover. |
|
|
1659
|
+
| `position` | `"top"` \| `"bottom"` | `"top"` | Posición preferida del tooltip; se invierte automáticamente si colisiona con el borde del viewport. |
|
|
1660
|
+
| `delay` | `number` | `150` | Milisegundos de espera antes de mostrar el tooltip tras el `mouseenter`. |
|
|
1661
|
+
| `style` | `object` | — | Estilos inline adicionales para el contenedor `span` que envuelve a `children`. |
|
|
1662
|
+
| `bgColor` | `string` | — | Color de fondo del tooltip (`--modaltooltip-bg`). |
|
|
1663
|
+
| `textColor` | `string` | — | Color del texto del tooltip (`--modaltooltip-text`). |
|
|
1664
|
+
| `...props` | — | — | Cualquier otro prop se pasa al `span` contenedor. |
|
|
1665
|
+
|
|
1666
|
+
**Ejemplos:**
|
|
1667
|
+
```jsx
|
|
1668
|
+
<ModalTooltip text="Shows after a longer delay" position="top" delay={600}>
|
|
1669
|
+
<button type="button">Slow tooltip</button>
|
|
1670
|
+
</ModalTooltip>
|
|
1671
|
+
```
|
|
1672
|
+
|
|
1673
|
+
---
|
|
1674
|
+
|
|
1675
|
+
### ErrorMessage
|
|
1676
|
+
|
|
1677
|
+
Banner de notificación en línea para mostrar mensajes de error o de éxito, con icono y título.
|
|
1678
|
+
|
|
1679
|
+
**Import:**
|
|
1680
|
+
```jsx
|
|
1681
|
+
import ErrorMessage from 'screens/components/Notification/Error/ErrorMessage';
|
|
1682
|
+
```
|
|
1683
|
+
|
|
1684
|
+
**Uso básico:**
|
|
1685
|
+
```jsx
|
|
1686
|
+
<ErrorMessage title="Atención" message="No se pudo completar la operación." variant="danger" />
|
|
1687
|
+
```
|
|
1688
|
+
|
|
1689
|
+
**Props:**
|
|
1690
|
+
|
|
1691
|
+
| Prop | Tipo | Default | Descripción |
|
|
1692
|
+
|---|---|---|---|
|
|
1693
|
+
| `message` | `string` | — | Texto del mensaje. Si es falsy, el componente no renderiza nada (`return null`). |
|
|
1694
|
+
| `title` | `string` | `"Atención"` | Título en negrita mostrado sobre el mensaje. |
|
|
1695
|
+
| `variant` | `"danger"` \| `"success"` | `"danger"` | Controla el icono (`AlertCircle` o `CheckCircle`) y el estilo del banner. |
|
|
1696
|
+
| `bgColor` | `string` | — | Color de fondo (`--errormessage-bg`). |
|
|
1697
|
+
| `borderColor` | `string` | — | Color del borde (`--errormessage-border`). |
|
|
1698
|
+
| `style` | `object` | — | Estilos inline adicionales. |
|
|
1699
|
+
|
|
1700
|
+
**Ejemplos:**
|
|
1701
|
+
```jsx
|
|
1702
|
+
<ErrorMessage title="Operación Exitosa" message="¡Contraseña actualizada correctamente!" variant="success" />
|
|
1703
|
+
```
|
|
1704
|
+
|
|
1705
|
+
---
|
|
1706
|
+
|
|
1707
|
+
### PasswordResetPanel
|
|
1708
|
+
|
|
1709
|
+
Panel deslizante (basado en `DrawPanel`) para que un administrador solicite y complete el restablecimiento de contraseña de un usuario, incluyendo lista de solicitudes pendientes, polling de estado y asignación de nueva clave.
|
|
1710
|
+
|
|
1711
|
+
**Import:**
|
|
1712
|
+
```jsx
|
|
1713
|
+
import PasswordResetPanel from 'screens/components/PasswordResetPanel';
|
|
1714
|
+
```
|
|
1715
|
+
|
|
1716
|
+
**Uso básico:**
|
|
1717
|
+
```jsx
|
|
1718
|
+
<PasswordResetPanel isOpen={isOpen} onClose={() => setIsOpen(false)} />
|
|
1719
|
+
```
|
|
1720
|
+
|
|
1721
|
+
**Props:**
|
|
1722
|
+
|
|
1723
|
+
| Prop | Tipo | Default | Descripción |
|
|
1724
|
+
|---|---|---|---|
|
|
1725
|
+
| `isOpen` | `boolean` | — | Controla si el panel está abierto. |
|
|
1726
|
+
| `onClose` | `function` | — | Callback al cerrar el panel. |
|
|
1727
|
+
| `cancelColor` | `string` | `'var(--button-red, #ef4444)'` | Color del botón "Cancelar Espera". |
|
|
1728
|
+
| `pendingColor` | `{ label, bg, text }` | `{ label: '#b45309', bg: '#fffbeb', text: '#92400e' }` | Colores para el estado "Pending" en la lista de solicitudes. |
|
|
1729
|
+
| `acceptedColor` | `{ label, bg, text }` | `{ label: '#16a34a', bg: '#f0fdf4', text: '#166534' }` | Colores para el estado "Accepted". |
|
|
1730
|
+
| `expiredColor` | `{ label, bg, text }` | `{ label: '#ef4444', bg: '#fef2f2', text: '#991b1b' }` | Colores para solicitudes expiradas. |
|
|
1731
|
+
|
|
1732
|
+
**Ejemplos:**
|
|
1733
|
+
```jsx
|
|
1734
|
+
<PasswordResetPanel isOpen={false} onClose={() => console.log('close panel')} />
|
|
1735
|
+
```
|
|
1736
|
+
|
|
1737
|
+
**Notas:** Internamente usa el hook `useAdminPasswordReset` (`hooks/useAdminPasswordReset.js`), que llama a `features/password-reset/api.js`. Para que las llamadas de red reales funcionen en una app consumidora hace falta tener configurado `configureApiClient` (`common/api/client.js`); sin esa configuración el panel igual renderiza su UI inicial/carga/error sin fallar.
|
|
1738
|
+
|
|
1739
|
+
---
|
|
1740
|
+
|
|
1741
|
+
### PlaceholderButton
|
|
1742
|
+
|
|
1743
|
+
Campo de configuración compuesto por un input (numérico, texto o multilínea) más un botón de guardado, con manejo de estado de carga, mensajes de éxito/error y validación.
|
|
1744
|
+
|
|
1745
|
+
**Import:**
|
|
1746
|
+
```jsx
|
|
1747
|
+
import PlaceholderButton from 'screens/components/PlaceholderButton';
|
|
1748
|
+
```
|
|
1749
|
+
|
|
1750
|
+
**Uso básico:**
|
|
1751
|
+
```jsx
|
|
1752
|
+
<PlaceholderButton
|
|
1753
|
+
icon={Calendar}
|
|
1754
|
+
placeholder="Días"
|
|
1755
|
+
unitText="días"
|
|
1756
|
+
buttonText="Guardar"
|
|
1757
|
+
initialValue="7"
|
|
1758
|
+
onSavePromise={(value) => api.save(value)}
|
|
1759
|
+
/>
|
|
1760
|
+
```
|
|
1761
|
+
|
|
1762
|
+
**Props:**
|
|
1763
|
+
|
|
1764
|
+
| Prop | Tipo | Default | Descripción |
|
|
1765
|
+
|---|---|---|---|
|
|
1766
|
+
| `icon` | `component` | — | Icono mostrado dentro del input (modo no-multilínea). |
|
|
1767
|
+
| `tooltipText` | `string` | — | (recibido pero no usado en el render actual). |
|
|
1768
|
+
| `placeholder` | `string` | — | Placeholder del input. |
|
|
1769
|
+
| `unitText` | `string` | — | Texto de unidad mostrado junto al input (p. ej. "días"). |
|
|
1770
|
+
| `buttonText` | `string` | — | Texto del botón de guardar. |
|
|
1771
|
+
| `hintText` | `string` | — | Texto de ayuda mostrado debajo del input. |
|
|
1772
|
+
| `disabledHintText` | `string` | — | Texto mostrado cuando `disabled` es `true`. |
|
|
1773
|
+
| `initialValue` | `string` | `''` | Valor inicial del input (se sincroniza si cambia). |
|
|
1774
|
+
| `inputType` | `"number"` \| `"text"` \| otros | `'number'` | Tipo de input; determina si el valor se parsea con `parseInt`. |
|
|
1775
|
+
| `min` | `string` | `"1"` | Atributo `min` del input numérico. |
|
|
1776
|
+
| `disabled` | `boolean` | `false` | Deshabilita el input y el botón. |
|
|
1777
|
+
| `multiline` | `boolean` | `false` | Si es `true`, usa un textarea (`InputWithIcon` multilínea) en vez de input simple. |
|
|
1778
|
+
| `onSavePromise` | `function` | — | Función que retorna una promesa; se invoca con el valor al guardar. |
|
|
1779
|
+
| `clearCache` | `function` | — | Callback opcional invocado tras guardar (limpieza de caché). |
|
|
1780
|
+
| `successMessage` | `string` | — | Mensaje mostrado tras guardar con éxito. |
|
|
1781
|
+
| `errorMessage` | `string` | — | Mensaje mostrado si `onSavePromise` falla. |
|
|
1782
|
+
| `validationErrorMsg` | `string` | — | Mensaje mostrado si la validación del valor falla. |
|
|
1783
|
+
| `clearOnSuccess` | `boolean` | `false` | Si es `true`, limpia el input tras guardar con éxito. |
|
|
1784
|
+
| `focusColor` | `string` | — | Color de foco (`--placeholderbutton-focus`). |
|
|
1785
|
+
| `unitBgColor` | `string` | — | Color de fondo del texto de unidad (`--placeholderbutton-unit-bg`). |
|
|
1786
|
+
|
|
1787
|
+
**Ejemplos:**
|
|
1788
|
+
```jsx
|
|
1789
|
+
<PlaceholderButton
|
|
1790
|
+
placeholder="Escribe una nota..."
|
|
1791
|
+
buttonText="Guardar nota"
|
|
1792
|
+
multiline
|
|
1793
|
+
clearOnSuccess
|
|
1794
|
+
onSavePromise={fakeSavePromise}
|
|
1795
|
+
/>
|
|
1796
|
+
|
|
1797
|
+
<PlaceholderButton
|
|
1798
|
+
{...defaultArgs}
|
|
1799
|
+
disabled
|
|
1800
|
+
disabledHintText="Esta opción está deshabilitada por ahora."
|
|
1801
|
+
/>
|
|
1802
|
+
```
|
|
1803
|
+
|
|
1804
|
+
---
|
|
1805
|
+
|
|
1806
|
+
### Profile
|
|
1807
|
+
|
|
1808
|
+
Encabezado de perfil de usuario para barras superiores/sidebars: avatar, nombre de usuario y botón de edición.
|
|
1809
|
+
|
|
1810
|
+
**Import:**
|
|
1811
|
+
```jsx
|
|
1812
|
+
import Profile from 'screens/components/Profile/index';
|
|
1813
|
+
```
|
|
1814
|
+
|
|
1815
|
+
**Uso básico:**
|
|
1816
|
+
```jsx
|
|
1817
|
+
<Profile username="Ana Gomez" avatarUrl="" onEditClick={() => {}} />
|
|
1818
|
+
```
|
|
1819
|
+
|
|
1820
|
+
**Props:**
|
|
1821
|
+
|
|
1822
|
+
| Prop | Tipo | Default | Descripción |
|
|
1823
|
+
|---|---|---|---|
|
|
1824
|
+
| `username` | `string` | — | Nombre mostrado junto al avatar. |
|
|
1825
|
+
| `avatarUrl` | `string` | — | URL de la imagen de avatar (si está vacío, se muestra el fallback con inicial). |
|
|
1826
|
+
| `onEditClick` | `function` | — | Callback al hacer click en el icono de lápiz. |
|
|
1827
|
+
| `textColor` | `string` | `'#ffffff'` | Color del texto del nombre y del icono de edición. |
|
|
1828
|
+
|
|
1829
|
+
**Ejemplos:**
|
|
1830
|
+
```jsx
|
|
1831
|
+
<Profile username="Maria Fernanda Rodriguez Castillo" avatarUrl="" onEditClick={() => {}} />
|
|
1832
|
+
```
|
|
1833
|
+
|
|
1834
|
+
**Notas:** Internamente renderiza `Profile/Avatar` (`UserAvatar`) con `size={35}` fijo, no configurable desde este componente.
|
|
1835
|
+
|
|
1836
|
+
---
|
|
1837
|
+
|
|
1838
|
+
### Avatar (Profile/Avatar)
|
|
1839
|
+
|
|
1840
|
+
Avatar de usuario (basado en MUI `Avatar`) con fallback de inicial y color generado a partir del nombre, estado de carga, indicador de actividad (online/offline) y vista ampliada opcional.
|
|
1841
|
+
|
|
1842
|
+
**Import:**
|
|
1843
|
+
```jsx
|
|
1844
|
+
import Avatar from 'screens/components/Profile/Avatar/index';
|
|
1845
|
+
```
|
|
1846
|
+
|
|
1847
|
+
**Uso básico:**
|
|
1848
|
+
```jsx
|
|
1849
|
+
<Avatar name="Ana Gomez" src="https://i.pravatar.cc/100?img=12" size={48} />
|
|
1850
|
+
```
|
|
1851
|
+
|
|
1852
|
+
**Props:**
|
|
1853
|
+
|
|
1854
|
+
| Prop | Tipo | Default | Descripción |
|
|
1855
|
+
|---|---|---|---|
|
|
1856
|
+
| `src` | `string` | — | URL de la imagen; si no hay, se muestra la inicial sobre un color generado del `name`. |
|
|
1857
|
+
| `name` | `string` | `'Usuario'` | Nombre usado para la inicial y el color de fallback. |
|
|
1858
|
+
| `size` | `number` | `35` | Tamaño (px) del avatar. |
|
|
1859
|
+
| `editable` | `boolean` | `false` | Si es `true`, envuelve el avatar en un `ModalTooltip` ("Cambiar Foto de Perfil") y muestra un overlay con icono de cámara al hover; el click dispara `onEditClick`. |
|
|
1860
|
+
| `onEditClick` | `function` | `() => {}` | Callback al hacer click cuando `editable` es `true`. |
|
|
1861
|
+
| `loading` | `boolean` | `false` | Muestra un spinner (`Loading`) en vez del avatar. |
|
|
1862
|
+
| `viewable` | `boolean` | `false` | Si es `true` y hay `src`, permite abrir la imagen en un `AlertModal` a pantalla completa al hacer click. |
|
|
1863
|
+
| `isActive` | `boolean` \| `null` | `null` | Si no es `null`/`undefined`, muestra un punto de estado (activo/inactivo). |
|
|
1864
|
+
| `fallbackBgColor` | `string` | — | Color de fondo del fallback (`--avatar-fallback-bg`). |
|
|
1865
|
+
| `activeStatusColor` | `string` | `'#10b981'` | Color del punto de estado cuando `isActive` es `true`. |
|
|
1866
|
+
| `inactiveStatusColor` | `string` | `'#ef4444'` | Color del punto de estado cuando `isActive` es `false`. |
|
|
1867
|
+
|
|
1868
|
+
**Ejemplos:**
|
|
1869
|
+
```jsx
|
|
1870
|
+
<Avatar name="Marta Ruiz" size={64} editable onEditClick={() => console.log('edit avatar clicked')} />
|
|
1871
|
+
|
|
1872
|
+
<Avatar name="Ana Gomez" size={48} loading />
|
|
1873
|
+
```
|
|
1874
|
+
|
|
1875
|
+
---
|
|
1876
|
+
|
|
1877
|
+
### ScrollBar
|
|
1878
|
+
|
|
1879
|
+
Contenedor con scrollbars personalizados (vertical y/u horizontal) que se ocultan automáticamente cuando no hay interacción.
|
|
1880
|
+
|
|
1881
|
+
**Import:**
|
|
1882
|
+
```jsx
|
|
1883
|
+
import ScrollBar from 'screens/components/ScrollBar';
|
|
1884
|
+
```
|
|
1885
|
+
|
|
1886
|
+
**Uso básico:**
|
|
1887
|
+
```jsx
|
|
1888
|
+
<ScrollBar vertical maxHeight={200}>
|
|
1889
|
+
<div>Contenido largo...</div>
|
|
1890
|
+
</ScrollBar>
|
|
1891
|
+
```
|
|
1892
|
+
|
|
1893
|
+
**Props:**
|
|
1894
|
+
|
|
1895
|
+
| Prop | Tipo | Default | Descripción |
|
|
1896
|
+
|---|---|---|---|
|
|
1897
|
+
| `children` | `node` | — | Contenido a scrollear. |
|
|
1898
|
+
| `vertical` | `boolean` | `true` | Habilita scroll/thumb vertical. |
|
|
1899
|
+
| `horizontal` | `boolean` | `true` | Habilita scroll/thumb horizontal. |
|
|
1900
|
+
| `autoHide` | `boolean` | `true` | Si es `false`, los thumbs permanecen siempre visibles. |
|
|
1901
|
+
| `maxHeight` | `string` \| `number` | — | Altura máxima del área scrolleable. |
|
|
1902
|
+
| `className` | `string` | `''` | Clase adicional para el contenedor raíz. |
|
|
1903
|
+
| `contentClassName` | `string` | `''` | Clase adicional para el área de scroll interna. |
|
|
1904
|
+
| `style` | `object` | — | Estilos inline para el contenedor raíz. |
|
|
1905
|
+
|
|
1906
|
+
**Ejemplos:**
|
|
1907
|
+
```jsx
|
|
1908
|
+
<ScrollBar vertical={false} horizontal autoHide>
|
|
1909
|
+
<div style={{ width: '1600px' }}>Contenido muy ancho...</div>
|
|
1910
|
+
</ScrollBar>
|
|
1911
|
+
```
|
|
1912
|
+
|
|
1913
|
+
**Notas:** Es usado internamente por `TableA` y `TableB` para el scroll horizontal de sus tablas.
|
|
1914
|
+
|
|
1915
|
+
---
|
|
1916
|
+
|
|
1917
|
+
### Sidebar
|
|
1918
|
+
|
|
1919
|
+
Barra lateral de navegación colapsable con grupos de items, badges por método HTTP, menú de usuario, menú contextual por item (editar/eliminar/fijar/colaboradores) y reordenamiento por drag & drop.
|
|
1920
|
+
|
|
1921
|
+
**Import:**
|
|
1922
|
+
```jsx
|
|
1923
|
+
import Sidebar from 'screens/components/Sidebar/index';
|
|
1924
|
+
// también disponible como export nombrado: import { ProSidebar } from 'screens/components/Sidebar/index';
|
|
1925
|
+
```
|
|
1926
|
+
|
|
1927
|
+
**Uso básico:**
|
|
1928
|
+
```jsx
|
|
1929
|
+
<Sidebar
|
|
1930
|
+
groups={groups}
|
|
1931
|
+
activeId={activeId}
|
|
1932
|
+
onSelect={(item) => setActiveId(item.id)}
|
|
1933
|
+
user={{ email: 'jane.doe@example.com' }}
|
|
1934
|
+
/>
|
|
1935
|
+
```
|
|
1936
|
+
|
|
1937
|
+
**Props:**
|
|
1938
|
+
|
|
1939
|
+
| Prop | Tipo | Default | Descripción |
|
|
1940
|
+
|---|---|---|---|
|
|
1941
|
+
| `groups` | `Array<{ title?, items: Array<{ id, label, icon?, badge?, badgeType?, pinned?, isOwner?, isShared? }> }>` | — | Estructura de grupos e items del menú. |
|
|
1942
|
+
| `activeId` | `string`\|`number` | — | Id del item actualmente activo. |
|
|
1943
|
+
| `onSelect` | `function(item)` | — | Callback al seleccionar un item. |
|
|
1944
|
+
| `collapsible` | `boolean` | `true` | Muestra el botón de colapsar y habilita el atajo de teclado para colapsar/expandir. |
|
|
1945
|
+
| `loading` | `boolean` | `false` | Muestra `skeletonItems` filas de `Skeleton` en vez de los grupos reales. |
|
|
1946
|
+
| `skeletonItems` | `number` | `15` | Cantidad de filas skeleton al cargar. |
|
|
1947
|
+
| `className` | `string` | `''` | Clase adicional para el `<aside>` raíz. |
|
|
1948
|
+
| `headerContent` | `node` | — | Contenido custom del header (oculto si está colapsado). |
|
|
1949
|
+
| `footerContent` | `node` | — | Contenido custom del footer (oculto si está colapsado). |
|
|
1950
|
+
| `user` | `{ email }` | — | Si tiene `email`, muestra el footer de usuario con menú desplegable. |
|
|
1951
|
+
| `userMenuItems` | `Array<{ id?, label, icon?, onClick?, variant? }>` | `[]` | Items del menú de usuario (variant `'danger'` los resalta en rojo). |
|
|
1952
|
+
| `onItemEdit` | `function(item)` | — | Habilita "Editar" en el menú contextual del item. |
|
|
1953
|
+
| `onItemDelete` | `function(item)` | — | Habilita "Eliminar"/"Salir" en el menú contextual. |
|
|
1954
|
+
| `onItemPin` | `function(item)` | — | Habilita "Fijar"/"Desfijar" en el menú contextual. |
|
|
1955
|
+
| `onItemCollaborators` | `function(item)` | — | Habilita "Colaboradores" (solo si `item.isOwner !== false && item.isShared`). |
|
|
1956
|
+
| `onReorderItems` | `function(orderedIds)` | — | Si se define, habilita drag & drop para reordenar items dentro de un grupo. |
|
|
1957
|
+
| `avatarBgColor` | `string` | — | Color del avatar de usuario. |
|
|
1958
|
+
| `pinnedIconColor` | `string` | — | Color del icono de "fijado". |
|
|
1959
|
+
| `methodBadgeColors` | `{ post?, get?, put?, delete?, info?: { bg, color } }` | — | Sobrescribe los colores de badge por método HTTP. |
|
|
1960
|
+
|
|
1961
|
+
**Ejemplos:**
|
|
1962
|
+
```jsx
|
|
1963
|
+
<Sidebar groups={[]} loading skeletonItems={8} user={{ email: 'jane.doe@example.com' }} />
|
|
1964
|
+
|
|
1965
|
+
<Sidebar
|
|
1966
|
+
groups={groups}
|
|
1967
|
+
user={{ email: 'jane.doe@example.com' }}
|
|
1968
|
+
onItemEdit={(item) => console.log('edit', item)}
|
|
1969
|
+
onItemDelete={(item) => console.log('delete', item)}
|
|
1970
|
+
onReorderItems={(orderedIds) => console.log('reordered', orderedIds)}
|
|
1971
|
+
/>
|
|
1972
|
+
```
|
|
1973
|
+
|
|
1974
|
+
**Notas:** Persiste el estado colapsado en `localStorage` bajo la clave `sidebar_collapsed`.
|
|
1975
|
+
|
|
1976
|
+
---
|
|
1977
|
+
|
|
1978
|
+
### Skeleton
|
|
1979
|
+
|
|
1980
|
+
Placeholder de carga (shimmer) simple, en forma de bloque, línea o círculo.
|
|
1981
|
+
|
|
1982
|
+
**Import:**
|
|
1983
|
+
```jsx
|
|
1984
|
+
import Skeleton from 'screens/components/Skeleton/index';
|
|
1985
|
+
// también disponible como export nombrado: import { Skeleton } from 'screens/components/Skeleton/index';
|
|
1986
|
+
```
|
|
1987
|
+
|
|
1988
|
+
**Uso básico:**
|
|
1989
|
+
```jsx
|
|
1990
|
+
<Skeleton width="200px" height="1em" />
|
|
1991
|
+
```
|
|
1992
|
+
|
|
1993
|
+
**Props:**
|
|
1994
|
+
|
|
1995
|
+
| Prop | Tipo | Default | Descripción |
|
|
1996
|
+
|---|---|---|---|
|
|
1997
|
+
| `width` | `string`\|`number` | `'100%'` | Ancho del skeleton. |
|
|
1998
|
+
| `height` | `string`\|`number` | `'1em'` | Alto del skeleton. |
|
|
1999
|
+
| `radius` | `string` | `'6px'` | Radio de borde (ignorado si `circle` es `true`). |
|
|
2000
|
+
| `circle` | `boolean` | `false` | Si es `true`, fuerza `border-radius: 50%`. |
|
|
2001
|
+
| `className` | `string` | `''` | Clase adicional. |
|
|
2002
|
+
| `style` | `object` | `{}` | Estilos inline adicionales. |
|
|
2003
|
+
|
|
2004
|
+
**Ejemplos:**
|
|
2005
|
+
```jsx
|
|
2006
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
|
2007
|
+
<Skeleton circle width={28} height={28} />
|
|
2008
|
+
<Skeleton width="60%" height="12px" />
|
|
2009
|
+
</div>
|
|
2010
|
+
```
|
|
2011
|
+
|
|
2012
|
+
---
|
|
2013
|
+
|
|
2014
|
+
### SubSidebarLayout
|
|
2015
|
+
|
|
2016
|
+
Layout de dos columnas: un sub-menú lateral con botones tipo pestaña y un área de contenido a la derecha.
|
|
2017
|
+
|
|
2018
|
+
**Import:**
|
|
2019
|
+
```jsx
|
|
2020
|
+
import SubSidebarLayout from 'screens/components/SubSidebarLayout';
|
|
2021
|
+
```
|
|
2022
|
+
|
|
2023
|
+
**Uso básico:**
|
|
2024
|
+
```jsx
|
|
2025
|
+
<SubSidebarLayout
|
|
2026
|
+
menuItems={[{ id: 'general', label: 'General', icon: <Settings size={16} /> }]}
|
|
2027
|
+
activeItemId="general"
|
|
2028
|
+
onItemClick={(id) => setActiveItemId(id)}
|
|
2029
|
+
>
|
|
2030
|
+
<div>Contenido de la sección</div>
|
|
2031
|
+
</SubSidebarLayout>
|
|
2032
|
+
```
|
|
2033
|
+
|
|
2034
|
+
**Props:**
|
|
2035
|
+
|
|
2036
|
+
| Prop | Tipo | Default | Descripción |
|
|
2037
|
+
|---|---|---|---|
|
|
2038
|
+
| `menuItems` | `Array<{ id, label, icon? }>` | `[]` | Items del sub-menú lateral (`icon` es un nodo React opcional). |
|
|
2039
|
+
| `activeItemId` | `string`\|`number` | — | Id del item activo. |
|
|
2040
|
+
| `onItemClick` | `function(id, item)` | — | Callback al hacer click en un item del menú. |
|
|
2041
|
+
| `children` | `node` | — | Contenido del área principal. |
|
|
2042
|
+
| `bgColor` | `string` | — | Color de fondo del sub-sidebar (`--subsidebarlayout-bg`). |
|
|
2043
|
+
|
|
2044
|
+
**Ejemplos:**
|
|
2045
|
+
```jsx
|
|
2046
|
+
<SubSidebarLayout menuItems={menuItems} activeItemId={activeItemId} onItemClick={setActiveItemId}>
|
|
2047
|
+
{null}
|
|
2048
|
+
</SubSidebarLayout>
|
|
2049
|
+
```
|
|
2050
|
+
|
|
2051
|
+
---
|
|
2052
|
+
|
|
2053
|
+
### SummaryCard
|
|
2054
|
+
|
|
2055
|
+
Tarjeta destacada (con gradiente) para mostrar un resumen generado, con botón opcional de copiar al portapapeles.
|
|
2056
|
+
|
|
2057
|
+
**Import:**
|
|
2058
|
+
```jsx
|
|
2059
|
+
import SummaryCard from 'screens/components/SummaryCard';
|
|
2060
|
+
```
|
|
2061
|
+
|
|
2062
|
+
**Uso básico:**
|
|
2063
|
+
```jsx
|
|
2064
|
+
<SummaryCard title="Resumen generado" text="Este es un resumen de ejemplo..." />
|
|
2065
|
+
```
|
|
2066
|
+
|
|
2067
|
+
**Props:**
|
|
2068
|
+
|
|
2069
|
+
| Prop | Tipo | Default | Descripción |
|
|
2070
|
+
|---|---|---|---|
|
|
2071
|
+
| `title` | `string` | — | Título de la tarjeta. |
|
|
2072
|
+
| `text` | `string` | — | Cuerpo del resumen. |
|
|
2073
|
+
| `enableCopy` | `boolean` | `false` | Muestra un botón para copiar `text` al portapapeles. |
|
|
2074
|
+
| `gradientStart` | `string` | — | Color inicial del gradiente de fondo (`--summarycard-gradient-start`). |
|
|
2075
|
+
| `gradientEnd` | `string` | — | Color final del gradiente (`--summarycard-gradient-end`). |
|
|
2076
|
+
| `headerColor` | `string` | — | Color del header/icono (`--summarycard-header-color`). |
|
|
2077
|
+
|
|
2078
|
+
**Ejemplos:**
|
|
2079
|
+
```jsx
|
|
2080
|
+
<SummaryCard title="Resumen con copia" text="..." enableCopy />
|
|
2081
|
+
```
|
|
2082
|
+
|
|
2083
|
+
---
|
|
2084
|
+
|
|
2085
|
+
### Swich
|
|
2086
|
+
|
|
2087
|
+
Interruptor (toggle) tipo switch con animación de ripple al hacer click y tooltip que indica el estado actual.
|
|
2088
|
+
|
|
2089
|
+
**Import:**
|
|
2090
|
+
```jsx
|
|
2091
|
+
import Swich from 'screens/components/Swich/index';
|
|
2092
|
+
```
|
|
2093
|
+
|
|
2094
|
+
**Uso básico:**
|
|
2095
|
+
```jsx
|
|
2096
|
+
const [value, setValue] = useState(false);
|
|
2097
|
+
<Swich value={value} onChange={setValue} />
|
|
2098
|
+
```
|
|
2099
|
+
|
|
2100
|
+
**Props:**
|
|
2101
|
+
|
|
2102
|
+
| Prop | Tipo | Default | Descripción |
|
|
2103
|
+
|---|---|---|---|
|
|
2104
|
+
| `value` | `boolean` | `false` | Estado controlado del switch (encendido/apagado). |
|
|
2105
|
+
| `onChange` | `function(newActive)` | — | Callback invocado con el nuevo valor al hacer click. |
|
|
2106
|
+
| `disabled` | `boolean` | `false` | Deshabilita la interacción. |
|
|
2107
|
+
| `activeColor` | `string` | `'#088d4f'` | Color de fondo cuando está activo. |
|
|
2108
|
+
| `inactiveColor` | `string` | `'#919191'` | Color de fondo cuando está inactivo. |
|
|
2109
|
+
| `thumbColor` | `string` | `'#ffffff'` | Color del "thumb" (círculo deslizante). |
|
|
2110
|
+
| `className` | `string` | `''` | Clase adicional para el botón. |
|
|
2111
|
+
| `style` | `object` | `{}` | Estilos inline adicionales. |
|
|
2112
|
+
|
|
2113
|
+
**Ejemplos:**
|
|
2114
|
+
```jsx
|
|
2115
|
+
<Swich value={true} activeColor="#2563eb" inactiveColor="#cbd5e1" thumbColor="#ffffff" />
|
|
2116
|
+
```
|
|
2117
|
+
|
|
2118
|
+
**Notas:** Es controlado, así que se debe pasar `value` junto con `onChange` para reflejar el estado externo. Envuelve el botón en un `ModalTooltip` que muestra "activado"/"desactivado".
|
|
2119
|
+
|
|
2120
|
+
---
|
|
2121
|
+
|
|
2122
|
+
### TableA
|
|
2123
|
+
|
|
2124
|
+
Tabla simple orientada a columnas con `accessor`/`render`, con estados de carga (skeleton), error y vacío incorporados.
|
|
2125
|
+
|
|
2126
|
+
**Import:**
|
|
2127
|
+
```jsx
|
|
2128
|
+
import TableA from 'screens/components/TableA';
|
|
2129
|
+
```
|
|
2130
|
+
|
|
2131
|
+
**Uso básico:**
|
|
2132
|
+
```jsx
|
|
2133
|
+
<TableA
|
|
2134
|
+
columns={[
|
|
2135
|
+
{ header: 'Nombre', accessor: 'name' },
|
|
2136
|
+
{ header: 'Email', accessor: 'email' },
|
|
2137
|
+
]}
|
|
2138
|
+
data={[{ id: 1, name: 'Ana Gomez', email: 'ana@correo.com' }]}
|
|
2139
|
+
keyExtractor={(row) => row.id}
|
|
2140
|
+
/>
|
|
2141
|
+
```
|
|
2142
|
+
|
|
2143
|
+
**Props:**
|
|
2144
|
+
|
|
2145
|
+
| Prop | Tipo | Default | Descripción |
|
|
2146
|
+
|---|---|---|---|
|
|
2147
|
+
| `columns` | `Array<{ header, accessor, align?, width?, render?(row), filter? }>` | `[]` | Definición de columnas. `header` es el texto de cabecera, `accessor` es la clave leída de cada fila (`row[col.accessor]`), `render(row)` sobreescribe el contenido de la celda, `align` es `'left'`\|`'center'`\|`'right'`. `filter` agrega un ícono de embudo junto al header (ver abajo). |
|
|
2148
|
+
| `data` | `Array<object>` | `[]` | Filas a renderizar; cada fila es un objeto plano cuyas claves coinciden con `accessor`. |
|
|
2149
|
+
| `keyExtractor` | `function(row) => key` | — | **Requerido** para renderizar filas reales (se usa como `key`). |
|
|
2150
|
+
| `rowClassName` | `function(row) => string` | — | Clase CSS adicional por fila. |
|
|
2151
|
+
| `loading` | `boolean` | `false` | Muestra `skeletonRows` filas de `Skeleton` en lugar de los datos. |
|
|
2152
|
+
| `skeletonRows` | `number` | `6` | Cantidad de filas skeleton. |
|
|
2153
|
+
| `error` | `string`\|`node` | `null` | Si está presente, muestra un mensaje de error con icono en vez de la tabla de datos. |
|
|
2154
|
+
| `onRetry` | `function` | — | Si se define junto con `error`, muestra un botón "Reintentar". |
|
|
2155
|
+
| `emptyIcon` | `component` | `Inbox` | Icono mostrado cuando `data` está vacío. |
|
|
2156
|
+
| `emptyMessage` | `string` | `"No hay datos disponibles"` | Mensaje mostrado cuando `data` está vacío. |
|
|
2157
|
+
| `onRowClick` | `function(row)` | — | Si se define, hace las filas clicables (cursor pointer). |
|
|
2158
|
+
| `surfaceColor`, `headerColor`, `textColor`, `headingColor`, `mutedTextColor`, `borderColor`, `hoverColor`, `rowBorderColor` | `string` | — | Overrides de tema vía variables CSS `--tableA-*`. |
|
|
2159
|
+
| `filterIconColor` | `string` | — | Color del ícono de embudo cuando la columna no tiene filtro activo. |
|
|
2160
|
+
| `filterActiveColor` | `string` | `'#10b981'` | Color del ícono de embudo cuando `col.filter.value` tiene un valor (filtro activo). |
|
|
2161
|
+
|
|
2162
|
+
**Filtro por columna (`col.filter`):**
|
|
2163
|
+
|
|
2164
|
+
Cualquier columna puede declarar `filter: { options, value, onChange, tooltip? }` para mostrar un ícono de embudo junto al header que, al hacer click, **cicla** al siguiente valor de `options` (vuelve al principio al llegar al final):
|
|
2165
|
+
|
|
2166
|
+
| Campo de `filter` | Tipo | Descripción |
|
|
2167
|
+
|---|---|---|
|
|
2168
|
+
| `options` | `Array<{ value, label }>` | **Requerido.** Lista de valores por los que cicla el ícono. La primera opción suele representar "sin filtro" (ej. `{ value: '', label: 'Todos' }`). |
|
|
2169
|
+
| `value` | `any` | Valor actualmente seleccionado (controlado por el consumidor). |
|
|
2170
|
+
| `onChange` | `function(nextValue)` | La tabla lo llama con el siguiente valor del ciclo; el consumidor solo necesita guardarlo en estado. |
|
|
2171
|
+
| `tooltip` | `string` | Texto del tooltip del ícono; por default muestra el `label` de la opción actual. |
|
|
2172
|
+
|
|
2173
|
+
La tabla **no filtra `data` por sí misma** — solo maneja el ciclo de valores y el ícono. El consumidor decide cómo aplicar `value` sobre `data` (ej. con un `.filter()` antes de pasarlo a la tabla), igual que decide qué hacer con `onRowClick` o `render`.
|
|
2174
|
+
|
|
2175
|
+
**Ejemplos:**
|
|
2176
|
+
```jsx
|
|
2177
|
+
<TableA columns={columns} data={[]} keyExtractor={(row) => row.id} loading skeletonRows={4} />
|
|
2178
|
+
|
|
2179
|
+
<TableA
|
|
2180
|
+
columns={columns}
|
|
2181
|
+
data={[]}
|
|
2182
|
+
keyExtractor={(row) => row.id}
|
|
2183
|
+
error="No se pudieron cargar los datos."
|
|
2184
|
+
onRetry={() => console.log('retry clicked')}
|
|
2185
|
+
/>
|
|
2186
|
+
|
|
2187
|
+
// Con filtro por columna
|
|
2188
|
+
function UsersTable() {
|
|
2189
|
+
const [statusFilter, setStatusFilter] = useState('');
|
|
2190
|
+
|
|
2191
|
+
const columns = [
|
|
2192
|
+
{ header: 'Nombre', accessor: 'name' },
|
|
2193
|
+
{
|
|
2194
|
+
header: 'Estado',
|
|
2195
|
+
accessor: 'active',
|
|
2196
|
+
filter: {
|
|
2197
|
+
options: [
|
|
2198
|
+
{ value: '', label: 'Todos' },
|
|
2199
|
+
{ value: 'active', label: 'Activo' },
|
|
2200
|
+
{ value: 'inactive', label: 'Inactivo' },
|
|
2201
|
+
],
|
|
2202
|
+
value: statusFilter,
|
|
2203
|
+
onChange: setStatusFilter,
|
|
2204
|
+
},
|
|
2205
|
+
},
|
|
2206
|
+
];
|
|
2207
|
+
|
|
2208
|
+
const filteredData = users.filter((u) => {
|
|
2209
|
+
if (statusFilter === 'active') return u.active;
|
|
2210
|
+
if (statusFilter === 'inactive') return !u.active;
|
|
2211
|
+
return true;
|
|
2212
|
+
});
|
|
2213
|
+
|
|
2214
|
+
return <TableA columns={columns} data={filteredData} keyExtractor={(row) => row.id} />;
|
|
2215
|
+
}
|
|
2216
|
+
```
|
|
2217
|
+
|
|
2218
|
+
> **Importante:** `TableA` usa columnas con forma `{ header, accessor, align, width, render, filter }` y filas como objetos planos accedidos por `accessor`. Ver `TableB` abajo — su forma es distinta, no son intercambiables.
|
|
2219
|
+
|
|
2220
|
+
---
|
|
2221
|
+
|
|
2222
|
+
### TableB
|
|
2223
|
+
|
|
2224
|
+
Tabla "moderna" orientada a columnas con `key`/`label`, con soporte para columnas de tipo badge y acciones, filas expandibles y estados de carga/error/vacío.
|
|
2225
|
+
|
|
2226
|
+
**Import:**
|
|
2227
|
+
```jsx
|
|
2228
|
+
import TableB from 'screens/components/TableB';
|
|
2229
|
+
```
|
|
2230
|
+
|
|
2231
|
+
**Uso básico:**
|
|
2232
|
+
```jsx
|
|
2233
|
+
<TableB
|
|
2234
|
+
columns={[
|
|
2235
|
+
{ key: 'name', label: 'Nombre' },
|
|
2236
|
+
{ key: 'species', label: 'Especie' },
|
|
2237
|
+
]}
|
|
2238
|
+
data={[{ id: 1, name: 'Firulais', species: 'Perro' }]}
|
|
2239
|
+
rowKey="id"
|
|
2240
|
+
/>
|
|
2241
|
+
```
|
|
2242
|
+
|
|
2243
|
+
**Props:**
|
|
2244
|
+
|
|
2245
|
+
| Prop | Tipo | Default | Descripción |
|
|
2246
|
+
|---|---|---|---|
|
|
2247
|
+
| `columns` | `Array<{ key, label, align?, width?, type?, render?(row, rowIndex), badgeType?(row), badgeClass?(row), actions?: Array<{ label, onClick(row), disabled?(row), icon?, invertIcon? }>, filter? }>` | `[]` | Definición de columnas. `label` es el texto de cabecera; `key` identifica la columna y por defecto se lee `row[col.key]`. `type: 'badge'` renderiza el valor dentro de un `Barnner` (color según `badgeType(row)`: `'success'`\|`'warning'`\|`'danger'`); `type: 'actions'` renderiza botones definidos en `actions`. `filter` agrega un ícono de embudo junto al header (misma forma que en `TableA`, ver abajo). |
|
|
2248
|
+
| `data` | `Array<object>` | `[]` | Filas a renderizar; objetos planos leídos por `col.key` (o por `col.render`). |
|
|
2249
|
+
| `loading` | `boolean` | `false` | Muestra `skeletonRows` filas de `Skeleton`. |
|
|
2250
|
+
| `skeletonRows` | `number` | `6` | Cantidad de filas skeleton. |
|
|
2251
|
+
| `error` | `string`\|`node` | `null` | Si está presente, muestra un `Loading` con frases de error en vez de la tabla. |
|
|
2252
|
+
| `onRetry` | `function` | — | Recibido pero actualmente sin efecto (el botón de reintentar está comentado en el código). |
|
|
2253
|
+
| `emptyIcon` | `component` | `Inbox` | Icono mostrado cuando `data` está vacío. |
|
|
2254
|
+
| `emptyMessage` | `string` | `"No hay datos disponibles."` | Mensaje mostrado cuando `data` está vacío. |
|
|
2255
|
+
| `expandable` | `{ rowExpandable?(row) => boolean, expandedRowRender(row, rowIndex) => node }` | — | Si se define, agrega una columna de expandir. |
|
|
2256
|
+
| `rowKey` | `string` | `'id'` | Nombre de la propiedad de `data` usada como clave/identificador de fila. |
|
|
2257
|
+
| `rowClassName` | `function(row, rowIndex) => string` | — | Clase CSS adicional por fila. |
|
|
2258
|
+
| `surfaceColor`, `headerColor`, `textColor`, `headingColor`, `mutedTextColor`, `borderColor`, `hoverColor`, `rowBorderColor` | `string` | — | Overrides de tema vía variables CSS `--tableB-*`. |
|
|
2259
|
+
| `badgeColors` | `{ success?, warning?, danger?: { bg, color } }` | — | Overrides de color para columnas tipo badge. |
|
|
2260
|
+
| `filterIconColor` | `string` | — | Color del ícono de embudo sin filtro activo. |
|
|
2261
|
+
| `filterActiveColor` | `string` | `'#10b981'` | Color del ícono de embudo con filtro activo. |
|
|
2262
|
+
|
|
2263
|
+
**Filtro por columna (`col.filter`):** misma API que en `TableA` — ver esa sección para el detalle de `options`/`value`/`onChange`/`tooltip`. La tabla solo cicla el valor y muestra el ícono; el filtrado real de `data` lo hace el consumidor.
|
|
2264
|
+
|
|
2265
|
+
**Ejemplos:**
|
|
2266
|
+
```jsx
|
|
2267
|
+
<TableB
|
|
2268
|
+
columns={columns}
|
|
2269
|
+
data={data}
|
|
2270
|
+
rowKey="id"
|
|
2271
|
+
expandable={{
|
|
2272
|
+
rowExpandable: () => true,
|
|
2273
|
+
expandedRowRender: (row) => <div>Detalles adicionales para {row.name}</div>,
|
|
2274
|
+
}}
|
|
2275
|
+
/>
|
|
2276
|
+
|
|
2277
|
+
<TableB columns={columns} data={[]} error="Error al cargar la información" />
|
|
2278
|
+
|
|
2279
|
+
// Con filtro por columna
|
|
2280
|
+
function PetsTable() {
|
|
2281
|
+
const [statusFilter, setStatusFilter] = useState('');
|
|
2282
|
+
|
|
2283
|
+
const columns = [
|
|
2284
|
+
{ key: 'name', label: 'Nombre' },
|
|
2285
|
+
{
|
|
2286
|
+
key: 'status',
|
|
2287
|
+
label: 'Estado',
|
|
2288
|
+
type: 'badge',
|
|
2289
|
+
badgeType: (row) => (row.status === 'Activo' ? 'success' : 'warning'),
|
|
2290
|
+
filter: {
|
|
2291
|
+
options: [
|
|
2292
|
+
{ value: '', label: 'Todos' },
|
|
2293
|
+
{ value: 'Activo', label: 'Activo' },
|
|
2294
|
+
{ value: 'Inactivo', label: 'Inactivo' },
|
|
2295
|
+
],
|
|
2296
|
+
value: statusFilter,
|
|
2297
|
+
onChange: setStatusFilter,
|
|
2298
|
+
},
|
|
2299
|
+
},
|
|
2300
|
+
];
|
|
2301
|
+
|
|
2302
|
+
const filteredData = statusFilter ? pets.filter((p) => p.status === statusFilter) : pets;
|
|
2303
|
+
|
|
2304
|
+
return <TableB columns={columns} data={filteredData} rowKey="id" />;
|
|
2305
|
+
}
|
|
2306
|
+
```
|
|
2307
|
+
|
|
2308
|
+
> **Confirmado:** `TableB` usa una forma de columna DISTINTA a `TableA`: `{ key, label, type, badgeType(row), actions }` en vez de `{ header, accessor, render }`.
|
|
2309
|
+
|
|
2310
|
+
---
|
|
2311
|
+
|
|
2312
|
+
### ToggleCard
|
|
2313
|
+
|
|
2314
|
+
Tarjeta informativa/aviso con icono, título y descripción (con soporte de texto resaltado tipo `**negrita**`), acción custom y botón de cierre opcional.
|
|
2315
|
+
|
|
2316
|
+
**Import:**
|
|
2317
|
+
```jsx
|
|
2318
|
+
import ToggleCard from 'screens/components/ToggleCard';
|
|
2319
|
+
```
|
|
2320
|
+
|
|
2321
|
+
**Uso básico:**
|
|
2322
|
+
```jsx
|
|
2323
|
+
<ToggleCard title="Nueva funcionalidad disponible" description="Ahora puedes **destacar** texto." icon={Info} />
|
|
2324
|
+
```
|
|
2325
|
+
|
|
2326
|
+
**Props:**
|
|
2327
|
+
|
|
2328
|
+
| Prop | Tipo | Default | Descripción |
|
|
2329
|
+
|---|---|---|---|
|
|
2330
|
+
| `title` | `string`\|`node` | — | Título de la tarjeta (si es `string`, se procesa con `formatHighlightedText` para resaltar `**texto**`). |
|
|
2331
|
+
| `description` | `string`\|`node` | — | Descripción de la tarjeta (mismo procesamiento de resaltado si es `string`). |
|
|
2332
|
+
| `icon` | `component` | — | Icono mostrado junto al título. |
|
|
2333
|
+
| `action` | `node` | — | Elemento de acción custom (p. ej. un botón) mostrado en la sección de acciones. |
|
|
2334
|
+
| `children` | `node` | — | Contenido adicional renderizado debajo del bloque principal. |
|
|
2335
|
+
| `onClose` | `function` | — | Si se define, muestra un botón de cierre. |
|
|
2336
|
+
| `closeText` | `string` | `"Cerrar"` | Texto del botón de cierre. |
|
|
2337
|
+
| `variant` | `"default"` \| `"floating"` | `"default"` | `"floating"` aplica un estilo flotante/elevado. |
|
|
2338
|
+
| `onClick` | `function` | — | Si se define, hace clicable toda la tarjeta. |
|
|
2339
|
+
| `backgroundColor` | `string` | — | Color de fondo custom. |
|
|
2340
|
+
| `borderColor` | `string` | — | Color de borde custom. |
|
|
2341
|
+
| `titleColor` | `string` | — | Color del título. |
|
|
2342
|
+
| `descriptionColor` | `string` | — | Color de la descripción. |
|
|
2343
|
+
| `iconColor` | `string` | — | Color del icono. |
|
|
2344
|
+
|
|
2345
|
+
**Ejemplos:**
|
|
2346
|
+
```jsx
|
|
2347
|
+
<ToggleCard
|
|
2348
|
+
title="Acción requerida"
|
|
2349
|
+
description="Revisa los cambios pendientes antes de continuar."
|
|
2350
|
+
icon={Info}
|
|
2351
|
+
action={<button type="button">Revisar</button>}
|
|
2352
|
+
backgroundColor="#fef3c7"
|
|
2353
|
+
borderColor="#f59e0b"
|
|
2354
|
+
onClick={() => console.log('card clicked')}
|
|
2355
|
+
/>
|
|
2356
|
+
```
|
|
2357
|
+
|
|
2358
|
+
**Notas:** Es usado internamente por `PasswordResetPanel` (variant `"floating"`) para mostrar avisos flotantes de estado.
|
|
2359
|
+
|
|
2360
|
+
---
|
|
2361
|
+
|
|
2362
|
+
### UserEditPopover
|
|
2363
|
+
|
|
2364
|
+
Popover (basado en MUI `Popover`) para editar el nombre de usuario, con guardado contra la API real.
|
|
2365
|
+
|
|
2366
|
+
**Import:**
|
|
2367
|
+
```jsx
|
|
2368
|
+
import UserEditPopover from 'screens/components/UserEditPopover';
|
|
2369
|
+
```
|
|
2370
|
+
|
|
2371
|
+
**Uso básico:**
|
|
2372
|
+
```jsx
|
|
2373
|
+
<UserEditPopover
|
|
2374
|
+
open={open}
|
|
2375
|
+
anchorEl={anchorEl}
|
|
2376
|
+
onClose={() => setOpen(false)}
|
|
2377
|
+
currentName="Ana Gomez"
|
|
2378
|
+
onSuccess={(name) => setUsername(name)}
|
|
2379
|
+
/>
|
|
2380
|
+
```
|
|
2381
|
+
|
|
2382
|
+
**Props:**
|
|
2383
|
+
|
|
2384
|
+
| Prop | Tipo | Default | Descripción |
|
|
2385
|
+
| ---------------| ---------------------| ---------| --------------------------------------------------------------------------------------------------------------------------------------|
|
|
2386
|
+
| `open` | `boolean` | — | Controla la visibilidad del popover. |
|
|
2387
|
+
| `anchorEl` | `HTMLElement` | — | Nodo DOM al que se ancla el popover (requerido por MUI `Popover`). |
|
|
2388
|
+
| `onClose` | `function` | — | Callback al cerrar el popover (también se llama tras guardar). |
|
|
2389
|
+
| `currentName` | `string` | — | Nombre actual, usado para precargar el input al abrir. |
|
|
2390
|
+
| `onSuccess` | `function(newName)` | — | Callback invocado con el nuevo nombre tras un guardado exitoso (o incluso si la llamada a la API falla, como fallback para pruebas). |
|
|
2391
|
+
| `bgColor` | `string` | — | Color de fondo del popover (`--usereditpopover-bg`). |
|
|
2392
|
+
| `saveColor` | `string` | — | Color del botón guardar (`--usereditpopover-save`). |
|
|
2393
|
+
| `cancelColor` | `string` | — | Color del botón cancelar (`--usereditpopover-cancel`). |
|
|
2394
|
+
|
|
2395
|
+
**Ejemplos:**
|
|
2396
|
+
```jsx
|
|
2397
|
+
<UserEditPopover open={true} anchorEl={anchorEl} currentName="" onClose={() => {}} onSuccess={(name) => console.log('saved name', name)} />
|
|
2398
|
+
```
|
|
2399
|
+
|
|
2400
|
+
**Notas:** Al guardar, llama a `updateUserName` de `features/user-profile/api.js` y a `getUserId` de `common/storage/LocalStorage.js`. Para que la petición real funcione en una app consumidora es necesario tener configurado `configureApiClient` (`common/api/client.js`); si la llamada falla, el componente igual invoca `onSuccess` con el nombre local como fallback para pruebas.
|