<script lang="ts">
	import type { HTMLImgAttributes } from 'svelte/elements';
	import type { Attachment } from 'svelte/attachments';

	let {
		src,
		alt,
		class: className = '',
		imgClass = 'h-full w-full object-cover',
		onload,
		onerror,
		...rest
	}: {
		src: string;
		alt: string;
		/** Classes for the wrapper box (sizing, rounding, ring, shadow, flex-none, etc.) */
		class?: string;
		/** Classes for the inner <img> (object-fit, padding). Defaults to fill+cover. */
		imgClass?: string;
		onload?: (e: Event) => void;
		onerror?: (e: Event) => void;
	} & HTMLImgAttributes = $props();

	let loaded = $state(false);

	// After SSR/hydration a cached image can already be complete before our
	// onload handler is attached, so reconcile once on mount.
	const reconcileCached: Attachment<HTMLImageElement> = (node) => {
		if (node.complete && node.naturalWidth > 0) loaded = true;
	};
</script>

<div class={['relative overflow-hidden', className]}>
	{#if !loaded}
		<div class="absolute inset-0 skeleton"></div>
	{/if}
	<img
		{@attach reconcileCached}
		{src}
		{alt}
		class={imgClass}
		loading="lazy"
		{...rest}
		onload={(e) => {
			loaded = true;
			onload?.(e);
		}}
		onerror={(e) => {
			loaded = true;
			onerror?.(e);
		}}
	/>
</div>
