Files
speckle-server/packages/frontend-2/components/form/file-upload/Zone.vue
T
Kristaps Fabians Geikins b02a07e2b6 feat: Frontend 2.0 MVP
2023-05-08 10:47:01 +03:00

98 lines
2.3 KiB
Vue

<!-- eslint-disable vuejs-accessibility/form-control-has-label -->
<template>
<div ref="fileUploadZone" class="file-upload-zone">
<slot
:is-dragging-files="isOverDropZone"
:open-file-picker="triggerPicker"
:activator-on="{ click: triggerPicker }"
/>
<input
ref="fileInput"
type="file"
class="hidden"
:accept="accept"
:multiple="multiple"
@click.stop
@change="onInputChange"
/>
</div>
</template>
<script setup lang="ts">
/* eslint-disable vue/require-default-prop */
import { Nullable } from '@speckle/shared'
import { useDropZone } from '@vueuse/core'
import {
UploadableFileItem,
usePrepareUploadableFiles
} from '~~/lib/form/composables/fileUpload'
const emit = defineEmits<{
(e: 'files-selected', v: { files: UploadableFileItem[] }): void
}>()
const props = withDefaults(
defineProps<{
/**
* https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept
*/
accept?: string
/**
* https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/multiple
*/
multiple?: boolean
/**
* Max file size in bytes
*/
sizeLimit?: number
/**
* Max file count if 'multiple' is set
*/
countLimit?: number
disabled?: boolean
}>(),
{
sizeLimit: 1024 * 1024 * 100 // 100mb
}
)
const fileUploadZone = ref(null as Nullable<HTMLDivElement>)
const fileInput = ref(null as Nullable<HTMLInputElement>)
const { buildUploadableFiles } = usePrepareUploadableFiles({
sizeLimit: computed(() => props.sizeLimit),
countLimit: computed(() => props.countLimit),
accept: computed(() => props.accept),
multiple: computed(() => props.multiple),
disabled: computed(() => props.disabled)
})
const handleIncomingFiles = (files: File[]) => {
const fileItems = buildUploadableFiles(files)
if (!fileItems?.length) return
emit('files-selected', { files: fileItems })
}
const { isOverDropZone } = useDropZone(fileUploadZone, (files) => {
if (!files?.length) return
handleIncomingFiles(files)
})
const onInputChange = () => {
const input = fileInput.value
if (!input) return
const files = [...(input.files || [])]
input.value = '' // Resetting value
if (!files.length) return
handleIncomingFiles(files)
}
const triggerPicker = () => {
fileInput.value?.click()
}
defineExpose({
triggerPicker
})
</script>