mirror of
https://github.com/codeaashu/claude-code.git
synced 2026-04-08 14:18:50 +03:00
88 lines
2.5 KiB
TypeScript
88 lines
2.5 KiB
TypeScript
// Detects Mac at module load time (safe to call on client, returns false on server)
|
|
export const isMac =
|
|
typeof navigator !== "undefined" && /Mac|iPhone|iPad/i.test(navigator.platform);
|
|
|
|
export interface ParsedKey {
|
|
mod: boolean;
|
|
ctrl: boolean;
|
|
shift: boolean;
|
|
alt: boolean;
|
|
key: string;
|
|
}
|
|
|
|
/**
|
|
* Parse a shortcut string like "mod+shift+k" into a structured object.
|
|
* Supports modifiers: mod, ctrl, shift, alt
|
|
* `mod` = Cmd on Mac, Ctrl on Win/Linux
|
|
*/
|
|
export function parseKey(keyString: string): ParsedKey {
|
|
const parts = keyString.toLowerCase().split("+");
|
|
const key = parts[parts.length - 1];
|
|
return {
|
|
mod: parts.includes("mod"),
|
|
ctrl: parts.includes("ctrl"),
|
|
shift: parts.includes("shift"),
|
|
alt: parts.includes("alt"),
|
|
key,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Test whether a KeyboardEvent matches a parsed key definition.
|
|
*/
|
|
export function matchesEvent(parsed: ParsedKey, e: KeyboardEvent): boolean {
|
|
// On Mac, `mod` maps to metaKey; on Win/Linux it maps to ctrlKey
|
|
const expectedMeta = isMac ? parsed.mod : false;
|
|
const expectedCtrl = isMac ? parsed.ctrl : parsed.mod || parsed.ctrl;
|
|
|
|
if (e.metaKey !== expectedMeta) return false;
|
|
if (e.ctrlKey !== expectedCtrl) return false;
|
|
if (e.altKey !== parsed.alt) return false;
|
|
|
|
// For alphanumeric keys, enforce the shift modifier check explicitly.
|
|
// For symbol characters (?, /, comma, etc.) shift is implicit in the key value,
|
|
// so we skip the shift check and just match on e.key.
|
|
const keyIsAlphanumeric = /^[a-z0-9]$/.test(parsed.key);
|
|
if (keyIsAlphanumeric && e.shiftKey !== parsed.shift) return false;
|
|
|
|
return e.key.toLowerCase() === parsed.key;
|
|
}
|
|
|
|
/**
|
|
* Format a key combo string for display.
|
|
* Returns an array of display segments, e.g. ["⌘", "K"] or ["Ctrl", "K"].
|
|
*/
|
|
export function formatKeyCombo(keyString: string): string[] {
|
|
const parts = keyString.split("+");
|
|
return parts.map((part) => {
|
|
switch (part.toLowerCase()) {
|
|
case "mod":
|
|
return isMac ? "⌘" : "Ctrl";
|
|
case "shift":
|
|
return isMac ? "⇧" : "Shift";
|
|
case "alt":
|
|
return isMac ? "⌥" : "Alt";
|
|
case "ctrl":
|
|
return isMac ? "⌃" : "Ctrl";
|
|
case "enter":
|
|
return "↵";
|
|
case "escape":
|
|
return "Esc";
|
|
case "backspace":
|
|
return "⌫";
|
|
case "tab":
|
|
return "Tab";
|
|
case "arrowup":
|
|
return "↑";
|
|
case "arrowdown":
|
|
return "↓";
|
|
case "arrowleft":
|
|
return "←";
|
|
case "arrowright":
|
|
return "→";
|
|
default:
|
|
return part.toUpperCase();
|
|
}
|
|
});
|
|
}
|