{"version":3,"file":"hotkey-manager.cjs","names":["#instance","Store","#platform","detectPlatform","parseHotkey","rawHotkeyToParsedHotkey","formatHotkey","#findConflictingRegistration","#unregister","getDefaultIgnoreInputs","defaultHotkeyOptions","#targetRegistrations","#ensureListenersForTarget","#removeListenersForTarget","#targetListeners","#createTargetKeyDownHandler","#createTargetKeyUpHandler","isEventForTarget","shouldIgnoreInputEvent","matchesKeyboardEvent","#executeHotkeyCallback","#shouldResetRegistration","#processTargetEvent","normalizeKeyName"],"sources":["../src/hotkey-manager.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\nimport { detectPlatform, normalizeKeyName } from './constants'\nimport { formatHotkey } from './format'\nimport { parseHotkey, rawHotkeyToParsedHotkey } from './parse'\nimport { matchesKeyboardEvent } from './match'\nimport {\n  defaultHotkeyOptions,\n  getDefaultIgnoreInputs,\n  handleConflict,\n  isEventForTarget,\n  shouldIgnoreInputEvent,\n} from './manager.utils'\nimport type { ConflictBehavior } from './manager.utils'\nimport type {\n  Hotkey,\n  HotkeyCallback,\n  HotkeyCallbackContext,\n  HotkeyMeta,\n  ParsedHotkey,\n  RegisterableHotkey,\n} from './hotkey'\n\nexport type { ConflictBehavior }\n\n/**\n * Options for registering a hotkey.\n */\nexport interface HotkeyOptions {\n  /** Behavior when this hotkey conflicts with an existing registration on the same target. Defaults to 'warn' */\n  conflictBehavior?: ConflictBehavior\n  /**\n   * Soft-disable: when `false`, the callback does not run but the registration\n   * stays in `HotkeyManager` (and in devtools). Toggling this should update the\n   * existing handle via `setOptions` rather than unregistering. Defaults to `true`.\n   */\n  enabled?: boolean\n  /** The event type to listen for. Defaults to 'keydown' */\n  eventType?: 'keydown' | 'keyup'\n  /** Whether to ignore hotkeys when keyboard events originate from input-like elements (text inputs, textarea, select, contenteditable — button-type inputs like type=button/submit/reset are not ignored). Defaults based on hotkey: true for single keys and Shift/Alt combos; false for Ctrl/Meta shortcuts and Escape */\n  ignoreInputs?: boolean\n  /** The target platform for resolving 'Mod' */\n  platform?: 'mac' | 'windows' | 'linux'\n  /** Prevent the default browser action when the hotkey matches. Defaults to true */\n  preventDefault?: boolean\n  /** If true, only trigger once until all keys are released. Default: false */\n  requireReset?: boolean\n  /** Stop event propagation when the hotkey matches. Defaults to true */\n  stopPropagation?: boolean\n  /** The DOM element to attach the event listener to. Defaults to document. */\n  target?: HTMLElement | Document | Window | null\n  /** Optional metadata (name, description, custom fields via declaration merging) */\n  meta?: HotkeyMeta\n}\n\n/**\n * A registered hotkey handler in the HotkeyManager.\n */\nexport interface HotkeyRegistration {\n  /** The callback to invoke */\n  callback: HotkeyCallback\n  /** Whether this registration has fired and needs reset (for requireReset) */\n  hasFired: boolean\n  /** The original hotkey string */\n  hotkey: Hotkey\n  /** Unique identifier for this registration */\n  id: string\n  /** Options for this registration */\n  options: HotkeyOptions\n  /** The parsed hotkey */\n  parsedHotkey: ParsedHotkey\n  /** The resolved target element for this registration */\n  target: HTMLElement | Document | Window\n  /** How many times this registration's callback has been triggered */\n  triggerCount: number\n}\n\n/**\n * Public view of a hotkey registration for display and introspection.\n * Omits the callback function which is an internal implementation detail.\n */\nexport interface HotkeyRegistrationView {\n  /** The original hotkey string */\n  hotkey: Hotkey\n  /** Unique identifier for this registration */\n  id: string\n  /** Options for this registration */\n  options: HotkeyOptions\n  /** The parsed hotkey */\n  parsedHotkey: ParsedHotkey\n  /** The resolved target element for this registration */\n  target: HTMLElement | Document | Window\n  /** How many times this registration's callback has been triggered */\n  triggerCount: number\n  /** Whether this registration has fired and needs reset (for requireReset) */\n  hasFired: boolean\n}\n\n/**\n * Creates a public view from an internal registration,\n * stripping the callback function.\n */\nexport function toHotkeyRegistrationView(\n  reg: HotkeyRegistration,\n): HotkeyRegistrationView {\n  return {\n    hotkey: reg.hotkey,\n    id: reg.id,\n    options: reg.options,\n    parsedHotkey: reg.parsedHotkey,\n    target: reg.target,\n    triggerCount: reg.triggerCount,\n    hasFired: reg.hasFired,\n  }\n}\n\n/**\n * A handle returned from HotkeyManager.register() that allows updating\n * the callback and options without re-registering the hotkey.\n *\n * @example\n * ```ts\n * const handle = manager.register('Mod+S', callback, options)\n *\n * // Update callback without re-registering (avoids stale closures)\n * handle.callback = newCallback\n *\n * // Update options without re-registering\n * handle.setOptions({ enabled: false })\n *\n * // Check if still active\n * if (handle.isActive) {\n *   // ...\n * }\n *\n * // Unregister when done\n * handle.unregister()\n * ```\n */\nexport interface HotkeyRegistrationHandle {\n  /**\n   * The callback function. Can be set directly to update without re-registering.\n   * This avoids stale closures when the callback references React state.\n   */\n  callback: HotkeyCallback\n  /** Unique identifier for this registration */\n  readonly id: string\n  /** Check if this registration is still active (not unregistered) */\n  readonly isActive: boolean\n  /**\n   * Update options (merged with existing options).\n   * Useful for updating `enabled`, `preventDefault`, etc. without re-registering.\n   */\n  setOptions: (options: Partial<HotkeyOptions>) => void\n  /** Unregister this hotkey */\n  unregister: () => void\n}\n\nlet registrationIdCounter = 0\n\n/**\n * Generates a unique ID for hotkey registrations.\n */\nfunction generateId(): string {\n  return `hotkey_${++registrationIdCounter}`\n}\n\n/**\n * Singleton manager for hotkey registrations.\n *\n * This class provides a centralized way to register and manage keyboard hotkeys.\n * It uses a single event listener for efficiency, regardless of how many hotkeys\n * are registered.\n *\n * @example\n * ```ts\n * const manager = HotkeyManager.getInstance()\n *\n * const unregister = manager.register('Mod+S', (event, context) => {\n *   console.log('Save triggered!')\n * })\n *\n * // Later, to unregister:\n * unregister()\n * ```\n */\nexport class HotkeyManager {\n  static #instance: HotkeyManager | null = null\n\n  /**\n   * The TanStack Store containing all hotkey registrations.\n   * Use this to subscribe to registration changes or access current registrations.\n   *\n   * @example\n   * ```ts\n   * const manager = HotkeyManager.getInstance()\n   *\n   * // Subscribe to registration changes\n   * const unsubscribe = manager.registrations.subscribe(() => {\n   *   console.log('Registrations changed:', manager.registrations.state.size)\n   * })\n   *\n   * // Access current registrations\n   * for (const [id, reg] of manager.registrations.state) {\n   *   console.log(reg.hotkey, reg.options.enabled)\n   * }\n   * ```\n   */\n  readonly registrations: Store<Map<string, HotkeyRegistration>> = new Store(\n    new Map(),\n  )\n  #platform: 'mac' | 'windows' | 'linux'\n  #targetListeners: Map<\n    HTMLElement | Document | Window,\n    {\n      keydown: (event: KeyboardEvent) => void\n      keyup: (event: KeyboardEvent) => void\n    }\n  > = new Map()\n  #targetRegistrations: Map<HTMLElement | Document | Window, Set<string>> =\n    new Map()\n\n  private constructor() {\n    this.#platform = detectPlatform()\n  }\n\n  /**\n   * Gets the singleton instance of HotkeyManager.\n   */\n  static getInstance(): HotkeyManager {\n    if (!HotkeyManager.#instance) {\n      HotkeyManager.#instance = new HotkeyManager()\n    }\n    return HotkeyManager.#instance\n  }\n\n  /**\n   * Resets the singleton instance. Useful for testing.\n   */\n  static resetInstance(): void {\n    if (HotkeyManager.#instance) {\n      HotkeyManager.#instance.destroy()\n      HotkeyManager.#instance = null\n    }\n  }\n\n  /**\n   * Registers a hotkey handler and returns a handle for updating the registration.\n   *\n   * The returned handle allows updating the callback and options without\n   * re-registering, which is useful for avoiding stale closures in React.\n   *\n   * @param hotkey - The hotkey string (e.g., 'Mod+S') or RawHotkey object\n   * @param callback - The function to call when the hotkey is pressed\n   * @param options - Options for the hotkey behavior\n   * @returns A handle for managing the registration\n   *\n   * @example\n   * ```ts\n   * const handle = manager.register('Mod+S', callback)\n   *\n   * // Update callback without re-registering (avoids stale closures)\n   * handle.callback = newCallback\n   *\n   * // Update options\n   * handle.setOptions({ enabled: false })\n   *\n   * // Unregister when done\n   * handle.unregister()\n   * ```\n   */\n  register(\n    hotkey: RegisterableHotkey,\n    callback: HotkeyCallback,\n    options: HotkeyOptions = {},\n  ): HotkeyRegistrationHandle {\n    // In SSR environments, return a no-op handle since there's no DOM to attach listeners to\n    if (typeof document === 'undefined' && !options.target) {\n      let currentCallback = callback\n      return {\n        id: generateId(),\n        unregister: () => {},\n        get callback() {\n          return currentCallback\n        },\n        set callback(newCallback: HotkeyCallback) {\n          currentCallback = newCallback\n        },\n        setOptions: () => {},\n        get isActive() {\n          return false\n        },\n      }\n    }\n\n    const id = generateId()\n    const platform = options.platform ?? this.#platform\n    const parsedHotkey =\n      typeof hotkey === 'string'\n        ? parseHotkey(hotkey, platform)\n        : rawHotkeyToParsedHotkey(hotkey, platform)\n    const hotkeyStr = (\n      typeof hotkey === 'string' ? hotkey : formatHotkey(parsedHotkey)\n    ) as Hotkey\n\n    // Resolve target: default to document if not provided\n    // Note: SSR case without explicit target is handled above\n    const target = options.target ?? document\n\n    // Resolve conflict behavior\n    const conflictBehavior = options.conflictBehavior ?? 'warn'\n\n    // Check for existing registrations with the same hotkey and target\n    const conflictingRegistration = this.#findConflictingRegistration(\n      hotkeyStr,\n      target,\n    )\n\n    if (conflictingRegistration) {\n      handleConflict(\n        conflictingRegistration.id,\n        hotkeyStr,\n        conflictBehavior,\n        (id) => this.#unregister(id),\n      )\n    }\n\n    const resolvedIgnoreInputs =\n      options.ignoreInputs ?? getDefaultIgnoreInputs(parsedHotkey)\n\n    const baseOptions = {\n      ...defaultHotkeyOptions,\n      requireReset: false,\n      ...options,\n      platform,\n    }\n\n    const registration: HotkeyRegistration = {\n      id,\n      hotkey: hotkeyStr,\n      parsedHotkey,\n      callback,\n      options: { ...baseOptions, ignoreInputs: resolvedIgnoreInputs },\n      hasFired: false,\n      triggerCount: 0,\n      target,\n    }\n\n    this.registrations.setState((prev) => new Map(prev).set(id, registration))\n\n    // Track registration for this target\n    if (!this.#targetRegistrations.has(target)) {\n      this.#targetRegistrations.set(target, new Set())\n    }\n    this.#targetRegistrations.get(target)!.add(id)\n\n    // Ensure listeners are attached for this target\n    this.#ensureListenersForTarget(target)\n\n    // Create and return the handle\n    const manager = this\n    const handle: HotkeyRegistrationHandle = {\n      get id() {\n        return id\n      },\n      unregister: () => {\n        manager.#unregister(id)\n      },\n      get callback() {\n        const reg = manager.registrations.state.get(id)\n        return reg?.callback ?? callback\n      },\n      set callback(newCallback: HotkeyCallback) {\n        const reg = manager.registrations.state.get(id)\n        if (reg) {\n          reg.callback = newCallback\n        }\n      },\n      setOptions: (newOptions: Partial<HotkeyOptions>) => {\n        manager.registrations.setState((prev) => {\n          const reg = prev.get(id)\n          if (reg) {\n            const next = new Map(prev)\n            next.set(id, { ...reg, options: { ...reg.options, ...newOptions } })\n            return next\n          }\n          return prev\n        })\n      },\n      get isActive() {\n        return manager.registrations.state.has(id)\n      },\n    }\n\n    return handle\n  }\n\n  /**\n   * Unregisters a hotkey by its registration ID.\n   */\n  #unregister(id: string): void {\n    const registration = this.registrations.state.get(id)\n    if (!registration) {\n      return\n    }\n\n    const target = registration.target\n\n    // Remove registration\n    this.registrations.setState((prev) => {\n      const next = new Map(prev)\n      next.delete(id)\n      return next\n    })\n\n    // Remove from target registrations tracking\n    const targetRegs = this.#targetRegistrations.get(target)\n    if (targetRegs) {\n      targetRegs.delete(id)\n      // If no more registrations for this target, remove listeners\n      if (targetRegs.size === 0) {\n        this.#removeListenersForTarget(target)\n      }\n    }\n  }\n\n  /**\n   * Ensures event listeners are attached for a specific target.\n   */\n  #ensureListenersForTarget(target: HTMLElement | Document | Window): void {\n    if (typeof document === 'undefined') {\n      return // SSR safety\n    }\n\n    // Skip if listeners already exist for this target\n    if (this.#targetListeners.has(target)) {\n      return\n    }\n\n    const keydownHandler = this.#createTargetKeyDownHandler(target)\n    const keyupHandler = this.#createTargetKeyUpHandler(target)\n\n    target.addEventListener('keydown', keydownHandler as EventListener)\n    target.addEventListener('keyup', keyupHandler as EventListener)\n\n    this.#targetListeners.set(target, {\n      keydown: keydownHandler,\n      keyup: keyupHandler,\n    })\n  }\n\n  /**\n   * Removes event listeners for a specific target.\n   */\n  #removeListenersForTarget(target: HTMLElement | Document | Window): void {\n    if (typeof document === 'undefined') {\n      return\n    }\n\n    const listeners = this.#targetListeners.get(target)\n    if (!listeners) {\n      return\n    }\n\n    target.removeEventListener('keydown', listeners.keydown as EventListener)\n    target.removeEventListener('keyup', listeners.keyup as EventListener)\n\n    this.#targetListeners.delete(target)\n    this.#targetRegistrations.delete(target)\n  }\n\n  /**\n   * Processes keyboard events for a specific target and event type.\n   */\n  #processTargetEvent(\n    event: KeyboardEvent,\n    target: HTMLElement | Document | Window,\n    eventType: 'keydown' | 'keyup',\n  ): void {\n    const targetRegs = this.#targetRegistrations.get(target)\n    if (!targetRegs) {\n      return\n    }\n\n    for (const id of targetRegs) {\n      const registration = this.registrations.state.get(id)\n      if (!registration) {\n        continue\n      }\n\n      // Check if event originated from or bubbled to this target\n      if (!isEventForTarget(event, target)) {\n        continue\n      }\n\n      if (!registration.options.enabled) {\n        continue\n      }\n\n      // Check if we should ignore input elements (defaults to true)\n      if (registration.options.ignoreInputs !== false) {\n        if (shouldIgnoreInputEvent(event, target, registration.target)) {\n          continue\n        }\n      }\n\n      // Handle keydown events\n      if (eventType === 'keydown') {\n        if (registration.options.eventType !== 'keydown') {\n          continue\n        }\n\n        // Check if the hotkey matches first\n        const matches = matchesKeyboardEvent(\n          event,\n          registration.parsedHotkey,\n          registration.options.platform,\n        )\n\n        if (matches) {\n          // Always apply preventDefault/stopPropagation if the hotkey matches,\n          // even when requireReset is active and has already fired\n          if (registration.options.preventDefault) {\n            event.preventDefault()\n          }\n          if (registration.options.stopPropagation) {\n            event.stopPropagation()\n          }\n\n          // Only execute callback if requireReset is not active or hasn't fired yet\n          if (!registration.options.requireReset || !registration.hasFired) {\n            this.#executeHotkeyCallback(registration, event)\n\n            // Mark as fired if requireReset is enabled\n            if (registration.options.requireReset) {\n              registration.hasFired = true\n            }\n          }\n        }\n      }\n      // Handle keyup events\n      else {\n        if (registration.options.eventType === 'keyup') {\n          if (\n            matchesKeyboardEvent(\n              event,\n              registration.parsedHotkey,\n              registration.options.platform,\n            )\n          ) {\n            this.#executeHotkeyCallback(registration, event)\n          }\n        }\n\n        // Reset hasFired when any key in the hotkey is released\n        if (registration.options.requireReset && registration.hasFired) {\n          if (this.#shouldResetRegistration(registration, event)) {\n            registration.hasFired = false\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Executes a hotkey callback with proper event handling.\n   */\n  #executeHotkeyCallback(\n    registration: HotkeyRegistration,\n    event: KeyboardEvent,\n  ): void {\n    if (registration.options.preventDefault) {\n      event.preventDefault()\n    }\n    if (registration.options.stopPropagation) {\n      event.stopPropagation()\n    }\n\n    registration.triggerCount++\n\n    // Notify the store so subscribers (e.g. devtools) see the updated count.\n    // We create a new Map but keep the same registration reference to preserve\n    // identity for mutation-based fields like hasFired.\n    this.registrations.setState((prev) => new Map(prev))\n\n    const context: HotkeyCallbackContext = {\n      hotkey: registration.hotkey,\n      parsedHotkey: registration.parsedHotkey,\n    }\n\n    registration.callback(event, context)\n  }\n\n  /**\n   * Creates a keydown handler for a specific target.\n   */\n  #createTargetKeyDownHandler(\n    target: HTMLElement | Document | Window,\n  ): (event: KeyboardEvent) => void {\n    return (event: KeyboardEvent) => {\n      this.#processTargetEvent(event, target, 'keydown')\n    }\n  }\n\n  /**\n   * Creates a keyup handler for a specific target.\n   */\n  #createTargetKeyUpHandler(\n    target: HTMLElement | Document | Window,\n  ): (event: KeyboardEvent) => void {\n    return (event: KeyboardEvent) => {\n      this.#processTargetEvent(event, target, 'keyup')\n    }\n  }\n\n  /**\n   * Finds an existing registration with the same hotkey and target.\n   */\n  #findConflictingRegistration(\n    hotkey: Hotkey,\n    target: HTMLElement | Document | Window,\n  ): HotkeyRegistration | null {\n    for (const registration of this.registrations.state.values()) {\n      if (registration.hotkey === hotkey && registration.target === target) {\n        return registration\n      }\n    }\n    return null\n  }\n\n  /**\n   * Determines if a registration should be reset based on the keyup event.\n   */\n  #shouldResetRegistration(\n    registration: HotkeyRegistration,\n    event: KeyboardEvent,\n  ): boolean {\n    const parsed = registration.parsedHotkey\n    const releasedKey = normalizeKeyName(event.key)\n\n    // Reset if the main key is released\n    // Compare case-insensitively for single-letter keys\n    const parsedKeyNormalized =\n      parsed.key.length === 1 ? parsed.key.toUpperCase() : parsed.key\n    const releasedKeyNormalized =\n      releasedKey.length === 1 ? releasedKey.toUpperCase() : releasedKey\n\n    if (releasedKeyNormalized === parsedKeyNormalized) {\n      return true\n    }\n\n    // Reset if any required modifier is released\n    // Use normalized key names and check against canonical modifier names\n    if (parsed.ctrl && releasedKey === 'Control') {\n      return true\n    }\n    if (parsed.shift && releasedKey === 'Shift') {\n      return true\n    }\n    if (parsed.alt && releasedKey === 'Alt') {\n      return true\n    }\n    if (parsed.meta && releasedKey === 'Meta') {\n      return true\n    }\n\n    return false\n  }\n\n  /**\n   * Triggers a registration's callback programmatically from devtools.\n   * Creates a synthetic KeyboardEvent and invokes the callback.\n   *\n   * @param id - The registration ID to trigger\n   * @returns True if the registration was found and triggered\n   */\n  triggerRegistration(id: string): boolean {\n    const registration = this.registrations.state.get(id)\n    if (!registration) {\n      return false\n    }\n\n    const parsed = registration.parsedHotkey\n    const syntheticEvent = new KeyboardEvent(\n      registration.options.eventType ?? 'keydown',\n      {\n        key: parsed.key,\n        ctrlKey: parsed.ctrl,\n        shiftKey: parsed.shift,\n        altKey: parsed.alt,\n        metaKey: parsed.meta,\n        bubbles: true,\n        cancelable: true,\n      },\n    )\n\n    registration.triggerCount++\n\n    // Notify the store so subscribers (e.g. devtools) see the updated count\n    this.registrations.setState((prev) => new Map(prev))\n\n    registration.callback(syntheticEvent, {\n      hotkey: registration.hotkey,\n      parsedHotkey: registration.parsedHotkey,\n    })\n\n    return true\n  }\n\n  /**\n   * Gets the number of registered hotkeys.\n   */\n  getRegistrationCount(): number {\n    return this.registrations.state.size\n  }\n\n  /**\n   * Checks if a specific hotkey is registered.\n   *\n   * @param hotkey - The hotkey string to check\n   * @param target - Optional target element to match (if provided, both hotkey and target must match)\n   * @returns True if a matching registration exists\n   */\n  isRegistered(\n    hotkey: Hotkey,\n    target?: HTMLElement | Document | Window,\n  ): boolean {\n    for (const registration of this.registrations.state.values()) {\n      if (registration.hotkey === hotkey) {\n        // If target is specified, both must match\n        if (target === undefined || registration.target === target) {\n          return true\n        }\n      }\n    }\n    return false\n  }\n\n  /**\n   * Destroys the manager and removes all listeners.\n   */\n  destroy(): void {\n    // Remove all target listeners\n    for (const target of this.#targetListeners.keys()) {\n      this.#removeListenersForTarget(target)\n    }\n\n    this.registrations.setState(() => new Map())\n    this.#targetListeners.clear()\n    this.#targetRegistrations.clear()\n  }\n}\n\n/**\n * Gets the singleton HotkeyManager instance.\n * Convenience function for accessing the manager.\n */\nexport function getHotkeyManager(): HotkeyManager {\n  return HotkeyManager.getInstance()\n}\n"],"mappings":"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"}