diff --git a/package.json b/package.json index d35bf9b28963f5d5a91d54af4c31a56ed4247e9b..eea1fdd79f108c2ef190f4e1d0b3a40846c39b94 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@vue-macros/volar": "0.17.2", "@vue/test-utils": "2.4.1", "@vue/tsconfig": "0.4.0", - "@vueuse/core": "10.3.0", + "@vueuse/core": "10.6.1", "conventional-changelog-cli": "4.1.0", "jsdom": "22.1.0", "lightningcss": "1.22.0", diff --git a/src/components/fileinput/FileInput.vue b/src/components/fileinput/FileInput.vue index da1b1a10f081192e8815c66e4b06544f628fe466..e654bac3aea4cb08783195f1e61060a955a88005 100644 --- a/src/components/fileinput/FileInput.vue +++ b/src/components/fileinput/FileInput.vue @@ -1,6 +1,7 @@ <script setup lang="ts"> -import { ref } from 'vue' +import { ref, computed } from 'vue' import { Icon } from '@iconify/vue' +import { useDropZone, useFileDialog } from '@vueuse/core' const props = defineProps<{ accept?: string[] @@ -9,39 +10,38 @@ const props = defineProps<{ }>() const emit = defineEmits<{ - (e: 'files', value: FileList): void + (e: 'files', value: File[]): void (e: 'file', value: File): void }>() -const input = ref<HTMLInputElement>() -const processFiles = async (fileList?: FileList) => { +const dropZone = ref<HTMLInputElement>() +const processFiles = (fileList: File[] | FileList | null) => { if (!fileList) return - emit('files', fileList) + emit('files', fileList instanceof Array ? fileList : Array.from(fileList)) emit('file', fileList[0]) - if (!props.autoReset || !input.value) return - input.value.value = '' + if (props.autoReset) reset() } -const isDraggedOver = ref(false) +const { isOverDropZone } = useDropZone(dropZone, { + onDrop: processFiles, + dataTypes: ['Files'] +}) + +const { open, reset, onChange } = useFileDialog() +onChange(processFiles) + +const accept = computed(() => props.accept?.join(', ') ?? '*') </script> <template> <div class="funkwhale file-input"> - <input - type="file" - ref="input" - :accept="accept?.join(', ')" - :multiple="multiple" - @dragover="isDraggedOver = true" - @dragleave="isDraggedOver = false" - @drop="isDraggedOver = false" - @change="processFiles(($event.target as HTMLInputElement)?.files ?? undefined)" - /> <div + ref="dropZone" class="drop-zone" - :class="{ 'is-dragged-over': isDraggedOver }" + :class="{ 'is-dragged-over': isOverDropZone }" + @click.prevent="open({ accept, multiple })" > <Icon icon="bi:upload" /> @@ -50,7 +50,7 @@ const isDraggedOver = ref(false) or open your <a>file browser</a> </div> - <p v-if="accept">supported formats: {{ accept.join(', ') }}</p> + <p v-if="accept !== '*'">supported formats: {{ accept }}</p> </div> </div> </template> diff --git a/yarn.lock b/yarn.lock index 27ba5796a58086585af63add8ea9c56e0ff27ad6..b70b68d111900eed64e9caeb5faa89a5462836a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -565,6 +565,11 @@ resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz#5c9f3c617f64a9735d7b72a7cc671e166d900c40" integrity sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA== +"@types/web-bluetooth@^0.0.20": + version "0.0.20" + resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz#f066abfcd1cbe66267cdbbf0de010d8a41b41597" + integrity sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow== + "@vitejs/plugin-vue@4.4.1": version "4.4.1" resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-4.4.1.tgz#5050895fb8b2258d2f228110849df4a8a94b9038" @@ -1155,6 +1160,16 @@ "@vueuse/shared" "10.3.0" vue-demi ">=0.14.5" +"@vueuse/core@10.6.1": + version "10.6.1" + resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.6.1.tgz#5b16d8238054c6983b6cb7cd77a78035f098dd89" + integrity sha512-Pc26IJbqgC9VG1u6VY/xrXXfxD33hnvxBnKrLlA2LJlyHII+BSrRoTPJgGYq7qZOu61itITFUnm6QbacwZ4H8Q== + dependencies: + "@types/web-bluetooth" "^0.0.20" + "@vueuse/metadata" "10.6.1" + "@vueuse/shared" "10.6.1" + vue-demi ">=0.14.6" + "@vueuse/integrations@^10.3.0": version "10.3.0" resolved "https://registry.yarnpkg.com/@vueuse/integrations/-/integrations-10.3.0.tgz#765e9505358590f21531998194c6e60a8b23655c" @@ -1169,6 +1184,11 @@ resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-10.3.0.tgz#14fe6cc909573785f73a56e4d9351edf3830b796" integrity sha512-Ema3YhNOa4swDsV0V7CEY5JXvK19JI/o1szFO1iWxdFg3vhdFtCtSTP26PCvbUpnUtNHBY2wx5y3WDXND5Pvnw== +"@vueuse/metadata@10.6.1": + version "10.6.1" + resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-10.6.1.tgz#100faa0ced3c0ab4c014fb8e66e781e85e4eb88d" + integrity sha512-qhdwPI65Bgcj23e5lpGfQsxcy0bMjCAsUGoXkJ7DsoeDUdasbZ2DBa4dinFCOER3lF4gwUv+UD2AlA11zdzMFw== + "@vueuse/shared@10.3.0": version "10.3.0" resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.3.0.tgz#ce6b4b6860e14aaa293025dcf0cbe1036a25869f" @@ -1176,6 +1196,13 @@ dependencies: vue-demi ">=0.14.5" +"@vueuse/shared@10.6.1": + version "10.6.1" + resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.6.1.tgz#1d9fc1e3f9083e45b59a693fc372bc50ad62a9e4" + integrity sha512-TECVDTIedFlL0NUfHWncf3zF9Gc4VfdxfQc8JFwoVZQmxpONhLxFrlm0eHQeidHj4rdTPL3KXJa0TZCk1wnc5Q== + dependencies: + vue-demi ">=0.14.6" + JSONStream@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -3164,6 +3191,11 @@ vue-demi@>=0.14.5: resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.5.tgz#676d0463d1a1266d5ab5cba932e043d8f5f2fbd9" integrity sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA== +vue-demi@>=0.14.6: + version "0.14.6" + resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.6.tgz#dc706582851dc1cdc17a0054f4fec2eb6df74c92" + integrity sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w== + vue-i18n@9.3.0-beta.24: version "9.3.0-beta.24" resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-9.3.0-beta.24.tgz#48c5f019cb9007c4789b989b644ece6cf6ffe75f"