51 lines
1.2 KiB
Svelte
51 lines
1.2 KiB
Svelte
<script lang="ts">
|
|
import { onMount, onDestroy } from 'svelte';
|
|
import { getImageSrc, revokeImageSrc, openImageInNewTab } from '$lib/media';
|
|
import { Card } from 'flowbite-svelte';
|
|
|
|
let {
|
|
path,
|
|
alt,
|
|
clazz = '',
|
|
fullPath
|
|
}: { path: string; alt: string; clazz?: string; fullPath?: string } = $props();
|
|
|
|
let src = $state<string | null>(null);
|
|
let error = $state<string | null>(null);
|
|
|
|
onMount(async () => {
|
|
if (!path) return;
|
|
try {
|
|
src = await getImageSrc(path);
|
|
} catch (e) {
|
|
console.error(`Failed to load image: ${path}`, e);
|
|
error = e instanceof Error ? e.message : 'Failed to load image';
|
|
}
|
|
});
|
|
|
|
onDestroy(() => {
|
|
if (src) {
|
|
revokeImageSrc(src);
|
|
}
|
|
});
|
|
|
|
function handleClick() {
|
|
const toOpen = fullPath || path;
|
|
if (toOpen) {
|
|
openImageInNewTab(toOpen);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
{#if error}
|
|
<div class="flex h-full w-full items-center justify-center bg-gray-200 text-red-500">
|
|
<p>{error}</p>
|
|
</div>
|
|
{:else if src}
|
|
<Card onclick={handleClick}><img {src} {alt} class="{clazz} cursor-pointer" /></Card>
|
|
{:else}
|
|
<div class="flex h-full w-full animate-pulse items-center justify-center bg-gray-200">
|
|
<!-- Placeholder -->
|
|
</div>
|
|
{/if}
|