|
8 | 8 | * - Spacing and alignment helpers |
9 | 9 | */ |
10 | 10 |
|
11 | | -import React, { useEffect } from 'react'; |
| 11 | +import React from 'react'; |
12 | 12 | import { DesignerProvider } from '../context/DesignerContext'; |
13 | 13 | import { Canvas } from './Canvas'; |
14 | 14 | import { PropertyPanel } from './PropertyPanel'; |
15 | 15 | import { FilteredComponentPalette } from './FilteredComponentPalette'; |
16 | 16 | import { ComponentTree } from './ComponentTree'; |
17 | 17 | import { useDesigner } from '../context/DesignerContext'; |
| 18 | +import { useKeyboardShortcuts } from '../hooks/useKeyboardShortcuts'; |
18 | 19 | import type { SchemaNode } from '@object-ui/core'; |
19 | 20 | import type { LayoutDesignerConfig } from '../types/designer-modes'; |
20 | 21 |
|
@@ -61,59 +62,19 @@ export const LayoutDesignerContent: React.FC = () => { |
61 | 62 | canRedo |
62 | 63 | } = useDesigner(); |
63 | 64 |
|
64 | | - // Keyboard shortcuts |
65 | | - useEffect(() => { |
66 | | - const handleKeyDown = (e: KeyboardEvent) => { |
67 | | - // Check if we're in an editable element |
68 | | - const target = e.target as HTMLElement; |
69 | | - const isEditing = |
70 | | - target.tagName === 'INPUT' || |
71 | | - target.tagName === 'TEXTAREA' || |
72 | | - target.tagName === 'SELECT' || |
73 | | - target.isContentEditable; |
74 | | - |
75 | | - // Undo: Ctrl+Z / Cmd+Z |
76 | | - if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey && canUndo) { |
77 | | - e.preventDefault(); |
78 | | - undo(); |
79 | | - } |
80 | | - // Redo: Ctrl+Y / Cmd+Shift+Z |
81 | | - else if (((e.ctrlKey || e.metaKey) && e.key === 'y') || ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'z')) { |
82 | | - if (canRedo) { |
83 | | - e.preventDefault(); |
84 | | - redo(); |
85 | | - } |
86 | | - } |
87 | | - // Copy: Ctrl+C / Cmd+C (only when not editing) |
88 | | - else if ((e.ctrlKey || e.metaKey) && e.key === 'c' && !isEditing && selectedNodeId) { |
89 | | - e.preventDefault(); |
90 | | - copyNode(selectedNodeId); |
91 | | - } |
92 | | - // Cut: Ctrl+X / Cmd+X (only when not editing) |
93 | | - else if ((e.ctrlKey || e.metaKey) && e.key === 'x' && !isEditing && selectedNodeId) { |
94 | | - e.preventDefault(); |
95 | | - cutNode(selectedNodeId); |
96 | | - } |
97 | | - // Paste: Ctrl+V / Cmd+V (only when not editing) |
98 | | - else if ((e.ctrlKey || e.metaKey) && e.key === 'v' && !isEditing) { |
99 | | - e.preventDefault(); |
100 | | - pasteNode(selectedNodeId); |
101 | | - } |
102 | | - // Duplicate: Ctrl+D / Cmd+D (only when not editing) |
103 | | - else if ((e.ctrlKey || e.metaKey) && e.key === 'd' && !isEditing && selectedNodeId) { |
104 | | - e.preventDefault(); |
105 | | - duplicateNode(selectedNodeId); |
106 | | - } |
107 | | - // Delete: Delete / Backspace (only when not editing) |
108 | | - else if ((e.key === 'Delete' || e.key === 'Backspace') && !isEditing && selectedNodeId) { |
109 | | - e.preventDefault(); |
110 | | - removeNode(selectedNodeId); |
111 | | - } |
112 | | - }; |
113 | | - |
114 | | - window.addEventListener('keydown', handleKeyDown); |
115 | | - return () => window.removeEventListener('keydown', handleKeyDown); |
116 | | - }, [undo, redo, copyNode, cutNode, duplicateNode, pasteNode, removeNode, selectedNodeId, canUndo, canRedo]); |
| 65 | + // Use shared keyboard shortcuts hook |
| 66 | + useKeyboardShortcuts({ |
| 67 | + undo, |
| 68 | + redo, |
| 69 | + copyNode, |
| 70 | + cutNode, |
| 71 | + duplicateNode, |
| 72 | + pasteNode, |
| 73 | + removeNode, |
| 74 | + selectedNodeId, |
| 75 | + canUndo, |
| 76 | + canRedo, |
| 77 | + }); |
117 | 78 |
|
118 | 79 | return ( |
119 | 80 | <div className="h-full flex flex-col bg-white text-gray-900 font-sans"> |
|
0 commit comments