mirror of https://github.com/VERT-sh/VERT.git
116 lines
3.0 KiB
Svelte
116 lines
3.0 KiB
Svelte
<script lang="ts">
|
|
import { Upload } from "lucide-svelte";
|
|
import clsx from "clsx";
|
|
import { onMount } from "svelte";
|
|
|
|
let fileList = $state<FileList>();
|
|
let dragBtn = $state<HTMLButtonElement>();
|
|
|
|
interface Props {
|
|
files: File[] | undefined;
|
|
}
|
|
|
|
$effect(() => {
|
|
if (!fileList) return;
|
|
files = Array.from(fileList);
|
|
});
|
|
|
|
let fileInput = $state<HTMLInputElement>();
|
|
let dragOver = $state(false);
|
|
|
|
let { files = $bindable() }: Props = $props();
|
|
|
|
function upload() {
|
|
if (!fileInput) return;
|
|
fileInput.click();
|
|
}
|
|
|
|
onMount(() => {
|
|
const handler = (e: Event) => e.preventDefault();
|
|
if (!dragBtn) return;
|
|
dragBtn.addEventListener("dragenter", handler);
|
|
dragBtn.addEventListener("dragstart", handler);
|
|
dragBtn.addEventListener("dragend", handler);
|
|
dragBtn.addEventListener("dragleave", handler);
|
|
dragBtn.addEventListener("dragover", handler);
|
|
dragBtn.addEventListener("drag", handler);
|
|
dragBtn.addEventListener("drop", handler);
|
|
|
|
return () => {
|
|
if (!dragBtn) return;
|
|
dragBtn.removeEventListener("dragenter", handler);
|
|
dragBtn.removeEventListener("dragstart", handler);
|
|
dragBtn.removeEventListener("dragend", handler);
|
|
dragBtn.removeEventListener("dragleave", handler);
|
|
dragBtn.removeEventListener("dragover", handler);
|
|
dragBtn.removeEventListener("drag", handler);
|
|
dragBtn.removeEventListener("drop", handler);
|
|
};
|
|
});
|
|
|
|
function drop(event: DragEvent) {
|
|
event.preventDefault();
|
|
dragOver = false;
|
|
if (!event.dataTransfer) return;
|
|
if (!files) files = Array.from(event.dataTransfer.files);
|
|
else files.push(...Array.from(event.dataTransfer.files));
|
|
return true;
|
|
}
|
|
|
|
function addFiles() {
|
|
if (!fileInput) return;
|
|
if (!fileInput.files) return;
|
|
if (!files) files = Array.from(fileInput.files);
|
|
else files.push(...Array.from(fileInput.files));
|
|
}
|
|
</script>
|
|
|
|
<button
|
|
bind:this={dragBtn}
|
|
onclick={upload}
|
|
ondragover={() => (dragOver = true)}
|
|
ondragleave={() => (dragOver = false)}
|
|
class={clsx(
|
|
"file-uploader",
|
|
"w-full h-80 flex items-center justify-center cursor-pointer",
|
|
"border-2 border-solid border-foreground-muted-alt rounded-2xl",
|
|
"hover:scale-95 hover:opacity-70 transition-all duration-150 ease-out",
|
|
{
|
|
"scale-95 opacity-70 blur-xs": dragOver,
|
|
},
|
|
)}
|
|
class:_drag-over={dragOver}
|
|
ondrop={drop}
|
|
>
|
|
<div
|
|
class="file-uploader-center flex items-center justify-center flex-col transition-all duration-150 ease-out"
|
|
>
|
|
<div
|
|
class="size-16 rounded-full text-accent-foreground bg-accent-background flex items-center justify-center"
|
|
>
|
|
<Upload class="size-8" />
|
|
</div>
|
|
<h2 class="font-display text-2xl mt-6">
|
|
Drop or click to upload files
|
|
</h2>
|
|
<p class="text-foreground-muted mt-4">
|
|
All processing is done on your device. No file or size limit.
|
|
</p>
|
|
</div>
|
|
</button>
|
|
|
|
<input
|
|
type="file"
|
|
class="hidden"
|
|
bind:this={fileInput}
|
|
onchange={addFiles}
|
|
multiple
|
|
/>
|
|
|
|
<style>
|
|
.file-uploader:hover .file-uploader-center,
|
|
.file-uploader._drag-over .file-uploader-center {
|
|
@apply scale-105;
|
|
}
|
|
</style>
|