{"version":3,"file":"viewport-awareness.mjs","sources":["../../../../src/lib/layouts/context-aware/viewport-awareness.ts"],"sourcesContent":["/**\n * @fileoverview Viewport Awareness System\n *\n * This module provides comprehensive viewport tracking including:\n * - Viewport dimensions and scroll position\n * - Element visibility tracking via IntersectionObserver\n * - Virtual viewport for performance optimization\n * - Safe area insets for modern devices\n *\n * Key design principles:\n * - Singleton pattern for global viewport state\n * - Throttled updates to prevent excessive callbacks\n * - Memory-efficient with automatic cleanup\n * - SSR-compatible with graceful degradation\n *\n * @module layouts/context-aware/viewport-awareness\n * @author Agent 4 - PhD Context Systems Expert\n * @version 1.0.0\n */\n\nimport type {\n  ViewportInfo,\n  ViewportPosition,\n  VisibilityState,\n  ComputedBounds,\n  ContextTrackingConfig,\n} from './types';\nimport { DEFAULT_TRACKING_CONFIG } from './types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Callback for viewport change events.\n */\nexport type ViewportChangeCallback = (viewport: ViewportInfo) => void;\n\n/**\n * Callback for element visibility changes.\n */\nexport type VisibilityChangeCallback = (element: Element, position: ViewportPosition) => void;\n\n/**\n * Options for visibility observation.\n */\nexport interface VisibilityObserverOptions {\n  /** Intersection thresholds (0-1) */\n  thresholds?: number[];\n  /** Root margin for early/late detection */\n  rootMargin?: string;\n  /** Whether to track continuous position updates */\n  trackPosition?: boolean;\n  /** Throttle interval for position updates (ms) */\n  throttleMs?: number;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Default intersection thresholds for visibility detection.\n */\nconst DEFAULT_THRESHOLDS = [0, 0.1, 0.25, 0.5, 0.75, 0.9, 1];\n\n/**\n * Default throttle interval for resize/scroll events.\n */\n// const DEFAULT_THROTTLE_MS = 16; // ~60fps\n\n// ============================================================================\n// ViewportTracker Class\n// ============================================================================\n\n/**\n * Tracks viewport state including dimensions, scroll position,\n * and element visibility.\n *\n * @remarks\n * Uses a singleton pattern to ensure consistent viewport state\n * across the application. All updates are throttled for performance.\n *\n * @example\n * ```typescript\n * const tracker = ViewportTracker.getInstance();\n * const viewport = tracker.getViewport();\n *\n * tracker.onViewportChange((viewport) => {\n *   console.log('Viewport changed:', viewport);\n * });\n *\n * tracker.observeVisibility(element, (element, position) => {\n *   console.log('Element visibility:', position.visibility);\n * });\n * ```\n */\nexport class ViewportTracker {\n  private static instance: ViewportTracker | null = null;\n\n  /** Current viewport state */\n  private viewport: ViewportInfo;\n\n  /** Set of viewport change listeners */\n  private readonly viewportListeners: Set<ViewportChangeCallback> = new Set();\n\n  /** Map of elements to visibility callbacks */\n  private readonly visibilityCallbacks: Map<Element, VisibilityChangeCallback[]> = new Map();\n\n  /** Map of elements to their last known position */\n  private readonly elementPositions: WeakMap<Element, ViewportPosition> = new WeakMap();\n\n  /** Intersection observer for visibility tracking */\n  private intersectionObserver: IntersectionObserver | null = null;\n\n  /** Resize observer for viewport changes */\n  private resizeObserver: ResizeObserver | null = null;\n\n  /** Configuration */\n  private readonly config: ContextTrackingConfig;\n\n  /** Throttle state for scroll events */\n  private scrollThrottleTimer: number | null = null;\n  private lastScrollTime = 0;\n\n  /** Throttle state for resize events */\n  private resizeThrottleTimer: number | null = null;\n  private lastResizeTime = 0;\n\n  /** Whether we're in SSR mode */\n  private readonly isSSR: boolean;\n\n  /**\n   * Creates a new ViewportTracker instance.\n   *\n   * @param config - Optional configuration\n   */\n  private constructor(config: Partial<ContextTrackingConfig> = {}) {\n    this.config = { ...DEFAULT_TRACKING_CONFIG, ...config };\n    this.isSSR = typeof window === 'undefined';\n    this.viewport = this.createInitialViewport();\n\n    if (!this.isSSR) {\n      this.initializeObservers();\n      this.attachEventListeners();\n    }\n  }\n\n  /**\n   * Gets the singleton instance.\n   *\n   * @param config - Optional configuration\n   * @returns ViewportTracker instance\n   */\n  public static getInstance(config?: Partial<ContextTrackingConfig>): ViewportTracker {\n    ViewportTracker.instance ??= new ViewportTracker(config);\n    return ViewportTracker.instance;\n  }\n\n  /**\n   * Resets the singleton instance.\n   */\n  public static resetInstance(): void {\n    if (ViewportTracker.instance) {\n      ViewportTracker.instance.destroy();\n      ViewportTracker.instance = null;\n    }\n  }\n\n  // ==========================================================================\n  // Public API - Viewport\n  // ==========================================================================\n\n  /**\n   * Gets the current viewport state.\n   *\n   * @returns Current ViewportInfo\n   */\n  public getViewport(): ViewportInfo {\n    if (!this.isSSR) {\n      // Always return fresh viewport on read\n      this.updateViewport();\n    }\n    return this.viewport;\n  }\n\n  /**\n   * Subscribes to viewport changes.\n   *\n   * @param callback - Callback function\n   * @returns Unsubscribe function\n   */\n  public onViewportChange(callback: ViewportChangeCallback): () => void {\n    this.viewportListeners.add(callback);\n    // Immediately call with current state\n    callback(this.viewport);\n\n    return () => {\n      this.viewportListeners.delete(callback);\n    };\n  }\n\n  /**\n   * Forces a viewport state update.\n   */\n  public refreshViewport(): void {\n    if (!this.isSSR) {\n      this.updateViewport();\n      this.notifyViewportListeners();\n    }\n  }\n\n  // ==========================================================================\n  // Public API - Visibility\n  // ==========================================================================\n\n  /**\n   * Observes an element for visibility changes.\n   *\n   * @param element - Element to observe\n   * @param callback - Callback for visibility changes\n   * @param _options\n   * @returns Unobserve function\n   */\n  public observeVisibility(\n    element: Element,\n    callback: VisibilityChangeCallback,\n    _options: VisibilityObserverOptions = {}\n  ): () => void {\n    if (this.isSSR) {\n      return () => {};\n    }\n\n    // Add callback to the element's callback list\n    const callbacks = this.visibilityCallbacks.get(element) ?? [];\n    callbacks.push(callback);\n    this.visibilityCallbacks.set(element, callbacks);\n\n    // Start observing if not already\n    if (callbacks.length === 1) {\n      this.intersectionObserver?.observe(element);\n    }\n\n    // Return unobserve function\n    return () => {\n      const cbs = this.visibilityCallbacks.get(element);\n      if (cbs) {\n        const index = cbs.indexOf(callback);\n        if (index !== -1) {\n          cbs.splice(index, 1);\n        }\n        if (cbs.length === 0) {\n          this.visibilityCallbacks.delete(element);\n          this.intersectionObserver?.unobserve(element);\n        }\n      }\n    };\n  }\n\n  /**\n   * Gets the current viewport position of an element.\n   *\n   * @param element - Element to check\n   * @returns ViewportPosition or null if not observed\n   */\n  public getElementPosition(element: Element): ViewportPosition | null {\n    if (this.isSSR) {\n      return null;\n    }\n\n    // Check cache first\n    const cached = this.elementPositions.get(element);\n    if (cached && Date.now() - cached.lastUpdated < 100) {\n      return cached;\n    }\n\n    // Compute fresh position\n    return this.computeElementPosition(element);\n  }\n\n  /**\n   * Checks if an element is currently visible in the viewport.\n   *\n   * @param element - Element to check\n   * @returns Whether element is visible\n   */\n  public isElementVisible(element: Element): boolean {\n    const position = this.getElementPosition(element);\n    return position?.visibility === 'visible' || position?.visibility === 'partial';\n  }\n\n  // ==========================================================================\n  // Public API - Virtual Viewport\n  // ==========================================================================\n\n  /**\n   * Creates a virtual viewport for optimized rendering.\n   * Useful for large lists or grids.\n   *\n   * @param totalItems - Total number of items\n   * @param itemHeight - Height of each item\n   * @param overscan - Number of items to render outside viewport\n   * @returns Virtual viewport bounds\n   */\n  public getVirtualViewportBounds(\n    totalItems: number,\n    itemHeight: number,\n    overscan = 5\n  ): { startIndex: number; endIndex: number; offsetTop: number } {\n    if (this.isSSR) {\n      return { startIndex: 0, endIndex: Math.min(20, totalItems), offsetTop: 0 };\n    }\n\n    const { scrollY } = this.viewport;\n    const viewportHeight = this.viewport.height;\n\n    // Calculate visible range\n    const startIndex = Math.max(0, Math.floor(scrollY / itemHeight) - overscan);\n    const visibleCount = Math.ceil(viewportHeight / itemHeight);\n    const endIndex = Math.min(totalItems, startIndex + visibleCount + overscan * 2);\n    const offsetTop = startIndex * itemHeight;\n\n    return { startIndex, endIndex, offsetTop };\n  }\n\n  // ==========================================================================\n  // Public API - Lifecycle\n  // ==========================================================================\n\n  /**\n   * Destroys the tracker and cleans up resources.\n   */\n  public destroy(): void {\n    if (this.isSSR) {\n      return;\n    }\n\n    // Clear timers\n    if (this.scrollThrottleTimer !== null) {\n      window.clearTimeout(this.scrollThrottleTimer);\n    }\n    if (this.resizeThrottleTimer !== null) {\n      window.clearTimeout(this.resizeThrottleTimer);\n    }\n\n    // Disconnect observers\n    this.intersectionObserver?.disconnect();\n    this.resizeObserver?.disconnect();\n\n    // Remove event listeners\n    window.removeEventListener('scroll', this.handleScroll);\n    window.removeEventListener('resize', this.handleResize);\n\n    // Clear all callbacks\n    this.viewportListeners.clear();\n    this.visibilityCallbacks.clear();\n  }\n\n  // ==========================================================================\n  // Private Methods - Initialization\n  // ==========================================================================\n\n  /**\n   * Creates initial viewport state.\n   */\n  private createInitialViewport(): ViewportInfo {\n    if (this.isSSR) {\n      return {\n        width: 1024,\n        height: 768,\n        scrollX: 0,\n        scrollY: 0,\n        scrollWidth: 1024,\n        scrollHeight: 768,\n        devicePixelRatio: 1,\n        isTouch: false,\n        orientation: 'landscape',\n        safeAreaInsets: { top: 0, right: 0, bottom: 0, left: 0 },\n      };\n    }\n\n    return this.computeViewport();\n  }\n\n  /**\n   * Initializes observers.\n   */\n  private initializeObservers(): void {\n    // Intersection Observer for visibility tracking\n    this.intersectionObserver = new IntersectionObserver(this.handleIntersection.bind(this), {\n      root: null, // viewport\n      rootMargin: '50px', // Slightly expand detection area\n      threshold: DEFAULT_THRESHOLDS,\n    });\n\n    // Resize Observer for viewport changes\n    if (typeof ResizeObserver !== 'undefined') {\n      this.resizeObserver = new ResizeObserver(() => {\n        this.throttledResize();\n      });\n      this.resizeObserver.observe(document.documentElement);\n    }\n  }\n\n  /**\n   * Attaches event listeners.\n   */\n  private attachEventListeners(): void {\n    window.addEventListener('scroll', this.handleScroll, { passive: true });\n    window.addEventListener('resize', this.handleResize, { passive: true });\n  }\n\n  // ==========================================================================\n  // Private Methods - Event Handlers\n  // ==========================================================================\n\n  /**\n   * Handles scroll events with throttling.\n   */\n  private handleScroll = (): void => {\n    this.throttledScroll();\n  };\n\n  /**\n   * Handles resize events with throttling.\n   */\n  private handleResize = (): void => {\n    this.throttledResize();\n  };\n\n  /**\n   * Handles intersection observer entries.\n   */\n  private handleIntersection(entries: IntersectionObserverEntry[]): void {\n    for (const entry of entries) {\n      const element = entry.target;\n      const position = this.computePositionFromEntry(entry);\n\n      // Update cache\n      this.elementPositions.set(element, position);\n\n      // Notify callbacks\n      const callbacks = this.visibilityCallbacks.get(element);\n      if (callbacks) {\n        callbacks.forEach((callback) => {\n          try {\n            callback(element, position);\n          } catch (error) {\n            if (this.config.debug) {\n              console.error('[ViewportTracker] Callback error:', error);\n            }\n          }\n        });\n      }\n    }\n  }\n\n  // ==========================================================================\n  // Private Methods - Throttling\n  // ==========================================================================\n\n  /**\n   * Throttled scroll update.\n   */\n  private throttledScroll(): void {\n    const now = Date.now();\n    const elapsed = now - this.lastScrollTime;\n\n    if (elapsed >= this.config.throttleMs) {\n      this.lastScrollTime = now;\n      this.updateViewport();\n      this.notifyViewportListeners();\n    } else {\n      this.scrollThrottleTimer ??= window.setTimeout(() => {\n        this.scrollThrottleTimer = null;\n        this.lastScrollTime = Date.now();\n        this.updateViewport();\n        this.notifyViewportListeners();\n      }, this.config.throttleMs - elapsed);\n    }\n  }\n\n  /**\n   * Throttled resize update.\n   */\n  private throttledResize(): void {\n    const now = Date.now();\n    const elapsed = now - this.lastResizeTime;\n\n    if (elapsed >= this.config.throttleMs) {\n      this.lastResizeTime = now;\n      this.updateViewport();\n      this.notifyViewportListeners();\n    } else {\n      this.resizeThrottleTimer ??= window.setTimeout(() => {\n        this.resizeThrottleTimer = null;\n        this.lastResizeTime = Date.now();\n        this.updateViewport();\n        this.notifyViewportListeners();\n      }, this.config.throttleMs - elapsed);\n    }\n  }\n\n  // ==========================================================================\n  // Private Methods - Computation\n  // ==========================================================================\n\n  /**\n   * Computes current viewport state.\n   */\n  private computeViewport(): ViewportInfo {\n    const width = window.innerWidth;\n    const height = window.innerHeight;\n    const scrollX = window.scrollX || window.pageXOffset;\n    const scrollY = window.scrollY || window.pageYOffset;\n    const { scrollWidth } = document.documentElement;\n    const { scrollHeight } = document.documentElement;\n    const devicePixelRatio = window.devicePixelRatio || 1;\n    const isTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n    const orientation = width > height ? 'landscape' : 'portrait';\n\n    // Get safe area insets (for notched devices)\n    const safeAreaInsets = this.getSafeAreaInsets();\n\n    return {\n      width,\n      height,\n      scrollX,\n      scrollY,\n      scrollWidth,\n      scrollHeight,\n      devicePixelRatio,\n      isTouch,\n      orientation,\n      safeAreaInsets,\n    };\n  }\n\n  /**\n   * Gets safe area insets from CSS environment variables.\n   */\n  private getSafeAreaInsets(): ViewportInfo['safeAreaInsets'] {\n    if (typeof CSS === 'undefined' || !CSS.supports('padding-top: env(safe-area-inset-top)')) {\n      return { top: 0, right: 0, bottom: 0, left: 0 };\n    }\n\n    const computeInset = (property: string): number => {\n      const div = document.createElement('div');\n      div.style.cssText = `position: fixed; ${property}: env(safe-area-inset-${property.replace('padding-', '')})`;\n      document.body.appendChild(div);\n      const value =\n        parseFloat(getComputedStyle(div)[property as keyof CSSStyleDeclaration] as string) || 0;\n      document.body.removeChild(div);\n      return value;\n    };\n\n    // Cache these values as they rarely change\n    return {\n      top: computeInset('padding-top'),\n      right: computeInset('padding-right'),\n      bottom: computeInset('padding-bottom'),\n      left: computeInset('padding-left'),\n    };\n  }\n\n  /**\n   * Updates the viewport state.\n   */\n  private updateViewport(): void {\n    this.viewport = this.computeViewport();\n  }\n\n  /**\n   * Notifies all viewport listeners.\n   */\n  private notifyViewportListeners(): void {\n    this.viewportListeners.forEach((callback) => {\n      try {\n        callback(this.viewport);\n      } catch (error) {\n        if (this.config.debug) {\n          console.error('[ViewportTracker] Listener error:', error);\n        }\n      }\n    });\n  }\n\n  /**\n   * Computes element position from intersection entry.\n   */\n  private computePositionFromEntry(entry: IntersectionObserverEntry): ViewportPosition {\n    const rect = entry.boundingClientRect;\n    const { viewport } = this;\n\n    // Compute bounds\n    const bounds: ComputedBounds = {\n      x: rect.x,\n      y: rect.y,\n      width: rect.width,\n      height: rect.height,\n      top: rect.top,\n      right: rect.right,\n      bottom: rect.bottom,\n      left: rect.left,\n      contentBox: { width: rect.width, height: rect.height },\n      paddingBox: { width: rect.width, height: rect.height },\n      borderBox: { width: rect.width, height: rect.height },\n    };\n\n    // Determine visibility state\n    let visibility: VisibilityState;\n    if (!entry.isIntersecting) {\n      visibility = 'hidden';\n    } else if (entry.intersectionRatio >= 0.99) {\n      visibility = 'visible';\n    } else {\n      visibility = 'partial';\n    }\n\n    // Compute distance from viewport edges\n    const distanceFromViewport = {\n      top: rect.top,\n      right: viewport.width - rect.right,\n      bottom: viewport.height - rect.bottom,\n      left: rect.left,\n    };\n\n    // Determine relative position\n    let relativePosition: ViewportPosition['relativePosition'];\n    if (rect.bottom < 0) {\n      relativePosition = 'above';\n    } else if (rect.top > viewport.height) {\n      relativePosition = 'below';\n    } else if (rect.right < 0) {\n      relativePosition = 'left';\n    } else if (rect.left > viewport.width) {\n      relativePosition = 'right';\n    } else {\n      relativePosition = 'within';\n    }\n\n    return {\n      bounds,\n      visibility,\n      intersectionRatio: entry.intersectionRatio,\n      distanceFromViewport,\n      relativePosition,\n      lastUpdated: Date.now(),\n    };\n  }\n\n  /**\n   * Computes element position directly (not from intersection entry).\n   */\n  private computeElementPosition(element: Element): ViewportPosition {\n    const rect = element.getBoundingClientRect();\n    const { viewport } = this;\n\n    // Compute bounds\n    const bounds: ComputedBounds = {\n      x: rect.x,\n      y: rect.y,\n      width: rect.width,\n      height: rect.height,\n      top: rect.top,\n      right: rect.right,\n      bottom: rect.bottom,\n      left: rect.left,\n      contentBox: { width: rect.width, height: rect.height },\n      paddingBox: { width: rect.width, height: rect.height },\n      borderBox: { width: rect.width, height: rect.height },\n    };\n\n    // Calculate intersection manually\n    const intersectionTop = Math.max(0, rect.top);\n    const intersectionLeft = Math.max(0, rect.left);\n    const intersectionBottom = Math.min(viewport.height, rect.bottom);\n    const intersectionRight = Math.min(viewport.width, rect.right);\n\n    const intersectionWidth = Math.max(0, intersectionRight - intersectionLeft);\n    const intersectionHeight = Math.max(0, intersectionBottom - intersectionTop);\n    const intersectionArea = intersectionWidth * intersectionHeight;\n    const elementArea = rect.width * rect.height;\n    const intersectionRatio = elementArea > 0 ? intersectionArea / elementArea : 0;\n\n    // Determine visibility state\n    let visibility: VisibilityState;\n    if (intersectionRatio === 0) {\n      visibility = 'hidden';\n    } else if (intersectionRatio >= 0.99) {\n      visibility = 'visible';\n    } else {\n      visibility = 'partial';\n    }\n\n    // Compute distance from viewport edges\n    const distanceFromViewport = {\n      top: rect.top,\n      right: viewport.width - rect.right,\n      bottom: viewport.height - rect.bottom,\n      left: rect.left,\n    };\n\n    // Determine relative position\n    let relativePosition: ViewportPosition['relativePosition'];\n    if (rect.bottom < 0) {\n      relativePosition = 'above';\n    } else if (rect.top > viewport.height) {\n      relativePosition = 'below';\n    } else if (rect.right < 0) {\n      relativePosition = 'left';\n    } else if (rect.left > viewport.width) {\n      relativePosition = 'right';\n    } else {\n      relativePosition = 'within';\n    }\n\n    const position: ViewportPosition = {\n      bounds,\n      visibility,\n      intersectionRatio,\n      distanceFromViewport,\n      relativePosition,\n      lastUpdated: Date.now(),\n    };\n\n    // Cache the position\n    this.elementPositions.set(element, position);\n\n    return position;\n  }\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Gets the singleton ViewportTracker instance.\n *\n * @param config - Optional configuration\n * @returns ViewportTracker instance\n */\nexport function getViewportTracker(config?: Partial<ContextTrackingConfig>): ViewportTracker {\n  return ViewportTracker.getInstance(config);\n}\n\n/**\n * Gets the current viewport information.\n *\n * @returns Current ViewportInfo\n */\nexport function getViewport(): ViewportInfo {\n  return getViewportTracker().getViewport();\n}\n\n/**\n * Subscribes to viewport changes.\n *\n * @param callback - Callback function\n * @returns Unsubscribe function\n */\nexport function onViewportChange(callback: ViewportChangeCallback): () => void {\n  return getViewportTracker().onViewportChange(callback);\n}\n\n/**\n * Checks if an element is visible in the viewport.\n *\n * @param element - Element to check\n * @returns Whether element is visible\n */\nexport function isElementInViewport(element: Element): boolean {\n  return getViewportTracker().isElementVisible(element);\n}\n\n/**\n * Gets viewport-relative position of an element.\n *\n * @param element - Element to check\n * @returns ViewportPosition or null\n */\nexport function getViewportPosition(element: Element): ViewportPosition | null {\n  return getViewportTracker().getElementPosition(element);\n}\n\n/**\n * Calculates the distance from an element to the viewport center.\n *\n * @param element - Element to check\n * @returns Distance in pixels, or Infinity if not in viewport\n */\nexport function getDistanceFromViewportCenter(element: Element): number {\n  const position = getViewportPosition(element);\n  if (!position) {\n    return Infinity;\n  }\n\n  const viewport = getViewport();\n  const viewportCenterX = viewport.width / 2;\n  const viewportCenterY = viewport.height / 2;\n\n  const elementCenterX = position.bounds.left + position.bounds.width / 2;\n  const elementCenterY = position.bounds.top + position.bounds.height / 2;\n\n  return Math.sqrt(\n    Math.pow(elementCenterX - viewportCenterX, 2) + Math.pow(elementCenterY - viewportCenterY, 2)\n  );\n}\n\n/**\n * Determines the optimal scroll position to bring an element into view.\n *\n * @param element - Element to scroll to\n * @param options - Scroll options\n * @returns Target scroll position\n */\nexport function getOptimalScrollPosition(\n  element: Element,\n  options: { alignment?: 'start' | 'center' | 'end'; offset?: number } = {}\n): { x: number; y: number } {\n  const { alignment = 'center', offset = 0 } = options;\n  const position = getViewportPosition(element);\n  const viewport = getViewport();\n\n  if (!position) {\n    return { x: viewport.scrollX, y: viewport.scrollY };\n  }\n\n  let targetY: number;\n  switch (alignment) {\n    case 'start':\n      targetY = viewport.scrollY + position.bounds.top - offset;\n      break;\n    case 'end':\n      targetY = viewport.scrollY + position.bounds.bottom - viewport.height + offset;\n      break;\n    case 'center':\n    default:\n      targetY =\n        viewport.scrollY + position.bounds.top + position.bounds.height / 2 - viewport.height / 2;\n      break;\n  }\n\n  return {\n    x: viewport.scrollX,\n    y: Math.max(0, Math.min(targetY, viewport.scrollHeight - viewport.height)),\n  };\n}\n"],"names":["DEFAULT_THRESHOLDS","ViewportTracker","config","DEFAULT_TRACKING_CONFIG","callback","element","_options","callbacks","cbs","index","cached","position","totalItems","itemHeight","overscan","scrollY","viewportHeight","startIndex","visibleCount","endIndex","offsetTop","entries","entry","error","now","elapsed","width","height","scrollX","scrollWidth","scrollHeight","devicePixelRatio","isTouch","orientation","safeAreaInsets","computeInset","property","div","value","rect","viewport","bounds","visibility","distanceFromViewport","relativePosition","intersectionTop","intersectionLeft","intersectionBottom","intersectionRight","intersectionWidth","intersectionHeight","intersectionArea","elementArea","intersectionRatio","getViewportTracker","getViewport","onViewportChange","isElementInViewport","getViewportPosition","getDistanceFromViewportCenter","viewportCenterX","viewportCenterY","elementCenterX","elementCenterY","getOptimalScrollPosition","options","alignment","offset","targetY"],"mappings":"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"}