or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdinternal-components.mdmain-plugin.mdpositioning-utilities.md
tile.json

positioning-utilities.mddocs/

Positioning Utilities

Specialized utilities for event positioning, coordinate calculations, and segment management within time grid views. These functions handle the complex mathematics of placing events accurately within time slots.

Capabilities

TimeColsSlatsCoords

Class responsible for coordinate calculations and positioning of elements within time slots.

/**
 * Manages positioning calculations for time slots and events
 * Handles coordinate mapping between time values and pixel positions
 */
export class TimeColsSlatsCoords {
  constructor(
    positions: PositionCache,
    dateProfile: DateProfile,
    slotDuration: Duration
  );

  /**
   * Safely computes top position for a date with bounds checking
   * @param date - Date to compute position for
   * @returns Top pixel position or null if out of bounds
   */
  safeComputeTop(date: DateMarker): number | null;

  /**
   * Computes top pixel position for a given date
   * @param when - Date to compute position for
   * @param startOfDayDate - Optional start of day reference
   * @returns Top pixel position
   */
  computeDateTop(when: DateMarker, startOfDayDate?: DateMarker): number;

  /**
   * Computes top pixel position for a time duration from start of day
   * @param duration - Time duration from start of day
   * @returns Top pixel position
   */
  computeTimeTop(duration: Duration): number;
}

Usage Examples:

import { TimeColsSlatsCoords } from '@fullcalendar/timegrid/internal';

// Create coordinate calculator
const slatCoords = new TimeColsSlatsCoords(positions, dateProfile, slotDuration);

// Get position for a specific time
const nineAM = createDuration({ hours: 9 });
const topPosition = slatCoords.computeTimeTop(nineAM);

// Safe position calculation with bounds checking
const eventDate = new Date('2023-12-01T14:30:00');
const safeTop = slatCoords.safeComputeTop(eventDate);

Time Slot Metadata Generation

Functions for creating and managing time slot metadata arrays.

/**
 * Builds array of time slot metadata for a date range
 * @param slotMinTime - Minimum time to display
 * @param slotMaxTime - Maximum time to display
 * @param explicitLabelInterval - Explicit label interval or null for automatic
 * @param slotDuration - Duration of each time slot
 * @param dateEnv - Date environment for date calculations
 * @returns Array of time slot metadata
 */
export function buildSlatMetas(
  slotMinTime: Duration,
  slotMaxTime: Duration,
  explicitLabelInterval: Duration | null,
  slotDuration: Duration,
  dateEnv: DateEnv
): TimeSlatMeta[];

interface TimeSlatMeta {
  date: DateMarker;      // Date for this time slot
  time: Duration;        // Time duration from start of day
  key: string;           // Unique identifier for the slot
  isoTimeStr: string;    // ISO format time string
  isLabeled: boolean;    // Whether slot should show time label
}

Usage Examples:

import { buildSlatMetas } from '@fullcalendar/timegrid/internal';

// Build time slots for 30-minute intervals from 8 AM to 6 PM
const slatMetas = buildSlatMetas(
  createDuration({ hours: 8 }),           // Start at 8 AM
  createDuration({ hours: 18 }),          // End at 6 PM
  null,                                   // Auto label interval
  createDuration({ minutes: 30 }),        // 30-minute slots
  dateEnv                                 // Date environment
);

// Use metadata for rendering
slatMetas.forEach(meta => {
  if (meta.isLabeled) {
    console.log(`Time slot: ${meta.isoTimeStr}`);
  }
});

Segment Management

Functions for managing and splitting event segments across columns and time ranges.

/**
 * Splits time column segments by column index
 * @param segs - Array of time column segments (can be null)
 * @param colCnt - Number of columns
 * @returns Array of segment arrays, one per column
 */
export function splitSegsByCol(
  segs: TimeColsSeg[] | null,
  colCnt: number
): TimeColsSeg[][];

/**
 * Splits interaction state by column for multi-column views
 * @param ui - Event segment UI interaction state
 * @param colCnt - Number of columns
 * @returns Array of interaction states per column
 */
export function splitInteractionByCol(
  ui: EventSegUiInteractionState | null,
  colCnt: number
): EventSegUiInteractionState[];

Usage Examples:

import { splitSegsByCol, splitInteractionByCol } from '@fullcalendar/timegrid/internal';

// Split segments for a week view (7 columns)
const segsByCol = splitSegsByCol(allSegments, 7);

// Handle drag interactions across columns
const interactionsByCol = splitInteractionByCol(dragState, 7);

