{"version":3,"file":"index.cjs","sources":["../src/utils.ts","../src/enhancer.ts","../src/index.ts"],"sourcesContent":["import type { RouteLocationRaw, Router } from 'vue-router';\nimport type { DebugLogger, ResolvedUrl } from './types';\n\n/**\n * Check if we're in a browser environment\n */\nexport function isBrowser(): boolean {\n  return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Check if we're in a server-side environment\n */\nexport function isSSR(): boolean {\n  return !isBrowser();\n}\n\n/**\n * Create a debug logger function\n */\nexport function createDebugLogger(debugMode: boolean): DebugLogger {\n  return (message: string, ...args: unknown[]) => {\n    if (debugMode && isBrowser()) {\n      // eslint-disable-next-line no-console\n      console.log(`[VueRouterNewTab] ${message}`, ...args);\n    }\n  };\n}\n\n/**\n * Resolve a route to a full URL for new tab navigation\n */\nexport function resolveRouteUrl(\n  router: Router,\n  to: RouteLocationRaw\n): ResolvedUrl {\n  try {\n    const resolved = router.resolve(to);\n    const href = resolved.href;\n\n    // Check if it's an external URL\n    const isExternal =\n      href.startsWith('http://') ||\n      href.startsWith('https://') ||\n      href.startsWith('//');\n\n    return {\n      href,\n      route: to,\n      isExternal,\n    };\n  } catch {\n    // Fallback for invalid routes\n    const href = typeof to === 'string' ? to : '#';\n    return {\n      href,\n      route: to,\n      isExternal: false,\n    };\n  }\n}\n\n/**\n * Open a URL in a new tab\n */\nexport function openInNewTab(\n  url: string,\n  target: string = '_blank'\n): Window | null {\n  if (!isBrowser()) {\n    return null;\n  }\n\n  try {\n    return window.open(url, target, 'noopener,noreferrer');\n  } catch (error) {\n    // eslint-disable-next-line no-console\n    console.warn('[VueRouterNewTab] Failed to open new tab:', error);\n    return null;\n  }\n}\n\n/**\n * Check if a modifier key is currently pressed\n */\nexport function isModifierKeyPressed(event: KeyboardEvent): boolean {\n  // Check for Cmd key (macOS) or Ctrl key (Windows/Linux)\n  return event.metaKey || event.ctrlKey;\n}\n","import type { NavigationFailure, RouteLocationRaw, Router } from 'vue-router';\nimport type {\n  DebugLogger,\n  EnhancedPushOptions,\n  KeyboardState,\n  NewTabRouterConfig,\n} from './types';\nimport {\n  createDebugLogger,\n  isBrowser,\n  isSSR,\n  openInNewTab,\n  resolveRouteUrl,\n} from './utils';\n\n/**\n * Keyboard monitoring class for detecting modifier key presses\n */\nclass KeyboardMonitor {\n  private state: KeyboardState = {\n    isModifierPressed: false,\n  };\n\n  private listeners: (() => void)[] = [];\n  private debug: DebugLogger;\n\n  constructor(debug: DebugLogger) {\n    this.debug = debug;\n    this.setupEventListeners();\n  }\n\n  /**\n   * Set up global keyboard event listeners\n   */\n  private setupEventListeners(): void {\n    if (!isBrowser()) {\n      this.debug('Keyboard monitoring disabled in SSR environment');\n      return;\n    }\n\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if (event.metaKey || event.ctrlKey) {\n        this.state.isModifierPressed = true;\n        this.debug('Modifier key pressed', {\n          metaKey: event.metaKey,\n          ctrlKey: event.ctrlKey,\n        });\n      }\n    };\n\n    const handleKeyUp = (event: KeyboardEvent) => {\n      if (!event.metaKey && !event.ctrlKey) {\n        this.state.isModifierPressed = false;\n        this.debug('Modifier key released');\n      }\n    };\n\n    // Add event listeners\n    document.addEventListener('keydown', handleKeyDown, { passive: true });\n    document.addEventListener('keyup', handleKeyUp, { passive: true });\n\n    // Store cleanup functions\n    this.listeners.push(() => {\n      document.removeEventListener('keydown', handleKeyDown);\n      document.removeEventListener('keyup', handleKeyUp);\n    });\n\n    // Handle window blur to reset state\n    const handleBlur = () => {\n      this.state.isModifierPressed = false;\n      this.debug('Window blurred, resetting modifier state');\n    };\n\n    window.addEventListener('blur', handleBlur);\n    this.listeners.push(() => {\n      window.removeEventListener('blur', handleBlur);\n    });\n  }\n\n  /**\n   * Check if a modifier key is currently pressed\n   */\n  public isModifierKeyPressed(): boolean {\n    return this.state.isModifierPressed;\n  }\n\n  /**\n   * Get current keyboard state\n   */\n  public getState(): KeyboardState {\n    return { ...this.state };\n  }\n\n  /**\n   * Clean up all event listeners\n   */\n  public destroy(): void {\n    this.listeners.forEach(cleanup => cleanup());\n    this.listeners = [];\n    this.debug('Keyboard monitor destroyed');\n  }\n}\n\n/**\n * New tab router class that adds Cmd/Ctrl+click functionality\n */\nclass NewTabRouterClass {\n  private router: Router;\n  private originalPush: Router['push'];\n  private keyboardMonitor: KeyboardMonitor;\n  private config: Required<NewTabRouterConfig>;\n  private debug: DebugLogger;\n\n  constructor(router: Router, config: NewTabRouterConfig = {}) {\n    this.router = router;\n    this.config = {\n      enableCtrlClick: true,\n      debugMode: false,\n      ...config,\n    };\n\n    this.debug = createDebugLogger(this.config.debugMode);\n    this.keyboardMonitor = new KeyboardMonitor(this.debug);\n\n    // Store original push method\n    this.originalPush = router.push.bind(router);\n\n    // Override the push method\n    this.setupNewTabRouter();\n\n    this.debug('New tab router initialized', this.config);\n  }\n\n  /**\n   * Setup the router with new tab functionality\n   */\n  private setupNewTabRouter(): void {\n    this.router.push = (\n      to: RouteLocationRaw,\n      options?: EnhancedPushOptions\n    ): Promise<NavigationFailure | void | undefined> => {\n      return this.newTabPush(to, options);\n    };\n  }\n\n  /**\n   * New tab push method with modifier key detection\n   */\n  private async newTabPush(\n    to: RouteLocationRaw,\n    options: EnhancedPushOptions = {}\n  ): Promise<NavigationFailure | void | undefined> {\n    this.debug('New tab push called', { to, options });\n\n    // Check for force new tab option\n    if (options.forceNewTab) {\n      this.debug('Force new tab requested');\n      return this.handleNewTabNavigation(to, options);\n    }\n\n    // Check for newTab option\n    if (options.newTab !== undefined) {\n      if (options.newTab && this.keyboardMonitor.isModifierKeyPressed()) {\n        this.debug('NewTab option with modifier key detected');\n        return this.handleNewTabNavigation(to, options);\n      } else if (options.newTab === false) {\n        this.debug(\n          'NewTab explicitly disabled, skipping modifier key behavior'\n        );\n        return this.originalPush(to);\n      }\n    }\n\n    // Check if modifier key is pressed and enhancement is enabled (default behavior)\n    if (\n      this.config.enableCtrlClick &&\n      this.keyboardMonitor.isModifierKeyPressed()\n    ) {\n      this.debug('Modifier key detected, opening in new tab');\n      return this.handleNewTabNavigation(to, options);\n    }\n\n    // Normal navigation\n    this.debug('Performing normal navigation');\n    return this.originalPush(to);\n  }\n\n  /**\n   * Handle new tab navigation\n   */\n  private async handleNewTabNavigation(\n    to: RouteLocationRaw,\n    _options: EnhancedPushOptions\n  ): Promise<NavigationFailure | void | undefined> {\n    try {\n      const resolved = resolveRouteUrl(this.router, to);\n\n      if (resolved.isExternal) {\n        this.debug('External URL detected, opening directly', {\n          url: resolved.href,\n        });\n        openInNewTab(resolved.href);\n      } else {\n        this.debug('Internal route, resolving and opening in new tab', {\n          route: to,\n          resolved: resolved.href,\n        });\n        openInNewTab(resolved.href);\n      }\n\n      return Promise.resolve();\n    } catch (error) {\n      this.debug(\n        'Error in new tab navigation, falling back to normal navigation',\n        error\n      );\n      return this.originalPush(to);\n    }\n  }\n\n  /**\n   * Get current configuration\n   */\n  public getConfig(): NewTabRouterConfig {\n    return { ...this.config };\n  }\n\n  /**\n   * Update configuration\n   */\n  public updateConfig(newConfig: Partial<NewTabRouterConfig>): void {\n    this.config = { ...this.config, ...newConfig };\n    this.debug = createDebugLogger(this.config.debugMode);\n    this.debug('Configuration updated', this.config);\n  }\n\n  /**\n   * Clean up the new tab router\n   */\n  public destroy(): void {\n    this.keyboardMonitor.destroy();\n\n    // Restore original push method\n    this.router.push = this.originalPush;\n\n    this.debug('New tab router destroyed');\n  }\n}\n\n/**\n * Add new tab functionality to a router instance with Cmd/Ctrl+click support\n */\nexport function newTabRouter(\n  router: Router,\n  config?: NewTabRouterConfig\n): Router {\n  if (isSSR()) {\n    // eslint-disable-next-line no-console\n    console.warn('[VueRouterNewTab] Enhancement skipped in SSR environment');\n    return router;\n  }\n\n  const newTabRouterInstance = new NewTabRouterClass(router, config);\n\n  // Store new tab router reference for potential cleanup\n  (router as unknown as Record<string, unknown>).__newTabRouter =\n    newTabRouterInstance;\n\n  return router;\n}\n\n/**\n * Get the new tab router instance from a router\n */\nexport function getNewTabRouter(router: Router): NewTabRouterClass | null {\n  return (\n    ((router as unknown as Record<string, unknown>)\n      .__newTabRouter as NewTabRouterClass) || null\n  );\n}\n\n/**\n * Destroy the new tab router for a router\n */\nexport function destroyNewTabRouter(router: Router): void {\n  const newTabRouterInstance = getNewTabRouter(router);\n  if (newTabRouterInstance) {\n    newTabRouterInstance.destroy();\n    delete (router as unknown as Record<string, unknown>).__newTabRouter;\n  }\n}\n","/**\n * Vue Router New Tab Enhancer\n *\n * A Vue 3 + Vue Router 4 enhancement package that adds intelligent navigation behavior,\n * specifically Cmd/Ctrl+click functionality to programmatic router.push() calls.\n *\n * @package vue-router-newtab\n * @version 1.0.0\n */\n\n// Module augmentation is handled in src/types.ts\n\n// Global fallback for any router implementation\ndeclare global {\n  interface Router {\n    /** Enhanced push method with additional options */\n    push(\n      to: import('vue-router').RouteLocationRaw,\n      options?: {\n        /** Force opening in new tab regardless of modifier key state */\n        forceNewTab?: boolean;\n        /** Open in new tab only if modifier key is pressed (false prevents new tab behavior) */\n        newTab?: boolean;\n      }\n    ): Promise<import('vue-router').NavigationFailure | void | undefined>;\n  }\n}\n\n// Main exports\nexport { destroyNewTabRouter, getNewTabRouter, newTabRouter } from './enhancer';\n\n// Type exports\nexport type {\n  DebugLogger,\n  EnhancedPushOptions,\n  NewTabRouterConfig,\n  ResolvedUrl,\n} from './types';\n\n// Utility exports\nexport {\n  createDebugLogger,\n  isBrowser,\n  isModifierKeyPressed,\n  isSSR,\n  openInNewTab,\n  resolveRouteUrl,\n} from './utils';\n\n/**\n * Version information\n */\nexport const VERSION = '1.0.0';\n"],"names":[],"mappings":"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"}