{"version":3,"file":"cls-guard.mjs","sources":["../../../../src/lib/layouts/adaptive/cls-guard.ts"],"sourcesContent":["/**\n * @fileoverview CLS (Cumulative Layout Shift) Guard System\n *\n * This module provides a comprehensive system for preventing and monitoring\n * Cumulative Layout Shift. It implements layout reservations, skeleton placeholders,\n * and real-time CLS measurement using the Performance Observer API.\n *\n * Key Features:\n * - Zero-CLS layout reservations\n * - Multiple reservation strategies (skeleton, dimensions, aspect-ratio)\n * - Real-time CLS monitoring\n * - Threshold-based alerts\n * - Performance Observer integration\n *\n * @module layouts/adaptive/cls-guard\n * @version 1.0.0\n */\n\nimport type {\n  CLSGuardConfig,\n  CLSGuardInterface,\n  CLSMeasurement,\n  Dimensions,\n  LayoutReservation,\n  LayoutShiftEntry,\n  ReservationStrategy,\n} from './types';\nimport { DEFAULT_CLS_GUARD_CONFIG } from './types';\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\n\n/**\n * CLS score thresholds based on Core Web Vitals.\n */\n// const CLS_THRESHOLDS = {\n//   good: 0.1,\n//   needsImprovement: 0.25,\n//   poor: 0.5,\n// } as const;\n\n/**\n * Maximum age for layout shift entries to consider (5 seconds).\n */\n// const MAX_ENTRY_AGE_MS = 5000;\n\n/**\n * Session window gap for CLS calculation (1 second).\n */\nconst SESSION_WINDOW_GAP_MS = 1000;\n\n/**\n * Maximum session window duration (5 seconds).\n */\nconst MAX_SESSION_WINDOW_MS = 5000;\n\n// =============================================================================\n// HELPER FUNCTIONS\n// =============================================================================\n\n/**\n * Generates a unique reservation ID.\n */\n// function _generateReservationId(): string {\n//   return `rsv_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n// }\n\n/**\n * Creates CSS for skeleton placeholder.\n */\nfunction createSkeletonStyles(dimensions: Dimensions): string {\n  return `\n    width: ${dimensions.width}px;\n    height: ${dimensions.height}px;\n    background: linear-gradient(\n      90deg,\n      var(--skeleton-base, #e0e0e0) 25%,\n      var(--skeleton-shine, #f0f0f0) 50%,\n      var(--skeleton-base, #e0e0e0) 75%\n    );\n    background-size: 200% 100%;\n    animation: skeleton-shimmer 1.5s ease-in-out infinite;\n    border-radius: 4px;\n  `;\n}\n\n/**\n * Injects skeleton animation CSS if not already present.\n */\nfunction ensureSkeletonAnimation(): void {\n  if (typeof document === 'undefined') return;\n\n  const styleId = 'cls-guard-skeleton-styles';\n  if (document.getElementById(styleId)) return;\n\n  const style = document.createElement('style');\n  style.id = styleId;\n  style.textContent = `\n    @keyframes skeleton-shimmer {\n      0% { background-position: 200% 0; }\n      100% { background-position: -200% 0; }\n    }\n  `;\n  document.head.appendChild(style);\n}\n\n// =============================================================================\n// CLS GUARD IMPLEMENTATION\n// =============================================================================\n\n/**\n * CLS Guard implementation that prevents layout shifts through\n * reservations and monitors actual CLS scores.\n *\n * @example\n * ```typescript\n * const guard = createCLSGuard({ maxCLS: 0.05 });\n *\n * // Reserve space for an image\n * const reservation = guard.createReservation('hero-image', {\n *   width: 1200,\n *   height: 600\n * }, 'skeleton');\n *\n * // Monitor CLS\n * const unsubscribe = guard.observeCLS((measurement) => {\n *   if (measurement.thresholdExceeded) {\n *     console.warn('CLS threshold exceeded:', measurement.score);\n *   }\n * });\n * ```\n */\nexport class CLSGuard implements CLSGuardInterface {\n  private readonly _reservations: Map<string, LayoutReservation>;\n  private readonly _reservationElements: Map<string, HTMLElement>;\n  private readonly _measurements: CLSMeasurement[];\n  private readonly _callbacks: Set<(measurement: CLSMeasurement) => void>;\n  private _observer: PerformanceObserver | null = null;\n  private _sessionEntries: LayoutShiftEntry[] = [];\n  private _sessionStart: number = 0;\n  private _destroyed: boolean = false;\n\n  constructor(config: Partial<CLSGuardConfig> = {}) {\n    this._config = { ...DEFAULT_CLS_GUARD_CONFIG, ...config };\n    this._reservations = new Map();\n    this._reservationElements = new Map();\n    this._measurements = [];\n    this._callbacks = new Set();\n\n    if (this._config.monitor && typeof window !== 'undefined') {\n      this._initializeObserver();\n    }\n\n    ensureSkeletonAnimation();\n  }\n\n  private _config: CLSGuardConfig;\n\n  /**\n   * Current configuration.\n   */\n  get config(): CLSGuardConfig {\n    return this._config;\n  }\n\n  private _currentScore: number = 0;\n\n  /**\n   * Current CLS score.\n   */\n  get currentScore(): number {\n    return this._currentScore;\n  }\n\n  /**\n   * Updates the guard configuration.\n   */\n  configure(config: Partial<CLSGuardConfig>): void {\n    this._assertNotDestroyed();\n    this._config = { ...this._config, ...config };\n\n    // Start or stop observer based on config\n    if (this._config.monitor && !this._observer) {\n      this._initializeObserver();\n    } else if (!this._config.monitor && this._observer) {\n      this._observer.disconnect();\n      this._observer = null;\n    }\n  }\n\n  /**\n   * Creates a layout reservation to prevent CLS.\n   *\n   * @param id - Unique identifier for the reservation\n   * @param dimensions - Dimensions to reserve\n   * @param strategy - Reservation strategy (defaults to config)\n   * @returns The created reservation\n   */\n  createReservation(\n    id: string,\n    dimensions: Dimensions,\n    strategy: ReservationStrategy = this._config.reservationStrategy\n  ): LayoutReservation {\n    this._assertNotDestroyed();\n\n    // Release existing reservation if present\n    if (this._reservations.has(id)) {\n      this.releaseReservation(id);\n    }\n\n    const reservation: LayoutReservation = {\n      id,\n      dimensions,\n      aspectRatio: dimensions.width / dimensions.height,\n      active: true,\n      createdAt: Date.now(),\n    };\n\n    this._reservations.set(id, reservation);\n\n    // Create reservation element based on strategy\n    if (strategy !== 'none' && typeof document !== 'undefined') {\n      this._createReservationElement(id, dimensions, strategy);\n    }\n\n    return reservation;\n  }\n\n  /**\n   * Releases a layout reservation.\n   *\n   * @param id - The reservation ID to release\n   */\n  releaseReservation(id: string): void {\n    this._assertNotDestroyed();\n\n    const reservation = this._reservations.get(id);\n    if (reservation) {\n      this._reservations.set(id, { ...reservation, active: false });\n    }\n\n    // Remove reservation element\n    const element = this._reservationElements.get(id);\n    if (element?.parentNode) {\n      element.parentNode.removeChild(element);\n    }\n    this._reservationElements.delete(id);\n  }\n\n  /**\n   * Measures the current CLS score.\n   *\n   * @returns CLS measurement result\n   */\n  measureCLS(): CLSMeasurement {\n    this._assertNotDestroyed();\n\n    const measurement: CLSMeasurement = {\n      score: this._currentScore,\n      entries: [...this._sessionEntries],\n      thresholdExceeded: this._currentScore > this._config.maxCLS,\n      timestamp: Date.now(),\n    };\n\n    this._measurements.push(measurement);\n\n    return measurement;\n  }\n\n  /**\n   * Subscribes to CLS updates.\n   *\n   * @param callback - Callback for CLS measurements\n   * @returns Unsubscribe function\n   */\n  observeCLS(callback: (measurement: CLSMeasurement) => void): () => void {\n    this._assertNotDestroyed();\n    this._callbacks.add(callback);\n\n    return () => {\n      this._callbacks.delete(callback);\n    };\n  }\n\n  /**\n   * Cleans up all resources.\n   */\n  destroy(): void {\n    if (this._destroyed) return;\n\n    if (this._observer) {\n      this._observer.disconnect();\n      this._observer = null;\n    }\n\n    // Remove all reservation elements\n    for (const element of this._reservationElements.values()) {\n      if (element.parentNode) {\n        element.parentNode.removeChild(element);\n      }\n    }\n\n    this._reservations.clear();\n    this._reservationElements.clear();\n    this._callbacks.clear();\n    this._measurements.length = 0;\n    this._destroyed = true;\n  }\n\n  // ===========================================================================\n  // PRIVATE METHODS\n  // ===========================================================================\n\n  /**\n   * Gets the reservation element for a given ID.\n   *\n   * @param id - Reservation ID\n   * @returns The reservation element or undefined\n   */\n  getReservationElement(id: string): HTMLElement | undefined {\n    return this._reservationElements.get(id);\n  }\n\n  /**\n   * Inserts a reservation element at a specific location.\n   *\n   * @param id - Reservation ID\n   * @param container - Container element to insert into\n   * @param position - Insert position\n   */\n  insertReservationElement(\n    id: string,\n    container: HTMLElement,\n    position: 'prepend' | 'append' | 'before' | 'after' = 'append'\n  ): void {\n    const element = this._reservationElements.get(id);\n    if (!element) return;\n\n    switch (position) {\n      case 'prepend':\n        container.prepend(element);\n        break;\n      case 'append':\n        container.appendChild(element);\n        break;\n      case 'before':\n        container.parentNode?.insertBefore(element, container);\n        break;\n      case 'after':\n        container.parentNode?.insertBefore(element, container.nextSibling);\n        break;\n    }\n  }\n\n  /**\n   * Initializes the Performance Observer for CLS tracking.\n   */\n  private _initializeObserver(): void {\n    if (typeof PerformanceObserver === 'undefined') return;\n\n    try {\n      this._observer = new PerformanceObserver((list) => {\n        for (const entry of list.getEntries()) {\n          // Type assertion for LayoutShift entry\n          const layoutShift = entry as PerformanceEntry & {\n            hadRecentInput: boolean;\n            value: number;\n            sources?: Array<{ node?: Element }>;\n          };\n\n          // Ignore shifts caused by user input\n          if (layoutShift.hadRecentInput) continue;\n\n          this._processLayoutShift(layoutShift);\n        }\n      });\n\n      this._observer.observe({ type: 'layout-shift', buffered: true });\n    } catch (error) {\n      // Performance Observer not supported or layout-shift not available\n      console.warn('[CLSGuard] Layout shift observation not available:', error);\n    }\n  }\n\n  /**\n   * Processes a layout shift entry.\n   */\n  private _processLayoutShift(entry: PerformanceEntry & { value: number; sources?: Array<{ node?: Element }> }): void {\n    const now = performance.now();\n\n    // Create our layout shift entry\n    const shiftEntry: LayoutShiftEntry = {\n      elementId: this._extractElementId(entry.sources),\n      value: entry.value,\n      hadRecentInput: false,\n      startTime: entry.startTime,\n    };\n\n    // Session window logic for CLS calculation\n    // https://web.dev/cls/#what-is-a-good-cls-score\n    const lastEntry = this._sessionEntries[this._sessionEntries.length - 1];\n\n    if (\n      this._sessionStart === 0 ||\n      now - this._sessionStart > MAX_SESSION_WINDOW_MS ||\n      (this._sessionEntries.length > 0 &&\n        lastEntry != null &&\n        now - lastEntry.startTime > SESSION_WINDOW_GAP_MS)\n    ) {\n      // Start new session\n      this._sessionStart = now;\n      this._sessionEntries = [shiftEntry];\n    } else {\n      // Continue current session\n      this._sessionEntries.push(shiftEntry);\n    }\n\n    // Calculate session score\n    const sessionScore = this._sessionEntries.reduce((sum, e) => sum + e.value, 0);\n\n    // Update current score if this session is worse\n    if (sessionScore > this._currentScore) {\n      this._currentScore = sessionScore;\n    }\n\n    // Check threshold and notify\n    if (this._currentScore > this._config.maxCLS) {\n      const measurement = this.measureCLS();\n\n      // Notify callbacks\n      for (const callback of this._callbacks) {\n        try {\n          callback(measurement);\n        } catch (error) {\n          console.error('[CLSGuard] Callback error:', error);\n        }\n      }\n\n      // Trigger threshold exceeded callback\n      this._config.onThresholdExceeded?.(this._currentScore);\n    }\n  }\n\n  /**\n   * Extracts element ID from layout shift sources.\n   */\n  private _extractElementId(sources?: Array<{ node?: Element }>): string | null {\n    if (sources == null || sources.length === 0) return null;\n\n    const [firstSource] = sources;\n    if (firstSource?.node == null) return null;\n\n    const { node: element } = firstSource;\n    const elementId = element.id;\n    const dataLayoutId = element.getAttribute('data-layout-id');\n    return (elementId != null && elementId !== '') ? elementId : dataLayoutId ?? null;\n  }\n\n  /**\n   * Creates a reservation element in the DOM.\n   */\n  private _createReservationElement(\n    id: string,\n    dimensions: Dimensions,\n    strategy: ReservationStrategy\n  ): void {\n    const element = document.createElement('div');\n    element.setAttribute('data-cls-reservation', id);\n    element.setAttribute('aria-hidden', 'true');\n\n    switch (strategy) {\n      case 'skeleton':\n        element.style.cssText = createSkeletonStyles(dimensions);\n        break;\n\n      case 'dimensions':\n        element.style.cssText = `\n          width: ${dimensions.width}px;\n          height: ${dimensions.height}px;\n          visibility: hidden;\n        `;\n        break;\n\n      case 'aspect-ratio': {\n        const aspectRatio = dimensions.width / dimensions.height;\n        element.style.cssText = `\n          width: 100%;\n          aspect-ratio: ${aspectRatio};\n          max-width: ${dimensions.width}px;\n          visibility: hidden;\n        `;\n        break;\n      }\n\n      case 'minimum':\n        element.style.cssText = `\n          min-width: ${dimensions.width}px;\n          min-height: ${dimensions.height}px;\n          visibility: hidden;\n        `;\n        break;\n    }\n\n    this._reservationElements.set(id, element);\n  }\n\n  /**\n   * Asserts that the guard has not been destroyed.\n   */\n  private _assertNotDestroyed(): void {\n    if (this._destroyed) {\n      throw new Error('CLSGuard has been destroyed and cannot be used.');\n    }\n  }\n}\n\n// =============================================================================\n// FACTORY FUNCTION\n// =============================================================================\n\n/**\n * Creates a new CLSGuard instance.\n *\n * @param config - Optional configuration overrides\n * @returns A new CLSGuard instance\n */\nexport function createCLSGuard(config: Partial<CLSGuardConfig> = {}): CLSGuardInterface {\n  return new CLSGuard(config);\n}\n\n// =============================================================================\n// UTILITY FUNCTIONS\n// =============================================================================\n\n/**\n * Calculates the predicted CLS impact of a layout change.\n *\n * @param beforeRects - Element positions before change\n * @param afterRects - Element positions after change\n * @param viewportDimensions - Viewport dimensions\n * @returns Predicted CLS score\n */\nexport function predictCLSImpact(\n  beforeRects: ReadonlyMap<string, DOMRect>,\n  afterRects: ReadonlyMap<string, DOMRect>,\n  viewportDimensions: Dimensions\n): number {\n  let totalImpact = 0;\n  const viewportArea = viewportDimensions.width * viewportDimensions.height;\n\n  for (const [id, beforeRect] of beforeRects) {\n    const afterRect = afterRects.get(id);\n    if (!afterRect) continue;\n\n    // Calculate distance fraction\n    const dx = Math.abs(afterRect.x - beforeRect.x);\n    const dy = Math.abs(afterRect.y - beforeRect.y);\n    const distance = Math.sqrt(dx * dx + dy * dy);\n    const maxDimension = Math.max(viewportDimensions.width, viewportDimensions.height);\n    const distanceFraction = distance / maxDimension;\n\n    // Calculate impact fraction (area of element relative to viewport)\n    const elementArea = beforeRect.width * beforeRect.height;\n    const impactFraction = elementArea / viewportArea;\n\n    // CLS = impact fraction * distance fraction\n    totalImpact += impactFraction * distanceFraction;\n  }\n\n  return totalImpact;\n}\n\n/**\n * Creates optimized dimension reservations based on content hints.\n *\n * @param contentHints - Array of content hints with expected dimensions\n * @returns Array of optimized reservations\n */\nexport function createOptimizedReservations(\n  contentHints: Array<{\n    id: string;\n    type: 'image' | 'video' | 'text' | 'custom';\n    expectedDimensions?: Dimensions;\n    aspectRatio?: number;\n  }>\n): Array<{ id: string; dimensions: Dimensions; strategy: ReservationStrategy }> {\n  return contentHints.map((hint) => {\n    let dimensions: Dimensions;\n    let strategy: ReservationStrategy;\n\n    if (hint.expectedDimensions != null) {\n      dimensions = hint.expectedDimensions;\n      strategy = 'dimensions';\n    } else if (hint.aspectRatio != null) {\n      // Use aspect ratio with reasonable default width\n      const defaultWidth = hint.type === 'video' ? 640 : 400;\n      dimensions = {\n        width: defaultWidth,\n        height: defaultWidth / hint.aspectRatio,\n      };\n      strategy = 'aspect-ratio';\n    } else {\n      // Use type-based defaults\n      switch (hint.type) {\n        case 'image':\n          dimensions = { width: 400, height: 300 };\n          strategy = 'skeleton';\n          break;\n        case 'video':\n          dimensions = { width: 640, height: 360 };\n          strategy = 'aspect-ratio';\n          break;\n        case 'text':\n          dimensions = { width: 600, height: 100 };\n          strategy = 'minimum';\n          break;\n        default:\n          dimensions = { width: 200, height: 150 };\n          strategy = 'skeleton';\n      }\n    }\n\n    return { id: hint.id, dimensions, strategy };\n  });\n}\n"],"names":["SESSION_WINDOW_GAP_MS","MAX_SESSION_WINDOW_MS","createSkeletonStyles","dimensions","ensureSkeletonAnimation","styleId","style","CLSGuard","config","DEFAULT_CLS_GUARD_CONFIG","id","strategy","reservation","element","measurement","callback","container","position","list","entry","layoutShift","error","now","shiftEntry","lastEntry","sessionScore","sum","e","sources","firstSource","elementId","dataLayoutId","aspectRatio","createCLSGuard","predictCLSImpact","beforeRects","afterRects","viewportDimensions","totalImpact","viewportArea","beforeRect","afterRect","dx","dy","distance","maxDimension","distanceFraction","impactFraction","createOptimizedReservations","contentHints","hint","defaultWidth"],"mappings":"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"}