Add hotkey feature, #122
This commit is contained in:
@@ -134,4 +134,189 @@ export function randomDate(): Date {
|
||||
let d = new Date()
|
||||
d.setDate(d.getDate() - Math.random() * 20)
|
||||
return d
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Hotkeys
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Füge diese Typdefinitionen am Anfang der Datei hinzu
|
||||
type HotkeyCallback = (params?: any) => void;
|
||||
type HotkeyEnabledCallback = () => boolean;
|
||||
|
||||
// Füge diese Variablen am Anfang der Datei hinzu
|
||||
const registeredHotkeys = new Map<string, {
|
||||
callback: HotkeyCallback;
|
||||
params: any;
|
||||
enabled: HotkeyEnabledCallback | undefined;
|
||||
}>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Registriert einen globalen Tastatur-Shortcut
|
||||
* @param keyCombination Tastaturkombination (z.B. 'Mod+S' für automatische Erkennung von Cmd/Ctrl)
|
||||
* @param callback Funktion, die aufgerufen werden soll
|
||||
* @param callbackParameters Optionale Parameter für den Callback
|
||||
* @param enabled Optionaler Callback, der angibt, ob der Shortcut aktiv ist
|
||||
* @returns Funktion zum Entfernen des Shortcuts
|
||||
*
|
||||
* @example
|
||||
* // Beispiel 1: Shortcut mit Plus-Taste
|
||||
* const removeZoomInShortcut = hotkey('Mod+plus', () => {
|
||||
* console.log('Zoom in')
|
||||
* });
|
||||
*
|
||||
* @example
|
||||
* // Beispiel 2: Shortcut mit Pfeiltasten
|
||||
* const removeMoveLeftShortcut = hotkey('leftarrow', () => {
|
||||
* console.log('Move left')
|
||||
* });
|
||||
*
|
||||
* @example
|
||||
* // Beispiel 3: Shortcut mit Enter-Taste
|
||||
* const removeSubmitShortcut = hotkey('enter', () => {
|
||||
* console.log('Submit form')
|
||||
* });
|
||||
*
|
||||
* @example
|
||||
* // Beispiel 4: Shortcut mit Escape-Taste
|
||||
* const removeCancelShortcut = hotkey('esc', () => {
|
||||
* console.log('Cancel action')
|
||||
* });
|
||||
*
|
||||
* @example
|
||||
* // Beispiel 5: Shortcut, der nur ausgelöst wird, wenn kein Eingabefeld fokussiert ist
|
||||
* const removeGlobalSearchShortcut = hotkey('Mod+k', () => {
|
||||
* console.log('Open global search')
|
||||
* });
|
||||
*/
|
||||
export function hotkey(
|
||||
keyCombination: string,
|
||||
callback: HotkeyCallback,
|
||||
callbackParameters?: any,
|
||||
enabled?: HotkeyEnabledCallback
|
||||
): () => void {
|
||||
// Ersetzen von 'Mod' durch den passenden Modifier
|
||||
const modifier = getPlatformModifier()
|
||||
|
||||
// Normalisieren der Tastaturkombination
|
||||
const normalizedCombination = keyCombination
|
||||
.toLowerCase()
|
||||
.replace('mod', modifier)
|
||||
.split('+')
|
||||
.map(key => normalizeKeyName(key))
|
||||
.join('+')
|
||||
|
||||
// Überprüfen, ob der Shortcut bereits registriert ist
|
||||
if (registeredHotkeys.has(normalizedCombination)) {
|
||||
console.warn(`Hotkey '${keyCombination}' is already registered. Overwriting existing hotkey.`)
|
||||
}
|
||||
|
||||
// Speichern der Hotkey-Informationen
|
||||
registeredHotkeys.set(normalizedCombination, {
|
||||
callback,
|
||||
params: callbackParameters,
|
||||
enabled
|
||||
});
|
||||
|
||||
// Rückgabe einer Funktion zum Entfernen des Shortcuts
|
||||
return () => {
|
||||
registeredHotkeys.delete(normalizedCombination)
|
||||
};
|
||||
}
|
||||
|
||||
function getPlatformModifier(): string {
|
||||
// Überprüfen, ob wir auf macOS/iOS sind
|
||||
if (navigator.userAgent.includes('Macintosh') ||
|
||||
navigator.userAgent.includes('iPhone') ||
|
||||
navigator.userAgent.includes('iPad')) {
|
||||
return 'cmd'
|
||||
}
|
||||
return 'ctrl'
|
||||
}
|
||||
|
||||
export function getPlatformModifierSymbol(): string {
|
||||
if (navigator.userAgent.includes('Macintosh') ||
|
||||
navigator.userAgent.includes('iPhone') ||
|
||||
navigator.userAgent.includes('iPad')) {
|
||||
return '⌘'
|
||||
}
|
||||
return 'Ctrl'
|
||||
}
|
||||
|
||||
function normalizeKeyName(key: string): string {
|
||||
const keyMap: Record<string, string> = {
|
||||
'+': 'plus',
|
||||
'-': 'minus',
|
||||
'arrowleft': 'leftarrow',
|
||||
'arrowright': 'rightarrow',
|
||||
'arrowup': 'uparrow',
|
||||
'arrowdown': 'downarrow',
|
||||
'return': 'enter',
|
||||
'esc': 'escape'
|
||||
};
|
||||
|
||||
// Konvertiere den Tastennamen in Kleinbuchstaben
|
||||
const lowerKey = key.toLowerCase()
|
||||
|
||||
// Ersetze den Tastennamen, falls in der Map vorhanden
|
||||
return keyMap[lowerKey] || lowerKey
|
||||
}
|
||||
|
||||
function handleKeyboardEvent(event: KeyboardEvent) {
|
||||
// Überprüfen, ob das Event-Element ein Eingabefeld, Textarea oder ähnliches ist
|
||||
const target = event.target as HTMLElement;
|
||||
if (target.tagName === 'INPUT' ||
|
||||
target.tagName === 'TEXTAREA' ||
|
||||
target.tagName === 'SELECT' ||
|
||||
target.isContentEditable) {
|
||||
// Wenn das Event-Element ein Eingabefeld ist, den Shortcut nicht auslösen
|
||||
return;
|
||||
}
|
||||
|
||||
// Erstellen einer normalisierten Tastaturkombination
|
||||
let combination = ''
|
||||
|
||||
// Bestimmen des passenden Modifiers
|
||||
const modifier = getPlatformModifier()
|
||||
|
||||
// Hinzufügen von Modifier-Tasten
|
||||
if ((modifier === 'ctrl' && event.ctrlKey) ||
|
||||
(modifier === 'cmd' && event.metaKey)) {
|
||||
combination += `${modifier}+`
|
||||
}
|
||||
if (event.shiftKey) {
|
||||
combination += 'shift+'
|
||||
}
|
||||
if (event.altKey) {
|
||||
combination += 'alt+'
|
||||
}
|
||||
|
||||
// Hinzufügen der Haupttaste
|
||||
combination += normalizeKeyName(event.key)
|
||||
|
||||
// Überprüfen, ob der Shortcut registriert ist
|
||||
const hotkeyInfo = registeredHotkeys.get(combination);
|
||||
if (hotkeyInfo) {
|
||||
// Überprüfen, ob der Shortcut aktiv ist
|
||||
if (!hotkeyInfo.enabled || hotkeyInfo.enabled()) {
|
||||
// Ausführen des Callbacks mit den Parametern
|
||||
hotkeyInfo.callback(hotkeyInfo.params)
|
||||
|
||||
// Verhindern der Standardaktion, falls gewünscht
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Registrieren des globalen Event-Listeners
|
||||
window.addEventListener('keydown', handleKeyboardEvent);
|
||||
|
||||
// Füge die Funktion zum Entfernen aller Hotkeys hinzu
|
||||
export function removeAllHotkeys() {
|
||||
registeredHotkeys.clear()
|
||||
}
|
||||
Reference in New Issue
Block a user