@adamosuiteservices/ui 2.10.12 → 2.11.13
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/dist/accordion-rounded.cjs +7 -7
- package/dist/accordion-rounded.js +1 -1
- package/dist/calendar-Bapd0vmU.js +2949 -0
- package/dist/calendar-DMvGcwMp.cjs +76 -0
- package/dist/calendar.cjs +1 -76
- package/dist/calendar.js +3 -2945
- package/dist/colors.css +1 -1
- package/dist/combobox-CW07jN3o.cjs +37 -0
- package/dist/combobox-CtdzWxGX.js +598 -0
- package/dist/combobox.cjs +1 -37
- package/dist/combobox.js +2 -596
- package/dist/components/layout/full-screen-loader/full-screen-loader-manager.d.ts +6 -0
- package/dist/components/layout/full-screen-loader/full-screen-loader-observable.d.ts +8 -0
- package/dist/components/layout/full-screen-loader/full-screen-loader.d.ts +4 -0
- package/dist/components/layout/full-screen-loader/index.d.ts +3 -0
- package/dist/components/ui/date-picker-selector/date-picker-selector.d.ts +21 -0
- package/dist/components/ui/date-picker-selector/index.d.ts +1 -0
- package/dist/date-picker-selector.cjs +1 -0
- package/dist/date-picker-selector.js +105 -0
- package/dist/full-screen-loader.cjs +4 -0
- package/dist/full-screen-loader.js +50 -0
- package/dist/spinner-B-sC3DVC.cjs +1 -0
- package/dist/spinner-DvrliN2E.js +19 -0
- package/dist/spinner.cjs +1 -1
- package/dist/spinner.js +1 -16
- package/dist/styles.css +1 -1
- package/dist/table.cjs +5 -5
- package/dist/table.js +2 -2
- package/dist/tailwind-colors.css +1 -1
- package/dist/tailwind-theme.css +1 -1
- package/dist/themes.css +1 -1
- package/dist/tooltip.cjs +5 -4
- package/dist/tooltip.js +4 -3
- package/dist/types/theme.type.d.ts +1 -1
- package/docs/components/layout/full-screen-loader.md +500 -0
- package/docs/components/ui/accordion-rounded.md +7 -7
- package/docs/components/ui/accordion.md +2 -2
- package/docs/components/ui/alert.md +3 -3
- package/docs/components/ui/avatar.md +10 -10
- package/docs/components/ui/badge.md +10 -53
- package/docs/components/ui/button.md +1 -1
- package/docs/components/ui/calendar.md +1 -1
- package/docs/components/ui/combobox.md +7 -7
- package/docs/components/ui/date-picker-selector.md +376 -0
- package/docs/components/ui/hover-card.md +1 -1
- package/docs/components/ui/icon.md +12 -12
- package/docs/components/ui/input-group.md +9 -14
- package/docs/components/ui/popover.md +2 -2
- package/docs/components/ui/spinner.md +1 -1
- package/docs/components/ui/table.md +1 -1
- package/docs/components/ui/tooltip.md +3 -3
- package/docs/components/ui/typography.md +1 -1
- package/package.json +9 -1
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
# Full Screen Loader Component
|
|
2
|
+
|
|
3
|
+
## Descripción
|
|
4
|
+
|
|
5
|
+
Overlay de **carga a pantalla completa** que bloquea la interacción del usuario durante operaciones asíncronas. Incluye un spinner animado y un fondo semi-transparente con efecto de backdrop, ideal para indicar operaciones críticas o procesos de carga inicial.
|
|
6
|
+
|
|
7
|
+
## Características
|
|
8
|
+
|
|
9
|
+
- ✅ Overlay a pantalla completa con posicionamiento fijo
|
|
10
|
+
- ✅ Fondo semi-transparente (`bg-black/50`)
|
|
11
|
+
- ✅ Spinner animado en color primario
|
|
12
|
+
- ✅ Control programático con `show()` y `hide()`
|
|
13
|
+
- ✅ Patrón observable para sincronización global
|
|
14
|
+
- ✅ Portal rendering para z-index óptimo (`z-100`)
|
|
15
|
+
- ✅ Centrado automático del spinner
|
|
16
|
+
- ✅ Bloqueo de interacción durante carga
|
|
17
|
+
|
|
18
|
+
## Importación
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import {
|
|
22
|
+
FullScreenLoader,
|
|
23
|
+
FullScreenLoaderManager,
|
|
24
|
+
} from "@adamosuiteservices/ui/full-screen-loader";
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Setup Inicial
|
|
28
|
+
|
|
29
|
+
Agrega el componente `FullScreenLoader` en el nivel más alto de tu aplicación:
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { FullScreenLoader } from "@adamosuiteservices/ui/full-screen-loader";
|
|
33
|
+
|
|
34
|
+
function App() {
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
{/* Tu app aquí */}
|
|
38
|
+
<FullScreenLoader />
|
|
39
|
+
</>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Importante**: Solo necesitas una instancia de `FullScreenLoader` en toda tu aplicación.
|
|
45
|
+
|
|
46
|
+
## Uso Básico
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { FullScreenLoaderManager } from "@adamosuiteservices/ui/full-screen-loader";
|
|
50
|
+
import { Button } from "@adamosuiteservices/ui/button";
|
|
51
|
+
|
|
52
|
+
function MyComponent() {
|
|
53
|
+
const handleAsyncOperation = async () => {
|
|
54
|
+
// Mostrar loader
|
|
55
|
+
FullScreenLoaderManager.show();
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
await someAsyncOperation();
|
|
59
|
+
} finally {
|
|
60
|
+
// Ocultar loader siempre, incluso si hay error
|
|
61
|
+
FullScreenLoaderManager.hide();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return <Button onClick={handleAsyncOperation}>Process Data</Button>;
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Patrones de Uso
|
|
70
|
+
|
|
71
|
+
### Operación Asíncrona Simple
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
async function fetchData() {
|
|
75
|
+
FullScreenLoaderManager.show();
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const data = await api.getData();
|
|
79
|
+
return data;
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error(error);
|
|
82
|
+
} finally {
|
|
83
|
+
FullScreenLoaderManager.hide();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Múltiples Operaciones en Secuencia
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
async function processMultipleSteps() {
|
|
92
|
+
FullScreenLoaderManager.show();
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
await step1();
|
|
96
|
+
await step2();
|
|
97
|
+
await step3();
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.error("Process failed:", error);
|
|
100
|
+
} finally {
|
|
101
|
+
FullScreenLoaderManager.hide();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Con Timeout Automático
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
function showTemporaryLoader() {
|
|
110
|
+
FullScreenLoaderManager.show();
|
|
111
|
+
|
|
112
|
+
// Auto-ocultar después de 3 segundos
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
FullScreenLoaderManager.hide();
|
|
115
|
+
}, 3000);
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Operaciones Paralelas con Promise.all
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
async function fetchMultipleResources() {
|
|
123
|
+
FullScreenLoaderManager.show();
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const [users, products, orders] = await Promise.all([
|
|
127
|
+
api.getUsers(),
|
|
128
|
+
api.getProducts(),
|
|
129
|
+
api.getOrders(),
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
return { users, products, orders };
|
|
133
|
+
} finally {
|
|
134
|
+
FullScreenLoaderManager.hide();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Navegación con Next.js Router
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
import { useRouter } from "next/navigation";
|
|
143
|
+
import { FullScreenLoaderManager } from "@adamosuiteservices/ui/full-screen-loader";
|
|
144
|
+
|
|
145
|
+
function NavigationComponent() {
|
|
146
|
+
const router = useRouter();
|
|
147
|
+
|
|
148
|
+
const handleNavigation = () => {
|
|
149
|
+
FullScreenLoaderManager.show();
|
|
150
|
+
router.push("/dashboard");
|
|
151
|
+
// El loader se ocultará después de que la página cargue
|
|
152
|
+
// Puedes usar un useEffect en la página de destino para ocultarlo
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
return <Button onClick={handleNavigation}>Go to Dashboard</Button>;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Carga Inicial de la Aplicación
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
import { FullScreenLoaderManager } from "@adamosuiteservices/ui/full-screen-loader";
|
|
163
|
+
import { useEffect } from "react";
|
|
164
|
+
|
|
165
|
+
function App() {
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
// Mostrar loader al inicio
|
|
168
|
+
FullScreenLoaderManager.show();
|
|
169
|
+
|
|
170
|
+
// Inicializar la app
|
|
171
|
+
initializeApp().then(() => {
|
|
172
|
+
FullScreenLoaderManager.hide();
|
|
173
|
+
});
|
|
174
|
+
}, []);
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<>
|
|
178
|
+
{/* App content */}
|
|
179
|
+
<FullScreenLoader />
|
|
180
|
+
</>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## API Reference
|
|
186
|
+
|
|
187
|
+
### FullScreenLoaderManager
|
|
188
|
+
|
|
189
|
+
Clase singleton para controlar el estado del loader globalmente.
|
|
190
|
+
|
|
191
|
+
#### `show()`
|
|
192
|
+
|
|
193
|
+
Muestra el loader de pantalla completa.
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
FullScreenLoaderManager.show();
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Uso**: Llamar antes de iniciar operaciones que requieran bloquear la UI.
|
|
200
|
+
|
|
201
|
+
#### `hide()`
|
|
202
|
+
|
|
203
|
+
Oculta el loader de pantalla completa.
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
FullScreenLoaderManager.hide();
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Uso**: Llamar después de completar operaciones, siempre en un bloque `finally` para garantizar ejecución.
|
|
210
|
+
|
|
211
|
+
## Comportamiento
|
|
212
|
+
|
|
213
|
+
### Estado Global
|
|
214
|
+
|
|
215
|
+
El loader usa un patrón observable que sincroniza el estado en toda la aplicación:
|
|
216
|
+
|
|
217
|
+
- Una sola instancia de `FullScreenLoader` responde a todos los llamados de `show()`/`hide()`
|
|
218
|
+
- Múltiples componentes pueden controlar el loader sin conflictos
|
|
219
|
+
- El estado se mantiene consistente incluso con navegación
|
|
220
|
+
|
|
221
|
+
### Z-Index y Posicionamiento
|
|
222
|
+
|
|
223
|
+
- **z-index**: `z-100` para estar sobre todo el contenido
|
|
224
|
+
- **Posicionamiento**: `fixed` con `inset-0` (cubre toda la ventana)
|
|
225
|
+
- **Centrado**: Flexbox con `items-center` y `justify-center`
|
|
226
|
+
|
|
227
|
+
### Estilos Visuales
|
|
228
|
+
|
|
229
|
+
```css
|
|
230
|
+
/* Overlay background */
|
|
231
|
+
bg-black/50 /* Negro con 50% opacidad */
|
|
232
|
+
|
|
233
|
+
/* Spinner */
|
|
234
|
+
text-4xl /* Tamaño grande del spinner */
|
|
235
|
+
text-primary /* Color primario del tema */
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Best Practices
|
|
239
|
+
|
|
240
|
+
### ✅ DO: Usar `finally` para Garantizar Hide
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
async function operation() {
|
|
244
|
+
FullScreenLoaderManager.show();
|
|
245
|
+
try {
|
|
246
|
+
await asyncOperation();
|
|
247
|
+
} finally {
|
|
248
|
+
// ✅ Siempre se ejecuta, incluso si hay error
|
|
249
|
+
FullScreenLoaderManager.hide();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### ❌ DON'T: Olvidar Ocultar el Loader
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
async function operation() {
|
|
258
|
+
FullScreenLoaderManager.show();
|
|
259
|
+
await asyncOperation();
|
|
260
|
+
// ❌ Si hay error, el loader queda visible
|
|
261
|
+
FullScreenLoaderManager.hide();
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### ✅ DO: Una Sola Instancia en la App
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
// ✅ En App.tsx o layout principal
|
|
269
|
+
function App() {
|
|
270
|
+
return (
|
|
271
|
+
<>
|
|
272
|
+
<YourApp />
|
|
273
|
+
<FullScreenLoader />
|
|
274
|
+
</>
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### ❌ DON'T: Múltiples Instancias
|
|
280
|
+
|
|
281
|
+
```tsx
|
|
282
|
+
// ❌ No crear múltiples instancias
|
|
283
|
+
function PageA() {
|
|
284
|
+
return (
|
|
285
|
+
<>
|
|
286
|
+
<Content />
|
|
287
|
+
<FullScreenLoader /> {/* ❌ Redundante */}
|
|
288
|
+
</>
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### ✅ DO: Operaciones Críticas y Largas
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
// ✅ Bueno para: autenticación, carga inicial, procesamiento pesado
|
|
297
|
+
async function authenticate() {
|
|
298
|
+
FullScreenLoaderManager.show();
|
|
299
|
+
await login();
|
|
300
|
+
FullScreenLoaderManager.hide();
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### ❌ DON'T: Operaciones Rápidas o Menores
|
|
305
|
+
|
|
306
|
+
```tsx
|
|
307
|
+
// ❌ No usar para operaciones menores de 500ms
|
|
308
|
+
async function quickAction() {
|
|
309
|
+
FullScreenLoaderManager.show(); // ❌ Muy intrusivo
|
|
310
|
+
await quickApi(); // < 500ms
|
|
311
|
+
FullScreenLoaderManager.hide();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// ✅ Mejor usar un spinner local o skeleton
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Casos de Uso
|
|
318
|
+
|
|
319
|
+
### ✅ Recomendado Para:
|
|
320
|
+
|
|
321
|
+
- **Autenticación y Login**: Procesos de inicio de sesión
|
|
322
|
+
- **Carga Inicial**: Primera carga de datos de la aplicación
|
|
323
|
+
- **Navegación Crítica**: Cambios de página con carga pesada
|
|
324
|
+
- **Procesamiento Pesado**: Cálculos complejos o batch operations
|
|
325
|
+
- **Uploads Grandes**: Subida de archivos que bloquean la UI
|
|
326
|
+
- **Transacciones Críticas**: Operaciones que no deben interrumpirse
|
|
327
|
+
|
|
328
|
+
### ❌ No Recomendado Para:
|
|
329
|
+
|
|
330
|
+
- **Operaciones Rápidas** (< 500ms): Usar spinner local
|
|
331
|
+
- **Búsquedas en Tiempo Real**: Usar loading states inline
|
|
332
|
+
- **Validaciones de Formulario**: Usar feedback local
|
|
333
|
+
- **Acciones Menores**: Usar botones con loading state
|
|
334
|
+
- **Scroll Infinito**: Usar skeleton loaders
|
|
335
|
+
|
|
336
|
+
## Accesibilidad
|
|
337
|
+
|
|
338
|
+
El componente incluye consideraciones básicas de accesibilidad:
|
|
339
|
+
|
|
340
|
+
- **Portal rendering**: Asegura que el loader esté en el nivel superior del DOM
|
|
341
|
+
- **Fixed positioning**: Garantiza visibilidad sobre todo el contenido
|
|
342
|
+
- **Visual feedback**: Spinner animado claramente visible
|
|
343
|
+
|
|
344
|
+
### Mejoras Sugeridas
|
|
345
|
+
|
|
346
|
+
Para aplicaciones con requisitos estrictos de accesibilidad, considera agregar:
|
|
347
|
+
|
|
348
|
+
```tsx
|
|
349
|
+
<div role="dialog" aria-modal="true" aria-label="Loading" aria-busy="true">
|
|
350
|
+
<Spinner />
|
|
351
|
+
</div>
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Troubleshooting
|
|
355
|
+
|
|
356
|
+
### El loader no aparece
|
|
357
|
+
|
|
358
|
+
**Causa**: Falta el componente `<FullScreenLoader />` en la aplicación.
|
|
359
|
+
|
|
360
|
+
**Solución**: Agregar en el nivel más alto de tu app (App.tsx, layout, etc.).
|
|
361
|
+
|
|
362
|
+
### El loader queda visible permanentemente
|
|
363
|
+
|
|
364
|
+
**Causa**: No se llamó `hide()` después de una operación, probablemente debido a un error.
|
|
365
|
+
|
|
366
|
+
**Solución**: Siempre usar bloque `try/finally` para garantizar que `hide()` se ejecute.
|
|
367
|
+
|
|
368
|
+
```tsx
|
|
369
|
+
try {
|
|
370
|
+
await operation();
|
|
371
|
+
} finally {
|
|
372
|
+
FullScreenLoaderManager.hide(); // ✅ Siempre se ejecuta
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### El loader aparece detrás de otros elementos
|
|
377
|
+
|
|
378
|
+
**Causa**: Algún elemento tiene un `z-index` mayor que 100.
|
|
379
|
+
|
|
380
|
+
**Solución**: El loader usa `z-100`. Verifica que ningún elemento tenga un z-index mayor. Si es necesario, ajusta el z-index del loader.
|
|
381
|
+
|
|
382
|
+
### Múltiples loaders aparecen simultáneamente
|
|
383
|
+
|
|
384
|
+
**Causa**: Múltiples instancias de `<FullScreenLoader />` en la aplicación.
|
|
385
|
+
|
|
386
|
+
**Solución**: Solo debe haber una instancia en toda la aplicación, en el nivel más alto.
|
|
387
|
+
|
|
388
|
+
## Integración con Otros Componentes
|
|
389
|
+
|
|
390
|
+
### Con React Query
|
|
391
|
+
|
|
392
|
+
```tsx
|
|
393
|
+
import { useMutation } from "@tanstack/react-query";
|
|
394
|
+
import { FullScreenLoaderManager } from "@adamosuiteservices/ui/full-screen-loader";
|
|
395
|
+
|
|
396
|
+
function MyComponent() {
|
|
397
|
+
const mutation = useMutation({
|
|
398
|
+
mutationFn: saveData,
|
|
399
|
+
onMutate: () => {
|
|
400
|
+
FullScreenLoaderManager.show();
|
|
401
|
+
},
|
|
402
|
+
onSettled: () => {
|
|
403
|
+
FullScreenLoaderManager.hide();
|
|
404
|
+
},
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
return <Button onClick={() => mutation.mutate()}>Save</Button>;
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Con Redux/Zustand
|
|
412
|
+
|
|
413
|
+
```tsx
|
|
414
|
+
// En tu action/slice
|
|
415
|
+
export const fetchData = createAsyncThunk("data/fetch", async () => {
|
|
416
|
+
FullScreenLoaderManager.show();
|
|
417
|
+
try {
|
|
418
|
+
const data = await api.getData();
|
|
419
|
+
return data;
|
|
420
|
+
} finally {
|
|
421
|
+
FullScreenLoaderManager.hide();
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Con Form Submit
|
|
427
|
+
|
|
428
|
+
```tsx
|
|
429
|
+
import { useForm } from "react-hook-form";
|
|
430
|
+
import { FullScreenLoaderManager } from "@adamosuiteservices/ui/full-screen-loader";
|
|
431
|
+
|
|
432
|
+
function FormComponent() {
|
|
433
|
+
const { handleSubmit } = useForm();
|
|
434
|
+
|
|
435
|
+
const onSubmit = async (data) => {
|
|
436
|
+
FullScreenLoaderManager.show();
|
|
437
|
+
try {
|
|
438
|
+
await api.submitForm(data);
|
|
439
|
+
} finally {
|
|
440
|
+
FullScreenLoaderManager.hide();
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
return <form onSubmit={handleSubmit(onSubmit)}>...</form>;
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
## Componentes Relacionados
|
|
449
|
+
|
|
450
|
+
- **[Spinner](../../ui/spinner.md)**: Loading indicator usado internamente
|
|
451
|
+
- **[Button](../../ui/button.md)**: Para triggers de operaciones con loading state
|
|
452
|
+
- **[Toaster](./toaster.md)**: Para feedback después de operaciones (combinar con loader)
|
|
453
|
+
|
|
454
|
+
## Ejemplo Completo
|
|
455
|
+
|
|
456
|
+
```tsx
|
|
457
|
+
import {
|
|
458
|
+
FullScreenLoader,
|
|
459
|
+
FullScreenLoaderManager,
|
|
460
|
+
} from "@adamosuiteservices/ui/full-screen-loader";
|
|
461
|
+
import { ToastManager } from "@adamosuiteservices/ui/toaster";
|
|
462
|
+
import { Button } from "@adamosuiteservices/ui/button";
|
|
463
|
+
|
|
464
|
+
function App() {
|
|
465
|
+
return (
|
|
466
|
+
<>
|
|
467
|
+
<Dashboard />
|
|
468
|
+
<FullScreenLoader />
|
|
469
|
+
</>
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function Dashboard() {
|
|
474
|
+
const handleSync = async () => {
|
|
475
|
+
FullScreenLoaderManager.show();
|
|
476
|
+
|
|
477
|
+
try {
|
|
478
|
+
await syncData();
|
|
479
|
+
ToastManager.show({
|
|
480
|
+
message: "Data synchronized successfully",
|
|
481
|
+
variant: "success",
|
|
482
|
+
});
|
|
483
|
+
} catch (error) {
|
|
484
|
+
ToastManager.show({
|
|
485
|
+
message: "Failed to synchronize data",
|
|
486
|
+
variant: "destructive",
|
|
487
|
+
});
|
|
488
|
+
} finally {
|
|
489
|
+
FullScreenLoaderManager.hide();
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
return (
|
|
494
|
+
<div>
|
|
495
|
+
<h1>Dashboard</h1>
|
|
496
|
+
<Button onClick={handleSync}>Sync Data</Button>
|
|
497
|
+
</div>
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
```
|
|
@@ -107,7 +107,7 @@ Contenedor individual de cada item del accordion.
|
|
|
107
107
|
**Estilos aplicados**:
|
|
108
108
|
|
|
109
109
|
- `rounded-2xl`: Bordes muy redondeados
|
|
110
|
-
- `bg-
|
|
110
|
+
- `bg-muted`: Fondo gris claro
|
|
111
111
|
- `mb-4`: Margen inferior de 1rem
|
|
112
112
|
- `last:mb-0`: Sin margen en el último item
|
|
113
113
|
|
|
@@ -246,7 +246,7 @@ Solo un item abierto a la vez:
|
|
|
246
246
|
/>
|
|
247
247
|
<AccordionContent>
|
|
248
248
|
<div className="p-4 space-y-3">
|
|
249
|
-
<div className="rounded-lg border
|
|
249
|
+
<div className="rounded-lg border p-3">
|
|
250
250
|
<h4 className="text-sm font-semibold text-foreground">Full Name</h4>
|
|
251
251
|
<p className="text-sm text-foreground mt-1">Required field</p>
|
|
252
252
|
</div>
|
|
@@ -374,21 +374,21 @@ Varios items pueden estar abiertos simultáneamente:
|
|
|
374
374
|
/>
|
|
375
375
|
<AccordionContent>
|
|
376
376
|
<div className="p-4 space-y-4">
|
|
377
|
-
<div className="flex items-center justify-between p-3 bg-
|
|
377
|
+
<div className="flex items-center justify-between p-3 bg-muted rounded-lg">
|
|
378
378
|
<div>
|
|
379
379
|
<p className="text-sm font-semibold text-foreground">
|
|
380
380
|
Credit Card
|
|
381
381
|
</p>
|
|
382
382
|
<p className="text-xs text-muted-foreground">•••• 4242</p>
|
|
383
383
|
</div>
|
|
384
|
-
<span className="text-xs text-success
|
|
384
|
+
<span className="text-xs text-success font-medium">Active</span>
|
|
385
385
|
</div>
|
|
386
|
-
<div className="flex items-center justify-between p-3 bg-
|
|
386
|
+
<div className="flex items-center justify-between p-3 bg-muted rounded-lg">
|
|
387
387
|
<div>
|
|
388
388
|
<p className="text-sm font-semibold text-foreground">PayPal</p>
|
|
389
389
|
<p className="text-xs text-muted-foreground">user@example.com</p>
|
|
390
390
|
</div>
|
|
391
|
-
<span className="text-xs text-success
|
|
391
|
+
<span className="text-xs text-success font-medium">Active</span>
|
|
392
392
|
</div>
|
|
393
393
|
</div>
|
|
394
394
|
</AccordionContent>
|
|
@@ -548,7 +548,7 @@ Sin badges para diseño minimalista:
|
|
|
548
548
|
| Característica | Accordion Regular | Accordion Rounded |
|
|
549
549
|
| ------------------ | ----------------------- | --------------------------------- |
|
|
550
550
|
| Bordes | Esquinas cuadradas | `rounded-2xl` (muy redondeado) |
|
|
551
|
-
| Fondo del Item | Transparente con border | `bg-
|
|
551
|
+
| Fondo del Item | Transparente con border | `bg-muted` (gris claro) |
|
|
552
552
|
| Separación | Border entre items | Margen `mb-4` entre items |
|
|
553
553
|
| Badge Support | No (solo children) | Sí (prop `badge` dedicada) |
|
|
554
554
|
| Estilo del Título | Normal | Mayúsculas, compacto, color gris |
|
|
@@ -236,7 +236,7 @@ El trigger incluye hover effect con subrayado:
|
|
|
236
236
|
<AccordionItem value="phase-1">
|
|
237
237
|
<AccordionTrigger>
|
|
238
238
|
<div className="flex items-center gap-2">
|
|
239
|
-
<
|
|
239
|
+
<Icon symbol="check_circle" className="text-lg" />
|
|
240
240
|
Phase 1: Planning
|
|
241
241
|
</div>
|
|
242
242
|
</AccordionTrigger>
|
|
@@ -260,7 +260,7 @@ El trigger incluye hover effect con subrayado:
|
|
|
260
260
|
|
|
261
261
|
- Usa Radix UI Accordion internamente
|
|
262
262
|
- Todos los estilos tienen prefijo ``
|
|
263
|
-
- El icono
|
|
263
|
+
- El icono keyboard_arrow_down se incluye automáticamente en el trigger
|
|
264
264
|
- Las animaciones son manejadas por CSS y data attributes
|
|
265
265
|
|
|
266
266
|
## Referencias
|
|
@@ -344,15 +344,15 @@ import { Progress } from "@adamosuiteservices/ui/progress";
|
|
|
344
344
|
</div>
|
|
345
345
|
<div className="flex gap-4 justify-between">
|
|
346
346
|
<span>Memory usage:</span>
|
|
347
|
-
<span className="text-
|
|
347
|
+
<span className="text-success">-23%</span>
|
|
348
348
|
</div>
|
|
349
349
|
<div className="flex gap-4 justify-between">
|
|
350
350
|
<span>CPU usage:</span>
|
|
351
|
-
<span className="text-
|
|
351
|
+
<span className="text-success">-31%</span>
|
|
352
352
|
</div>
|
|
353
353
|
<div className="flex gap-4 justify-between">
|
|
354
354
|
<span>Battery life:</span>
|
|
355
|
-
<span className="text-
|
|
355
|
+
<span className="text-success">+18%</span>
|
|
356
356
|
</div>
|
|
357
357
|
</div>
|
|
358
358
|
</AlertDescription>
|
|
@@ -378,16 +378,16 @@ Para mostrar estado online/offline/busy:
|
|
|
378
378
|
<AvatarFallback>JD</AvatarFallback>
|
|
379
379
|
</Avatar>
|
|
380
380
|
{/* Indicador de estado */}
|
|
381
|
-
<span className="absolute bottom-0 right-0 block h-3 w-3 rounded-full bg-
|
|
381
|
+
<span className="absolute bottom-0 right-0 block h-3 w-3 rounded-full bg-success ring-2 ring-background" />
|
|
382
382
|
</div>
|
|
383
383
|
```
|
|
384
384
|
|
|
385
385
|
**Variantes de estado**:
|
|
386
386
|
|
|
387
|
-
- `bg-
|
|
387
|
+
- `bg-success`: Online
|
|
388
388
|
- `bg-gray-400`: Offline
|
|
389
|
-
- `bg-
|
|
390
|
-
- `bg-
|
|
389
|
+
- `bg-warning`: Away/Idle
|
|
390
|
+
- `bg-destructive`: Busy/Do Not Disturb
|
|
391
391
|
|
|
392
392
|
### Avatar con Badge
|
|
393
393
|
|
|
@@ -525,7 +525,7 @@ Mantén tamaños consistentes por contexto:
|
|
|
525
525
|
```tsx
|
|
526
526
|
<Avatar>
|
|
527
527
|
<AvatarImage src={url} alt="User" />
|
|
528
|
-
<AvatarFallback className="bg-
|
|
528
|
+
<AvatarFallback className="bg-primary text-primary-foreground">AB</AvatarFallback>
|
|
529
529
|
</Avatar>
|
|
530
530
|
```
|
|
531
531
|
|
|
@@ -534,11 +534,11 @@ Mantén tamaños consistentes por contexto:
|
|
|
534
534
|
```typescript
|
|
535
535
|
function getAvatarColor(name: string): string {
|
|
536
536
|
const colors = [
|
|
537
|
-
"bg-
|
|
538
|
-
"bg-
|
|
539
|
-
"bg-
|
|
540
|
-
"bg-
|
|
541
|
-
"bg-
|
|
537
|
+
"bg-destructive",
|
|
538
|
+
"bg-primary",
|
|
539
|
+
"bg-success",
|
|
540
|
+
"bg-warning",
|
|
541
|
+
"bg-primary",
|
|
542
542
|
];
|
|
543
543
|
const index = name.charCodeAt(0) % colors.length;
|
|
544
544
|
return colors[index];
|