-
Notifications
You must be signed in to change notification settings - Fork 256
Expand file tree
/
Copy pathDragCaptureOverlay.tsx
More file actions
73 lines (62 loc) · 2.5 KB
/
Copy pathDragCaptureOverlay.tsx
File metadata and controls
73 lines (62 loc) · 2.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
'use client';
/**
* DragCaptureOverlay Component
*
* Renders a transparent overlay during drag-and-drop operations from
* ElementLibrary to Canvas. This overlay prevents the iframe from
* capturing/swallowing mouse events, ensuring they bubble up to the
* document level where our drag handlers are listening.
*
* Renders as a PORTAL to document.body to escape CSS stacking contexts
* created by transform (zoom) on the canvas. Without this, the overlay
* would be behind the transformed canvas despite having higher z-index.
*/
import { useEffect } from 'react';
import { createPortal } from 'react-dom';
import { useEditorStore } from '@/stores/useEditorStore';
import { setDragCursor, clearDragCursor } from '@/lib/drag-cursor';
export function DragCaptureOverlay() {
// Subscribe directly to store to avoid parent re-renders
const isDraggingToCanvas = useEditorStore((state) => state.isDraggingToCanvas);
const isDraggingLayerOnCanvas = useEditorStore((state) => state.isDraggingLayerOnCanvas);
// Show overlay for both element-to-canvas drag AND sibling reorder drag
const isDragging = isDraggingToCanvas || isDraggingLayerOnCanvas;
// Set cursor on both documents when overlay appears
useEffect(() => {
if (!isDragging) return;
// Find the canvas iframe and set cursor on its document AND the iframe element itself
const iframe = document.querySelector('iframe[title="Canvas Editor"]') as HTMLIFrameElement | null;
const iframeDoc = iframe?.contentDocument;
// Pass both iframe document and iframe element for comprehensive cursor setting
setDragCursor(iframeDoc, iframe);
return () => {
clearDragCursor(iframeDoc);
};
}, [isDragging]);
// Only render when actively dragging
if (!isDragging || typeof document === 'undefined') return null;
// Render as portal to document.body to escape stacking context issues
return createPortal(
<div
style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 9998,
// Transparent
background: 'transparent',
// Ensure pointer events are captured by this overlay
pointerEvents: 'auto',
// Cursor to indicate dragging is active - must be grabbing
cursor: 'grabbing',
}}
// Prevent any click/mousedown from reaching elements beneath
onMouseDown={(e) => e.preventDefault()}
onClick={(e) => e.preventDefault()}
/>,
document.body
);
}
export default DragCaptureOverlay;