{"version":3,"file":"parse.cjs","names":["detectPlatform","normalizeKeyName","MODIFIER_ALIASES","resolveModifier","MODIFIER_ORDER"],"sources":["../src/parse.ts"],"sourcesContent":["import {\n  MODIFIER_ALIASES,\n  MODIFIER_ORDER,\n  detectPlatform,\n  normalizeKeyName,\n  resolveModifier,\n} from './constants'\nimport type {\n  CanonicalModifier,\n  Hotkey,\n  Key,\n  ParsedHotkey,\n  RawHotkey,\n  RegisterableHotkey,\n} from './hotkey'\n\n/**\n * Parses a hotkey string into its component parts.\n *\n * @param hotkey - The hotkey string to parse (e.g., 'Mod+Shift+S')\n * @param platform - The target platform for resolving 'Mod' (defaults to auto-detection)\n * @returns A ParsedHotkey object with the key and modifier flags\n *\n * @example\n * ```ts\n * parseHotkey('Mod+S') // On Mac: { key: 'S', ctrl: false, shift: false, alt: false, meta: true, modifiers: ['Meta'] }\n * parseHotkey('Mod+S') // On Windows: { key: 'S', ctrl: true, shift: false, alt: false, meta: false, modifiers: ['Control'] }\n * parseHotkey('Control+Shift+A') // { key: 'A', ctrl: true, shift: true, alt: false, meta: false, modifiers: ['Control', 'Shift'] }\n * ```\n */\nexport function parseHotkey(\n  hotkey: Hotkey | (string & {}),\n  platform: 'mac' | 'windows' | 'linux' = detectPlatform(),\n): ParsedHotkey {\n  const parts = hotkey.split('+')\n  const modifiers: Set<CanonicalModifier> = new Set()\n  let key = ''\n\n  for (let i = 0; i < parts.length; i++) {\n    const part = parts[i]!.trim()\n\n    if (i === parts.length - 1) {\n      // Last part is always the key\n      key = normalizeKeyName(part)\n    } else {\n      // All other parts are modifiers\n      const alias =\n        MODIFIER_ALIASES[part] ?? MODIFIER_ALIASES[part.toLowerCase()]\n\n      if (alias) {\n        const resolved = resolveModifier(alias, platform)\n        modifiers.add(resolved)\n      } else {\n        // Unknown modifier, treat as part of the key if it's the only part\n        // or ignore if there are more parts\n        if (parts.length === 1) {\n          key = normalizeKeyName(part)\n        }\n      }\n    }\n  }\n\n  // If no key was found (empty string), use the last part as-is\n  if (!key && parts.length > 0) {\n    key = normalizeKeyName(parts[parts.length - 1]!.trim())\n  }\n\n  return {\n    key,\n    ctrl: modifiers.has('Control'),\n    shift: modifiers.has('Shift'),\n    alt: modifiers.has('Alt'),\n    meta: modifiers.has('Meta'),\n    modifiers: MODIFIER_ORDER.filter((m) => modifiers.has(m)),\n  }\n}\n\n/**\n * Converts a RawHotkey object to a ParsedHotkey.\n * Optional modifier booleans default to false; modifiers array is derived from them.\n * When `mod` is true, it is resolved to Control or Meta based on platform.\n *\n * @param raw - The raw hotkey object\n * @param platform - The target platform for resolving 'Mod' (defaults to auto-detection)\n * @returns A ParsedHotkey suitable for matching and formatting\n *\n * @example\n * ```ts\n * rawHotkeyToParsedHotkey({ key: 'Escape' })\n * // { key: 'Escape', ctrl: false, shift: false, alt: false, meta: false, modifiers: [] }\n *\n * rawHotkeyToParsedHotkey({ key: 'S', mod: true }, 'mac')\n * // { key: 'S', ctrl: false, shift: false, alt: false, meta: true, modifiers: ['Meta'] }\n *\n * rawHotkeyToParsedHotkey({ key: 'S', mod: true, shift: true }, 'windows')\n * // { key: 'S', ctrl: true, shift: true, alt: false, meta: false, modifiers: ['Control', 'Shift'] }\n * ```\n */\nexport function rawHotkeyToParsedHotkey(\n  raw: RawHotkey,\n  platform: 'mac' | 'windows' | 'linux' = detectPlatform(),\n): ParsedHotkey {\n  let ctrl = raw.ctrl ?? false\n  const shift = raw.shift ?? false\n  const alt = raw.alt ?? false\n  let meta = raw.meta ?? false\n\n  if (raw.mod) {\n    const resolved = resolveModifier('Mod', platform)\n    if (resolved === 'Control') {\n      ctrl = true\n    } else {\n      meta = true\n    }\n  }\n\n  const modifiers: Array<CanonicalModifier> = MODIFIER_ORDER.filter((m) => {\n    switch (m) {\n      case 'Control':\n        return ctrl\n      case 'Shift':\n        return shift\n      case 'Alt':\n        return alt\n      case 'Meta':\n        return meta\n      default:\n        return false\n    }\n  })\n  return {\n    key: raw.key,\n    ctrl,\n    shift,\n    alt,\n    meta,\n    modifiers,\n  }\n}\n\n/**\n * Serializes a parsed hotkey to the canonical string form used for registration\n * and storage: `Mod` first when the platform allows, then `Alt`, then `Shift`;\n * otherwise full `Control+Alt+Shift+Meta` order.\n */\nfunction normalizedHotkeyStringFromParsed(\n  parsed: ParsedHotkey,\n  platform: 'mac' | 'windows' | 'linux',\n): Hotkey {\n  const canUseMod =\n    platform === 'mac'\n      ? parsed.meta && !parsed.ctrl\n      : parsed.ctrl && !parsed.meta\n\n  const parts: Array<string> = []\n\n  if (canUseMod) {\n    parts.push('Mod')\n    if (parsed.alt) {\n      parts.push('Alt')\n    }\n    if (parsed.shift) {\n      parts.push('Shift')\n    }\n  } else {\n    for (const modifier of MODIFIER_ORDER) {\n      if (parsed.modifiers.includes(modifier)) {\n        parts.push(modifier)\n      }\n    }\n  }\n\n  parts.push(normalizeKeyName(parsed.key))\n  return parts.join('+') as Hotkey\n}\n\n/**\n * Normalizes a hotkey string to its canonical form.\n *\n * - When `Mod` is allowed for the platform (Command on Mac without Control;\n *   Control on Windows/Linux without Meta): emits `Mod`, then `Alt`, then `Shift`,\n *   then the key (e.g. `Mod+Shift+E`, `Mod+S`).\n * - Otherwise: literal modifiers in `Control+Alt+Shift+Meta` order, then the key.\n * - Resolves aliases and normalizes key casing (e.g. `esc` → `Escape`, `a` → `A`).\n *\n * @param hotkey - The hotkey string to normalize\n * @param platform - The target platform for resolving `Mod` (defaults to auto-detection)\n * @returns The normalized hotkey string\n *\n * @example\n * ```ts\n * normalizeHotkey('shift+meta+e', 'mac') // 'Mod+Shift+E'\n * normalizeHotkey('ctrl+a', 'windows') // 'Mod+A'\n * normalizeHotkey('esc') // 'Escape'\n * ```\n */\nexport function normalizeHotkey(\n  hotkey: Key | (string & {}),\n  platform: 'mac' | 'windows' | 'linux' = detectPlatform(),\n): Hotkey {\n  return normalizedHotkeyStringFromParsed(\n    parseHotkey(hotkey, platform),\n    platform,\n  )\n}\n\n/**\n * Same canonical string as {@link normalizeHotkey}, but from an already-parsed hotkey.\n */\nexport function normalizeHotkeyFromParsed(\n  parsed: ParsedHotkey,\n  platform: 'mac' | 'windows' | 'linux' = detectPlatform(),\n): Hotkey {\n  return normalizedHotkeyStringFromParsed(parsed, platform)\n}\n\n/**\n * Normalizes a string or {@link RawHotkey} object to the same canonical hotkey string.\n * Use this in framework adapters instead of branching on `formatHotkey(rawHotkeyToParsedHotkey(...))`.\n */\nexport function normalizeRegisterableHotkey(\n  hotkey: RegisterableHotkey,\n  platform: 'mac' | 'windows' | 'linux' = detectPlatform(),\n): Hotkey {\n  return typeof hotkey === 'string'\n    ? normalizeHotkey(hotkey, platform)\n    : normalizeHotkeyFromParsed(\n        rawHotkeyToParsedHotkey(hotkey, platform),\n        platform,\n      )\n}\n\n/**\n * Checks if a string is a recognized modifier token (including aliases).\n *\n * For a `KeyboardEvent`, use `isModifier(normalizeKeyName(event.key))` so DOM\n * spellings like `OS` / `Win` match the same alias table.\n *\n * @param key - Key name or alias (e.g. from a hotkey string or `event.key`)\n * @returns True if the string is a recognized modifier\n */\nexport function isModifierKey(\n  key: Key | (string & {}),\n): key is keyof typeof MODIFIER_ALIASES {\n  return key in MODIFIER_ALIASES || key.toLowerCase() in MODIFIER_ALIASES\n}\n\n/**\n * Parses a KeyboardEvent into a ParsedHotkey object.\n *\n * This function extracts the key and modifier state from a keyboard event\n * and converts it into the same format used by `parseHotkey()`.\n *\n * @param event - The KeyboardEvent to parse\n * @param platform - The target platform for resolving modifiers (defaults to auto-detection)\n * @returns A ParsedHotkey object representing the keyboard event\n *\n * @example\n * ```ts\n * document.addEventListener('keydown', (event) => {\n *   const parsed = parseKeyboardEvent(event)\n *   console.log(parsed) // { key: 'S', ctrl: true, shift: false, ... }\n * })\n * ```\n */\nexport function parseKeyboardEvent(event: KeyboardEvent): ParsedHotkey {\n  const normalizedKey = normalizeKeyName(event.key)\n\n  // Build modifiers array in canonical order\n  const modifiers: Array<CanonicalModifier> = []\n  if (event.ctrlKey) modifiers.push('Control')\n  if (event.altKey) modifiers.push('Alt')\n  if (event.shiftKey) modifiers.push('Shift')\n  if (event.metaKey) modifiers.push('Meta')\n\n  return {\n    key: normalizedKey,\n    ctrl: event.ctrlKey,\n    shift: event.shiftKey,\n    alt: event.altKey,\n    meta: event.metaKey,\n    modifiers,\n  }\n}\n\n/**\n * Normalizes a keyboard event to the same canonical hotkey string as {@link normalizeHotkey}.\n *\n * @param event - The keyboard event (typically `keydown`)\n * @param platform - Target platform for `Mod` eligibility\n */\nexport function normalizeHotkeyFromEvent(\n  event: KeyboardEvent,\n  platform: 'mac' | 'windows' | 'linux' = detectPlatform(),\n): Hotkey {\n  return normalizedHotkeyStringFromParsed(parseKeyboardEvent(event), platform)\n}\n\n/**\n * Checks if a hotkey or ParsedHotkey contains at least one non-modifier key.\n *\n * This is useful for validating that a recorded hotkey is complete and not\n * just a combination of modifiers without an action key.\n *\n * @param hotkey - The hotkey string or ParsedHotkey to check\n * @param platform - The target platform for parsing (defaults to auto-detection)\n * @returns True if the hotkey contains at least one non-modifier key\n *\n * @example\n * ```ts\n * hasNonModifierKey('Control+Shift+S') // true\n * hasNonModifierKey('Control+Shift') // false (no action key)\n * hasNonModifierKey(parseHotkey('Mod+A')) // true\n * ```\n */\nexport function hasNonModifierKey(\n  hotkey: Hotkey | ParsedHotkey | (string & {}),\n  platform: 'mac' | 'windows' | 'linux' = detectPlatform(),\n): boolean {\n  const parsed =\n    typeof hotkey === 'string' ? parseHotkey(hotkey, platform) : hotkey\n\n  // Check if the key part is actually a modifier\n  const keyIsModifier = isModifierKey(parsed.key)\n\n  // A valid hotkey must have a non-modifier key\n  return !keyIsModifier && parsed.key.length > 0\n}\n"],"mappings":"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"}