This commit is contained in:
Macbook
2026-06-14 23:39:51 +09:00
parent b2788ee629
commit 0045f0ef2d
6 changed files with 221 additions and 70 deletions
@@ -0,0 +1,89 @@
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import {
bindPaletteDragOverlayElement,
notifyPaletteDragCancel,
notifyPaletteDragEnd,
notifyPaletteDragMove,
registerPaletteDragOverlay,
type PaletteDragOverlaySession,
} from '../../utils/paletteDragSession';
/**
* Tauri WebView — 드래그 중 전체 화면 overlay 가 pointer 이벤트·drop 을 수신
*/
export default function PaletteDragOverlay() {
const [session, setSession] = useState<PaletteDragOverlaySession | null>(null);
const [cursor, setCursor] = useState({ x: 0, y: 0 });
const overlayRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
registerPaletteDragOverlay({
mount: next => {
setCursor({ x: next.x, y: next.y });
setSession(next);
},
unmount: () => setSession(null),
bindElement: el => {
overlayRef.current = el as HTMLDivElement | null;
},
});
return () => registerPaletteDragOverlay(null);
}, []);
useLayoutEffect(() => {
bindPaletteDragOverlayElement(overlayRef.current);
return () => bindPaletteDragOverlayElement(null);
}, [session]);
useLayoutEffect(() => {
if (!session || !overlayRef.current) return;
try {
overlayRef.current.setPointerCapture(session.pointerId);
} catch {
/* body capture fallback */
}
}, [session]);
const onPointerMove = useCallback((e: React.PointerEvent) => {
if (!session || e.pointerId !== session.pointerId) return;
e.preventDefault();
e.stopPropagation();
setCursor({ x: e.clientX, y: e.clientY });
notifyPaletteDragMove(e.clientX, e.clientY);
}, [session]);
const onPointerUp = useCallback((e: React.PointerEvent) => {
if (!session || e.pointerId !== session.pointerId) return;
e.preventDefault();
e.stopPropagation();
notifyPaletteDragEnd(e.clientX, e.clientY);
}, [session]);
const onPointerCancel = useCallback((e: React.PointerEvent) => {
if (!session || e.pointerId !== session.pointerId) return;
e.preventDefault();
e.stopPropagation();
notifyPaletteDragCancel(e.clientX, e.clientY);
}, [session]);
if (!session) return null;
return createPortal(
<div
ref={overlayRef}
className="se-palette-drag-overlay"
onPointerMove={onPointerMove}
onPointerUp={onPointerUp}
onPointerCancel={onPointerCancel}
>
<div
className="se-palette-drag-overlay-label"
style={{ left: cursor.x, top: cursor.y }}
>
{session.payload.label}
</div>
</div>,
document.body,
);
}