Event Placement Calculations

Advanced functions for computing optimal event positioning and handling overlaps.

/**
 * Computes vertical coordinates for event segments
 * @param segs - Array of time column segments
 * @param colDate - Date for the column
 * @param slatCoords - Coordinate calculator (default: null)
 * @param eventMinHeight - Minimum height for events (default: 0)
 * @returns Array of segment spans with positioning
 */
export function computeSegVCoords(
  segs: TimeColsSeg[],
  colDate: DateMarker,
  slatCoords: TimeColsSlatsCoords | null = null,
  eventMinHeight: number = 0
): SegSpan[];

/**
 * Computes final placement for foreground event segments
 * @param segs - Array of time column segments
 * @param segVCoords - Vertical coordinates for segments
 * @param eventOrderStrict - Whether to enforce strict event ordering
 * @param eventMaxStack - Maximum number of events to stack
 * @returns Placement information and hidden groups
 */
export function computeFgSegPlacements(
  segs: TimeColsSeg[],
  segVCoords: SegSpan[],
  eventOrderStrict?: boolean,
  eventMaxStack?: number
): {
  segPlacements: TimeColFgSegPlacement[];
  hiddenGroups: TimeColsSeg[][];
};

interface TimeColFgSegPlacement {
  seg: TimeColsSeg;
  rect: SegRect;
}

interface SegSpan {
  start: number;
  end: number;
}

interface SegRect {
  left: number;
  right: number;
  top: number;
  bottom: number;
}

Web Positioning System

Advanced positioning system for handling complex overlapping scenarios.

/**
 * Extended segment rectangle with stack positioning information
 */
interface SegWebRect extends SegRect {
  stackDepth: number;     // Depth in the stack (0-based)
  stackForward: number;   // Forward stack position
}

/**
 * Builds optimal positioning layout for overlapping segments
 * @param segInputs - Input segments with positioning data
 * @param strictOrder - Whether to maintain strict ordering
 * @param maxStackCnt - Maximum stack count allowed
 * @returns Positioned rectangles and hidden groups
 */
export function buildPositioning(
  segInputs: any[],
  strictOrder?: boolean,
  maxStackCnt?: number
): {
  segRects: SegWebRect[];
  hiddenGroups: any[][];
};

Usage Examples:

import { 
  computeSegVCoords, 
  computeFgSegPlacements, 
  buildPositioning 
} from '@fullcalendar/timegrid/internal';

// Compute vertical positioning for events
const vCoords = computeSegVCoords(segments, columnDate, slatCoords, 20);

// Calculate final placements with overlap handling
const { segPlacements, hiddenGroups } = computeFgSegPlacements(
  segments,
  vCoords,
  true,  // strict ordering
  4      // max 4 events stacked
);

// Advanced web positioning for complex layouts
const { segRects, hiddenGroups } = buildPositioning(
  segmentInputs,
  false, // flexible ordering
  6      // max 6 in stack
);

Types

interface PositionCache {
  els: HTMLElement[];
  originClientRect: ClientRect;
  lefts: number[];
  rights: number[];
  tops: number[];
  bottoms: number[];
}

interface DateFormatter {
  (date: DateMarker, context: any): string;
}

interface DateFormatterGenerator {
  (): DateFormatter;
}

interface EventSegUiInteractionState {
  affectedInstances: { [instanceId: string]: EventInstance };
  segs: Seg[];
  isEvent: boolean;
}

interface EventInteractionState {
  affectedInstances: { [instanceId: string]: EventInstance };
  mutatedEvents: EventStore;
  isEvent: boolean;
}

interface EventInstance {
  instanceId: string;
  defId: string;
  range: DateRange;
  forcedStartTzo?: number;
  forcedEndTzo?: number;
}

interface EventStore {
  defs: { [defId: string]: EventDef };
  instances: { [instanceId: string]: EventInstance };
}

interface EventDef {
  defId: string;
  sourceId: string;
  allDay: boolean;
  hasEnd: boolean;
  recurringDef?: RecurringDef;
  title: string;
  url: string;
  groupId: string;
  publicId: string;
  extendedProps: { [prop: string]: any };
}

interface DateEnv {
  timeZone: string;
  locale: any;
  weekDow: number;
  add(date: DateMarker, duration: Duration): DateMarker;
  subtract(date: DateMarker, duration: Duration): DateMarker;
  startOf(date: DateMarker, unit: string): DateMarker;
  format(date: DateMarker, formatter: any): string;
}