Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(useDropZone): Upload Files Support Folders #3718

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
70 changes: 59 additions & 11 deletions packages/core/useDropZone/index.ts
Expand Up @@ -34,12 +34,56 @@ export function useDropZone(
let isDataTypeIncluded = true
if (isClient) {
const _options = typeof options === 'function' ? { onDrop: options } : options
const getFiles = (event: DragEvent) => {
const list = Array.from(event.dataTransfer?.files ?? [])
return (files.value = list.length === 0 ? null : list)
const getFiles = async (event: DragEvent): Promise<File[]> => {
return new Promise((resolve) => {
const dataTransfer = event.dataTransfer!
const items = dataTransfer.items
let list: File[] = []
if (items[0].type === 'text/plain' || !window.webkitURL) {
list = Array.from(event.dataTransfer?.files ?? [])
resolve(list)
}
else {
const u = items.length
let k = 0
const returnResolve = () => {
if (k === u)
resolve(list)
}
for (let i = 0; i < items.length; i++) {
const item = items[i]
const ItemEntry = item.webkitGetAsEntry()!
if (ItemEntry.isFile) {
const fileEntry = ItemEntry as FileSystemFileEntry
fileEntry.file((file) => {
list.push(file)
k = k + 1
returnResolve()
})
}
if (ItemEntry.isDirectory) {
const directoryEntry = ItemEntry as FileSystemDirectoryEntry
const reader = directoryEntry.createReader()
reader.readEntries((entries) => {
for (let i = 0; i < entries.length; i++) {
const entry = entries[i] as FileSystemFileEntry
if (entry.isFile) {
entry.file((file) => {
list.push(file)
if (i === entries.length - 1)
k = k + 1
returnResolve()
})
}
}
})
}
}
}
})
}

useEventListener<DragEvent>(target, 'dragenter', (event) => {
useEventListener<DragEvent>(target, 'dragenter', async (event) => {
const types = Array.from(event?.dataTransfer?.items || [])
.map(i => i.kind === 'file' ? i.type : null)
.filter(notNullish)
Expand All @@ -57,28 +101,32 @@ export function useDropZone(
event.preventDefault()
counter += 1
isOverDropZone.value = true
_options.onEnter?.(getFiles(event), event)
const files = await getFiles(event) as File[]
_options.onDrop?.(files, event)
})
useEventListener<DragEvent>(target, 'dragover', (event) => {
useEventListener<DragEvent>(target, 'dragover', async (event) => {
if (!isDataTypeIncluded)
return
event.preventDefault()
_options.onOver?.(getFiles(event), event)
const files = await getFiles(event) as File[]
_options.onDrop?.(files, event)
})
useEventListener<DragEvent>(target, 'dragleave', (event) => {
useEventListener<DragEvent>(target, 'dragleave', async (event) => {
if (!isDataTypeIncluded)
return
event.preventDefault()
counter -= 1
if (counter === 0)
isOverDropZone.value = false
_options.onLeave?.(getFiles(event), event)
const files = await getFiles(event) as File[]
_options.onDrop?.(files, event)
})
useEventListener<DragEvent>(target, 'drop', (event) => {
useEventListener<DragEvent>(target, 'drop', async (event) => {
event.preventDefault()
counter = 0
isOverDropZone.value = false
_options.onDrop?.(getFiles(event), event)
const files = await getFiles(event) as File[]
_options.onDrop?.(files, event)
})
}

Expand Down