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;
 |