diff --git a/src/runtime/components/FileUpload.vue b/src/runtime/components/FileUpload.vue index 80b3d1987b..89f7cd4357 100644 --- a/src/runtime/components/FileUpload.vue +++ b/src/runtime/components/FileUpload.vue @@ -125,7 +125,7 @@ export interface FileUploadSlots { @@ -365,18 +367,18 @@ defineExpose({ - + /> diff --git a/src/runtime/composables/useFileUpload.ts b/src/runtime/composables/useFileUpload.ts index 308a8c51ce..1f04b43642 100644 --- a/src/runtime/composables/useFileUpload.ts +++ b/src/runtime/composables/useFileUpload.ts @@ -1,4 +1,5 @@ import { ref, computed, unref, onMounted, watch, reactive } from 'vue' +import type { VisuallyHidden } from 'reka-ui' import { useFileDialog, useDropZone } from '@vueuse/core' import type { MaybeRef } from '@vueuse/core' @@ -45,12 +46,12 @@ export function useFileUpload(options: UseFileUploadOptions) { dropzone = true, onUpdate } = options - const inputRef = ref() + const inputRef = ref>() const dropzoneRef = ref() const dataTypes = computed(() => parseAcceptToDataTypes(unref(accept))) - const onDrop = (files: FileList | File[] | null) => { + const onDrop = (files: FileList | File[] | null, fromDropZone = false) => { if (!files || files.length === 0) { return } @@ -60,6 +61,18 @@ export function useFileUpload(options: UseFileUploadOptions) { if (files.length > 1 && !multiple) { files = [files[0]!] } + + // Sync dropped files to the input element for proper native validation + if (fromDropZone && inputRef.value?.$el) { + try { + const dt = new DataTransfer() + files.forEach(file => dt.items.add(file)) + inputRef.value.$el.files = dt.files + } catch (e) { + console.warn('Could not sync files to input element:', e) + } + } + onUpdate(files) } @@ -75,7 +88,7 @@ export function useFileUpload(options: UseFileUploadOptions) { onMounted(() => { const { isOverDropZone } = dropzone - ? useDropZone(dropzoneRef, { dataTypes: dataTypes.value, onDrop }) + ? useDropZone(dropzoneRef, { dataTypes: dataTypes.value, onDrop: files => onDrop(files, true) }) : { isOverDropZone: ref(false) } watch(isOverDropZone, (value) => { @@ -85,13 +98,13 @@ export function useFileUpload(options: UseFileUploadOptions) { const { onChange, open } = useFileDialog({ accept: unref(accept), multiple, - input: unref(inputRef), + input: unref(inputRef)?.$el, reset }) fileDialog.open = open - onChange(fileList => onDrop(fileList)) + onChange(fileList => onDrop(fileList, false)) }) return { diff --git a/test/components/__snapshots__/FileUpload-vue.spec.ts.snap b/test/components/__snapshots__/FileUpload-vue.spec.ts.snap index 612e7a7a7b..f1afc7357a 100644 --- a/test/components/__snapshots__/FileUpload-vue.spec.ts.snap +++ b/test/components/__snapshots__/FileUpload-vue.spec.ts.snap @@ -10,7 +10,7 @@ exports[`FileUpload > renders with accept correctly 1`] = ` - + " `; @@ -31,7 +31,7 @@ exports[`FileUpload > renders with actions slot correctly 1`] = ` - + " `; @@ -45,7 +45,7 @@ exports[`FileUpload > renders with ariaLabel correctly 1`] = ` - + " `; @@ -59,7 +59,7 @@ exports[`FileUpload > renders with as correctly 1`] = ` - + " `; @@ -73,11 +73,11 @@ exports[`FileUpload > renders with class correctly 1`] = ` - + " `; -exports[`FileUpload > renders with default slot correctly 1`] = `"
Default slot
"`; +exports[`FileUpload > renders with default slot correctly 1`] = `"
Default slot
"`; exports[`FileUpload > renders with description correctly 1`] = ` "
@@ -89,7 +89,7 @@ exports[`FileUpload > renders with description correctly 1`] = `
- + " `; @@ -110,7 +110,7 @@ exports[`FileUpload > renders with description slot correctly 1`] = ` - + " `; @@ -124,7 +124,7 @@ exports[`FileUpload > renders with disabled correctly 1`] = ` - + " `; @@ -138,7 +138,7 @@ exports[`FileUpload > renders with disabled correctly 2`] = ` - + " `; @@ -154,7 +154,7 @@ exports[`FileUpload > renders with file slot correctly 1`] = `
File slot
-
+ " `; @@ -173,7 +173,7 @@ exports[`FileUpload > renders with file-leading slot correctly 1`] = ` - + " `; @@ -194,7 +194,7 @@ exports[`FileUpload > renders with file-name slot correctly 1`] = ` - + " `; @@ -215,7 +215,7 @@ exports[`FileUpload > renders with file-size slot correctly 1`] = ` - + " `; @@ -233,7 +233,7 @@ exports[`FileUpload > renders with file-trailing slot correctly 1`] = `
File trailing slot
- + " `; @@ -254,7 +254,7 @@ exports[`FileUpload > renders with fileDelete correctly 1`] = ` - + " `; @@ -275,7 +275,7 @@ exports[`FileUpload > renders with fileDeleteIcon correctly 1`] = ` - + " `; @@ -296,7 +296,7 @@ exports[`FileUpload > renders with fileIcon correctly 1`] = ` - + " `; @@ -310,7 +310,7 @@ exports[`FileUpload > renders with files slot correctly 1`] = ` -
Files slot
+
Files slot
" `; @@ -331,7 +331,7 @@ exports[`FileUpload > renders with files-bottom slot correctly 1`] = ` - Files bottom slot + Files bottom slot " `; @@ -351,7 +351,7 @@ exports[`FileUpload > renders with files-top slot correctly 1`] = ` - + " `; @@ -365,7 +365,7 @@ exports[`FileUpload > renders with icon correctly 1`] = ` - + " `; @@ -379,7 +379,7 @@ exports[`FileUpload > renders with id correctly 1`] = ` - + " `; @@ -393,7 +393,7 @@ exports[`FileUpload > renders with label correctly 1`] = ` - + " `; @@ -414,7 +414,7 @@ exports[`FileUpload > renders with label slot correctly 1`] = ` - + " `; @@ -435,7 +435,7 @@ exports[`FileUpload > renders with layout grid correctly 1`] = ` - + " `; @@ -452,7 +452,7 @@ exports[`FileUpload > renders with layout grid multiple correctly 1`] = ` - + " `; @@ -473,7 +473,7 @@ exports[`FileUpload > renders with layout list correctly 1`] = ` - + " `; @@ -494,7 +494,7 @@ exports[`FileUpload > renders with layout list multiple correctly 1`] = ` - + " `; @@ -515,7 +515,7 @@ exports[`FileUpload > renders with leading slot correctly 1`] = ` - + " `; @@ -536,7 +536,7 @@ exports[`FileUpload > renders with modelValue correctly 1`] = ` - + " `; @@ -553,7 +553,7 @@ exports[`FileUpload > renders with multiple correctly 1`] = ` - + " `; @@ -567,7 +567,7 @@ exports[`FileUpload > renders with name correctly 1`] = ` - + " `; @@ -581,7 +581,7 @@ exports[`FileUpload > renders with neutral color correctly 1`] = ` - + " `; @@ -598,7 +598,7 @@ exports[`FileUpload > renders with position inside correctly 1`] = ` - + " `; @@ -615,7 +615,7 @@ exports[`FileUpload > renders with position inside multiple correctly 1`] = ` - + " `; @@ -636,7 +636,7 @@ exports[`FileUpload > renders with position outside correctly 1`] = ` - + " `; @@ -653,7 +653,7 @@ exports[`FileUpload > renders with position outside multiple correctly 1`] = ` - + " `; @@ -667,7 +667,7 @@ exports[`FileUpload > renders with required correctly 1`] = ` - + " `; @@ -681,7 +681,7 @@ exports[`FileUpload > renders with required correctly 2`] = ` - + " `; @@ -702,7 +702,7 @@ exports[`FileUpload > renders with size lg correctly 1`] = ` - + " `; @@ -720,7 +720,7 @@ exports[`FileUpload > renders with size lg variant button correctly 1`] = ` - + " `; @@ -741,7 +741,7 @@ exports[`FileUpload > renders with size md correctly 1`] = ` - + " `; @@ -759,7 +759,7 @@ exports[`FileUpload > renders with size md variant button correctly 1`] = ` - + " `; @@ -780,7 +780,7 @@ exports[`FileUpload > renders with size sm correctly 1`] = ` - + " `; @@ -798,7 +798,7 @@ exports[`FileUpload > renders with size sm variant button correctly 1`] = ` - + " `; @@ -819,7 +819,7 @@ exports[`FileUpload > renders with size xl correctly 1`] = ` - + " `; @@ -837,7 +837,7 @@ exports[`FileUpload > renders with size xl variant button correctly 1`] = ` - + " `; @@ -858,7 +858,7 @@ exports[`FileUpload > renders with size xs correctly 1`] = ` - + " `; @@ -876,7 +876,7 @@ exports[`FileUpload > renders with size xs variant button correctly 1`] = ` - + " `; @@ -890,7 +890,7 @@ exports[`FileUpload > renders with ui correctly 1`] = ` - + " `; @@ -911,7 +911,7 @@ exports[`FileUpload > renders with variant area correctly 1`] = ` - + " `; @@ -929,7 +929,7 @@ exports[`FileUpload > renders with variant button correctly 1`] = ` - + " `; @@ -943,7 +943,7 @@ exports[`FileUpload > renders without dropzone correctly 1`] = ` - + " `; @@ -957,6 +957,6 @@ exports[`FileUpload > renders without interactive correctly 1`] = ` - + " `; diff --git a/test/components/__snapshots__/FileUpload.spec.ts.snap b/test/components/__snapshots__/FileUpload.spec.ts.snap index 20c8d36826..c851554be5 100644 --- a/test/components/__snapshots__/FileUpload.spec.ts.snap +++ b/test/components/__snapshots__/FileUpload.spec.ts.snap @@ -10,7 +10,7 @@ exports[`FileUpload > renders with accept correctly 1`] = ` - + " `; @@ -31,7 +31,7 @@ exports[`FileUpload > renders with actions slot correctly 1`] = ` - + " `; @@ -45,7 +45,7 @@ exports[`FileUpload > renders with ariaLabel correctly 1`] = ` - + " `; @@ -59,7 +59,7 @@ exports[`FileUpload > renders with as correctly 1`] = ` - + " `; @@ -73,11 +73,11 @@ exports[`FileUpload > renders with class correctly 1`] = ` - + " `; -exports[`FileUpload > renders with default slot correctly 1`] = `"
Default slot
"`; +exports[`FileUpload > renders with default slot correctly 1`] = `"
Default slot
"`; exports[`FileUpload > renders with description correctly 1`] = ` "
@@ -89,7 +89,7 @@ exports[`FileUpload > renders with description correctly 1`] = `
- + " `; @@ -110,7 +110,7 @@ exports[`FileUpload > renders with description slot correctly 1`] = ` - + " `; @@ -124,7 +124,7 @@ exports[`FileUpload > renders with disabled correctly 1`] = ` - + " `; @@ -138,7 +138,7 @@ exports[`FileUpload > renders with disabled correctly 2`] = ` - + " `; @@ -154,7 +154,7 @@ exports[`FileUpload > renders with file slot correctly 1`] = `
File slot
-
+ " `; @@ -173,7 +173,7 @@ exports[`FileUpload > renders with file-leading slot correctly 1`] = ` - + " `; @@ -194,7 +194,7 @@ exports[`FileUpload > renders with file-name slot correctly 1`] = ` - + " `; @@ -215,7 +215,7 @@ exports[`FileUpload > renders with file-size slot correctly 1`] = ` - + " `; @@ -233,7 +233,7 @@ exports[`FileUpload > renders with file-trailing slot correctly 1`] = `
File trailing slot
- + " `; @@ -254,7 +254,7 @@ exports[`FileUpload > renders with fileDelete correctly 1`] = ` - + " `; @@ -275,7 +275,7 @@ exports[`FileUpload > renders with fileDeleteIcon correctly 1`] = ` - + " `; @@ -296,7 +296,7 @@ exports[`FileUpload > renders with fileIcon correctly 1`] = ` - + " `; @@ -310,7 +310,7 @@ exports[`FileUpload > renders with files slot correctly 1`] = ` -
Files slot
+
Files slot
" `; @@ -331,7 +331,7 @@ exports[`FileUpload > renders with files-bottom slot correctly 1`] = ` - Files bottom slot + Files bottom slot " `; @@ -351,7 +351,7 @@ exports[`FileUpload > renders with files-top slot correctly 1`] = ` - + " `; @@ -365,7 +365,7 @@ exports[`FileUpload > renders with icon correctly 1`] = ` - + " `; @@ -379,7 +379,7 @@ exports[`FileUpload > renders with id correctly 1`] = ` - + " `; @@ -393,7 +393,7 @@ exports[`FileUpload > renders with label correctly 1`] = ` - + " `; @@ -414,7 +414,7 @@ exports[`FileUpload > renders with label slot correctly 1`] = ` - + " `; @@ -435,7 +435,7 @@ exports[`FileUpload > renders with layout grid correctly 1`] = ` - + " `; @@ -452,7 +452,7 @@ exports[`FileUpload > renders with layout grid multiple correctly 1`] = ` - + " `; @@ -473,7 +473,7 @@ exports[`FileUpload > renders with layout list correctly 1`] = ` - + " `; @@ -494,7 +494,7 @@ exports[`FileUpload > renders with layout list multiple correctly 1`] = ` - + " `; @@ -515,7 +515,7 @@ exports[`FileUpload > renders with leading slot correctly 1`] = ` - + " `; @@ -536,7 +536,7 @@ exports[`FileUpload > renders with modelValue correctly 1`] = ` - + " `; @@ -553,7 +553,7 @@ exports[`FileUpload > renders with multiple correctly 1`] = ` - + " `; @@ -567,7 +567,7 @@ exports[`FileUpload > renders with name correctly 1`] = ` - + " `; @@ -581,7 +581,7 @@ exports[`FileUpload > renders with neutral color correctly 1`] = ` - + " `; @@ -598,7 +598,7 @@ exports[`FileUpload > renders with position inside correctly 1`] = ` - + " `; @@ -615,7 +615,7 @@ exports[`FileUpload > renders with position inside multiple correctly 1`] = ` - + " `; @@ -636,7 +636,7 @@ exports[`FileUpload > renders with position outside correctly 1`] = ` - + " `; @@ -653,7 +653,7 @@ exports[`FileUpload > renders with position outside multiple correctly 1`] = ` - + " `; @@ -667,7 +667,7 @@ exports[`FileUpload > renders with required correctly 1`] = ` - + " `; @@ -681,7 +681,7 @@ exports[`FileUpload > renders with required correctly 2`] = ` - + " `; @@ -702,7 +702,7 @@ exports[`FileUpload > renders with size lg correctly 1`] = ` - + " `; @@ -720,7 +720,7 @@ exports[`FileUpload > renders with size lg variant button correctly 1`] = ` - + " `; @@ -741,7 +741,7 @@ exports[`FileUpload > renders with size md correctly 1`] = ` - + " `; @@ -759,7 +759,7 @@ exports[`FileUpload > renders with size md variant button correctly 1`] = ` - + " `; @@ -780,7 +780,7 @@ exports[`FileUpload > renders with size sm correctly 1`] = ` - + " `; @@ -798,7 +798,7 @@ exports[`FileUpload > renders with size sm variant button correctly 1`] = ` - + " `; @@ -819,7 +819,7 @@ exports[`FileUpload > renders with size xl correctly 1`] = ` - + " `; @@ -837,7 +837,7 @@ exports[`FileUpload > renders with size xl variant button correctly 1`] = ` - + " `; @@ -858,7 +858,7 @@ exports[`FileUpload > renders with size xs correctly 1`] = ` - + " `; @@ -876,7 +876,7 @@ exports[`FileUpload > renders with size xs variant button correctly 1`] = ` - + " `; @@ -890,7 +890,7 @@ exports[`FileUpload > renders with ui correctly 1`] = ` - + " `; @@ -911,7 +911,7 @@ exports[`FileUpload > renders with variant area correctly 1`] = ` - + " `; @@ -929,7 +929,7 @@ exports[`FileUpload > renders with variant button correctly 1`] = ` - + " `; @@ -943,7 +943,7 @@ exports[`FileUpload > renders without dropzone correctly 1`] = ` - + " `; @@ -957,6 +957,6 @@ exports[`FileUpload > renders without interactive correctly 1`] = ` - + " `;