/** * Event-layout, recurrence and navigation logic for the Calendar component. * * Pure date geometry (grids, week numbers, ranges, comparison, formatting) * lives in the Svelte-free `$lib/date` layer and is imported from there. This * module keeps only the Calendar-specific concerns: positioning timed and * multi-day events, expanding recurrence rules and time-slot generation. * No Svelte dependencies — fully testable in isolation. */ import type { CalendarEvent, PositionedEvent, TimeSlot } from './calendar.types.js'; /** * Get day info for a multi-day event on a specific date. * Returns the 0-based day index, total days, and start/end flags. */ export declare function getEventDayInfo(event: { start: Date; end?: Date; }, date: Date): { dayIndex: number; totalDays: number; isStart: boolean; isEnd: boolean; }; /** * Order the events of ONE day for a list: all-day first, then timed events by * start; ties go to the longer event. * * The reading order of a day is a property of the day, not of the array a * consumer happened to build. Events generated per resource (chairs, rooms, * staff) arrive grouped by resource — 12:20, 12:15, 13:20, 13:15 — and the * list-based views rendered exactly that (#95). The time grid hid it, because * it positions by the hour rather than by array index. * * All-day before timed follows the convention every calendar app uses: an * all-day event has no hour to sort against, so it heads the day rather than * landing at midnight among the timed ones. `allDay` is read the way the rest * of the component reads it — `!== false`, since the documented default is * `true` and only an explicit `false` marks an event as timed. * * The tie-break repeats the stacking rule of `getMultiDayEventLayout` and * `resolveOverlaps` (longer first), so a day's list order matches the order the * same events stack in the grid. `Array.prototype.sort` is stable, so events * that are equal under both keys keep the order they were passed in. */ export declare function compareDayEvents(a: { start: Date; end?: Date; allDay?: boolean; }, b: { start: Date; end?: Date; allDay?: boolean; }): number; /** * Foreground colour for a consumer-supplied background. The implementation * moved to `$lib/internal/contrast` when ResourceTimeline became its second * caller — a timeline bar and a calendar event chip both paint a surface from a * `DateCategory.color` the consumer chose, and face the same question. * Re-exported here so Calendar's own sub-components keep importing it from the * engine. */ export { getContrastTextColor } from '../../internal/contrast.js'; /** * Compute layout segments for multi-day events in the month grid. * Each multi-day event is split into per-week segments with column positions. * * @param events - All events to layout * @param grid - The 2D date grid from getMonthGrid() * @param maxRows - Maximum bar rows per week before overflow (default: 3) * @returns Per-week array of bar segments and overflow counts */ export declare function getMultiDayEventLayout(events: Array<{ id: string; start: Date; end?: Date; }>, grid: Date[][], maxRows?: number): Array<{ segments: Array<{ eventId: string; startCol: number; spanCols: number; isFirstSegment: boolean; isLastSegment: boolean; row: number; }>; overflow: number; }>; /** * Generate time slots for a time grid. * * @param startHour - First visible hour (0-23) * @param endHour - Last visible hour, exclusive (1-24) * @param interval - Slot interval in minutes (30 or 60) * @returns Array of TimeSlot objects */ export declare function generateTimeSlots(startHour: number, endHour: number, interval?: 30 | 60): TimeSlot[]; /** * Position timed events within a time grid for a single day. * Calculates top/height as percentages and resolves overlapping columns * via a sweep-line algorithm for O(n log n) performance. * * @param events - Timed events for a single day * @param forDate - The specific day being rendered * @param startHour - First visible hour * @param endHour - Last visible hour (exclusive) * @returns Array of positioned events with layout info */ export declare function positionEvents(events: CalendarEvent[], forDate: Date, startHour: number, endHour: number): PositionedEvent[]; /** * Expand a recurring event into concrete instances within a date range. * Only generates occurrences that fall within [rangeStart, rangeEnd]. * Each instance gets a unique ID (`${originalId}-${YYYY-MM-DD}`) and * preserves all other event properties with adjusted dates. * * @param event - Source event with a recurrence rule * @param rangeStart - Start of the visible range (inclusive) * @param rangeEnd - End of the visible range (inclusive) * @returns Array of concrete CalendarEvent instances */ export declare function expandRecurrence(event: CalendarEvent, rangeStart: Date, rangeEnd: Date): CalendarEvent[];