import { CSSProperties, memo } from "react";
import { ImagType } from "../types";
import { StringUtils } from "../utils/string";
export const nextjsWidthArr: number[] = [640, 750, 828, 1080, 1200, 1920, 2048, 3840];
export const widthArr: number[] = [480, 720, 1080, 1440, 1920, 2048];
interface ImgProp extends React.HTMLAttributes<HTMLImageElement> {
src: string;
alt?: string;
width?: number;
height?: number;
decoding?: "async" | "auto";
loading?: "eager" | "lazy";
responsive?: boolean;
extensions?: Array<ImagType>;
widths?: number[];
objectFit?: "contain" | "cover" | "fill" | "none" | "scale-down";
objectPosition?: "top" | "center" | "bottom" | "left" | "right" | string;
fetchPriority?: "auto" | "low" | "high";
style?: CSSProperties;
[x: string]: any;
}
interface SrcSetGenerator {
imgStr: string;
extension: string;
widths?: number[];
}
export const srcSetGenerator = ({ imgStr, extension, widths = widthArr }: SrcSetGenerator): string => {
return widths.map((width) => `${imgStr}_${width}${extension} ${width}w`).join(",");
};
const Img = ({
src,
alt,
width,
height,
loading,
decoding,
objectFit,
objectPosition,
fetchPriority,
widths = widthArr,
responsive,
extensions,
style,
...props
}: ImgProp) => {
// str = /images/hero, ext = .png
const [str, ext] = StringUtils.getExt(src);
const sizes = `
(max-width:720) 720px,
(min-width:721) and (max-width: 1079px) 1080px,
(min-width:1080) and (max-width: 1399px) 1440px,
(min-width:1400) and (max-width: 1999px) 1920px,
(min-width:2000) 2048px
`;
if (!responsive) {
return (
<>
<picture {...props}>
{extensions?.includes("avif") ?? <source type="image/avif" srcSet={`${str}.avif`} />}
{extensions?.includes("webp") ?? <source type="image/webp" srcSet={`${str}.webp`} />}
<img
className={props.className}
alt={alt}
src={src}
loading={loading}
decoding={decoding}
fetchpriority={fetchPriority}
width={width}
height={height}
style={{ objectPosition: objectPosition, objectFit: objectFit, ...style }}
/>
</picture>
</>
);
}
return (
<>
<picture {...props}>
<source type="image/avif" srcSet={srcSetGenerator({ imgStr: str, extension: ".avif", widths })} sizes={sizes} />
<source type="image/webp" srcSet={srcSetGenerator({ imgStr: str, extension: ".webp", widths })} sizes={sizes} />
<img
className={props.className}
alt={alt}
srcSet={srcSetGenerator({ imgStr: str, extension: ext, widths })}
sizes={sizes}
src={src}
loading={loading}
decoding={decoding}
fetchpriority={fetchPriority}
width={width}
height={height}
style={{ objectPosition: objectPosition, objectFit: objectFit, ...style }}
/>
</picture>
</>
);
};
Img.defaultProps = {
alt: "image",
loading: "lazy",
responsive: true,
decoding: "async",
fetchPriority: "auto",
};
export default memo(Img);