92 lines
3.2 KiB
TypeScript
92 lines
3.2 KiB
TypeScript
|
|
/**
|
||
|
|
* EventStackManager - Manages visual stacking of overlapping calendar events
|
||
|
|
*
|
||
|
|
* This class handles the creation and maintenance of "stack chains" - doubly-linked
|
||
|
|
* lists of overlapping events stored directly in DOM elements via data attributes.
|
||
|
|
*
|
||
|
|
* Implements 3-phase algorithm for grid + nested stacking:
|
||
|
|
* Phase 1: Group events by start time proximity (configurable threshold)
|
||
|
|
* Phase 2: Decide container type (GRID vs STACKING)
|
||
|
|
* Phase 3: Handle late arrivals (nested stacking - NOT IMPLEMENTED)
|
||
|
|
*
|
||
|
|
* @see STACKING_CONCEPT.md for detailed documentation
|
||
|
|
* @see stacking-visualization.html for visual examples
|
||
|
|
*/
|
||
|
|
import { ICalendarEvent } from '../types/CalendarTypes';
|
||
|
|
import { Configuration } from '../configurations/CalendarConfig';
|
||
|
|
export interface IStackLink {
|
||
|
|
prev?: string;
|
||
|
|
next?: string;
|
||
|
|
stackLevel: number;
|
||
|
|
}
|
||
|
|
export interface IEventGroup {
|
||
|
|
events: ICalendarEvent[];
|
||
|
|
containerType: 'NONE' | 'GRID' | 'STACKING';
|
||
|
|
startTime: Date;
|
||
|
|
}
|
||
|
|
export declare class EventStackManager {
|
||
|
|
private static readonly STACK_OFFSET_PX;
|
||
|
|
private config;
|
||
|
|
constructor(config: Configuration);
|
||
|
|
/**
|
||
|
|
* Group events by time conflicts (both start-to-start and end-to-start within threshold)
|
||
|
|
*
|
||
|
|
* Events are grouped if:
|
||
|
|
* 1. They start within ±threshold minutes of each other (start-to-start)
|
||
|
|
* 2. One event starts within threshold minutes before another ends (end-to-start conflict)
|
||
|
|
*/
|
||
|
|
groupEventsByStartTime(events: ICalendarEvent[]): IEventGroup[];
|
||
|
|
/**
|
||
|
|
* Decide container type for a group of events
|
||
|
|
*
|
||
|
|
* Rule: Events starting simultaneously (within threshold) should ALWAYS use GRID,
|
||
|
|
* even if they overlap each other. This provides better visual indication that
|
||
|
|
* events start at the same time.
|
||
|
|
*/
|
||
|
|
decideContainerType(group: IEventGroup): 'NONE' | 'GRID' | 'STACKING';
|
||
|
|
/**
|
||
|
|
* Check if two events overlap in time
|
||
|
|
*/
|
||
|
|
doEventsOverlap(event1: ICalendarEvent, event2: ICalendarEvent): boolean;
|
||
|
|
/**
|
||
|
|
* Create optimized stack links (events share levels when possible)
|
||
|
|
*/
|
||
|
|
createOptimizedStackLinks(events: ICalendarEvent[]): Map<string, IStackLink>;
|
||
|
|
/**
|
||
|
|
* Calculate marginLeft based on stack level
|
||
|
|
*/
|
||
|
|
calculateMarginLeft(stackLevel: number): number;
|
||
|
|
/**
|
||
|
|
* Calculate zIndex based on stack level
|
||
|
|
*/
|
||
|
|
calculateZIndex(stackLevel: number): number;
|
||
|
|
/**
|
||
|
|
* Serialize stack link to JSON string
|
||
|
|
*/
|
||
|
|
serializeStackLink(stackLink: IStackLink): string;
|
||
|
|
/**
|
||
|
|
* Deserialize JSON string to stack link
|
||
|
|
*/
|
||
|
|
deserializeStackLink(json: string): IStackLink | null;
|
||
|
|
/**
|
||
|
|
* Apply stack link to DOM element
|
||
|
|
*/
|
||
|
|
applyStackLinkToElement(element: HTMLElement, stackLink: IStackLink): void;
|
||
|
|
/**
|
||
|
|
* Get stack link from DOM element
|
||
|
|
*/
|
||
|
|
getStackLinkFromElement(element: HTMLElement): IStackLink | null;
|
||
|
|
/**
|
||
|
|
* Apply visual styling to element based on stack level
|
||
|
|
*/
|
||
|
|
applyVisualStyling(element: HTMLElement, stackLevel: number): void;
|
||
|
|
/**
|
||
|
|
* Clear stack link from element
|
||
|
|
*/
|
||
|
|
clearStackLinkFromElement(element: HTMLElement): void;
|
||
|
|
/**
|
||
|
|
* Clear visual styling from element
|
||
|
|
*/
|
||
|
|
clearVisualStyling(element: HTMLElement): void;
|
||
|
|
}
|