export class AllDayLayoutEngine { constructor(weekDates) { this.weekDates = weekDates; this.tracks = []; } /** * Calculate layout for all events using clean day-based logic */ calculateLayout(events) { let layouts = []; // Reset tracks for new calculation this.tracks = [new Array(this.weekDates.length).fill(false)]; // Filter to only visible events const visibleEvents = events.filter(event => this.isEventVisible(event)); // Process events in input order (no sorting) for (const event of visibleEvents) { const startDay = this.getEventStartDay(event); const endDay = this.getEventEndDay(event); if (startDay > 0 && endDay > 0) { const track = this.findAvailableTrack(startDay - 1, endDay - 1); // Convert to 0-based for tracks // Mark days as occupied for (let day = startDay - 1; day <= endDay - 1; day++) { this.tracks[track][day] = true; } const layout = { calenderEvent: event, gridArea: `${track + 1} / ${startDay} / ${track + 2} / ${endDay + 1}`, startColumn: startDay, endColumn: endDay, row: track + 1, columnSpan: endDay - startDay + 1 }; layouts.push(layout); } } return layouts; } /** * Find available track for event spanning from startDay to endDay (0-based indices) */ findAvailableTrack(startDay, endDay) { for (let trackIndex = 0; trackIndex < this.tracks.length; trackIndex++) { if (this.isTrackAvailable(trackIndex, startDay, endDay)) { return trackIndex; } } // Create new track if none available this.tracks.push(new Array(this.weekDates.length).fill(false)); return this.tracks.length - 1; } /** * Check if track is available for the given day range (0-based indices) */ isTrackAvailable(trackIndex, startDay, endDay) { for (let day = startDay; day <= endDay; day++) { if (this.tracks[trackIndex][day]) { return false; } } return true; } /** * Get start day index for event (1-based, 0 if not visible) */ getEventStartDay(event) { const eventStartDate = this.formatDate(event.start); const firstVisibleDate = this.weekDates[0]; // If event starts before visible range, clip to first visible day const clippedStartDate = eventStartDate < firstVisibleDate ? firstVisibleDate : eventStartDate; const dayIndex = this.weekDates.indexOf(clippedStartDate); return dayIndex >= 0 ? dayIndex + 1 : 0; } /** * Get end day index for event (1-based, 0 if not visible) */ getEventEndDay(event) { const eventEndDate = this.formatDate(event.end); const lastVisibleDate = this.weekDates[this.weekDates.length - 1]; // If event ends after visible range, clip to last visible day const clippedEndDate = eventEndDate > lastVisibleDate ? lastVisibleDate : eventEndDate; const dayIndex = this.weekDates.indexOf(clippedEndDate); return dayIndex >= 0 ? dayIndex + 1 : 0; } /** * Check if event is visible in the current date range */ isEventVisible(event) { if (this.weekDates.length === 0) return false; const eventStartDate = this.formatDate(event.start); const eventEndDate = this.formatDate(event.end); const firstVisibleDate = this.weekDates[0]; const lastVisibleDate = this.weekDates[this.weekDates.length - 1]; // Event overlaps if it doesn't end before visible range starts // AND doesn't start after visible range ends return !(eventEndDate < firstVisibleDate || eventStartDate > lastVisibleDate); } /** * Format date to YYYY-MM-DD string using local date */ formatDate(date) { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } } //# sourceMappingURL=AllDayLayoutEngine.js.map