80 lines
1.7 KiB
TypeScript
80 lines
1.7 KiB
TypeScript
import { asset } from "$fresh/runtime.ts";
|
|
import * as CSS from "https://esm.sh/csstype@3.1.2";
|
|
|
|
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
|
|
|
|
const Image = (
|
|
props: {
|
|
class: string;
|
|
src: string;
|
|
alt?: string;
|
|
thumbnail?: string;
|
|
fill?: boolean;
|
|
width?: number | string;
|
|
height?: number | string;
|
|
style?: CSS.HtmlAttributes;
|
|
},
|
|
) => {
|
|
const responsiveAttributes = generateResponsiveAttributes(
|
|
props.src,
|
|
widths,
|
|
"/api/images",
|
|
);
|
|
|
|
return (
|
|
<span
|
|
style={{
|
|
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}
|
|
srcset={responsiveAttributes.srcset}
|
|
sizes={responsiveAttributes.sizes}
|
|
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>
|
|
);
|
|
};
|
|
|
|
export default Image;
|