memorium/components/Image.tsx

80 lines
1.7 KiB
TypeScript
Raw Normal View History

2023-08-09 13:32:28 +02:00
import { asset } from "$fresh/runtime.ts";
2023-08-08 21:55:10 +02:00
import * as CSS from "https://esm.sh/csstype@3.1.2";
2023-08-11 16:37:54 +02:00
interface ResponsiveAttributes {
srcset: string;
sizes: string;
}
function generateResponsiveAttributes(
imageUrl: string,
widths: number[],
baseApiUrl: string,
sizes = "100vw",
): ResponsiveAttributes {
const srcsets: string[] = [];
for (const width of widths) {
const apiUrl = `${baseApiUrl}?image=${imageUrl}&width=${width}`;
srcsets.push(`${apiUrl} ${width}w`);
}
const srcset = srcsets.join(", ");
return {
srcset,
sizes,
};
}
const widths = [320, 640, 960, 1280]; // List of widths for srcset
2023-08-08 21:50:23 +02:00
2023-08-08 21:55:10 +02:00
const Image = (
props: {
class: string;
src: string;
alt?: string;
thumbnail?: string;
2023-08-12 18:32:56 +02:00
fill?: boolean;
2023-08-08 21:55:10 +02:00
width?: number | string;
height?: number | string;
style?: CSS.HtmlAttributes;
},
) => {
const responsiveAttributes = generateResponsiveAttributes(
props.src,
widths,
"/api/images",
);
2023-08-11 16:37:54 +02:00
2023-08-08 21:50:23 +02:00
return (
<span
style={{
2023-08-12 18:32:56 +02:00
position: props.fill ? "absolute" : "",
width: props.fill ? "100%" : "",
height: props.fill ? "100%" : "",
zIndex: props.fill ? -1 : "",
}}
data-thumb={props.thumbnail}
>
<img
data-thumb={props.thumbnail}
data-thumb-img
loading="lazy"
alt={props.alt}
style={props.style}
2023-08-11 16:37:54 +02:00
srcset={responsiveAttributes.srcset}
sizes={responsiveAttributes.sizes}
2025-01-05 23:14:19 +01:00
src={`/api/images?image=${asset(props.src)}${
props.width ? `&width=${props.width}` : ""
}${props.height ? `&height=${props.height}` : ""}`}
width={props.width}
height={props.height}
class={props.class}
/>
</span>
2023-08-08 21:50:23 +02:00
);
2023-08-08 21:55:10 +02:00
};
export default Image;