summaryrefslogtreecommitdiff
path: root/apps/web/src/hooks/use-drag-drop.ts
blob: 768014ec6d7a6cf8446ea45599d09ab7b600b31f (plain) (blame)
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
74
75
76
77
78
79
80
81
82
83
84
85
import { useState, useRef } from "react";

interface UseDragDropOptions {
	onDrop?: (files: FileList) => void;
}

// Helper function to check if drag contains files from external sources (not internal app drags)
const containsFiles = (dataTransfer: DataTransfer): boolean => {
	// Check if this is an internal app drag (media item)
	if (dataTransfer.types.includes("application/x-media-item")) {
		return false;
	}

	// Only show overlay for external file drags
	return dataTransfer.types.includes("Files");
};

export function useDragDrop(options: UseDragDropOptions = {}) {
	const [isDragOver, setIsDragOver] = useState(false);
	const dragCounterRef = useRef(0);

	const handleDragEnter = (e: React.DragEvent) => {
		e.preventDefault();

		// Only handle external file drags, not internal app element drags
		if (!containsFiles(e.dataTransfer)) {
			return;
		}

		dragCounterRef.current += 1;
		if (!isDragOver) {
			setIsDragOver(true);
		}
	};

	const handleDragOver = (e: React.DragEvent) => {
		e.preventDefault();

		// Only handle file drags
		if (!containsFiles(e.dataTransfer)) {
			return;
		}
	};

	const handleDragLeave = (e: React.DragEvent) => {
		e.preventDefault();

		// Only handle file drags
		if (!containsFiles(e.dataTransfer)) {
			return;
		}

		dragCounterRef.current -= 1;
		if (dragCounterRef.current === 0) {
			setIsDragOver(false);
		}
	};

	const handleDrop = (e: React.DragEvent) => {
		e.preventDefault();
		setIsDragOver(false);
		dragCounterRef.current = 0;

		// Only handle file drops
		if (
			options.onDrop &&
			e.dataTransfer.files &&
			containsFiles(e.dataTransfer)
		) {
			options.onDrop(e.dataTransfer.files);
		}
	};

	const dragProps = {
		onDragEnter: handleDragEnter,
		onDragOver: handleDragOver,
		onDragLeave: handleDragLeave,
		onDrop: handleDrop,
	};

	return {
		isDragOver,
		dragProps,
	};
}