{"version":3,"file":"validate.cjs","names":["MODIFIER_ALIASES","ALL_KEYS"],"sources":["../src/validate.ts"],"sourcesContent":["import { ALL_KEYS, MODIFIER_ALIASES } from './constants'\nimport type { Hotkey, ValidationResult } from './hotkey'\n\n/**\n * Validates a hotkey string and returns any warnings or errors.\n *\n * Checks for:\n * - Valid syntax (modifier+...+key format)\n * - Known modifiers\n * - Known keys\n *\n * @param hotkey - The hotkey string to validate\n * @returns A ValidationResult with validity status, warnings, and errors\n *\n * @example\n * ```ts\n * validateHotkey('Mod+S')\n * // { valid: true, warnings: [], errors: [] }\n *\n * validateHotkey('')\n * // { valid: false, warnings: [], errors: ['Hotkey cannot be empty'] }\n * ```\n */\nexport function validateHotkey(\n  hotkey: Hotkey | (string & {}),\n): ValidationResult {\n  const warnings: Array<string> = []\n  const errors: Array<string> = []\n\n  // Check for empty string\n  if (!hotkey || hotkey.trim() === '') {\n    return {\n      valid: false,\n      warnings: [],\n      errors: ['Hotkey cannot be empty'],\n    }\n  }\n\n  const parts = hotkey.split('+').map((p) => p.trim())\n\n  // Must have at least one part (the key)\n  if (parts.length === 0 || parts.some((p) => p === '')) {\n    return {\n      valid: false,\n      warnings: [],\n      errors: ['Invalid hotkey format: empty parts detected'],\n    }\n  }\n\n  // Validate modifiers (all parts except the last)\n  const modifierParts = parts.slice(0, -1)\n  const keyPart = parts[parts.length - 1]!\n\n  // Check for unknown modifiers\n  for (const modifier of modifierParts) {\n    const normalized =\n      MODIFIER_ALIASES[modifier] ?? MODIFIER_ALIASES[modifier.toLowerCase()]\n    if (!normalized) {\n      errors.push(`Unknown modifier: '${modifier}'`)\n    }\n  }\n\n  // Check if key is known\n  const normalizedKey = normalizeKeyForValidation(keyPart)\n  if (!isKnownKey(normalizedKey) && !isKnownKey(keyPart)) {\n    warnings.push(\n      `Unknown key: '${keyPart}'. This may still work but won't have type-safe autocomplete.`,\n    )\n  }\n\n  return {\n    valid: errors.length === 0,\n    warnings,\n    errors,\n  }\n}\n\n/**\n * Normalizes a key for validation checking.\n */\nfunction normalizeKeyForValidation(key: string): string {\n  // Single letter to uppercase\n  if (key.length === 1 && /^[a-zA-Z]$/.test(key)) {\n    return key.toUpperCase()\n  }\n\n  // Function keys to uppercase\n  if (/^f([1-9]|1[0-2])$/i.test(key)) {\n    return key.toUpperCase()\n  }\n\n  return key\n}\n\n/**\n * Checks if a key is in the known keys set.\n */\nfunction isKnownKey(key: string): boolean {\n  // Check direct match\n  if (ALL_KEYS.has(key as any)) {\n    return true\n  }\n\n  // Check uppercase version for letters\n  if (key.length === 1 && ALL_KEYS.has(key.toUpperCase() as any)) {\n    return true\n  }\n\n  // Check common aliases\n  const aliases: Record<string, boolean> = {\n    Esc: true,\n    Return: true,\n    Space: true,\n    ' ': true,\n    Del: true,\n    Up: true,\n    Down: true,\n    Left: true,\n    Right: true,\n  }\n\n  return key in aliases\n}\n\n/**\n * Validates a hotkey and throws an error if invalid.\n * Useful for development-time validation.\n *\n * @param hotkey - The hotkey string to validate\n * @throws Error if the hotkey is invalid\n *\n * @example\n * ```ts\n * assertValidHotkey('Mod+S') // OK\n * assertValidHotkey('') // Throws Error: Invalid hotkey: Hotkey cannot be empty\n * ```\n */\nexport function assertValidHotkey(hotkey: Hotkey | (string & {})): void {\n  const result = validateHotkey(hotkey)\n  if (!result.valid) {\n    throw new Error(`Invalid hotkey '${hotkey}': ${result.errors.join(', ')}`)\n  }\n}\n\n/**\n * Validates a hotkey and logs warnings to the console.\n * Useful for development-time feedback.\n *\n * @param hotkey - The hotkey string to validate\n * @returns True if the hotkey is valid (may still have warnings)\n *\n * @example\n * ```ts\n * checkHotkey('Alt+C')\n * // Console: Warning: Alt+C may not work reliably on macOS...\n * // Returns: true\n * ```\n */\nexport function checkHotkey(hotkey: Hotkey | (string & {})): boolean {\n  const result = validateHotkey(hotkey)\n\n  if (result.errors.length > 0) {\n    console.error(`Hotkey '${hotkey}' errors:`, result.errors.join('; '))\n  }\n\n  if (result.warnings.length > 0) {\n    console.warn(`Hotkey '${hotkey}' warnings:`, result.warnings.join('; '))\n  }\n\n  return result.valid\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,eACd,QACkB;CAClB,MAAM,WAA0B,EAAE;CAClC,MAAM,SAAwB,EAAE;AAGhC,KAAI,CAAC,UAAU,OAAO,MAAM,KAAK,GAC/B,QAAO;EACL,OAAO;EACP,UAAU,EAAE;EACZ,QAAQ,CAAC,yBAAyB;EACnC;CAGH,MAAM,QAAQ,OAAO,MAAM,IAAI,CAAC,KAAK,MAAM,EAAE,MAAM,CAAC;AAGpD,KAAI,MAAM,WAAW,KAAK,MAAM,MAAM,MAAM,MAAM,GAAG,CACnD,QAAO;EACL,OAAO;EACP,UAAU,EAAE;EACZ,QAAQ,CAAC,8CAA8C;EACxD;CAIH,MAAM,gBAAgB,MAAM,MAAM,GAAG,GAAG;CACxC,MAAM,UAAU,MAAM,MAAM,SAAS;AAGrC,MAAK,MAAM,YAAY,cAGrB,KAAI,EADFA,mCAAiB,aAAaA,mCAAiB,SAAS,aAAa,GAErE,QAAO,KAAK,sBAAsB,SAAS,GAAG;AAMlD,KAAI,CAAC,WADiB,0BAA0B,QAAQ,CAC1B,IAAI,CAAC,WAAW,QAAQ,CACpD,UAAS,KACP,iBAAiB,QAAQ,+DAC1B;AAGH,QAAO;EACL,OAAO,OAAO,WAAW;EACzB;EACA;EACD;;;;;AAMH,SAAS,0BAA0B,KAAqB;AAEtD,KAAI,IAAI,WAAW,KAAK,aAAa,KAAK,IAAI,CAC5C,QAAO,IAAI,aAAa;AAI1B,KAAI,qBAAqB,KAAK,IAAI,CAChC,QAAO,IAAI,aAAa;AAG1B,QAAO;;;;;AAMT,SAAS,WAAW,KAAsB;AAExC,KAAIC,2BAAS,IAAI,IAAW,CAC1B,QAAO;AAIT,KAAI,IAAI,WAAW,KAAKA,2BAAS,IAAI,IAAI,aAAa,CAAQ,CAC5D,QAAO;AAgBT,QAAO,OAZkC;EACvC,KAAK;EACL,QAAQ;EACR,OAAO;EACP,KAAK;EACL,KAAK;EACL,IAAI;EACJ,MAAM;EACN,MAAM;EACN,OAAO;EACR;;;;;;;;;;;;;;;AAkBH,SAAgB,kBAAkB,QAAsC;CACtE,MAAM,SAAS,eAAe,OAAO;AACrC,KAAI,CAAC,OAAO,MACV,OAAM,IAAI,MAAM,mBAAmB,OAAO,KAAK,OAAO,OAAO,KAAK,KAAK,GAAG;;;;;;;;;;;;;;;;AAkB9E,SAAgB,YAAY,QAAyC;CACnE,MAAM,SAAS,eAAe,OAAO;AAErC,KAAI,OAAO,OAAO,SAAS,EACzB,SAAQ,MAAM,WAAW,OAAO,YAAY,OAAO,OAAO,KAAK,KAAK,CAAC;AAGvE,KAAI,OAAO,SAAS,SAAS,EAC3B,SAAQ,KAAK,WAAW,OAAO,cAAc,OAAO,SAAS,KAAK,KAAK,CAAC;AAG1E,QAAO,OAAO"}