<script lang="ts"> import { onDestroy } from "svelte"; import CarbonImage from "~icons/carbon/image"; // import EosIconsLoading from "~icons/eos-icons/loading"; export let files: File[]; let file_error_message = ""; let errorTimeout: ReturnType<typeof setTimeout>; export let onDrag = false; async function dropHandle(event: DragEvent) { event.preventDefault(); if (event.dataTransfer && event.dataTransfer.items) { // Use DataTransferItemList interface to access the file(s) if (files.length > 0) { files = []; } // get only the first file // optionally: we need to handle multiple files, if we want to support document upload for example // for multimodal we only support one image at a time but we could support multiple PDFs if (event.dataTransfer.items[0].kind === "file") { const file = event.dataTransfer.items[0].getAsFile(); if (file) { if (!event.dataTransfer.items[0].type.startsWith("image")) { setErrorMsg("Only images are supported"); files = []; return; } // if image is bigger than 2MB abort if (file.size > 2 * 1024 * 1024) { setErrorMsg("Image is too big. (2MB max)"); files = []; return; } files = [file]; onDrag = false; } } } } function setErrorMsg(errorMsg: string) { if (errorTimeout) { clearTimeout(errorTimeout); } file_error_message = errorMsg; errorTimeout = setTimeout(() => { file_error_message = ""; onDrag = false; }, 2000); } onDestroy(() => { if (errorTimeout) { clearTimeout(errorTimeout); } }); </script> <div id="dropzone" role="form" on:drop={dropHandle} class="relative flex w-full max-w-4xl flex-col items-center rounded-xl border bg-gray-100 focus-within:border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:focus-within:border-gray-500" > <div class="object-center"> {#if file_error_message} <div class="absolute bottom-0 left-0 right-0 top-0 flex flex-col items-center justify-center gap-2 rounded-xl bg-gray-100 bg-opacity-50 dark:bg-gray-700 dark:bg-opacity-50" > <p class="text-red-500 dark:text-red-400">{file_error_message}</p> <div class="h-2.5 w-1/2 rounded-full bg-gray-200 dark:bg-gray-700"> <div class="animate-progress-bar h-2.5 rounded-full bg-red-500 dark:text-red-400 " /> </div> </div> {/if} <div class="mt-3 flex justify-center" class:opacity-0={file_error_message}> <CarbonImage class="text-5xl text-gray-500 dark:text-gray-400" /> </div> <p class="mb-3 mt-3 text-sm text-gray-500 dark:text-gray-400" class:opacity-0={file_error_message} > Drag and drop <span class="font-semibold">one image</span> here </p> </div> </div> <style> @keyframes slideInFromLeft { 0% { width: 0; } 100% { width: 100%; } } .animate-progress-bar { /* This section calls the slideInFromLeft animation we defined above */ animation: 2s linear 0s 1 slideInFromLeft; } </style>