UNPKG

@nuxt/ui

Version:

A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.

79 lines (78 loc) 2.18 kB
import { ref, computed, unref, onMounted, watch, reactive } from "vue"; import { useFileDialog, useDropZone } from "@vueuse/core"; function parseAcceptToDataTypes(accept) { if (!accept || accept === "*") { return void 0; } const types = accept.split(",").map((type) => { const trimmedType = type.trim(); if (trimmedType.includes("/") && trimmedType.endsWith("/*")) { return trimmedType.split("/")[0] || trimmedType; } return trimmedType; }).filter((type) => { return !type.startsWith("."); }); return types.length > 0 ? types : void 0; } export function useFileUpload(options) { const { accept = "*", reset = false, multiple = false, dropzone = true, onUpdate } = options; const inputRef = ref(); const dropzoneRef = ref(); const dataTypes = computed(() => parseAcceptToDataTypes(unref(accept))); const onDrop = (files, fromDropZone = false) => { if (!files || files.length === 0) { return; } if (files instanceof FileList) { files = Array.from(files); } if (files.length > 1 && !multiple) { files = [files[0]]; } 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); }; const isDragging = ref(false); const fileDialog = reactive({ open: () => { } }); function open() { fileDialog.open(); } onMounted(() => { const { isOverDropZone } = dropzone ? useDropZone(dropzoneRef, { dataTypes: dataTypes.value, onDrop: (files) => onDrop(files, true) }) : { isOverDropZone: ref(false) }; watch(isOverDropZone, (value) => { isDragging.value = value; }); const { onChange, open: open2 } = useFileDialog({ accept: unref(accept), multiple, input: unref(inputRef)?.$el, reset }); fileDialog.open = open2; onChange((fileList) => onDrop(fileList, false)); }); return { isDragging, open, inputRef, dropzoneRef }; }