{"version":3,"file":"interaction-replay.mjs","sources":["../../../src/lib/hydration/interaction-replay.ts"],"sourcesContent":["/**\n * @file Interaction Replay System\n * @description Captures and replays user interactions during the hydration process.\n *\n * When a user interacts with a component that hasn't been hydrated yet, this system:\n * 1. Captures the interaction details (event type, target, position, etc.)\n * 2. Optionally prevents default behavior to avoid inconsistent state\n * 3. Stores the interaction in a bounded buffer\n * 4. After hydration completes, replays the interactions in order\n *\n * This provides a seamless user experience where interactions aren't lost,\n * even when they occur before the component is fully interactive.\n *\n * Key Design Decisions:\n * - Interactions are captured per-boundary for targeted replay\n * - Buffer has time and size limits to prevent memory issues\n * - Synthetic events are used for replay to match original behavior\n * - Visual feedback can be shown during capture (optional)\n *\n * @module hydration/interaction-replay\n */\n\nimport type {\n  CapturedInteraction,\n  HydrationBoundaryId,\n  InteractionReplayConfig,\n  ReplayableInteractionType,\n} from './types';\nimport { DEFAULT_REPLAY_CONFIG } from './types';\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Generates a unique ID for captured interactions.\n */\nfunction generateInteractionId(): string {\n  return `interaction-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\n/**\n * Generates a unique selector for an element.\n * Uses a combination of strategies for reliable re-targeting.\n *\n * @param element - The DOM element to create a selector for\n * @returns A CSS selector string\n */\nfunction generateSelector(element: Element): string {\n  // Try ID first (most reliable)\n  if (element.id) {\n    return `#${CSS.escape(element.id)}`;\n  }\n\n  // Try data-testid (common in React apps)\n  const testId = element.getAttribute('data-testid');\n  if (testId !== null && testId !== '') {\n    return `[data-testid=\"${CSS.escape(testId)}\"]`;\n  }\n\n  // Try data-hydration-target (our custom attribute)\n  const hydrationTarget = element.getAttribute('data-hydration-target');\n  if (hydrationTarget !== null && hydrationTarget !== '') {\n    return `[data-hydration-target=\"${CSS.escape(hydrationTarget)}\"]`;\n  }\n\n  // Build path from root\n  const path: string[] = [];\n  let current: Element | null = element;\n\n  while (current && current !== document.body) {\n    let selector = current.tagName.toLowerCase();\n\n    // Add classes for specificity\n    if (current.classList.length > 0) {\n      const classes = Array.from(current.classList)\n        .filter((c) => !c.startsWith('hydration-'))\n        .slice(0, 2)\n        .map((c) => `.${CSS.escape(c)}`)\n        .join('');\n      selector += classes;\n    }\n\n    // Add nth-child for disambiguation\n    const parent = current.parentElement;\n    if (parent) {\n      const currentTagName = current.tagName;\n      const siblings = Array.from(parent.children).filter(\n        (child) => child.tagName === currentTagName\n      );\n      if (siblings.length > 1) {\n        const index = siblings.indexOf(current) + 1;\n        selector += `:nth-of-type(${index})`;\n      }\n    }\n\n    path.unshift(selector);\n    current = current.parentElement;\n  }\n\n  return path.join(' > ');\n}\n\n/**\n * Extracts key information from a keyboard event.\n */\nfunction extractKeyInfo(event: KeyboardEvent): CapturedInteraction['keyInfo'] {\n  return {\n    key: event.key,\n    code: event.code,\n    shiftKey: event.shiftKey,\n    ctrlKey: event.ctrlKey,\n    altKey: event.altKey,\n    metaKey: event.metaKey,\n  };\n}\n\n/**\n * Extracts pointer position from a mouse or touch event.\n */\nfunction extractPointerPosition(\n  event: MouseEvent | TouchEvent\n): CapturedInteraction['pointerPosition'] {\n  if ('touches' in event && event.touches.length > 0) {\n    const [touch] = event.touches;\n    if (touch == null) return undefined;\n    return {\n      clientX: touch.clientX,\n      clientY: touch.clientY,\n    };\n  }\n\n  if ('clientX' in event) {\n    return {\n      clientX: event.clientX,\n      clientY: event.clientY,\n    };\n  }\n\n  return undefined;\n}\n\n/**\n * Creates event init options from a captured interaction.\n */\nfunction createEventInit(interaction: CapturedInteraction): EventInit {\n\n\n  return {\n    bubbles: true,\n    cancelable: true,\n    ...interaction.eventInit,\n  };\n}\n\n/**\n * Creates the appropriate event for replay.\n */\nfunction createReplayEvent(interaction: CapturedInteraction): Event {\n  switch (interaction.type) {\n    case 'click':\n      return new MouseEvent('click', {\n        ...createEventInit(interaction),\n        clientX: interaction.pointerPosition?.clientX ?? 0,\n        clientY: interaction.pointerPosition?.clientY ?? 0,\n      } as MouseEventInit);\n\n    case 'focus':\n      return new FocusEvent('focus', createEventInit(interaction));\n\n    case 'input':\n      return new InputEvent('input', {\n        ...createEventInit(interaction),\n        data: interaction.inputValue ?? '',\n        inputType: 'insertText',\n      } as InputEventInit);\n\n    case 'change':\n      return new Event('change', createEventInit(interaction));\n\n    case 'keydown':\n      return new KeyboardEvent('keydown', {\n        ...createEventInit(interaction),\n        ...interaction.keyInfo,\n      } as KeyboardEventInit);\n\n    case 'keyup':\n      return new KeyboardEvent('keyup', {\n        ...createEventInit(interaction),\n        ...interaction.keyInfo,\n      } as KeyboardEventInit);\n\n    case 'submit':\n      return new SubmitEvent('submit', createEventInit(interaction));\n\n    case 'touchstart':\n      return new TouchEvent('touchstart', createEventInit(interaction) as TouchEventInit);\n\n    case 'touchend':\n      return new TouchEvent('touchend', createEventInit(interaction) as TouchEventInit);\n\n    default:\n      return new Event(interaction.type, createEventInit(interaction));\n  }\n}\n\n// ============================================================================\n// Interaction Buffer Class\n// ============================================================================\n\n/**\n * Bounded buffer for storing captured interactions.\n * Automatically evicts old interactions based on time and size limits.\n */\nclass InteractionBuffer {\n  private readonly buffer: CapturedInteraction[] = [];\n  private readonly maxSize: number;\n  private readonly maxAge: number;\n\n  constructor(maxSize: number, maxAge: number) {\n    this.maxSize = maxSize;\n    this.maxAge = maxAge;\n  }\n\n  /**\n   * Returns the number of interactions in the buffer.\n   */\n  get size(): number {\n    return this.buffer.length;\n  }\n\n  /**\n   * Adds an interaction to the buffer.\n   */\n  push(interaction: CapturedInteraction): void {\n    // Remove stale interactions\n    this.evictStale();\n\n    // Remove oldest if at capacity\n    while (this.buffer.length >= this.maxSize) {\n      this.buffer.shift();\n    }\n\n    this.buffer.push(interaction);\n  }\n\n  /**\n   * Removes and returns all interactions from the buffer.\n   */\n  drain(): CapturedInteraction[] {\n    const interactions = [...this.buffer];\n    this.buffer.length = 0;\n    return interactions;\n  }\n\n  /**\n   * Checks if the buffer is empty.\n   */\n  isEmpty(): boolean {\n    return this.buffer.length === 0;\n  }\n\n  /**\n   * Clears all interactions from the buffer.\n   */\n  clear(): void {\n    this.buffer.length = 0;\n  }\n\n  /**\n   * Returns a copy of all interactions without removing them.\n   */\n  peek(): readonly CapturedInteraction[] {\n    return [...this.buffer];\n  }\n\n  /**\n   * Removes interactions older than maxAge.\n   */\n  private evictStale(): void {\n    const now = Date.now();\n    const cutoff = now - this.maxAge;\n\n    while (this.buffer.length > 0 && this.buffer[0] && this.buffer[0].capturedAt < cutoff) {\n      this.buffer.shift();\n    }\n  }\n}\n\n// ============================================================================\n// Interaction Replay Manager\n// ============================================================================\n\n/**\n * Manages interaction capture and replay for hydration boundaries.\n *\n * @example\n * ```typescript\n * const replayManager = new InteractionReplayManager();\n *\n * // Start capturing for a boundary\n * replayManager.startCapture('boundary-1', containerElement);\n *\n * // ... user interacts with the component ...\n *\n * // After hydration, replay interactions\n * await replayManager.replayInteractions('boundary-1');\n * ```\n */\nexport class InteractionReplayManager {\n  /** Configuration */\n  private readonly config: InteractionReplayConfig;\n\n  /** Buffers per boundary */\n  private readonly buffers = new Map<HydrationBoundaryId, InteractionBuffer>();\n\n  /** Active event listeners per boundary */\n  private readonly listeners = new Map<\n    HydrationBoundaryId,\n    Map<ReplayableInteractionType, (e: Event) => void>\n  >();\n\n  /** Container elements per boundary */\n  private readonly containers = new Map<HydrationBoundaryId, HTMLElement>();\n\n  /** Debug mode */\n  private readonly debug: boolean;\n\n  /**\n   * Creates a new InteractionReplayManager.\n   *\n   * @param config - Replay configuration\n   * @param debug - Enable debug logging\n   */\n  constructor(config: Partial<InteractionReplayConfig> = {}, debug = false) {\n    this.config = {\n      ...DEFAULT_REPLAY_CONFIG,\n      ...config,\n    };\n    this.debug = debug;\n  }\n\n  // ==========================================================================\n  // Capture API\n  // ==========================================================================\n\n  /**\n   * Starts capturing interactions for a hydration boundary.\n   *\n   * @param boundaryId - ID of the hydration boundary\n   * @param container - Container element to capture events from\n   */\n  startCapture(boundaryId: HydrationBoundaryId, container: HTMLElement): void {\n    // Clean up any existing capture\n    this.stopCapture(boundaryId);\n\n    // Create buffer\n    const buffer = new InteractionBuffer(\n      this.config.maxBufferSize,\n      this.config.maxBufferTime\n    );\n    this.buffers.set(boundaryId, buffer);\n    this.containers.set(boundaryId, container);\n\n    // Create event listeners\n    const listenerMap = new Map<ReplayableInteractionType, (e: Event) => void>();\n\n    for (const eventType of this.config.captureTypes) {\n      const listener = this.createCaptureListener(boundaryId, eventType);\n      listenerMap.set(eventType, listener);\n      container.addEventListener(eventType, listener, { capture: true, passive: false });\n    }\n\n    this.listeners.set(boundaryId, listenerMap);\n\n    // Add capture indicator if configured\n    if (this.config.showCaptureIndicator) {\n      container.classList.add('hydration-capture-active');\n    }\n\n    this.log(`Started capture for boundary: ${boundaryId}`);\n  }\n\n  /**\n   * Stops capturing interactions for a hydration boundary.\n   *\n   * @param boundaryId - ID of the hydration boundary\n   */\n  stopCapture(boundaryId: HydrationBoundaryId): void {\n    const container = this.containers.get(boundaryId);\n    const listenerMap = this.listeners.get(boundaryId);\n\n    if (container && listenerMap) {\n      for (const [eventType, listener] of listenerMap) {\n        container.removeEventListener(eventType, listener, { capture: true });\n      }\n\n      if (this.config.showCaptureIndicator) {\n        container.classList.remove('hydration-capture-active');\n      }\n    }\n\n    this.listeners.delete(boundaryId);\n    this.containers.delete(boundaryId);\n\n    this.log(`Stopped capture for boundary: ${boundaryId}`);\n  }\n\n  /**\n   * Replays all captured interactions for a boundary.\n   *\n   * @param boundaryId - ID of the hydration boundary\n   * @returns Number of interactions replayed\n   */\n  async replayInteractions(boundaryId: HydrationBoundaryId): Promise<number> {\n    // Stop capturing first\n    this.stopCapture(boundaryId);\n\n    // Get and clear buffer\n    const buffer = this.buffers.get(boundaryId);\n    if (!buffer || buffer.isEmpty()) {\n      this.buffers.delete(boundaryId);\n      return 0;\n    }\n\n    const interactions = buffer.drain();\n    this.buffers.delete(boundaryId);\n\n    this.log(`Replaying ${interactions.length} interactions for boundary: ${boundaryId}`);\n\n    // Replay each interaction with delay\n    let replayed = 0;\n\n    for (const interaction of interactions) {\n      const success = this.replayInteraction(interaction);\n      if (success) {\n        replayed++;\n      }\n\n      // Small delay between replays to allow DOM updates\n      if (this.config.replayDelay > 0) {\n        await new Promise((resolve) => setTimeout(resolve, this.config.replayDelay));\n      }\n    }\n\n    this.log(`Replayed ${replayed}/${interactions.length} interactions for boundary: ${boundaryId}`);\n\n    return replayed;\n  }\n\n  /**\n   * Returns the number of captured interactions for a boundary.\n   *\n   * @param boundaryId - ID of the hydration boundary\n   * @returns Number of captured interactions\n   */\n  getCapturedCount(boundaryId: HydrationBoundaryId): number {\n    const buffer = this.buffers.get(boundaryId);\n    return buffer?.size ?? 0;\n  }\n\n  // ==========================================================================\n  // Replay API\n  // ==========================================================================\n\n  /**\n   * Returns all captured interactions for a boundary without removing them.\n   *\n   * @param boundaryId - ID of the hydration boundary\n   * @returns Array of captured interactions\n   */\n  peekCaptured(boundaryId: HydrationBoundaryId): readonly CapturedInteraction[] {\n    const buffer = this.buffers.get(boundaryId);\n    return buffer?.peek() ?? [];\n  }\n\n  /**\n   * Checks if a boundary has any captured interactions.\n   *\n   * @param boundaryId - ID of the hydration boundary\n   * @returns true if there are captured interactions\n   */\n  hasCaptured(boundaryId: HydrationBoundaryId): boolean {\n    const buffer = this.buffers.get(boundaryId);\n    return buffer ? !buffer.isEmpty() : false;\n  }\n\n  // ==========================================================================\n  // Query API\n  // ==========================================================================\n\n  /**\n   * Checks if a boundary is currently capturing interactions.\n   *\n   * @param boundaryId - ID of the hydration boundary\n   * @returns true if capture is active\n   */\n  isCapturing(boundaryId: HydrationBoundaryId): boolean {\n    return this.listeners.has(boundaryId);\n  }\n\n  /**\n   * Clears all captured interactions for a boundary without replaying.\n   *\n   * @param boundaryId - ID of the hydration boundary\n   */\n  clearCaptured(boundaryId: HydrationBoundaryId): void {\n    this.stopCapture(boundaryId);\n    this.buffers.delete(boundaryId);\n  }\n\n  /**\n   * Cleans up all resources.\n   * Call this when unmounting the hydration system.\n   */\n  dispose(): void {\n    // Stop all captures\n    for (const boundaryId of this.listeners.keys()) {\n      this.stopCapture(boundaryId);\n    }\n\n    // Clear all buffers\n    this.buffers.clear();\n    this.containers.clear();\n\n    this.log('InteractionReplayManager disposed');\n  }\n\n  /**\n   * Creates a capture listener for a specific event type.\n   */\n  private createCaptureListener(\n    boundaryId: HydrationBoundaryId,\n    eventType: ReplayableInteractionType\n  ): (e: Event) => void {\n    return (event: Event) => {\n      const target = event.target as Element | null;\n\n      if (!target) {\n        return;\n      }\n\n      // Capture the interaction\n      const interaction = this.captureInteraction(event, target, eventType);\n\n      // Store in buffer\n      const buffer = this.buffers.get(boundaryId);\n      if (buffer) {\n        buffer.push(interaction);\n        this.log(`Captured ${eventType} for boundary: ${boundaryId}`);\n      }\n\n      // Optionally prevent default\n      if (this.config.preventDefaultDuringCapture && event.cancelable) {\n        event.preventDefault();\n        event.stopPropagation();\n      }\n    };\n  }\n\n  // ==========================================================================\n  // Cleanup API\n  // ==========================================================================\n\n  /**\n   * Captures details of an interaction.\n   */\n  private captureInteraction(\n    event: Event,\n    target: Element,\n    type: ReplayableInteractionType\n  ): CapturedInteraction {\n    const interaction: CapturedInteraction = {\n      id: generateInteractionId(),\n      type,\n      targetSelector: generateSelector(target),\n      eventInit: {\n        bubbles: event.bubbles,\n        cancelable: event.cancelable,\n        composed: event.composed,\n      },\n      capturedAt: Date.now(),\n    };\n\n    // Add type-specific data\n    if (type === 'input' || type === 'change') {\n      if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {\n        return {\n          ...interaction,\n          inputValue: target.value,\n        };\n      }\n    }\n\n    if (type === 'keydown' || type === 'keyup') {\n      return {\n        ...interaction,\n        keyInfo: extractKeyInfo(event as KeyboardEvent),\n      };\n    }\n\n    if (type === 'click' || type === 'touchstart' || type === 'touchend') {\n      return {\n        ...interaction,\n        pointerPosition: extractPointerPosition(event as MouseEvent | TouchEvent),\n      };\n    }\n\n    return interaction;\n  }\n\n  /**\n   * Replays a single interaction.\n   */\n  private replayInteraction(interaction: CapturedInteraction): boolean {\n    try {\n      // Find target element\n      const target = document.querySelector(interaction.targetSelector);\n\n      if (target == null) {\n        this.log(`Target not found for replay: ${interaction.targetSelector}`, 'warn');\n        return false;\n      }\n\n      // Handle special cases\n      if (interaction.type === 'focus') {\n        if (target instanceof HTMLElement) {\n          target.focus();\n          return true;\n        }\n        return false;\n      }\n\n      if (interaction.type === 'input' && interaction.inputValue !== undefined) {\n        if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {\n          // Set value directly and dispatch event\n          target.value = interaction.inputValue;\n          target.dispatchEvent(createReplayEvent(interaction));\n          return true;\n        }\n      }\n\n      // Dispatch synthetic event\n      const event = createReplayEvent(interaction);\n      target.dispatchEvent(event);\n\n      return true;\n    } catch (error) {\n      this.log(`Failed to replay interaction: ${String(error)}`, 'error');\n      return false;\n    }\n  }\n\n  // ==========================================================================\n  // Internal\n  // ==========================================================================\n\n  /**\n   * Debug logging helper.\n   */\n  private log(message: string, level: 'log' | 'warn' | 'error' = 'log'): void {\n    if (this.debug) {\n      let logger: typeof console.log;\n      if (level === 'error') {\n        logger = console.error;\n      } else if (level === 'warn') {\n        logger = console.warn;\n      } else {\n        logger = console.info;\n      }\n      logger(`[InteractionReplay] ${message}`);\n    }\n  }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet replayManagerInstance: InteractionReplayManager | null = null;\n\n/**\n * Gets or creates the global InteractionReplayManager instance.\n *\n * @param config - Replay configuration (only used if creating new instance)\n * @param debug - Enable debug logging\n * @returns The global InteractionReplayManager instance\n */\nexport function getInteractionReplayManager(\n  config?: Partial<InteractionReplayConfig>,\n  debug = false\n): InteractionReplayManager {\n  replayManagerInstance ??= new InteractionReplayManager(config, debug);\n  return replayManagerInstance;\n}\n\n/**\n * Resets the global InteractionReplayManager instance.\n * Primarily useful for testing.\n */\nexport function resetInteractionReplayManager(): void {\n  if (replayManagerInstance) {\n    replayManagerInstance.dispose();\n    replayManagerInstance = null;\n  }\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport type {\n  CapturedInteraction,\n  ReplayableInteractionType,\n  InteractionReplayConfig,\n};\n"],"names":["generateInteractionId","generateSelector","element","testId","hydrationTarget","path","current","selector","classes","parent","currentTagName","siblings","child","index","extractKeyInfo","event","extractPointerPosition","touch","createEventInit","interaction","createReplayEvent","InteractionBuffer","maxSize","maxAge","interactions","cutoff","InteractionReplayManager","config","debug","DEFAULT_REPLAY_CONFIG","boundaryId","container","buffer","listenerMap","eventType","listener","replayed","resolve","target","type","error","message","level","logger","replayManagerInstance","getInteractionReplayManager","resetInteractionReplayManager"],"mappings":"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"}