Hooks
All hooks must be used inside a <CalendarProvider> component. If you’re using the <Calendar> component, the provider is already set up for you.
useCalendar()
Section titled “useCalendar()”Main orchestrator — combines state, events, and navigation.
import { useCalendar } from "trud-calendar";
const { currentDate, // DateString — current focused date view, // CalendarView — current view events, // CalendarEvent[] — all events visibleEvents, // CalendarEvent[] — filtered to visible range visibleRange, // { start: DateString, end: DateString } locale, // string — BCP 47 locale prev, // () => void — go to previous period next, // () => void — go to next period today, // () => void — go to today setDate, // (date: DateString) => void setView, // (view: CalendarView) => void} = useCalendar();useNavigation()
Section titled “useNavigation()”Date navigation and view switching. Lighter than useCalendar — use this when you only need nav controls.
import { useNavigation } from "trud-calendar";
const { currentDate, // DateString view, // CalendarView formattedDate, // string — locale-aware title (e.g., "March 2026") prev, // () => void next, // () => void today, // () => void setDate, // (date: DateString) => void setView, // (view: CalendarView) => void} = useNavigation();useEvents()
Section titled “useEvents()”Access event data for the current visible range.
import { useEvents } from "trud-calendar";
const { visibleEvents, // CalendarEvent[] — sorted, filtered to visible range getForDay, // (date: DateString) => CalendarEvent[] partitioned, // { allDay: CalendarEvent[], timed: CalendarEvent[] } segments, // EventSegment[] — multi-day event segments groupedByDate, // Map<DateString, CalendarEvent[]>} = useEvents();Example: Get events for a specific day
Section titled “Example: Get events for a specific day”const { getForDay } = useEvents();const todayEvents = getForDay("2026-03-13");useEventLayout(events)
Section titled “useEventLayout(events)”Column-packing algorithm for overlapping events. Used internally by the week/day time grid — call it yourself when building custom time-based layouts.
import { useEventLayout } from "trud-calendar";
const positioned: PositionedEvent[] = useEventLayout(timedEvents);Each PositionedEvent contains:
interface PositionedEvent { event: CalendarEvent; column: number; // 0-based column index in overlap group totalColumns: number; // Total columns in overlap group top: number; // % from top (0-100) height: number; // % height (0-100)}Use these values to position events with 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?)
Section titled “useCurrentTime(intervalMs?)”Live clock for “current time” indicators. Updates every 60 seconds by default.
import { useCurrentTime } from "trud-calendar";
const { now, // string — ISO datetime of current moment today, // string — YYYY-MM-DD of today timeOfDay, // number — fractional hour (14.5 = 2:30 PM)} = useCurrentTime();
// Custom interval: update every 10 secondsconst time = useCurrentTime(10_000);Example: Current time indicator
Section titled “Example: Current time indicator”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()
Section titled “useDateFormat()”Locale-aware date formatting functions powered by the Intl API.
import { useDateFormat } from "trud-calendar";
const fmt = useDateFormat();
fmt.toolbarTitle("2026-03-13", "month"); // "March 2026"fmt.toolbarTitle("2026-03-13", "week"); // "Mar 9 – 15, 2026"fmt.time("2026-03-13T14:30:00"); // "2:30 PM"fmt.timeRange(start, end); // "2:30 – 3:00 PM"fmt.weekdayShort("2026-03-13"); // "Fri"fmt.weekdayNarrow("2026-03-13"); // "F"fmt.dayNumber("2026-03-13"); // "13"fmt.agendaDate("2026-03-13"); // "Friday, March 13"fmt.monthDay("2026-03-13"); // "Mar 13"All functions respect the locale set in the CalendarProvider.
useEventDrag()
Section titled “useEventDrag()”Pointer-based event drag hook for building custom drag interactions. Used internally by WeekView and MonthView.
import { useEventDrag } from "trud-calendar";
const { dragState, // DragState | null — current drag state onPointerDown, // (e: React.PointerEvent, event: CalendarEvent) => void isDragging, // boolean didDrag, // React.RefObject<boolean> — true if a drag occurred (suppress click)} = useEventDrag({ mode: "time", // "time" for week/day, "date" for month onEventDrop, // (event, newStart, newEnd) => void enableDnD, // boolean});DragState contains:
event— the event being draggedghostX,ghostY— cursor position for rendering a drag ghosttargetDay— the day column the cursor is over (detected viadata-dayattributes)
Supports both mouse and touch interactions via Pointer Events API.
useGridKeyboard()
Section titled “useGridKeyboard()”Keyboard navigation hook implementing the WAI-ARIA roving tabindex grid pattern.
import { useGridKeyboard } from "trud-calendar";
const grid = useGridKeyboard({ cols: 7, rows: 24, onActivate: (row, col) => { /* Enter/Space pressed */ }, onEscape: () => { /* Escape pressed */ },});Returns:
registerCell(row, col)— ref callback for grid cellsgetTabIndex(row, col)— returns0for the active cell,-1for othershandleKeyDown— keyboard event handlerhandleFocus(row, col)— focus event handler
useUndoableEvents()
Section titled “useUndoableEvents()”Wraps a CalendarEvent[] with a full undo/redo stack. Auto-snapshots before onEventDrop and onEventResize apply, and registers Ctrl+Z / Ctrl+Shift+Z (Ctrl+Y) keyboard shortcuts.
import { useUndoableEvents } from "trud-calendar";
const { events, // CalendarEvent[] — current state setEvents, // (events: CalendarEvent[]) => void — update + auto-snapshot onEventDrop, // (event, newStart, newEnd) => void — snapshots before applying onEventResize, // (event, newStart, newEnd) => void — snapshots before applying undo, // () => void redo, // () => void canUndo, // boolean canRedo, // boolean snapshot, // () => void — manual snapshot (e.g., before a batch update)} = useUndoableEvents({ initialEvents: myEvents, maxHistory: 30, // optional, defaults to 30});Example: Calendar with undo/redo
Section titled “Example: Calendar with undo/redo”function App() { const undoable = useUndoableEvents({ initialEvents: myEvents });
return ( <> <div className="flex gap-2 mb-2"> <button onClick={undoable.undo} disabled={!undoable.canUndo}>Undo</button> <button onClick={undoable.redo} disabled={!undoable.canRedo}>Redo</button> </div> <Calendar events={undoable.events} enableDnD onEventDrop={undoable.onEventDrop} onEventResize={undoable.onEventResize} /> </> );}useEventSelection()
Section titled “useEventSelection()”Multi-select event management with Set-based tracking. Supports toggle (Ctrl+click), range select (Shift+click), select all, and clear.
import { useEventSelection } from "trud-calendar";
const { selectedIds, // Set<string> — currently selected event IDs isSelected, // (id: string) => boolean select, // (id: string) => void — single select (clears others) toggle, // (id: string) => void — Ctrl+click behavior rangeSelect, // (id: string, sortedIds: string[]) => void — Shift+click clearSelection, // () => void selectAll, // (ids: string[]) => void lastSelectedId, // string | null — anchor for range selection} = useEventSelection();The <Calendar> component uses SelectionProvider internally, which wraps useEventSelection with modifier key detection. Selected events show a visual ring highlight.
useResponsiveView()
Section titled “useResponsiveView()”Adaptive layout hook using ResizeObserver. Returns breakpoint flags and the recommended number of visible day columns.
import { useResponsiveView } from "trud-calendar";
const ref = useRef<HTMLDivElement>(null);const { isMobile, // boolean — container < 640px isTablet, // boolean — container 640px–1024px containerWidth, // number — measured width in px visibleDays, // 1 (mobile) | 3 (tablet) | 7 (desktop)} = useResponsiveView(ref);The <Calendar> component uses this internally to adapt the week view column count and month view cell sizes.
useSwipeNavigation()
Section titled “useSwipeNavigation()”Touch swipe detection for prev/next navigation. Only activates for pointerType === "touch" — mouse drags are ignored.
import { useSwipeNavigation } from "trud-calendar";
const swipe = useSwipeNavigation({ onSwipeLeft: () => next(), // navigate forward onSwipeRight: () => prev(), // navigate backward threshold: 50, // min horizontal px (default: 50) maxVertical: 30, // max vertical px (default: 30)});
// Spread on the container element:<div onPointerDown={swipe.onPointerDown} onPointerMove={swipe.onPointerMove} onPointerUp={swipe.onPointerUp}> {/* calendar content */}</div>useVirtualScroll()
Section titled “useVirtualScroll()”Viewport-based scroll tracking for filtering visible events. Useful for large datasets where rendering all events is expensive.
import { useVirtualScroll } from "trud-calendar";
const { viewportTop, // number — top edge as % (0–100) viewportBottom, // number — bottom edge as % (0–100) isVirtualized, // boolean — true when enabled} = useVirtualScroll({ containerRef: scrollRef, totalHours: 24, enabled: true, // default: false overscanHours: 2, // extra hours to render above/below viewport});Pair with filterVisibleEvents() from trud-calendar-core to cull off-screen events:
import { filterVisibleEvents } from "trud-calendar-core";
const visible = filterVisibleEvents(positioned, viewportTop, viewportBottom);