Files
TaskMate/frontend/js/shortcuts.js
Claude Project Manager ab1e5be9a9 Initial commit
2025-12-28 21:36:45 +00:00

142 Zeilen
3.2 KiB
JavaScript

/**
* TASKMATE - Keyboard Shortcuts Module
* =====================================
* Global keyboard shortcuts (only non-browser-conflicting)
*/
import store from './store.js';
import { $ } from './utils.js';
class ShortcutsManager {
constructor() {
this.shortcuts = new Map();
this.isEnabled = true;
this.registerDefaultShortcuts();
this.bindEvents();
}
bindEvents() {
document.addEventListener('keydown', (e) => this.handleKeydown(e));
}
handleKeydown(e) {
// Don't handle shortcuts when typing in inputs
if (this.isInputFocused()) return;
// Don't handle when modals are open (except escape)
if (store.get('openModals').length > 0 && e.key !== 'Escape') return;
// Don't handle when disabled
if (!this.isEnabled) return;
const combo = this.getKeyCombo(e);
const handler = this.shortcuts.get(combo);
if (handler) {
e.preventDefault();
handler(e);
}
}
getKeyCombo(e) {
const parts = [];
if (e.ctrlKey || e.metaKey) parts.push('Ctrl');
if (e.altKey) parts.push('Alt');
if (e.shiftKey) parts.push('Shift');
// Get the key
let key = e.key;
if (key === ' ') key = 'Space';
if (key.length === 1) key = key.toUpperCase();
parts.push(key);
return parts.join('+');
}
isInputFocused() {
const activeElement = document.activeElement;
const tagName = activeElement?.tagName.toLowerCase();
const isContentEditable = activeElement?.contentEditable === 'true';
return ['input', 'textarea', 'select'].includes(tagName) || isContentEditable;
}
// =====================
// SHORTCUT REGISTRATION
// =====================
register(combo, handler, description = '') {
this.shortcuts.set(combo, handler);
// Store description for help display
handler.description = description;
}
unregister(combo) {
this.shortcuts.delete(combo);
}
enable() {
this.isEnabled = true;
}
disable() {
this.isEnabled = false;
}
// =====================
// DEFAULT SHORTCUTS
// =====================
registerDefaultShortcuts() {
// Only Escape - close modals (doesn't conflict with browser)
this.register('Escape', () => this.handleEscape(), 'Schließen / Abbrechen');
}
// =====================
// SHORTCUT HANDLERS
// =====================
handleEscape() {
const openModals = store.get('openModals');
if (openModals.length > 0) {
// Close the topmost modal
const topModal = openModals[openModals.length - 1];
window.dispatchEvent(new CustomEvent('modal:close', {
detail: { modalId: topModal }
}));
} else {
// Clear selection
store.clearSelection();
}
}
showHelp() {
// No longer needed - shortcuts removed
}
// =====================
// HELP DISPLAY
// =====================
getShortcutsList() {
// Minimal shortcuts that don't conflict with browser
return {
actions: {
title: 'Aktionen',
shortcuts: [
{ combo: 'Escape', description: 'Dialog schließen / Auswahl aufheben' }
]
}
};
}
}
// Create and export singleton
const shortcutsManager = new ShortcutsManager();
export default shortcutsManager;