Hooks
Todos los hooks deben usarse dentro de un componente <CalendarProvider>. Si estas usando el componente <Calendar>, el provider ya esta configurado.
useCalendar()
Sección titulada «useCalendar()»Orquestador principal — combina estado, eventos y navegacion.
import { useCalendar } from "trud-calendar";
const { currentDate, // DateString — fecha enfocada actual view, // CalendarView — vista actual events, // CalendarEvent[] — todos los eventos visibleEvents, // CalendarEvent[] — filtrados al rango visible visibleRange, // { start: DateString, end: DateString } locale, // string — locale BCP 47 prev, // () => void — ir al periodo anterior next, // () => void — ir al siguiente periodo today, // () => void — ir a hoy setDate, // (date: DateString) => void setView, // (view: CalendarView) => void} = useCalendar();useNavigation()
Sección titulada «useNavigation()»Navegacion de fechas y cambio de vistas. Mas ligero que useCalendar — usalo cuando solo necesitas controles de navegacion.
import { useNavigation } from "trud-calendar";
const { currentDate, // DateString view, // CalendarView formattedDate, // string — titulo con formato de locale (ej: "marzo 2026") prev, // () => void next, // () => void today, // () => void setDate, // (date: DateString) => void setView, // (view: CalendarView) => void} = useNavigation();useEvents()
Sección titulada «useEvents()»Accede a los datos de eventos del rango visible actual.
import { useEvents } from "trud-calendar";
const { visibleEvents, // CalendarEvent[] — ordenados, filtrados al rango visible getForDay, // (date: DateString) => CalendarEvent[] partitioned, // { allDay: CalendarEvent[], timed: CalendarEvent[] } segments, // EventSegment[] — segmentos de eventos multi-dia groupedByDate, // Map<DateString, CalendarEvent[]>} = useEvents();Ejemplo: Obtener eventos de un dia especifico
Sección titulada «Ejemplo: Obtener eventos de un dia especifico»const { getForDay } = useEvents();const eventosDeHoy = getForDay("2026-03-13");useEventLayout(events)
Sección titulada «useEventLayout(events)»Algoritmo de column-packing para eventos solapados. Usado internamente por la grilla de tiempo de semana/dia — usalo tu mismo cuando construyas layouts personalizados basados en tiempo.
import { useEventLayout } from "trud-calendar";
const positioned: PositionedEvent[] = useEventLayout(timedEvents);Cada PositionedEvent contiene:
interface PositionedEvent { event: CalendarEvent; column: number; // Indice de columna (base 0) en grupo de solapamiento totalColumns: number; // Total de columnas en grupo de solapamiento top: number; // % desde arriba (0-100) height: number; // % de altura (0-100)}Usa estos valores para posicionar eventos con CSS:
{positioned.map(({ event, column, totalColumns, top, height }) => ( <div key={event.id} style={{ position: "absolute", top: `${top}%`, height: `${height}%`, left: `${(column / totalColumns) * 100}%`, width: `${100 / totalColumns}%`, }} > {event.title} </div>))}useCurrentTime(intervalMs?)
Sección titulada «useCurrentTime(intervalMs?)»Reloj en vivo para indicadores de “hora actual”. Se actualiza cada 60 segundos por defecto.
import { useCurrentTime } from "trud-calendar";
const { now, // string — datetime ISO del momento actual today, // string — YYYY-MM-DD de hoy timeOfDay, // number — hora fraccional (14.5 = 2:30 PM)} = useCurrentTime();
// Intervalo personalizado: actualizar cada 10 segundosconst time = useCurrentTime(10_000);Ejemplo: Indicador de hora actual
Sección titulada «Ejemplo: Indicador de hora actual»const { timeOfDay } = useCurrentTime();const topPercent = ((timeOfDay - dayStartHour) / (dayEndHour - dayStartHour)) * 100;
<div className="absolute left-0 right-0 border-t-2 border-red-500 z-10" style={{ top: `${topPercent}%` }}/>useDateFormat()
Sección titulada «useDateFormat()»Funciones de formato de fecha con soporte de locale, basadas en la API Intl.
import { useDateFormat } from "trud-calendar";
const fmt = useDateFormat();
fmt.toolbarTitle("2026-03-13", "month"); // "marzo 2026" (con locale es-ES)fmt.time("2026-03-13T14:30:00"); // "14:30"fmt.timeRange(start, end); // "14:30 – 15:00"fmt.weekdayShort("2026-03-13"); // "vie"fmt.weekdayNarrow("2026-03-13"); // "V"fmt.dayNumber("2026-03-13"); // "13"fmt.agendaDate("2026-03-13"); // "viernes, 13 de marzo"fmt.monthDay("2026-03-13"); // "13 mar"Todas las funciones respetan el locale configurado en el CalendarProvider.
useEventDrag()
Sección titulada «useEventDrag()»Hook de drag basado en Pointer Events para construir interacciones de arrastre personalizadas. Usado internamente por WeekView y MonthView.
import { useEventDrag } from "trud-calendar";
const { dragState, // DragState | null — estado actual del drag onPointerDown, // (e: React.PointerEvent, event: CalendarEvent) => void isDragging, // boolean didDrag, // React.RefObject<boolean> — true si ocurrio un drag (suprime click)} = useEventDrag({ mode: "time", // "time" para semana/dia, "date" para mes onEventDrop, // (event, newStart, newEnd) => void enabled: true, // boolean snapDuration: 15, // incremento de snap en minutos dragConstraint, // (event, newStart, newEnd) => boolean — opcional});DragState contiene:
event— el evento siendo arrastradoghostX,ghostY— posicion del cursor para renderizar el ghost de dragtargetDay— la columna de dia sobre la que esta el cursor (detectada via atributosdata-day)
Soporta mouse y touch mediante la API de Pointer Events.
useAutoScroll()
Sección titulada «useAutoScroll()»Auto-scroll del contenedor cuando el puntero se acerca al borde superior o inferior. Integrado en la vista semana/dia durante drag, resize y seleccion — solo necesitas este hook si construyes layouts scrollables personalizados.
import { useAutoScroll } from "trud-calendar";
const { handleAutoScroll, stopAutoScroll } = useAutoScroll({ containerRef: scrollRef, // React.RefObject<HTMLElement> enabled: isDragging, // activar solo durante interacciones});
// Llamar en cada pointermove:handleAutoScroll(e.clientY);
// Llamar en pointerup:stopAutoScroll();useGridKeyboard()
Sección titulada «useGridKeyboard()»Hook de navegacion por teclado que implementa el patron WAI-ARIA roving tabindex grid.
import { useGridKeyboard } from "trud-calendar";
const grid = useGridKeyboard({ cols: 7, rows: 24, onActivate: (row, col) => { /* Enter/Space presionado */ }, onEscape: () => { /* Escape presionado */ },});Devuelve:
registerCell(row, col)— callback ref para celdas de la grillagetTabIndex(row, col)— devuelve0para la celda activa,-1para las demashandleKeyDown— manejador de eventos de tecladohandleFocus(row, col)— manejador de eventos de foco
useUndoableEvents()
Sección titulada «useUndoableEvents()»Envuelve un CalendarEvent[] con un stack completo de undo/redo. Toma snapshots automaticamente antes de onEventDrop y onEventResize, y registra atajos de teclado Ctrl+Z / Ctrl+Shift+Z (Ctrl+Y).
import { useUndoableEvents } from "trud-calendar";
const { events, // CalendarEvent[] — estado actual setEvents, // (events: CalendarEvent[]) => void — actualizar + auto-snapshot onEventDrop, // (event, newStart, newEnd) => void — snapshot antes de aplicar onEventResize, // (event, newStart, newEnd) => void — snapshot antes de aplicar undo, // () => void redo, // () => void canUndo, // boolean canRedo, // boolean snapshot, // () => void — snapshot manual (ej: antes de una actualizacion masiva)} = useUndoableEvents({ initialEvents: myEvents, maxHistory: 30, // opcional, por defecto 30});Ejemplo: Calendario con undo/redo
Sección titulada «Ejemplo: Calendario con undo/redo»function App() { const undoable = useUndoableEvents({ initialEvents: myEvents });
return ( <> <div className="flex gap-2 mb-2"> <button onClick={undoable.undo} disabled={!undoable.canUndo}>Deshacer</button> <button onClick={undoable.redo} disabled={!undoable.canRedo}>Rehacer</button> </div> <Calendar events={undoable.events} enableDnD onEventDrop={undoable.onEventDrop} onEventResize={undoable.onEventResize} /> </> );}useEventSelection()
Sección titulada «useEventSelection()»Gestion de multi-seleccion de eventos con seguimiento basado en Set. Soporta toggle (Ctrl+click), seleccion por rango (Shift+click), seleccionar todo y limpiar.
import { useEventSelection } from "trud-calendar";
const { selectedIds, // Set<string> — IDs de eventos seleccionados isSelected, // (id: string) => boolean select, // (id: string) => void — seleccion individual (limpia otros) toggle, // (id: string) => void — comportamiento Ctrl+click rangeSelect, // (id: string, sortedIds: string[]) => void — Shift+click clearSelection, // () => void selectAll, // (ids: string[]) => void lastSelectedId, // string | null — ancla para seleccion por rango} = useEventSelection();El componente <Calendar> usa SelectionProvider internamente, que envuelve useEventSelection con deteccion de teclas modificadoras. Los eventos seleccionados muestran un resaltado visual con ring.
useResponsiveView()
Sección titulada «useResponsiveView()»Hook de layout adaptativo usando ResizeObserver. Devuelve flags de breakpoint y el numero recomendado de columnas de dias visibles.
import { useResponsiveView } from "trud-calendar";
const ref = useRef<HTMLDivElement>(null);const { isMobile, // boolean — contenedor < 640px isTablet, // boolean — contenedor 640px–1024px containerWidth, // number — ancho medido en px visibleDays, // 1 (movil) | 3 (tablet) | 7 (escritorio)} = useResponsiveView(ref);El componente <Calendar> lo usa internamente para adaptar las columnas de la vista semanal y el tamano de celdas en la vista mensual.
useSwipeNavigation()
Sección titulada «useSwipeNavigation()»Deteccion de swipe tactil para navegacion prev/next. Solo se activa para pointerType === "touch" — los arrastres de mouse se ignoran.
import { useSwipeNavigation } from "trud-calendar";
const swipe = useSwipeNavigation({ onSwipeLeft: () => next(), // navegar adelante onSwipeRight: () => prev(), // navegar atras threshold: 50, // min px horizontal (default: 50) maxVertical: 30, // max px vertical (default: 30)});
// Aplicar al elemento contenedor:<div onPointerDown={swipe.onPointerDown} onPointerMove={swipe.onPointerMove} onPointerUp={swipe.onPointerUp}> {/* contenido del calendario */}</div>useVirtualScroll()
Sección titulada «useVirtualScroll()»Seguimiento de scroll basado en viewport para filtrar eventos visibles. Util para datasets grandes donde renderizar todos los eventos es costoso.
import { useVirtualScroll } from "trud-calendar";
const { viewportTop, // number — borde superior como % (0–100) viewportBottom, // number — borde inferior como % (0–100) isVirtualized, // boolean — true cuando esta habilitado} = useVirtualScroll({ containerRef: scrollRef, totalHours: 24, enabled: true, // default: false overscanHours: 2, // horas extra a renderizar arriba/abajo del viewport});Combinar con filterVisibleEvents() de trud-calendar-core para eliminar eventos fuera de pantalla:
import { filterVisibleEvents } from "trud-calendar-core";
const visible = filterVisibleEvents(positioned, viewportTop, viewportBottom);useEventSources()
Sección titulada «useEventSources()»Obtiene eventos de una o mas fuentes basandose en el rango de fechas visible. Cachea resultados por rango y deduplica peticiones.
import { useEventSources, useCalendar } from "trud-calendar";
const { visibleRange } = useCalendar();
const { events, isLoading, refetch } = useEventSources({ sources: [ { url: "/api/events" }, { fetcher: async (start, end) => { const res = await fetch(`/api/team-events?from=${start}&to=${end}`); return res.json(); }}, ], start: visibleRange.start, end: visibleRange.end,});
// Pass to Calendar<Calendar events={events} />Cada fuente puede ser una url (los parametros start y end se agregan automaticamente) o una funcion fetcher. Los resultados de todas las fuentes se combinan en un solo array.
Devuelve:
events— eventos combinados de todas las fuentesisLoading— true mientras alguna fuente esta cargandorefetch()— limpia el cache y re-obtiene todas las fuentes
useExternalDrag()
Sección titulada «useExternalDrag()»Permite arrastrar elementos desde fuera del calendario hacia franjas horarias. Usa la API nativa de HTML5 Drag and Drop.
import { useExternalDrag } from "trud-calendar";
const { makeDraggable, dropTargetProps } = useExternalDrag({ onExternalDrop: (info) => { console.log(info.day); // "2026-03-25" console.log(info.start); // "2026-03-25T10:00:00" console.log(info.resourceId); // "room-a" (if resource view) console.log(info.data); // { taskId: "123", title: "My Task" } }, dayStartHour: 8, dayEndHour: 20, snapDuration: 15,});
// Hacer arrastrables los items del sidebar<div {...makeDraggable({ taskId: "123", title: "My Task" })}> Arrastra al calendario</div>
// Envolver el calendario para aceptar drops<div {...dropTargetProps}> <Calendar events={events} /></div>ExternalDropInfo contiene:
day— la fecha destinostart— hora de inicio ajustada al snapresourceId— ID del recurso si se solta en una columna de recursodata— el objeto de datos adjuntado viamakeDraggable