Files
drp-48/src/lib/components/inputs/Images.svelte
2025-06-11 17:53:55 +01:00

98 lines
2.2 KiB
Svelte

<script lang="ts">
import cameraUrl from "$lib/assets/camera.svg";
import Carousel from "../Carousel.svelte";
interface Props {
name: string;
height?: string;
minHeight?: string;
files?: FileList;
required?: boolean;
scrollPosition?: number;
}
let {
name,
height,
minHeight,
files = $bindable(),
scrollPosition = $bindable(),
...rest
}: Props = $props();
</script>
<label
for={name}
style="height: {height || 'auto'}; min-height: {minHeight || 'auto'};"
class:no-bg={files && files.length > 0}
>
{#if files && files.length > 0}
<Carousel
urls={files
? Array(files.length)
.keys()
.map((i) => URL.createObjectURL(files![i]))
.toArray()
: []}
ondelete={(idx) => {
if (!files) return;
const dt = new DataTransfer();
for (let i = 0; i < files.length; i++) {
if (i !== idx) dt.items.add(files[i]);
}
files = dt.files;
}}
bind:scrollPosition
/>
{:else}
<div class="message">
<img src={cameraUrl} class="icon" alt="camera icon" />
<span>Click to upload a photo</span>
</div>
{/if}
<input
type="file"
id={name}
{name}
multiple
accept=".png, .jpg, .jpeg, .svg"
{...rest}
bind:files
/>
</label>
<style>
label {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
padding: 0.5rem;
border-radius: 0.5rem;
background-color: #eaffeb;
cursor: pointer;
}
label.no-bg {
background-color: transparent;
padding: 0;
}
label input {
display: none;
}
.message {
display: flex;
flex-direction: column;
align-items: center;
color: #49bd85;
}
.preview {
max-height: 100%;
max-width: 100%;
}
.message .icon {
width: 2rem;
}
</style>