@corti/dictation-web
Version:
Web component for Corti Dictation
125 lines • 3.94 kB
JavaScript
/**
* Checks if the current platform is macOS.
* Uses userAgent string for reliable cross-browser detection.
*
* @returns true if running on macOS
*/
function isMac() {
if (typeof navigator === "undefined") {
return false;
}
// Check user agent for Mac patterns (most reliable method)
return /Mac|iPhone|iPad|iPod/.test(navigator.userAgent);
}
/**
* Capitalizes the first letter of a string.
*
* @param str - String to capitalize
* @returns String with first letter capitalized
*/
function capitalize(str) {
if (str.length === 0) {
return str;
}
return str.charAt(0).toUpperCase() + str.slice(1);
}
/**
* Normalizes a key string to the keybinding format.
* Handles platform-specific mappings and capitalization.
*
* @param key - Key string to normalize (will be trimmed and lowercased)
* @returns Formatted key string for keybinding
*
* @example
* normalizeKeyForKeybinding("Control") // "Ctrl"
* normalizeKeyForKeybinding("META") // "Cmd" on Mac, "Meta" elsewhere
* normalizeKeyForKeybinding(" alt ") // "Opt" on Mac, "Alt" elsewhere
* normalizeKeyForKeybinding("shift") // "Shift"
* normalizeKeyForKeybinding("k") // "k"
*/
function normalizeKeyForKeybinding(key) {
if (key === " ") {
return "Space";
}
const normalized = key.trim().toLowerCase();
if (normalized === "control") {
return "Ctrl";
}
if (normalized === "meta" || normalized === "cmd") {
return isMac() ? "Cmd" : "Meta";
}
if (normalized === "alt" || normalized === "opt") {
return isMac() ? "Opt" : "Alt";
}
if (normalized === "space") {
return "Space";
}
return normalized.length > 1 ? capitalize(normalized) : normalized;
}
/**
* Normalizes a keybinding string.
*
* @param keybinding - Keybinding string to normalize
* @returns Normalized keybinding string or null if empty
*
* @example
* normalizeKeybinding("k") // "k"
* normalizeKeybinding("meta") // "Cmd" on Mac
* normalizeKeybinding(" space ") // "Space"
*/
export function normalizeKeybinding(keybinding) {
if (!keybinding) {
return null;
}
const trimmed = keybinding.trim();
if (trimmed === "") {
return null;
}
return normalizeKeyForKeybinding(trimmed);
}
/**
* Checks if a pressed key matches the keybinding.
* Checks both event.key and event.code for better reliability.
*
* @param event - KeyboardEvent to check
* @param keybinding - Keybinding string to match against
* @returns true if either the key or code matches the keybinding
*
* @example
* matchesKeybinding(event, "k") // true if event.key is "k" or event.code is "KeyK"
* matchesKeybinding(event, "`") // true if event.key is "`" or event.code is "Backquote"
*/
export function matchesKeybinding(event, keybinding) {
const normalizedKeybinding = normalizeKeybinding(keybinding);
if (!normalizedKeybinding) {
return false;
}
const normalizedKey = normalizeKeyForKeybinding(event.key);
const normalizedCode = normalizeKeyForKeybinding(event.code);
return (normalizedKey === normalizedKeybinding ||
normalizedCode === normalizedKeybinding);
}
/**
* Checks if keybindings should be ignored for the current active element.
* Returns true if the user is typing in an input field.
*
* @param element - Element to check
* @returns true if keybindings should be ignored for this element
*
* @example
* shouldIgnoreKeybinding(document.activeElement) // true if input/textarea/contenteditable
*/
export function shouldIgnoreKeybinding(element) {
if (!element) {
return false;
}
const tagName = element.tagName.toLowerCase();
if (tagName === "input" || tagName === "textarea") {
return true;
}
if (element instanceof HTMLElement && element.contentEditable === "true") {
return true;
}
return false;
}
//# sourceMappingURL=keybinding.js.map