componentes / date-range-picker
DateRangePicker
Campo que abre un Calendar para elegir inicio y fin, con atajos listos.
Cómo usar
Muestra `inicio – fin` y abre un `Calendar` en modo intervalo; el panel se cierra tras el segundo clic. `onValueChange` se ejecuta dos veces por intervalo: primero solo con `from`, luego con `from` y `to`. `presets` añade una columna de atajos (Hoy, Últimos 7 días...) que fijan todo el intervalo; pasa `true` para los predeterminados o tu propia lista, a partir de `getDatePresets()`.
preview
DateRangePicker.tsx
import { DateRangePicker, getDatePresets } from "vaiperui"; const [period, setPeriod] = useState<DateRange>({}); <DateRangePicker label="Estancia" presets value={period} onValueChange={setPeriod} /> // Custom list, translated labels<DateRangePicker presets={[ ...getDatePresets({ today: "Hoy" }).slice(0, 3), { label: "Q4", range: { from: new Date(2026, 9, 1), to: new Date(2026, 11, 31) } },]} />Atajos
`presets` añade una columna de atajos. `true` usa los predeterminados; pasa una lista para los tuyos.
preview
atajos.tsx
<DateRangePicker presets /><DateRangePicker presets={[{ label: "Q4", range: { from, to } }]} />Tamaños
preview
tamanos.tsx
<DateRangePicker size="sm" /><DateRangePicker size="md" /><DateRangePicker size="lg" />Estados
preview
Detalle extra
Esto es obligatorio
estados.tsx
<DateRangePicker label="..." helperText="..." /><DateRangePicker label="..." errorMessage="..." /><DateRangePicker label="..." disabled /><DateRangePicker label="..." readOnly />Props
| Prop | Valores | Predeterminado | Descripción |
|---|---|---|---|
| value / defaultValue | { from?: Date; to?: Date } | ninguno | Intervalo, controlado o inicial. Sin `to`, solo se eligió el inicio |
| onValueChange | (range: DateRange) => void | ninguno | Se llama en cada clic |
| presets | boolean | { label: string; range: { from: Date; to: Date } }[] | ninguno | Columna de atajos; true usa getDatePresets(). Los atajos fuera de minDate/maxDate quedan deshabilitados |
| presetLabels | { today, last7Days, last30Days, thisMonth, lastMonth } | ninguno | Traduce los atajos predeterminados (presets={true}) |
| fromName / toName | string | ninguno | Nombres de los campos de inicio y fin; cada uno envía yyyy-mm-dd |
| label / helperText | string | ninguno | Etiqueta sobre el campo y texto de ayuda debajo |
| errorMessage | string | ninguno | Texto de error; su sola presencia fuerza el estado de error |
| placeholder | string | del idioma | Texto cuando no se eligió nada (p. ej. dd/mm/aaaa) |
| disabled / readOnly | boolean | false | No abre el panel; readOnly aún muestra el valor |
| variant | ring | outline | ring | Estilo de foco, igual que Input |
| size / radius | sm | md | lg / none | sm | md | lg | full | md / md | Altura del campo y redondeo de las esquinas |
| aria-label | string | ninguno | Nombre accesible cuando no hay etiqueta |
| panelLabel | string | ninguno | Nombre accesible del panel abierto |
| minDate / maxDate | Date | ninguno | Primer y último día permitidos; el resto y las flechas de mes que llevan fuera quedan deshabilitados |
| locale | string | "en-US" | Idioma de los nombres de mes/día y formato de la fecha (BCP 47) |
| weekStartsOn | 0 – 6 | 0 | Primer día de la semana (0 = domingo) |
| previousMonthLabel / nextMonthLabel | string | "Previous month" / "Next month" | Nombres accesibles de los botones de mes |
| variantColor / customColor / animation | primary | success | warning | danger / CSS color / none | smooth | fast | bounce | primary / smooth | Color de la selección y del foco, y velocidad de la transición |
Accesibilidad
- El disparador es un `<button>` con `aria-haspopup="dialog"` y `aria-expanded` que refleja el estado del panel.
- El `label` se enlaza con `htmlFor`; sin `label`, el disparador usa `aria-label`.
- `errorMessage` define `aria-invalid` y `aria-describedby` apuntando al mensaje; sin error, `helperText` se enlaza con `aria-describedby`.
- El panel es un `role="dialog"` nombrado por `panelLabel`, renderizado en un portal en `document.body`.
- `disabled` deshabilita el botón; `readOnly` mantiene el foco posible, pero el panel nunca se abre.
- El texto del disparador se muestra como `inicio – fin`; mientras solo se eligió el inicio, muestra `inicio – …`.
- Los presets son `<button>`s con `aria-pressed` cuando coinciden con el intervalo actual y `disabled` cuando quedan fuera de `minDate`/`maxDate`.
- Al abrir, el foco va a un día en el `Calendar` de intervalo, que sigue su patrón de cuadrícula.
Teclado
| Tecla | Acción |
|---|---|
| Enter / Space | Abre o cierra el panel desde el disparador. |
| Arrow keys, Home, End, Page Up/Down | Navegan por los días dentro del panel abierto (ver Calendar); Enter o Espacio elige el inicio y luego el fin, que cierra el panel. |
| Esc | Cierra el panel y devuelve el foco al disparador. |
Ten en cuenta
- El panel no atrapa el foco: Tab sale de él y, como se renderiza al final de `<body>`, Tab desde el disparador no entra en él por sí solo.
- Hacer clic fuera cierra el panel sin devolver el foco; solo Esc restaura el foco en el disparador.
- Pasa `presetLabels` (o tus propios `presets`) traducidos al usar presets; los valores por defecto están en inglés. Las fechas no se pueden escribir.