feat(builder): implement Ctrl+C/V copy-paste shortcuts
The context menu advertised Ctrl+C/Ctrl+V hints but useKeyboardShortcuts only handled undo/redo/delete/duplicate/escape -- pressing them did nothing. Add a tiny shared module-level clipboard (src/hooks/clipboard.ts) used by both the keyboard hook and the context menu so copying via one entry point and pasting via the other stay consistent. Ctrl/Cmd+C stores the selected node id (skipping ROOT). Ctrl/Cmd+V inserts a copy as a sibling of the current selection via regenerateTreeIds, mirroring the existing context-menu paste behavior. Both respect the existing "disabled while typing" guard. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import { findDeletableTarget } from '../../utils/craft-helpers';
|
||||
import { useSitesmithModal } from '../../state/SitesmithContext';
|
||||
import { buildSitesmithTarget } from '../../utils/sitesmith-target';
|
||||
import { regenerateTreeIds } from '../../utils/craft-tree';
|
||||
import { getClipboardNodeId, setClipboardNodeId } from '../../hooks/clipboard';
|
||||
|
||||
interface ContextMenuProps {
|
||||
visible: boolean;
|
||||
@@ -32,7 +33,6 @@ export const ContextMenu: React.FC<ContextMenuProps> = ({
|
||||
const { actions, query } = useEditor();
|
||||
const { open: openSitesmith } = useSitesmithModal();
|
||||
const menuRef = useRef<HTMLDivElement>(null);
|
||||
const clipboardRef = useRef<string | null>(null);
|
||||
|
||||
// Close on click outside
|
||||
useEffect(() => {
|
||||
@@ -80,7 +80,7 @@ export const ContextMenu: React.FC<ContextMenuProps> = ({
|
||||
const copyNode = useCallback(() => {
|
||||
if (!nodeId || nodeId === 'ROOT') return;
|
||||
try {
|
||||
clipboardRef.current = nodeId;
|
||||
setClipboardNodeId(nodeId);
|
||||
} catch (e) {
|
||||
console.error('Copy failed:', e);
|
||||
}
|
||||
@@ -88,7 +88,7 @@ export const ContextMenu: React.FC<ContextMenuProps> = ({
|
||||
}, [nodeId, onClose]);
|
||||
|
||||
const pasteNode = useCallback(() => {
|
||||
const sourceId = clipboardRef.current;
|
||||
const sourceId = getClipboardNodeId();
|
||||
if (!sourceId) {
|
||||
onClose();
|
||||
return;
|
||||
@@ -210,7 +210,7 @@ export const ContextMenu: React.FC<ContextMenuProps> = ({
|
||||
label: 'Paste',
|
||||
shortcut: 'Ctrl+V',
|
||||
action: pasteNode,
|
||||
disabled: !clipboardRef.current,
|
||||
disabled: !getClipboardNodeId(),
|
||||
dividerAfter: true,
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user