Coves frontend - a photon fork
1<script lang="ts">
2 import { Label, TextInput } from 'mono-svelte'
3 import { DocumentPlus, Icon } from 'svelte-hero-icons/dist'
4
5 interface Props {
6 accept?: string
7 files?: FileList | undefined | null
8 label?: string | undefined
9 url?: string | undefined
10 }
11
12 let {
13 accept = 'image/*',
14 files = $bindable(null),
15 label = undefined,
16 url = undefined,
17 }: Props = $props()
18
19 let dragover = $state(false)
20
21 let previewURL = $derived(files ? URL.createObjectURL(files[0]) : undefined)
22</script>
23
24<div class="flex flex-col">
25 <Label text={label} class="mb-1" />
26 <label
27 class="flex flex-col items-center px-8 py-4 mx-auto w-full rounded-xl
28 border border-slate-200 dark:border-zinc-800 bg-white dark:bg-black
29 cursor-pointer min-h-36 transition-colors {dragover
30 ? 'border-sky-500 text-sky-500'
31 : ''}
32 {url != undefined ? 'rounded-b-none' : ''}
33 "
34 ondrop={(event: DragEvent) => {
35 event.preventDefault()
36 files = event.dataTransfer?.files ?? null
37 }}
38 ondragover={(event: DragEvent) => {
39 event.preventDefault()
40 if (event.dataTransfer) {
41 event.dataTransfer.dropEffect = 'copy'
42 dragover = true
43 }
44 }}
45 ondragleave={(event: DragEvent) => {
46 event.preventDefault()
47 dragover = false
48 }}
49 >
50 {#if files}
51 <!-- svelte-ignore a11y_missing_attribute -->
52 <img
53 src={previewURL}
54 onload={() => {
55 if (previewURL) URL.revokeObjectURL(previewURL)
56 }}
57 class="w-full max-w-sm h-full rounded-lg"
58 />
59 {:else if url}
60 <img src={url} alt="" />
61 {:else}
62 <Icon src={DocumentPlus} class="opacity-50" size="36" />
63 <p class="text-sm opacity-50">Attach a file</p>
64 {/if}
65 <input type="file" bind:files {accept} class="hidden" />
66 </label>
67 {#if url != undefined}
68 <TextInput class="rounded-t-none border-t-0 rounded-xl" />
69 {/if}
70</div>