Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b01cfd4

Browse files
authored
fix(useDropZone): validate all file types individually when dropping multiple files (#4325)
1 parent a123a6e commit b01cfd4

File tree

3 files changed

+36
-35
lines changed

3 files changed

+36
-35
lines changed

packages/core/useDropZone/demo.vue

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { useDropZone, useEventListener } from '@vueuse/core'
2+
import { useDropZone } from '@vueuse/core'
33
import { ref } from 'vue'
44
55
const filesData = ref<{ name: string, size: number, type: string, lastModified: number }[]>([])
@@ -31,32 +31,16 @@ function onImageDrop(files: File[] | null) {
3131
3232
const dropZoneRef = ref<HTMLElement>()
3333
const imageDropZoneRef = ref<HTMLElement>()
34-
const pngRef = ref()
3534
3635
const { isOverDropZone } = useDropZone(dropZoneRef, onDrop)
3736
38-
useEventListener(pngRef, 'dragstart', (event) => {
39-
event.dataTransfer?.setData('image/png', '/vue.png')
40-
})
41-
4237
const { isOverDropZone: isOverImageDropZone } = useDropZone(imageDropZoneRef, { dataTypes: ['image/png'], onDrop: onImageDrop })
4338
</script>
4439

4540
<template>
4641
<div class="flex flex-col gap-2">
4742
<div class="w-full h-auto relative">
48-
<p>Drop files on to drop zones</p>
49-
50-
<div class="flex gap-6">
51-
<div class="flex flex-col items-center">
52-
<img ref="pngRef" src="/vue.png" alt="Drag me" h-10>
53-
<span>PNG</span>
54-
</div>
55-
<div class="flex flex-col items-center">
56-
<img src="/favicon.svg" alt="Drag me" h-10>
57-
<span>SVG</span>
58-
</div>
59-
</div>
43+
<p>Drop files from your computer on to drop zones</p>
6044

6145
<div grid="~ cols-2 gap-2">
6246
<div

packages/core/useDropZone/index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ category: Elements
66

77
Create a zone where files can be dropped.
88

9+
::: warning
10+
11+
Due to Safari browser limitations, file type validation is only possible during the drop event, not during drag events. As a result, the `isOverDropZone` value will always be `true` during drag operations in Safari, regardless of file type.
12+
13+
:::
14+
915
## Usage
1016

1117
```vue

packages/core/useDropZone/index.ts

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,34 +52,45 @@ export function useDropZone(
5252
}
5353

5454
const checkDataTypes = (types: string[]) => {
55-
if (_options.dataTypes) {
56-
const dataTypes = unref(_options.dataTypes)
57-
return typeof dataTypes === 'function'
58-
? dataTypes(types)
59-
: dataTypes
60-
? dataTypes.some(item => types.includes(item))
61-
: true
62-
}
63-
return true
55+
const dataTypes = unref(_options.dataTypes)
56+
57+
if (typeof dataTypes === 'function')
58+
return dataTypes(types)
59+
60+
if (!dataTypes?.length)
61+
return true
62+
63+
if (types.length === 0)
64+
return false
65+
66+
return types.every(type =>
67+
dataTypes.some(allowedType => type.includes(allowedType)),
68+
)
6469
}
6570

66-
const checkValidity = (event: DragEvent) => {
67-
const items = Array.from(event.dataTransfer?.items ?? [])
68-
const types = items.map(item => item.type)
71+
const checkValidity = (items: DataTransferItemList) => {
72+
const types = Array.from(items ?? []).map(item => item.type)
6973

7074
const dataTypesValid = checkDataTypes(types)
7175
const multipleFilesValid = multiple || items.length <= 1
7276

7377
return dataTypesValid && multipleFilesValid
7478
}
7579

80+
const isSafari = () => (
81+
/^(?:(?!chrome|android).)*safari/i.test(navigator.userAgent)
82+
&& !('chrome' in window)
83+
)
84+
7685
const handleDragEvent = (event: DragEvent, eventType: 'enter' | 'over' | 'leave' | 'drop') => {
77-
isValid = checkValidity(event)
86+
const dataTransferItemList = event.dataTransfer?.items
87+
isValid = (dataTransferItemList && checkValidity(dataTransferItemList)) ?? false
7888

79-
if (!isValid) {
80-
if (preventDefaultForUnhandled) {
81-
event.preventDefault()
82-
}
89+
if (preventDefaultForUnhandled) {
90+
event.preventDefault()
91+
}
92+
93+
if (!isSafari() && !isValid) {
8394
if (event.dataTransfer) {
8495
event.dataTransfer.dropEffect = 'none'
8596
}

0 commit comments

Comments
 (0)