/** * Keyboard event handlers */ /** * Create keyboard event handler * @param {HTMLElement} container - Container element * @param {Object} state - Editor state * @param {Object} callbacks - Callback functions * @param {Function} callbacks.setMode - Set editor mode * @param {Function} callbacks.getActiveShape - Get active shape * @param {Function} callbacks.promoteToKeyframe - Promote to keyframe * @param {Function} callbacks.commitFrame - Commit frame * @param {Function} callbacks.redraw - Redraw canvas * @param {Function} callbacks.removeDocumentListeners - Remove document listeners * @param {Function} callbacks.updateAddPointButton - Update add point button */ export function createKeyboardHandlers(container, state, callbacks) { function handleKeydown(e) { // Only handle if not typing in an input if (e.target.tagName === "INPUT" || e.target.tagName === "TEXTAREA") { return; } if (e.key === "b" || e.key === "B") { state.selectedCurves.clear(); state.selectedPoints.clear(); callbacks.setMode("draw"); e.preventDefault(); } else if (e.key === "v" || e.key === "V") { callbacks.setMode("edit"); e.preventDefault(); } else if (e.key === "Delete" || e.key === "Backspace") { if (state.mode === "edit" && state.selectedCurves.size > 0) { const shape = callbacks.getActiveShape(); const frameKey = String(state.currentFrame); // Promote only the selected curves to be deleted state.selectedCurves.forEach(curveId => { callbacks.promoteToKeyframe(curveId); }); const curves = shape.frames[frameKey] || []; state.selectedCurves.forEach(curveId => { const index = curves.findIndex(c => c.id === curveId); if (index !== -1) { curves.splice(index, 1); } }); state.selectedCurves.clear(); state.selectedPoints.clear(); callbacks.commitFrame(); callbacks.redraw(); e.preventDefault(); } } else if (e.key === "Escape") { // Cancel selection box if active if (state.selectionBox !== null) { state.selectionBox = null; } // Cancel add point mode if active if (state.addPointMode) { state.addPointMode = false; callbacks.updateAddPointButton(); } // Cancel dragging if active if (state.dragging) { state.dragging = false; state.dragStart = null; callbacks.removeDocumentListeners(); } state.selectedCurves.clear(); state.selectedPoints.clear(); callbacks.redraw(); e.preventDefault(); } } // Keyboard shortcuts (scoped to container, with document fallback) container.addEventListener("keydown", handleKeydown); document.addEventListener("keydown", handleKeydown); }