mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-25 20:15:37 +02:00
When editors are empty, the internal drop overlay was too small to be useful. Move the overlay to the parent container with a lighter style so the drop target covers the full input area regardless of content. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
70 lines
1.8 KiB
TypeScript
70 lines
1.8 KiB
TypeScript
import { useState, useEffect, useCallback, useRef, type DragEvent } from "react";
|
|
|
|
interface UseFileDropZoneOptions {
|
|
onDrop: (files: File[]) => void;
|
|
enabled?: boolean;
|
|
}
|
|
|
|
function useFileDropZone({ onDrop, enabled = true }: UseFileDropZoneOptions) {
|
|
const [isDragOver, setIsDragOver] = useState(false);
|
|
const onDropRef = useRef(onDrop);
|
|
onDropRef.current = onDrop;
|
|
|
|
// Clear on any document-level drop or dragend (e.g. user drops outside the zone)
|
|
useEffect(() => {
|
|
if (!enabled) return;
|
|
const clear = () => setIsDragOver(false);
|
|
document.addEventListener("drop", clear);
|
|
document.addEventListener("dragend", clear);
|
|
return () => {
|
|
document.removeEventListener("drop", clear);
|
|
document.removeEventListener("dragend", clear);
|
|
};
|
|
}, [enabled]);
|
|
|
|
const handleDragEnter = useCallback(
|
|
(e: DragEvent) => {
|
|
e.preventDefault();
|
|
if (enabled && e.dataTransfer.types.includes("Files")) {
|
|
setIsDragOver(true);
|
|
}
|
|
},
|
|
[enabled],
|
|
);
|
|
|
|
const handleDragOver = useCallback((e: DragEvent) => {
|
|
e.preventDefault();
|
|
}, []);
|
|
|
|
const handleDragLeave = useCallback((e: DragEvent) => {
|
|
if (!e.currentTarget.contains(e.relatedTarget as Node)) {
|
|
setIsDragOver(false);
|
|
}
|
|
}, []);
|
|
|
|
const handleDrop = useCallback(
|
|
(e: DragEvent) => {
|
|
const alreadyHandled = e.nativeEvent.defaultPrevented;
|
|
e.preventDefault();
|
|
setIsDragOver(false);
|
|
if (alreadyHandled || !enabled) return;
|
|
const files = e.dataTransfer?.files;
|
|
if (files?.length) {
|
|
onDropRef.current(Array.from(files));
|
|
}
|
|
},
|
|
[enabled],
|
|
);
|
|
|
|
const dropZoneProps = {
|
|
onDragEnter: handleDragEnter,
|
|
onDragOver: handleDragOver,
|
|
onDragLeave: handleDragLeave,
|
|
onDrop: handleDrop,
|
|
};
|
|
|
|
return { isDragOver: enabled && isDragOver, dropZoneProps };
|
|
}
|
|
|
|
export { useFileDropZone };
|