{"version":3,"file":"index.cjs","sources":["../src/ProximityPrefetch.vue","../src/vite-plugin.ts","../src/index.ts"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * ProximityPrefetch Component\n * \n * This component tracks mouse movements and prefetches routes when the cursor\n * approaches links, improving perceived navigation speed.\n */\nimport { ref, onMounted, onUnmounted, watch, computed } from 'vue';\nimport { useRouter } from 'vue-router';\n\n// Étendre l'interface Window pour inclure notre propriété PPF_DEBUG\ndeclare global {\n  interface Window {\n    PPF_DEBUG?: boolean;\n  }\n}\n\n/**\n * Component props interface\n */\ninterface Props {\n  /** Distance threshold in pixels to trigger prefetching */\n  threshold?: number;\n  /** Interval for periodic checks in milliseconds (0 means reactive to mouse movements) */\n  predictionInterval?: number;\n  /** Enable debug logging */\n  debug?: boolean;\n  /** Enable mobile support with viewport-based prefetching */\n  mobileSupport?: boolean;\n  /** Viewport margin for mobile prefetching */\n  viewportMargin?: number;\n  /** Enable prefetching of all links on the page at once */\n  prefetchAllLinks?: boolean;\n  /** Delay before starting to prefetch all links (ms) */\n  prefetchAllLinksDelay?: number;\n}\n\n// Check if PPF_DEBUG environment variable is set\nconst PPF_DEBUG = typeof window !== 'undefined' && window.PPF_DEBUG === true;\n\n// Default prop values\nconst props = withDefaults(defineProps<Props>(), {\n  threshold: 200,\n  predictionInterval: 0,\n  debug: false, // Debug disabled by default in production\n  mobileSupport: true,\n  viewportMargin: 300,\n  prefetchAllLinks: false,\n  prefetchAllLinksDelay: 1500\n});\n\n// Determine if debug mode is enabled (either from props or PPF_DEBUG global)\nconst isDebugEnabled = computed(() => props.debug || PPF_DEBUG);\n\n// Router access for prefetching\nconst router = useRouter();\n\n// Track mouse position\nconst mousePosition = ref({ x: 0, y: 0 });\n\n// Store already prefetched routes to avoid duplication\nconst prefetchedRoutes = ref<Set<string>>(new Set());\n\n// Store link elements with their position data\nconst links = ref<Array<{ el: HTMLAnchorElement; href: string; rect: DOMRect }>>([]);\n\n// Track if mouse is near any link\nconst isMouseNearLink = ref(false);\n\n// Last time proximity was checked (for throttling)\nconst lastProximityCheck = ref(Date.now());\n\n// Minimum interval between proximity checks (ms)\nconst THROTTLE_INTERVAL = 100;\n\n// Detect if we're on a touch device\nconst isTouchDevice = ref(false);\n\n/**\n * Detect touch devices\n */\nconst detectTouchDevice = (): boolean => {\n  return (\n    typeof window !== 'undefined' && \n    (('ontouchstart' in window) || \n     (navigator.maxTouchPoints > 0) || \n     (navigator.msMaxTouchPoints > 0))\n  );\n};\n\n/**\n * Scan the DOM and update the list of tracked links\n */\nconst updateLinks = () => {\n  // Get all anchor elements with href attribute\n  const anchors = Array.from(\n    document.querySelectorAll('a[href]')\n  ) as HTMLAnchorElement[];\n  \n  if (isDebugEnabled.value) {\n    console.debug(`[ProximityPrefetch] Found ${anchors.length} links in the page`);\n  }\n  \n  // Filter and process valid internal links\n  links.value = anchors\n    .map((el) => {\n      const href = el.getAttribute('href');\n      \n      // Only include internal links (starting with / or without ://) and not anchor links\n      if (href && (href.startsWith('/') || !href.includes('://')) && !href.startsWith('#')) {\n        const rect = el.getBoundingClientRect();\n        \n        if (isDebugEnabled.value) {\n          console.debug(`[ProximityPrefetch] Link found: ${href}, rect:`, rect);\n        }\n        \n        return {\n          el,\n          href,\n          rect\n        };\n      }\n      return null;\n    })\n    .filter((link): link is { el: HTMLAnchorElement; href: string; rect: DOMRect } => link !== null);\n};\n\n/**\n * Calculate Euclidean distance between two points\n */\nconst calculateDistance = (x1: number, y1: number, x2: number, y2: number): number => {\n  return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);\n};\n\n/**\n * Calculate the center point of a DOMRect\n */\nconst calculateCenterPoint = (rect: DOMRect): { x: number, y: number } => {\n  return {\n    x: rect.left + rect.width / 2,\n    y: rect.top + rect.height / 2\n  };\n};\n\n/**\n * Check if a link is in or near the viewport\n */\nconst isLinkInViewport = (rect: DOMRect): boolean => {\n  return (\n    rect.top >= -props.viewportMargin &&\n    rect.left >= -props.viewportMargin &&\n    rect.bottom <= window.innerHeight + props.viewportMargin &&\n    rect.right <= window.innerWidth + props.viewportMargin\n  );\n};\n\n/**\n * Check if mouse is within threshold distance of any link\n * @returns boolean indicating if mouse is near any link\n */\nconst checkProximity = (): boolean => {\n  if (!links.value.length) {\n    return false;\n  }\n  \n  // Update link rectangles to account for layout changes\n  links.value.forEach(link => {\n    link.rect = link.el.getBoundingClientRect();\n  });\n  \n  // Calculate distance between mouse and each link\n  const linksWithDistance = links.value.map((link) => {\n    const center = calculateCenterPoint(link.rect);\n    const distance = calculateDistance(\n      mousePosition.value.x,\n      mousePosition.value.y,\n      center.x,\n      center.y\n    );\n    return { ...link, distance };\n  });\n  \n  // Find links within threshold distance\n  const closestLinks = linksWithDistance.filter(\n    (link) => link.distance < props.threshold\n  );\n  \n  if (isDebugEnabled.value && closestLinks.length > 0) {\n    console.debug(`[ProximityPrefetch] ${closestLinks.length} links within threshold ${props.threshold}px`);\n    closestLinks.forEach(link => {\n      console.debug(`[ProximityPrefetch] Link: ${link.href}, Distance: ${link.distance.toFixed(2)}px`);\n    });\n  }\n  \n  return closestLinks.length > 0;\n};\n\n/**\n * Check which links are in or near the viewport (for mobile)\n * @returns boolean indicating if there are links in the viewport\n */\nconst checkViewportLinks = (): boolean => {\n  if (!links.value.length) {\n    return false;\n  }\n  \n  // Update link rectangles to account for layout changes\n  links.value.forEach(link => {\n    link.rect = link.el.getBoundingClientRect();\n  });\n  \n  // Find links within viewport (plus margin)\n  const visibleLinks = links.value.filter(link => isLinkInViewport(link.rect));\n  \n  if (isDebugEnabled.value && visibleLinks.length > 0) {\n    console.debug(`[ProximityPrefetch] ${visibleLinks.length} links in viewport (plus margin ${props.viewportMargin}px)`);\n  }\n  \n  return visibleLinks.length > 0;\n};\n\n/**\n * Prefetch routes for nearby links\n */\nconst prefetchNearbyRoutes = (): void => {\n  // Apply throttling to limit frequency of checks\n  const now = Date.now();\n  if (now - lastProximityCheck.value < THROTTLE_INTERVAL) {\n    return;\n  }\n  lastProximityCheck.value = now;\n  \n  // Choose detection strategy based on device type\n  let hasNearbyLinks;\n  \n  if (isTouchDevice.value && props.mobileSupport) {\n    // Mobile: viewport-based detection\n    hasNearbyLinks = checkViewportLinks();\n  } else {\n    // Desktop: mouse proximity detection\n    hasNearbyLinks = checkProximity();\n  }\n  \n  isMouseNearLink.value = hasNearbyLinks;\n  \n  // Exit early if no links are nearby\n  if (!hasNearbyLinks || !links.value.length) {\n    return;\n  }\n  \n  // Update link rectangles to account for layout changes\n  links.value.forEach(link => {\n    link.rect = link.el.getBoundingClientRect();\n  });\n  \n  let linksToProcess;\n  \n  if (isTouchDevice.value && props.mobileSupport) {\n    // For mobile: Get links in viewport\n    linksToProcess = links.value.filter(link => isLinkInViewport(link.rect));\n    // Sort by vertical position (links at the top first)\n    linksToProcess.sort((a, b) => a.rect.top - b.rect.top);\n  } else {\n    // For desktop: Calculate distances to find closest links\n    const linksWithDistance = links.value.map((link) => {\n      const center = calculateCenterPoint(link.rect);\n      const distance = calculateDistance(\n        mousePosition.value.x,\n        mousePosition.value.y,\n        center.x,\n        center.y\n      );\n      return { ...link, distance };\n    });\n\n    // Sort by distance (closest first)\n    linksWithDistance.sort((a, b) => a.distance - b.distance);\n\n    // Filter for links within threshold\n    linksToProcess = linksWithDistance\n      .filter((link) => link.distance < props.threshold)\n      .map(({ el, href, rect }) => ({ el, href, rect })); // Strip the distance property\n  }\n  \n  // Get routes to prefetch\n  const routesToPrefetch = linksToProcess.map((link) => link.href);\n\n  // Limit to 3 routes at a time to avoid excessive prefetching\n  const MAX_PREFETCH = 3;\n  for (const route of routesToPrefetch.slice(0, MAX_PREFETCH)) {\n    // Skip already prefetched routes\n    if (prefetchedRoutes.value.has(route)) {\n      continue;\n    }\n    \n    if (isDebugEnabled.value) {\n      console.log('[ProximityPrefetch] Prefetching:', route);\n    }\n    \n    try {\n      // Resolve the route to get corresponding route records\n      const resolved = router.resolve(route);\n      \n      // Trigger navigation to prefetch route components without actually navigating\n      router.getRoutes().forEach(routeRecord => {\n        if (routeRecord.path === resolved.path && routeRecord.components) {\n          // Load components without navigating\n          const comps = routeRecord.components;\n          Object.values(comps).forEach(comp => {\n            // Use a safer approach with explicit type casting\n            const asyncComp = comp as any;\n            \n            if (typeof asyncComp === 'function') {\n              try {\n                // Call component to trigger loading\n                asyncComp();\n              } catch (e) {\n                if (isDebugEnabled.value) {\n                  console.error('[ProximityPrefetch] Error loading component:', e);\n                }\n              }\n            }\n          });\n        }\n      });\n      \n      // Mark as prefetched to avoid duplicate prefetching\n      prefetchedRoutes.value.add(route);\n      \n      // Add visual indicator for prefetched links in debug mode\n      if (isDebugEnabled.value) {\n        // Find all link elements pointing to this route\n        const matchingAnchors = Array.from(\n          document.querySelectorAll(`a[href=\"${route}\"]`)\n        ) as HTMLAnchorElement[];\n        \n        matchingAnchors.forEach(anchor => {\n          // Add a red border directly to the link element if not already applied\n          if (!anchor.hasAttribute('data-ppf-debug-applied')) {\n            anchor.setAttribute('data-ppf-debug-applied', 'true');\n            anchor.classList.add('ppf-debug-highlight');\n            anchor.title = `Prefetched: ${route}`;\n          }\n        });\n      }\n    } catch (err) {\n      if (isDebugEnabled.value) {\n        console.error('[ProximityPrefetch] Error prefetching route:', err);\n      }\n    }\n  }\n};\n\n/**\n * Prefetch a single route\n */\nconst prefetchRoute = (route: string): void => {\n  // Skip already prefetched routes\n  if (prefetchedRoutes.value.has(route)) {\n    return;\n  }\n  \n  if (isDebugEnabled.value) {\n    console.log('[ProximityPrefetch] Prefetching:', route);\n  }\n  \n  try {\n    // Resolve the route to get corresponding route records\n    const resolved = router.resolve(route);\n    \n    // Trigger navigation to prefetch route components without actually navigating\n    router.getRoutes().forEach(routeRecord => {\n      if (routeRecord.path === resolved.path && routeRecord.components) {\n        // Load components without navigating\n        const comps = routeRecord.components;\n        Object.values(comps).forEach(comp => {\n          // Use a safer approach with explicit type casting\n          const asyncComp = comp as any;\n          \n          if (typeof asyncComp === 'function') {\n            try {\n              // Call component to trigger loading\n              asyncComp();\n            } catch (e) {\n              if (isDebugEnabled.value) {\n                console.error('[ProximityPrefetch] Error loading component:', e);\n              }\n            }\n          }\n        });\n      }\n    });\n    \n    // Mark as prefetched to avoid duplicate prefetching\n    prefetchedRoutes.value.add(route);\n    \n    // Add visual indicator for prefetched links in debug mode\n    if (isDebugEnabled.value) {\n      // Find all link elements pointing to this route\n      const matchingAnchors = Array.from(\n        document.querySelectorAll(`a[href=\"${route}\"]`)\n      ) as HTMLAnchorElement[];\n      \n      matchingAnchors.forEach(anchor => {\n        // Add a red border directly to the link element if not already applied\n        if (!anchor.hasAttribute('data-ppf-debug-applied')) {\n          anchor.setAttribute('data-ppf-debug-applied', 'true');\n          anchor.classList.add('ppf-debug-highlight');\n          anchor.title = `Prefetched: ${route}`;\n        }\n      });\n    }\n  } catch (err) {\n    if (isDebugEnabled.value) {\n      console.error('[ProximityPrefetch] Error prefetching route:', err);\n    }\n  }\n};\n\n/**\n * Prefetch all links on the page\n */\nconst prefetchAllPageLinks = (): void => {\n  updateLinks();\n  \n  if (!links.value.length) {\n    if (isDebugEnabled.value) {\n      console.log('[ProximityPrefetch] No links found to prefetch');\n    }\n    return;\n  }\n  \n  if (isDebugEnabled.value) {\n    console.log(`[ProximityPrefetch] Prefetching all links: ${links.value.length} links found`);\n  }\n  \n  // Get unique routes\n  const uniqueRoutes = [...new Set(links.value.map(link => link.href))];\n  \n  if (isDebugEnabled.value) {\n    console.log(`[ProximityPrefetch] Unique routes to prefetch: ${uniqueRoutes.length}`);\n  }\n  \n  // Batch prefetching with small delays to avoid network congestion\n  let processed = 0;\n  const batchSize = 3;\n  const batchDelay = 300;\n  \n  const processBatch = () => {\n    const batch = uniqueRoutes.slice(processed, processed + batchSize);\n    if (batch.length === 0) return;\n    \n    for (const route of batch) {\n      prefetchRoute(route);\n    }\n    \n    processed += batch.length;\n    \n    if (processed < uniqueRoutes.length) {\n      setTimeout(processBatch, batchDelay);\n    } else if (isDebugEnabled.value) {\n      console.log(`[ProximityPrefetch] Finished prefetching all links: ${processed} routes prefetched`);\n    }\n  };\n  \n  processBatch();\n};\n\n/**\n * Handle mouse movement events\n */\nconst handleMouseMove = (e: MouseEvent): void => {\n  mousePosition.value = { x: e.clientX, y: e.clientY };\n};\n\n/**\n * Handle scroll events (for mobile)\n */\nconst handleScroll = (): void => {\n  if (isTouchDevice.value && props.mobileSupport) {\n    const now = Date.now();\n    if (now - lastProximityCheck.value >= THROTTLE_INTERVAL) {\n      prefetchNearbyRoutes();\n    }\n  }\n};\n\n/**\n * Handle touch events (for mobile)\n */\nconst handleTouch = (): void => {\n  if (isTouchDevice.value && props.mobileSupport) {\n    prefetchNearbyRoutes();\n  }\n};\n\n// Register event listeners based on device type\nonMounted(() => {\n  // Detect device type\n  isTouchDevice.value = detectTouchDevice();\n  \n  if (isDebugEnabled.value) {\n    console.log('[ProximityPrefetch] Component mounted with options:', {\n      threshold: props.threshold,\n      predictionInterval: props.predictionInterval,\n      debug: isDebugEnabled.value,\n      mobileSupport: props.mobileSupport,\n      viewportMargin: props.viewportMargin,\n      deviceType: isTouchDevice.value ? 'Touch device' : 'Desktop device'\n    });\n    \n    // Add debug styles for the visual indicators\n    const style = document.createElement('style');\n    style.textContent = `\n      .ppf-debug-highlight {\n        border: 2px solid red !important;\n        box-sizing: border-box;\n      }\n    `;\n    document.head.appendChild(style);\n  }\n  \n  // Scan for links after a short delay to ensure DOM is fully loaded\n  setTimeout(() => {\n    updateLinks();\n    if (isDebugEnabled.value) {\n      console.log(`[ProximityPrefetch] Initial links detection: ${links.value.length} links found`);\n    }\n\n    // Initial prefetch on load (particularly important for mobile)\n    prefetchNearbyRoutes();\n  }, 500);\n\n  // Set up MutationObserver to detect new links or changes to existing ones\n  const observer = new MutationObserver(() => {\n    updateLinks();\n  });\n\n  // Start observing DOM changes\n  observer.observe(document.body, {\n    childList: true,  // Watch for added/removed nodes\n    subtree: true,    // Include descendants\n    attributes: true, // Watch for attribute changes\n    attributeFilter: ['href'] // Only care about href changes\n  });\n\n  // Configure event listeners based on device type\n  if (isTouchDevice.value && props.mobileSupport) {\n    // Mobile: use scroll and touch events\n    window.addEventListener('scroll', handleScroll, { passive: true });\n    window.addEventListener('touchstart', handleTouch, { passive: true });\n    window.addEventListener('resize', handleScroll, { passive: true });\n    \n    if (isDebugEnabled.value) {\n      console.log('[ProximityPrefetch] Mobile mode initialized with viewport margin:', props.viewportMargin + 'px');\n    }\n  } else {\n    // Desktop: use mouse events\n    window.addEventListener('mousemove', handleMouseMove);\n    \n    if (isDebugEnabled.value) {\n      console.log('[ProximityPrefetch] Desktop mode initialized');\n    }\n  }\n\n  /**\n   * Configure prefetching system based on parameters\n   */\n  let intervalId: number | undefined;\n\n  // Two prefetching modes:\n  if (props.predictionInterval > 0) {\n    // 1. Interval mode: periodic checking\n    intervalId = window.setInterval(() => {\n      // Only check if mouse has moved (avoid unnecessary checks) for desktop\n      // or always check for mobile\n      if (isTouchDevice.value || mousePosition.value.x !== 0 || mousePosition.value.y !== 0) {\n        prefetchNearbyRoutes();\n      }\n    }, props.predictionInterval);\n  } else if (!isTouchDevice.value) {\n    // 2. Reactive mode: check on mouse movements with throttling (desktop only)\n    const throttledPrefetch = (): void => {\n      const now = Date.now();\n      if (now - lastProximityCheck.value >= THROTTLE_INTERVAL) {\n        prefetchNearbyRoutes();\n      }\n    };\n    \n    // Watch for mouse position changes\n    watch(mousePosition, () => {\n      throttledPrefetch();\n    });\n  }\n\n  // Prefetch all links if enabled\n  if (props.prefetchAllLinks) {\n    setTimeout(() => {\n      prefetchAllPageLinks();\n    }, props.prefetchAllLinksDelay);\n  }\n\n  // Clean up event listeners and observers on component unmount\n  onUnmounted(() => {\n    if (isTouchDevice.value && props.mobileSupport) {\n      window.removeEventListener('scroll', handleScroll);\n      window.removeEventListener('touchstart', handleTouch);\n      window.removeEventListener('resize', handleScroll);\n    } else {\n      window.removeEventListener('mousemove', handleMouseMove);\n    }\n    \n    observer.disconnect();\n    if (intervalId) {\n      window.clearInterval(intervalId);\n    }\n  });\n});\n</script>\n\n<template>\n  <!-- This component doesn't render anything visually -->\n  <!-- It acts as a functionality wrapper that can be placed anywhere in your app -->\n  <slot></slot>\n</template>","/**\n * Vue Proximity Prefetch - Vite Plugin\n * \n * This plugin enhances Vue Router applications by adding proximity-based prefetching\n * capabilities, improving user experience through faster route transitions.\n */\n\nimport type { Plugin } from 'vite';\n\n/**\n * Configuration options for the Vue Proximity Prefetch plugin\n */\nexport interface VueProximityPrefetchOptions {\n  /**\n   * Distance threshold in pixels that triggers prefetching when the cursor\n   * approaches a link element\n   * @default 200\n   */\n  threshold?: number;\n  \n  /**\n   * Interval for periodic prediction checks (in milliseconds)\n   * When set to 0, checks are triggered by mouse movements\n   * @default 0\n   */\n  predictionInterval?: number;\n  \n  /**\n   * Maximum number of routes to prefetch simultaneously\n   * Limits resource usage while still enhancing perceived performance\n   * @default 3\n   */\n  maxPrefetch?: number;\n  \n  /**\n   * Enable debug logging in the console\n   * Useful for development and troubleshooting\n   * @default false\n   */\n  debug?: boolean;\n\n  /**\n   * Enable automatic prefetching without needing to add the Vue component\n   * When true, a global script is injected that handles prefetching for all routes\n   * @default false\n   */\n  automaticPrefetch?: boolean;\n  \n  /**\n   * Enable mobile support for touch devices\n   * When true, touch events and viewport-based prefetching are enabled\n   * @default true\n   */\n  mobileSupport?: boolean;\n  \n  /**\n   * Viewport margin (in pixels) for prefetching on mobile\n   * Links that are within this distance from the viewport will be prefetched\n   * @default 300\n   */\n  viewportMargin?: number;\n  \n  /**\n   * Enable prefetching of all links on the page at once\n   * When true, all internal links will be prefetched after page load\n   * @default false\n   */\n  prefetchAllLinks?: boolean;\n  \n  /**\n   * Delay (in milliseconds) before starting to prefetch all links\n   * Only used when prefetchAllLinks is true\n   * @default 1500\n   */\n  prefetchAllLinksDelay?: number;\n}\n\n/**\n * Default configuration values\n */\nconst DEFAULT_OPTIONS: Required<VueProximityPrefetchOptions> = {\n  threshold: 200,\n  predictionInterval: 0,\n  maxPrefetch: 3,\n  debug: false,\n  automaticPrefetch: false,\n  mobileSupport: true,\n  viewportMargin: 300,\n  prefetchAllLinks: false,\n  prefetchAllLinksDelay: 1500\n};\n\n/**\n * Generate the prefetch script to be injected in the page\n */\nfunction generatePrefetchScript(options: Required<VueProximityPrefetchOptions>): string {\n  return `\n  <!-- Injected by Vue Proximity Prefetch Plugin -->\n  <script>\n    (function() {\n      // Set global PPF_DEBUG flag for the Vue component to detect\n      window.PPF_DEBUG = ${options.debug};\n      \n      // Configuration from Vite plugin\n      const config = {\n        threshold: ${options.threshold},\n        predictionInterval: ${options.predictionInterval},\n        maxPrefetch: ${options.maxPrefetch},\n        debug: ${options.debug} || (typeof window !== 'undefined' && window.PPF_DEBUG === true),\n        mobileSupport: ${options.mobileSupport},\n        viewportMargin: ${options.viewportMargin},\n        prefetchAllLinks: ${options.prefetchAllLinks},\n        prefetchAllLinksDelay: ${options.prefetchAllLinksDelay}\n      };\n      \n      // Utils\n      const log = config.debug ? console.log.bind(console, '[ProximityPrefetch]') : () => {};\n      log('Automatic prefetching enabled with options:', config);\n      \n      // State variables\n      let mousePosition = { x: 0, y: 0 };\n      let prefetchedRoutes = new Set();\n      let lastCheck = Date.now();\n      const THROTTLE_INTERVAL = 100;\n      \n      // Device detection\n      let isTouchDevice = false;\n      \n      // Detect touch devices\n      function detectTouchDevice() {\n        return (('ontouchstart' in window) || \n                (navigator.maxTouchPoints > 0) || \n                (navigator.msMaxTouchPoints > 0));\n      }\n      \n      // Calculate Euclidean distance between two points\n      function calculateDistance(x1, y1, x2, y2) {\n        return Math.sqrt((x2 - x1) ** 2 + (y1 - y2) ** 2);\n      }\n      \n      // Calculate center point of a DOMRect\n      function calculateCenterPoint(rect) {\n        return {\n          x: rect.left + rect.width / 2,\n          y: rect.top + rect.height / 2\n        };\n      }\n      \n      // Get all valid links on the page\n      function getLinks() {\n        const anchors = Array.from(document.querySelectorAll('a[href]'));\n        return anchors\n          .map((el) => {\n            const href = el.getAttribute('href');\n            // Only include internal links (starting with / or without ://) and not anchor links\n            if (href && (href.startsWith('/') || !href.includes('://')) && !href.startsWith('#')) {\n              const rect = el.getBoundingClientRect();\n              return { el, href, rect };\n            }\n            return null;\n          })\n          .filter(link => link !== null);\n      }\n      \n      // Prefetch a single route\n      function prefetchRoute(route) {\n        if (prefetchedRoutes.has(route)) return;\n        \n        try {\n          // Create a prefetch link element\n          const link = document.createElement('link');\n          link.rel = 'prefetch';\n          link.href = route;\n          link.as = 'document';\n          document.head.appendChild(link);\n          \n          prefetchedRoutes.add(route);\n          \n          // In debug mode, add a visual indicator around the link\n          if (config.debug) {\n            // Find all link elements pointing to this route\n            const matchingAnchors = Array.from(document.querySelectorAll('a[href=\"' + route + '\"]'));\n            \n            matchingAnchors.forEach(anchor => {\n              // Add a red border directly to the link element if not already applied\n              if (!anchor.hasAttribute('data-ppf-debug-applied')) {\n                anchor.setAttribute('data-ppf-debug-applied', 'true');\n                anchor.classList.add('ppf-debug-highlight');\n                anchor.title = 'Prefetched: ' + route;\n              }\n            });\n          }\n          \n          return true;\n        } catch (err) {\n          console.error('[ProximityPrefetch] Error prefetching route:', route, err);\n          return false;\n        }\n      }\n      \n      // Prefetch all links on the page\n      function prefetchAllPageLinks() {\n        const links = getLinks();\n        if (!links.length) return;\n        \n        log('Prefetching all links on page: ' + links.length + ' links found');\n        \n        // Get unique routes\n        const uniqueRoutes = [...new Set(links.map(link => link.href))];\n        \n        // Batch prefetching with small delays to avoid network congestion\n        let processed = 0;\n        const batchSize = 3;\n        const batchDelay = 300;\n        \n        function processBatch() {\n          const batch = uniqueRoutes.slice(processed, processed + batchSize);\n          if (batch.length === 0) return;\n          \n          for (const route of batch) {\n            prefetchRoute(route);\n          }\n          \n          processed += batch.length;\n          \n          if (processed < uniqueRoutes.length) {\n            setTimeout(processBatch, batchDelay);\n          } else if (config.debug) {\n            log('Finished prefetching all links: ' + processed + ' routes prefetched');\n          }\n        }\n        \n        processBatch();\n      }\n      \n      // Check if a link is in or near the viewport\n      function isLinkInViewport(rect) {\n        // Check if fully in viewport\n        const isVisible = (\n          rect.top >= -config.viewportMargin &&\n          rect.left >= -config.viewportMargin &&\n          rect.bottom <= window.innerHeight + config.viewportMargin &&\n          rect.right <= window.innerWidth + config.viewportMargin\n        );\n        \n        return isVisible;\n      }\n      \n      // Check if mouse is near any links (for desktop)\n      function checkProximity() {\n        const links = getLinks();\n        if (!links.length) return false;\n        \n        // Calculate distance between mouse and each link\n        const linksWithDistance = links.map((link) => {\n          const center = calculateCenterPoint(link.rect);\n          const distance = calculateDistance(\n            mousePosition.x,\n            mousePosition.y,\n            center.x,\n            center.y\n          );\n          return { ...link, distance };\n        });\n        \n        // Find links within threshold distance\n        const closestLinks = linksWithDistance.filter(\n          (link) => link.distance < config.threshold\n        );\n        \n        if (config.debug && closestLinks.length > 0) {\n          log(closestLinks.length + ' links within threshold ' + config.threshold + 'px');\n        }\n        \n        return closestLinks;\n      }\n      \n      // Check which links are in or near viewport (for mobile)\n      function checkViewportLinks() {\n        const links = getLinks();\n        if (!links.length) return false;\n        \n        // Filter links that are in or near the viewport\n        const visibleLinks = links.filter(link => isLinkInViewport(link.rect));\n        \n        if (config.debug && visibleLinks.length > 0) {\n          log(visibleLinks.length + ' links in viewport (plus margin ' + config.viewportMargin + 'px)');\n        }\n        \n        return visibleLinks;\n      }\n      \n      // Prefetch routes when mouse is near links or links are in viewport\n      function prefetchNearbyRoutes() {\n        const now = Date.now();\n        if (now - lastCheck < THROTTLE_INTERVAL) return;\n        lastCheck = now;\n        \n        // Choose detection strategy based on device type\n        const links = isTouchDevice ? checkViewportLinks() : checkProximity();\n        if (!links || !links.length) return;\n        \n        // Sort links: by distance for desktop, by position for mobile\n        if (isTouchDevice) {\n          // On mobile, prioritize links near the top of viewport\n          links.sort((a, b) => a.rect.top - b.rect.top);\n        } else {\n          // On desktop, keep sorting by distance\n          links.sort((a, b) => a.distance - b.distance);\n        }\n        \n        // Limit prefetching to maxPrefetch routes\n        const routesToPrefetch = links.slice(0, config.maxPrefetch).map(link => link.href);\n        \n        // Keep track of the first link being processed\n        let isFirstPrefetch = !window.PPF_HAS_PREFETCHED;\n        \n        // Prefetch routes\n        for (const route of routesToPrefetch) {\n          prefetchRoute(route);\n        }\n      }\n      \n      // Initialize\n      function init() {\n        // Detect device type\n        isTouchDevice = detectTouchDevice();\n        log('Device detection: ' + (isTouchDevice ? 'Touch device' : 'Desktop device'));\n        \n        // Add debug styles to the page if in debug mode\n        if (config.debug) {\n          const style = document.createElement('style');\n          style.textContent = \n            '.ppf-debug-highlight {' +\n            '  box-shadow: 0 0 0 2px red !important;' +\n            '  box-sizing: border-box;' +\n            '}';\n          document.head.appendChild(style);\n        }\n        \n        // If prefetchAllLinks is enabled, prefetch all links after a delay\n        if (config.prefetchAllLinks) {\n          log('prefetchAllLinks enabled, will prefetch all links after ' + config.prefetchAllLinksDelay + 'ms');\n          setTimeout(prefetchAllPageLinks, config.prefetchAllLinksDelay);\n        }\n        \n        if (isTouchDevice && config.mobileSupport) {\n          // Mobile approach: viewport-based prefetching\n          \n          // 1. Check on page load\n          prefetchNearbyRoutes();\n          \n          // 2. Check on scroll with throttling\n          window.addEventListener('scroll', () => {\n            const now = Date.now();\n            if (now - lastCheck > THROTTLE_INTERVAL) {\n              prefetchNearbyRoutes();\n            }\n          }, { passive: true });\n          \n          // 3. Check on touch events\n          window.addEventListener('touchstart', () => {\n            prefetchNearbyRoutes();\n          }, { passive: true });\n          \n          // 4. Check periodically if interval is set\n          if (config.predictionInterval > 0) {\n            setInterval(prefetchNearbyRoutes, config.predictionInterval);\n          }\n          \n          log('Mobile prefetching initialized with viewport margin:', config.viewportMargin + 'px');\n        } else {\n          // Desktop approach: mouse proximity\n          \n          // Mouse move listener\n          window.addEventListener('mousemove', (e) => {\n            mousePosition = { x: e.clientX, y: e.clientY };\n            \n            // Reactive mode\n            if (config.predictionInterval === 0) {\n              prefetchNearbyRoutes();\n            }\n          });\n          \n          // Interval mode\n          if (config.predictionInterval > 0) {\n            setInterval(() => {\n              if (mousePosition.x !== 0 || mousePosition.y !== 0) {\n                prefetchNearbyRoutes();\n              }\n            }, config.predictionInterval);\n          }\n          \n          log('Desktop proximity prefetching initialized');\n        }\n        \n        // Window resize handler to update link positions\n        window.addEventListener('resize', () => {\n          // Throttle resize event\n          const now = Date.now();\n          if (now - lastCheck > THROTTLE_INTERVAL * 2) {\n            lastCheck = now;\n            prefetchNearbyRoutes();\n          }\n        }, { passive: true });\n      }\n      \n      // Start when DOM is ready\n      if (document.readyState === 'loading') {\n        document.addEventListener('DOMContentLoaded', init);\n      } else {\n        init();\n      }\n    })();\n  </script>\n  `;\n}\n\n/**\n * Creates a Vite plugin that enhances Vue Router with proximity-based prefetching\n * \n * @param options - Configuration options for the prefetching behavior\n * @returns Vite plugin instance\n */\nexport function viteProximityPrefetch(options: VueProximityPrefetchOptions = {}): Plugin {\n  // Check if PPF_DEBUG environment variable is set\n  const PPF_DEBUG = process.env.PPF_DEBUG === 'true';\n  \n  // Merge provided options with defaults, respecting PPF_DEBUG\n  const resolvedOptions: Required<VueProximityPrefetchOptions> = {\n    ...DEFAULT_OPTIONS,\n    ...options,\n    debug: options.debug || PPF_DEBUG\n  };\n\n  return {\n    name: 'vite-plugin-vue-proximity-prefetch',\n    \n    configResolved() {\n      console.log('Vue Proximity Prefetch Plugin enabled');\n      \n      if (resolvedOptions.debug) {\n        console.log('Options:', {\n          threshold: resolvedOptions.threshold,\n          predictionInterval: resolvedOptions.predictionInterval,\n          maxPrefetch: resolvedOptions.maxPrefetch,\n          automaticPrefetch: resolvedOptions.automaticPrefetch,\n          debug: resolvedOptions.debug,\n          mobileSupport: resolvedOptions.mobileSupport,\n          viewportMargin: resolvedOptions.viewportMargin\n        });\n      }\n    },\n    \n    /**\n     * Transform HTML to add prefetch attributes to preloaded modules\n     * and inject the automatic prefetching script if enabled\n     */\n    transformIndexHtml(html) {\n      // Add prefetch attribute to module preload links\n      const transformedHtml = html.replace(\n        /<link rel=\"modulepreload\"/g,\n        '<link rel=\"modulepreload\" data-prefetch=\"true\"'\n      );\n      \n      // If automatic prefetching is enabled, inject the script\n      if (resolvedOptions.automaticPrefetch) {\n        const injectionPoint = '</head>';\n        const prefetchScript = generatePrefetchScript(resolvedOptions);\n        \n        return transformedHtml.replace(\n          injectionPoint,\n          `${prefetchScript}\\n${injectionPoint}`\n        );\n      }\n      \n      return transformedHtml;\n    }\n  };\n}\n\nexport default viteProximityPrefetch;","/**\n * Vue Proximity Prefetch\n * A Vue plugin that prefetches routes when the mouse approaches links\n * for faster navigation and improved user experience.\n */\n\nimport type { Plugin } from 'vue';\nimport type { App } from '@vue/runtime-core';\nimport ProximityPrefetch from './ProximityPrefetch.vue';\n\n// Export the Vue component for direct usage\nexport { ProximityPrefetch };\n\n// Re-export the Vite plugin\nexport * from './vite-plugin';\n\n/**\n * Component props interface\n */\nexport interface ProximityPrefetchProps {\n  /** Distance threshold in pixels to trigger prefetching */\n  threshold?: number;\n  /** Interval for periodic checks in milliseconds (0 means reactive to mouse movements) */\n  predictionInterval?: number;\n  /** Enable debug logging */\n  debug?: boolean;\n  /** Enable mobile support with viewport-based prefetching */\n  mobileSupport?: boolean;\n  /** Viewport margin for mobile prefetching */\n  viewportMargin?: number;\n  /** Enable prefetching of all links on the page at once */\n  prefetchAllLinks?: boolean;\n  /** Delay before starting to prefetch all links (ms) */\n  prefetchAllLinksDelay?: number;\n}\n\n/**\n * Plugin configuration options\n */\nexport interface ProximityPrefetchOptions {\n  /** Distance threshold in pixels to trigger prefetching */\n  threshold?: number;\n  /** Interval for periodic checks in milliseconds */\n  predictionInterval?: number;\n  /** Maximum number of routes to prefetch simultaneously */\n  maxPrefetch?: number;\n  /** Enable automatic prefetching without the Vue component */\n  automaticPrefetch?: boolean;\n  /** Enable debug logging */\n  debug?: boolean;\n  /** Enable mobile support for touch devices */\n  mobileSupport?: boolean;\n  /** Viewport margin for mobile prefetching */\n  viewportMargin?: number;\n  /** Enable prefetching of all links on the page at once */\n  prefetchAllLinks?: boolean;\n  /** Delay before starting to prefetch all links (ms) */\n  prefetchAllLinksDelay?: number;\n}\n\n/**\n * Vue plugin for proximity-based route prefetching\n * Usage: app.use(ProximityPrefetchPlugin)\n */\nexport const ProximityPrefetchPlugin: Plugin = {\n  install(app: App) {\n    // Register the component globally\n    app.component('ProximityPrefetch', ProximityPrefetch);\n  }\n};"],"names":["THROTTLE_INTERVAL","PPF_DEBUG","props","__props","isDebugEnabled","computed","router","useRouter","mousePosition","ref","prefetchedRoutes","links","isMouseNearLink","lastProximityCheck","isTouchDevice","detectTouchDevice","updateLinks","anchors","el","href","rect","link","calculateDistance","x1","y1","x2","y2","calculateCenterPoint","isLinkInViewport","checkProximity","closestLinks","center","distance","checkViewportLinks","visibleLinks","prefetchNearbyRoutes","now","hasNearbyLinks","linksToProcess","a","b","linksWithDistance","routesToPrefetch","MAX_PREFETCH","route","resolved","routeRecord","comps","comp","asyncComp","e","anchor","err","prefetchRoute","prefetchAllPageLinks","uniqueRoutes","processed","batchSize","batchDelay","processBatch","batch","handleMouseMove","handleScroll","handleTouch","onMounted","style","observer","intervalId","throttledPrefetch","watch","onUnmounted","DEFAULT_OPTIONS","generatePrefetchScript","options","viteProximityPrefetch","resolvedOptions","html","transformedHtml","injectionPoint","prefetchScript","ProximityPrefetchPlugin","app","ProximityPrefetch"],"mappings":"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A,4BACpBA,EAAQ,gBAAgB;AAAA,iCACnBA,EAAQ,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAgT9D,CAQgB,SAAAC,EAAsBD,EAAuC,GAAY,CAEjF,MAAAxE,EAAY,QAAQ,IAAI,YAAc,OAGtC0E,EAAyD,CAC7D,GAAGJ,EACH,GAAGE,EACH,MAAOA,EAAQ,OAASxE,CAC1B,EAEO,MAAA,CACL,KAAM,qCAEN,gBAAiB,CACf,QAAQ,IAAI,uCAAuC,EAE/C0E,EAAgB,OAClB,QAAQ,IAAI,WAAY,CACtB,UAAWA,EAAgB,UAC3B,mBAAoBA,EAAgB,mBACpC,YAAaA,EAAgB,YAC7B,kBAAmBA,EAAgB,kBACnC,MAAOA,EAAgB,MACvB,cAAeA,EAAgB,cAC/B,eAAgBA,EAAgB,cAAA,CACjC,CAEL,EAMA,mBAAmBC,EAAM,CAEvB,MAAMC,EAAkBD,EAAK,QAC3B,6BACA,gDACF,EAGA,GAAID,EAAgB,kBAAmB,CACrC,MAAMG,EAAiB,UACjBC,EAAiBP,EAAuBG,CAAe,EAE7D,OAAOE,EAAgB,QACrBC,EACA,GAAGC,CAAc;AAAA,EAAKD,CAAc,EACtC,CAAA,CAGK,OAAAD,CAAA,CAEX,CACF,CC/ZO,MAAMG,EAAkC,CAC7C,QAAQC,EAAU,CAEZA,EAAA,UAAU,oBAAqBC,CAAiB,CAAA,CAExD"}