import type { CSSProperties, ImgHTMLAttributes, Ref } from 'react'; import React from 'react'; import classNames from 'classnames'; import { Image as CoreImage, useTranslations } from '@shoptet/ui-core-web'; import type { Exact, SafeExtract, SafeOmit } from '@shoptet/utils'; import { omit, pick } from '@shoptet/utils'; import type { Size } from '../../tokens/types'; import { Icon } from '../Icon/Icon'; import { Text } from '../Typography/Text/Text'; import { dictionary } from './dictionary'; type ImageContainerProps = SafeOmit< ImgHTMLAttributes, 'className' | 'src' | 'srcSet' | 'alt' | 'style' >; export interface ImageProps extends ImageContainerProps { /** * Ref for the underlying image element. */ ref?: Ref; /** * Image source URL. */ src: string | null | undefined; /** * The `srcSet` attribute for the image. */ srcSet?: string | undefined; /** * Alternative text for the image. Use an empty string for decorative images. */ alt: string; /** * Custom aspect ratio for the fixed layout. * @default '3 / 2' */ aspectRatio?: `${number} / ${number}` | number; /** * Whether the image should use its intrinsic aspect ratio. * @default false */ responsive?: boolean; /** * Controls how the image fits inside its box. * @default 'contain' */ fit?: 'contain' | 'cover'; /** * Sets predefined image width. * @default 'md' */ size?: SafeExtract; } const hiddenImgStyle: CSSProperties = { opacity: 0, transition: 'none' }; export const Image = ({ alt: altProp, aspectRatio = '3 / 2', fit = 'contain', ref, responsive = false, size = 'md', src: srcProp, srcSet, ...rest }: ImageProps) => { rest satisfies Exact; const src = (srcProp ?? '').trim(); const translations = useTranslations(dictionary); const alt = altProp === '' ? null : altProp; const aspectRatioValue = typeof aspectRatio === 'number' ? `${aspectRatio}` : aspectRatio; return ( (state.loadingState === 'success' ? {} : hiddenImgStyle)} /> {({ state, props }) => ({ error: ( {alt === null ? translations.loadingError : alt} ), initial: ( ), success: , pending: , })[state.loadingState] } ); };