@adamosuiteservices/ui 2.10.13 → 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/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/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/themes.css +1 -1
- package/docs/components/layout/full-screen-loader.md +500 -0
- package/docs/components/ui/date-picker-selector.md +376 -0
- package/package.json +9 -1
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# Date Picker Selector
|
|
2
|
+
|
|
3
|
+
A comprehensive date range selector component combining preset date ranges with custom calendar selection.
|
|
4
|
+
|
|
5
|
+
## Descripción
|
|
6
|
+
|
|
7
|
+
El componente `DatePickerSelector` proporciona una interfaz intuitiva para seleccionar rangos de fechas. Incluye opciones predefinidas (últimos 7, 30, 90 días) y un selector de calendario personalizado para rangos específicos.
|
|
8
|
+
|
|
9
|
+
## Características
|
|
10
|
+
|
|
11
|
+
- ✅ Rangos predefinidos (7, 30, 90 días)
|
|
12
|
+
- ✅ Selector de calendario personalizado para rangos específicos
|
|
13
|
+
- ✅ Formato de fecha limpio (medianoche, sin horas)
|
|
14
|
+
- ✅ Labels personalizables para internacionalización
|
|
15
|
+
- ✅ Integración con Combobox y Calendar
|
|
16
|
+
- ✅ Props personalizables para Combobox y Calendar
|
|
17
|
+
- ✅ Estado controlado con callback onChange
|
|
18
|
+
|
|
19
|
+
## Importación
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { DatePickerSelector } from "@adamosuiteservices/ui/date-picker-selector";
|
|
23
|
+
import type { DateRange } from "react-day-picker";
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Uso Básico
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { DatePickerSelector } from "@adamosuiteservices/ui/date-picker-selector";
|
|
30
|
+
import { useState } from "react";
|
|
31
|
+
import type { DateRange } from "react-day-picker";
|
|
32
|
+
|
|
33
|
+
function MyComponent() {
|
|
34
|
+
const [dateRange, setDateRange] = useState<DateRange>({
|
|
35
|
+
from: undefined,
|
|
36
|
+
to: undefined,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<DatePickerSelector
|
|
41
|
+
dateRange={dateRange}
|
|
42
|
+
onDateRangeChange={setDateRange}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Props
|
|
49
|
+
|
|
50
|
+
| Prop | Tipo | Default | Descripción |
|
|
51
|
+
| ------------------ | ------------------------ | ----------- | -------------------------------------------------------------- |
|
|
52
|
+
| `dateRange` | `DateRange` | - | **Requerido**. Rango de fechas actual |
|
|
53
|
+
| `onDateRangeChange`| `(dateRange: DateRange) => void` | - | **Requerido**. Callback al cambiar el rango |
|
|
54
|
+
| `labels` | `DatePickerSelectorLabels` | - | Labels personalizables para todos los textos de UI |
|
|
55
|
+
| `combobox` | `ComboboxProps` | - | Props adicionales para el componente Combobox |
|
|
56
|
+
| `calendar` | `CalendarProps` | - | Props adicionales para el componente Calendar |
|
|
57
|
+
| `className` | `string` | - | Clases CSS adicionales para el contenedor |
|
|
58
|
+
| ...props | `HTMLAttributes<HTMLDivElement>` | - | Props nativas de div |
|
|
59
|
+
|
|
60
|
+
### DateRange Type
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
type DateRange = {
|
|
64
|
+
from: Date | undefined;
|
|
65
|
+
to: Date | undefined;
|
|
66
|
+
};
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### DatePickerSelectorLabels Type
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
type DatePickerSelectorLabels = {
|
|
73
|
+
last30Days?: string; // Default: "Last 30 days"
|
|
74
|
+
last7Days?: string; // Default: "Last 7 days"
|
|
75
|
+
last90Days?: string; // Default: "Last 90 days"
|
|
76
|
+
custom?: string; // Default: "Custom"
|
|
77
|
+
placeholder?: string; // Default: "Date"
|
|
78
|
+
cancel?: string; // Default: "Cancel"
|
|
79
|
+
apply?: string; // Default: "Apply"
|
|
80
|
+
};
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Patrones de Uso
|
|
84
|
+
|
|
85
|
+
### Con Valor Inicial
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
import { subDays, startOfDay } from "date-fns";
|
|
89
|
+
|
|
90
|
+
function MyComponent() {
|
|
91
|
+
const today = startOfDay(new Date());
|
|
92
|
+
const [dateRange, setDateRange] = useState<DateRange>({
|
|
93
|
+
from: subDays(today, 30),
|
|
94
|
+
to: today,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<DatePickerSelector
|
|
99
|
+
dateRange={dateRange}
|
|
100
|
+
onDateRangeChange={setDateRange}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Con Labels Personalizados (Internacionalización)
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
<DatePickerSelector
|
|
110
|
+
dateRange={dateRange}
|
|
111
|
+
onDateRangeChange={setDateRange}
|
|
112
|
+
labels={{
|
|
113
|
+
last7Days: "Últimos 7 días",
|
|
114
|
+
last30Days: "Últimos 30 días",
|
|
115
|
+
last90Days: "Últimos 90 días",
|
|
116
|
+
custom: "Personalizado",
|
|
117
|
+
placeholder: "Fecha",
|
|
118
|
+
cancel: "Cancelar",
|
|
119
|
+
apply: "Aplicar",
|
|
120
|
+
}}
|
|
121
|
+
/>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Con Props Personalizados del Combobox
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
<DatePickerSelector
|
|
128
|
+
dateRange={dateRange}
|
|
129
|
+
onDateRangeChange={setDateRange}
|
|
130
|
+
combobox={{
|
|
131
|
+
classNames: {
|
|
132
|
+
trigger: "w-[300px]",
|
|
133
|
+
},
|
|
134
|
+
}}
|
|
135
|
+
/>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Con Props Personalizados del Calendar
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
<DatePickerSelector
|
|
142
|
+
dateRange={dateRange}
|
|
143
|
+
onDateRangeChange={setDateRange}
|
|
144
|
+
calendar={{
|
|
145
|
+
fromYear: 2020,
|
|
146
|
+
toYear: 2030,
|
|
147
|
+
}}
|
|
148
|
+
/>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Formato de Fecha con date-fns
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
import { format } from "date-fns";
|
|
155
|
+
|
|
156
|
+
function MyComponent() {
|
|
157
|
+
const [dateRange, setDateRange] = useState<DateRange>({
|
|
158
|
+
from: undefined,
|
|
159
|
+
to: undefined,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const formatDateRange = () => {
|
|
163
|
+
if (!dateRange.from || !dateRange.to) return "No date selected";
|
|
164
|
+
return `${format(dateRange.from, "MMM d, yyyy")} - ${format(dateRange.to, "MMM d, yyyy")}`;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<div>
|
|
169
|
+
<DatePickerSelector
|
|
170
|
+
dateRange={dateRange}
|
|
171
|
+
onDateRangeChange={setDateRange}
|
|
172
|
+
/>
|
|
173
|
+
<p>Selected: {formatDateRange()}</p>
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Validación de Rango
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
function MyComponent() {
|
|
183
|
+
const [dateRange, setDateRange] = useState<DateRange>({
|
|
184
|
+
from: undefined,
|
|
185
|
+
to: undefined,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const handleDateRangeChange = (newRange: DateRange) => {
|
|
189
|
+
// Validate that both dates are selected
|
|
190
|
+
if (newRange.from && newRange.to) {
|
|
191
|
+
setDateRange(newRange);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const isValidRange = dateRange.from && dateRange.to;
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<div>
|
|
199
|
+
<DatePickerSelector
|
|
200
|
+
dateRange={dateRange}
|
|
201
|
+
onDateRangeChange={handleDateRangeChange}
|
|
202
|
+
/>
|
|
203
|
+
{!isValidRange && (
|
|
204
|
+
<p className="text-destructive text-sm mt-2">
|
|
205
|
+
Please select a complete date range
|
|
206
|
+
</p>
|
|
207
|
+
)}
|
|
208
|
+
</div>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Comportamiento
|
|
214
|
+
|
|
215
|
+
### Rangos Predefinidos
|
|
216
|
+
|
|
217
|
+
El componente ofrece tres rangos predefinidos:
|
|
218
|
+
|
|
219
|
+
- **Last 7 days**: Desde hace 7 días hasta hoy
|
|
220
|
+
- **Last 30 days**: Desde hace 30 días hasta hoy
|
|
221
|
+
- **Last 90 days**: Desde hace 90 días hasta hoy
|
|
222
|
+
|
|
223
|
+
Todos los rangos predefinidos:
|
|
224
|
+
- Usan `date-fns` para cálculos precisos
|
|
225
|
+
- Establecen las fechas a medianoche (00:00:00)
|
|
226
|
+
- Se calculan dinámicamente basándose en la fecha actual
|
|
227
|
+
|
|
228
|
+
### Rango Personalizado
|
|
229
|
+
|
|
230
|
+
Al seleccionar la opción "Custom":
|
|
231
|
+
1. Se abre un popover con un calendario
|
|
232
|
+
2. El usuario selecciona un rango de fechas
|
|
233
|
+
3. Los botones "Cancel" y "Apply" permiten confirmar o descartar la selección
|
|
234
|
+
4. El rango personalizado se mantiene independiente de los rangos predefinidos
|
|
235
|
+
|
|
236
|
+
### Separación de Estados
|
|
237
|
+
|
|
238
|
+
- Los rangos predefinidos resetean cualquier selección personalizada previa
|
|
239
|
+
- El rango personalizado mantiene su valor hasta que se seleccione un rango predefinido
|
|
240
|
+
- Esto previene conflictos entre los dos modos de selección
|
|
241
|
+
|
|
242
|
+
## Casos de Uso
|
|
243
|
+
|
|
244
|
+
**Filtros de reportes**: Seleccionar rango de fechas para generar reportes
|
|
245
|
+
**Dashboards**: Filtrar datos por períodos de tiempo
|
|
246
|
+
**Analytics**: Comparar métricas en diferentes rangos
|
|
247
|
+
**Búsquedas**: Filtrar resultados por rango de fechas
|
|
248
|
+
**Logs**: Visualizar registros en períodos específicos
|
|
249
|
+
|
|
250
|
+
## Dependencias
|
|
251
|
+
|
|
252
|
+
Este componente utiliza internamente:
|
|
253
|
+
|
|
254
|
+
- **Combobox**: Para el selector de opciones con el ícono de calendario
|
|
255
|
+
- **Calendar**: Para la selección de rangos personalizados
|
|
256
|
+
- **Popover**: Para mostrar el calendario
|
|
257
|
+
- **Button**: Para las acciones "Cancel" y "Apply"
|
|
258
|
+
- **date-fns**: Para cálculos de fechas (`startOfDay`, `subDays`)
|
|
259
|
+
- **react-day-picker**: Para la gestión del calendario
|
|
260
|
+
|
|
261
|
+
## Estilos Base
|
|
262
|
+
|
|
263
|
+
- **Contenedor**: `flex w-max flex-col`
|
|
264
|
+
- **Combobox**: Con placeholder siempre visible, ícono de calendario, feedback tipo check
|
|
265
|
+
- **Calendar**: Con `captionLayout="dropdown"` para navegación por años
|
|
266
|
+
- **Botones**: Estilo `variant="link"` para Cancel y Apply
|
|
267
|
+
|
|
268
|
+
## Accesibilidad
|
|
269
|
+
|
|
270
|
+
- ✅ Labels descriptivos para todas las opciones
|
|
271
|
+
- ✅ Navegación por teclado en combobox y calendario
|
|
272
|
+
- ✅ Estados de selección claramente indicados
|
|
273
|
+
- ✅ Feedback visual en checkmarks
|
|
274
|
+
- ✅ Acciones claramente etiquetadas (Cancel/Apply)
|
|
275
|
+
|
|
276
|
+
## Mejores Prácticas
|
|
277
|
+
|
|
278
|
+
### Gestión del Estado
|
|
279
|
+
|
|
280
|
+
```tsx
|
|
281
|
+
// ✅ Correcto - Estado controlado
|
|
282
|
+
const [dateRange, setDateRange] = useState<DateRange>({
|
|
283
|
+
from: undefined,
|
|
284
|
+
to: undefined,
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
<DatePickerSelector
|
|
288
|
+
dateRange={dateRange}
|
|
289
|
+
onDateRangeChange={setDateRange}
|
|
290
|
+
/>
|
|
291
|
+
|
|
292
|
+
// ❌ Incorrecto - Estado no inicializado
|
|
293
|
+
const [dateRange, setDateRange] = useState();
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Validación
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
// ✅ Correcto - Validar rango completo
|
|
300
|
+
const handleChange = (range: DateRange) => {
|
|
301
|
+
if (range.from && range.to) {
|
|
302
|
+
// Procesar rango válido
|
|
303
|
+
setDateRange(range);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// ✅ Correcto - Mostrar feedback de validación
|
|
308
|
+
{!dateRange.from || !dateRange.to ? (
|
|
309
|
+
<p className="text-destructive">Please select both dates</p>
|
|
310
|
+
) : null}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Formateo de Fechas
|
|
314
|
+
|
|
315
|
+
```tsx
|
|
316
|
+
import { format } from "date-fns";
|
|
317
|
+
|
|
318
|
+
// ✅ Correcto - Formatear con date-fns
|
|
319
|
+
const displayDate = dateRange.from
|
|
320
|
+
? format(dateRange.from, "PP")
|
|
321
|
+
: "Not selected";
|
|
322
|
+
|
|
323
|
+
// ❌ Evitar - toString() no es user-friendly
|
|
324
|
+
const displayDate = dateRange.from?.toString();
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Internacionalización
|
|
328
|
+
|
|
329
|
+
```tsx
|
|
330
|
+
// ✅ Correcto - Proporcionar todos los labels
|
|
331
|
+
<DatePickerSelector
|
|
332
|
+
labels={{
|
|
333
|
+
last7Days: t("dateRange.last7Days"),
|
|
334
|
+
last30Days: t("dateRange.last30Days"),
|
|
335
|
+
last90Days: t("dateRange.last90Days"),
|
|
336
|
+
custom: t("dateRange.custom"),
|
|
337
|
+
placeholder: t("dateRange.placeholder"),
|
|
338
|
+
cancel: t("actions.cancel"),
|
|
339
|
+
apply: t("actions.apply"),
|
|
340
|
+
}}
|
|
341
|
+
/>
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Limitaciones
|
|
345
|
+
|
|
346
|
+
- ❌ Solo soporta rangos (no fechas individuales)
|
|
347
|
+
- ❌ Los rangos predefinidos son fijos (7, 30, 90 días)
|
|
348
|
+
- ❌ No incluye presets personalizables adicionales
|
|
349
|
+
- ❌ No soporta selección de hora (solo fechas)
|
|
350
|
+
|
|
351
|
+
## Troubleshooting
|
|
352
|
+
|
|
353
|
+
**Problema**: Las fechas tienen horas no deseadas
|
|
354
|
+
**Solución**: El componente usa `startOfDay()` automáticamente. Si pasas fechas con horas, normalízalas antes:
|
|
355
|
+
|
|
356
|
+
```tsx
|
|
357
|
+
import { startOfDay } from "date-fns";
|
|
358
|
+
|
|
359
|
+
const normalizedRange = {
|
|
360
|
+
from: dateRange.from ? startOfDay(dateRange.from) : undefined,
|
|
361
|
+
to: dateRange.to ? startOfDay(dateRange.to) : undefined,
|
|
362
|
+
};
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**Problema**: El calendario no se abre
|
|
366
|
+
**Solución**: Verifica que estás pasando las props correctamente y que el componente Calendar está importado.
|
|
367
|
+
|
|
368
|
+
**Problema**: Los rangos predefinidos no funcionan
|
|
369
|
+
**Solución**: Asegúrate de que `onDateRangeChange` esté actualizando el estado correctamente.
|
|
370
|
+
|
|
371
|
+
## Referencias
|
|
372
|
+
|
|
373
|
+
- **Combobox**: [Ver documentación](./combobox.md)
|
|
374
|
+
- **Calendar**: [Ver documentación](./calendar.md)
|
|
375
|
+
- **date-fns**: https://date-fns.org/
|
|
376
|
+
- **react-day-picker**: https://react-day-picker.js.org/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adamosuiteservices/ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.13",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,6 +38,10 @@
|
|
|
38
38
|
"types": "./dist/components/layout/toaster/index.d.ts",
|
|
39
39
|
"import": "./dist/toaster.js"
|
|
40
40
|
},
|
|
41
|
+
"./full-screen-loader": {
|
|
42
|
+
"types": "./dist/components/layout/full-screen-loader/index.d.ts",
|
|
43
|
+
"import": "./dist/full-screen-loader.js"
|
|
44
|
+
},
|
|
41
45
|
"./accordion": {
|
|
42
46
|
"types": "./dist/components/ui/accordion/accordion.d.ts",
|
|
43
47
|
"import": "./dist/accordion.js"
|
|
@@ -94,6 +98,10 @@
|
|
|
94
98
|
"types": "./dist/components/ui/context-menu/context-menu.d.ts",
|
|
95
99
|
"import": "./dist/context-menu.js"
|
|
96
100
|
},
|
|
101
|
+
"./date-picker-selector": {
|
|
102
|
+
"types": "./dist/components/ui/date-picker-selector/date-picker-selector.d.ts",
|
|
103
|
+
"import": "./dist/date-picker-selector.js"
|
|
104
|
+
},
|
|
97
105
|
"./dialog": {
|
|
98
106
|
"types": "./dist/components/ui/dialog/dialog.d.ts",
|
|
99
107
|
"import": "./dist/dialog.js"
|