import clsx from 'clsx'; import { ForwardedRef, forwardRef, HTMLAttributes, type ImgHTMLAttributes, ReactNode } from 'react'; import { Img } from 'react-image'; import styles from './image.module.css'; import { Icon } from '/@/shared/components/icon/icon'; import { Skeleton } from '/@/shared/components/skeleton/skeleton'; import { useInViewport } from '/@/shared/hooks/use-in-viewport'; interface ImageContainerProps extends HTMLAttributes { children: ReactNode; enableAnimation?: boolean; } interface ImageLoaderProps { className?: string; } interface ImageProps extends Omit, 'src'> { containerClassName?: string; enableAnimation?: boolean; imageContainerProps?: Omit; includeLoader?: boolean; includeUnloader?: boolean; src: string | string[] | undefined; thumbHash?: string; } interface ImageUnloaderProps { className?: string; } const FALLBACK_SVG = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMDAiIGhlaWdodD0iMzAwIj48ZmlsdGVyIGlkPSJhIiB4PSIwIiB5PSIwIj48ZmVUdXJidWxlbmNlIHR5cGU9ImZyYWN0YWxOb2lzZSIgYmFzZUZyZXF1ZW5jeT0iLjc1IiBzdGl0Y2hUaWxlcz0ic3RpdGNoIi8+PGZlQ29sb3JNYXRyaXggdHlwZT0ic2F0dXJhdGUiIHZhbHVlcz0iMCIvPjwvZmlsdGVyPjxwYXRoIGZpbHRlcj0idXJsKCNhKSIgb3BhY2l0eT0iLjA1IiBkPSJNMCAwaDMwMHYzMDBIMHoiLz48L3N2Zz4='; export function Image({ className, containerClassName, enableAnimation, imageContainerProps, includeLoader = true, includeUnloader = true, src, ...props }: ImageProps) { const { inViewport, ref } = useInViewport(); if (src) { return ( ( {children} )} loader={ includeLoader ? ( ) : null } src={inViewport ? src : FALLBACK_SVG} unloader={ includeUnloader ? ( ) : null } {...props} /> ); } return ( ); } const ImageContainer = forwardRef( ( { children, className, enableAnimation, ...props }: ImageContainerProps, ref: ForwardedRef, ) => { if (!enableAnimation) { return (
{children}
); } return (
{children}
); }, ); function ImageLoader({ className }: ImageLoaderProps) { return ( ); } function ImageUnloader({ className }: ImageUnloaderProps) { return (
); }