Skip to content

Commit 4bfa0be

Browse files
authored
feat: support file drag-and-drop functionality (#3)
1 parent bb064e1 commit 4bfa0be

File tree

3 files changed

+77
-7
lines changed

3 files changed

+77
-7
lines changed

README.md

-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@
33
Stream data through multiple QRCodes
44

55
https://github.com/user-attachments/assets/5328d238-0f4e-4eb6-80ec-deb59d2e9897
6-

app/components/DropZone.vue

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<script setup lang="ts">
2+
import { onMounted, onUnmounted, ref } from 'vue'
3+
4+
defineProps<{
5+
text: string
6+
}>()
7+
8+
const emit = defineEmits<{
9+
(e: 'file', files: File): void
10+
}>()
11+
12+
// Ported from https://github.com/react-dropzone/react-dropzone/issues/753#issuecomment-774782919
13+
const isDragging = ref(false)
14+
const dragCounter = ref(0)
15+
16+
function onDragEnter(event: DragEvent) {
17+
event.preventDefault()
18+
dragCounter.value++
19+
isDragging.value = true
20+
}
21+
22+
function onDragLeave(event: DragEvent) {
23+
event.preventDefault()
24+
dragCounter.value--
25+
if (dragCounter.value > 0)
26+
return
27+
isDragging.value = false
28+
}
29+
30+
function onDragOver(event: DragEvent) {
31+
event.preventDefault()
32+
}
33+
34+
async function onDrop(event: DragEvent) {
35+
event.preventDefault()
36+
isDragging.value = false
37+
if (event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length > 0) {
38+
dragCounter.value = 0
39+
if (event.dataTransfer.files.length > 1) {
40+
console.warn('Multiple files are not supported. Only the first file will be processed.')
41+
}
42+
const firstFile = event.dataTransfer.files[0]
43+
if (!firstFile)
44+
return
45+
46+
emit('file', firstFile)
47+
event.dataTransfer.clearData()
48+
}
49+
}
50+
51+
onMounted(() => {
52+
window.addEventListener('dragenter', onDragEnter)
53+
window.addEventListener('dragleave', onDragLeave)
54+
window.addEventListener('dragover', onDragOver)
55+
window.addEventListener('drop', onDrop)
56+
})
57+
58+
onUnmounted(() => {
59+
window.removeEventListener('dragenter', onDragEnter)
60+
window.removeEventListener('dragleave', onDragLeave)
61+
window.removeEventListener('dragover', onDragOver)
62+
window.removeEventListener('drop', onDrop)
63+
})
64+
</script>
65+
66+
<template>
67+
<div
68+
v-if="isDragging"
69+
fixed inset-0 z-50 flex items-center justify-center bg-gray-900 bg-opacity-50 p-4
70+
>
71+
<div h-full w-full flex items-center justify-center border-4 border-white rounded-lg border-dashed p-8>
72+
<span text-2xl text-white>{{ text }}</span>
73+
</div>
74+
</div>
75+
</template>

app/pages/index.vue

+2-6
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,7 @@ async function onFileChange(file?: File) {
6969
min-h="[calc(100vh-250px)]" h-full w-full
7070
text="neutral-600 dark:neutral-400"
7171
@file="onFileChange"
72-
>
73-
<div i-carbon:document-add text-2xl />
74-
<p font-semi-bold pl-4 text-2xl>
75-
<span>Choose</span>
76-
</p>
77-
</InputFile>
72+
/>
73+
<DropZone text="Drop File Here" @file="onFileChange" />
7874
</div>
7975
</template>

0 commit comments

Comments
 (0)