useDragDrop Composable
Simple drag and drop functionality with reactive drop zone state
Code
import { ref, onMounted, onUnmounted, type Ref } from 'vue';
export function useDragDrop(
target: Ref<HTMLElement | null>,
onDrop: (files: File[]) => void
) {
const isDraggingOver = ref(false);
const dragCounter = ref(0);
// Prevent default browser behavior
const handleDragEvents = (e: DragEvent) => {
e.preventDefault();
e.stopPropagation();
};
const handleDragEnter = (e: DragEvent) => {
handleDragEvents(e);
dragCounter.value++;
isDraggingOver.value = true;
};
const handleDragLeave = (e: DragEvent) => {
handleDragEvents(e);
dragCounter.value--;
__TOKEN_26__ (dragCounter.value === 0) {
isDraggingOver.value = false;
}
};
const handleDrop = (e: DragEvent) => {
handleDragEvents(e);
dragCounter.value = 0;
isDraggingOver.value = false;
__TOKEN_28__ (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {
const files = Array.__TOKEN_30__(e.dataTransfer.files);
onDrop(files);
}
};
onMounted(() => {
__TOKEN_31__ (!target.value) return;
const el = target.value;
el.addEventListener('dragenter', handleDragEnter);
el.addEventListener('dragover', handleDragEvents);
el.addEventListener('dragleave', handleDragLeave);
el.addEventListener('drop', handleDrop);
});
onUnmounted(() => {
__TOKEN_34__ (!target.value) return;
const el = target.value;
el.removeEventListener('dragenter', handleDragEnter);
el.removeEventListener('dragover', handleDragEvents);
el.removeEventListener('dragleave', handleDragLeave);
el.removeEventListener('drop', handleDrop);
});
return { isDraggingOver };
}
// Usage example
// const dropZoneRef = ref<HTMLElement | null>(null);
// const { isDraggingOver } = useDragDrop(dropZoneRef, (files) => {
// console.log('Dropped files:', files);
// // Handle file upload
// });