{"version":3,"file":"Image.mjs","names":[],"sources":["../../src/Image.tsx"],"sourcesContent":["/* eslint-disable eslint-comments/disable-enable-pair */\n/* eslint-disable @typescript-eslint/explicit-function-return-type */\nimport * as React from 'react';\nimport type {PartialDeep} from 'type-fest';\nimport type {Image as ImageType} from './storefront-api-types.js';\n\n/*\n * An optional prop you can use to change the\n * default srcSet generation behaviour\n */\ntype SrcSetOptions = {\n  /** The number of sizes to generate */\n  intervals: number;\n  /** The smallest image size */\n  startingWidth: number;\n  /** The increment by which to increase for each size, in pixels */\n  incrementSize: number;\n  /** The size used for placeholder fallback images */\n  placeholderWidth: number;\n};\n\ntype NormalizedProps = {\n  alt: string;\n  aspectRatio: string | undefined;\n  height: string;\n  src: string | undefined;\n  width: string;\n};\n\nexport type LoaderParams = {\n  /** The base URL of the image */\n  src?: ImageType['url'];\n  /** The URL param that controls width */\n  width?: number;\n  /** The URL param that controls height */\n  height?: number;\n  /** The URL param that controls the cropping region */\n  crop?: Crop;\n};\n\nexport type Loader = (params: LoaderParams) => string;\n\n/*\n * @TODO: Expand to include focal point support; and/or switch this to be an SF API type\n */\ntype Crop = 'center' | 'top' | 'bottom' | 'left' | 'right';\n\n/** @publicDocs */\nexport type HydrogenImageProps = React.ComponentPropsWithRef<'img'> &\n  HydrogenImageBaseProps;\n\ntype HydrogenImageBaseProps = {\n  /** The aspect ratio of the image, in the format of `width/height`.\n   *\n   * @example\n   * ```\n   * <Image data={productImage} aspectRatio=\"4/5\" />\n   * ```\n   */\n  aspectRatio?: string;\n  /** The crop position of the image.\n   *\n   * @remarks\n   * In the event that AspectRatio is set, without specifying a crop,\n   * the Shopify CDN won't return the expected image.\n   *\n   * @defaultValue `center`\n   */\n  crop?: Crop;\n  /** Data mapping to the [Storefront API `Image`](https://shopify.dev/docs/api/storefront/2026-04/objects/Image) object. Must be an Image object.\n   *\n   * @example\n   * ```\n   * import {IMAGE_FRAGMENT, Image} from '@shopify/hydrogen';\n   *\n   * export const IMAGE_QUERY = `#graphql\n   * ${IMAGE_FRAGMENT}\n   * query {\n   *   product {\n   *     featuredImage {\n   *       ...Image\n   *     }\n   *   }\n   * }`\n   *\n   * <Image\n   *   data={productImage}\n   *   sizes=\"(min-width: 45em) 50vw, 100vw\"\n   *   aspectRatio=\"4/5\"\n   * />\n   * ```\n   *\n   * Image: {@link https://shopify.dev/api/storefront/reference/common-objects/image}\n   */\n  data?: PartialDeep<ImageType, {recurseIntoArrays: true}>;\n  /** A function that returns a URL string for an image.\n   *\n   * @remarks\n   * By default, this uses Shopify’s CDN {@link https://cdn.shopify.com/} but you can provide\n   * your own function to use a another provider, as long as they support URL based image transformations.\n   */\n  loader?: Loader;\n  /** An optional prop you can use to change the default srcSet generation behaviour */\n  srcSetOptions?: SrcSetOptions;\n};\n\n/**\n * A Storefront API GraphQL fragment that can be used to query for an image.\n */\nexport const IMAGE_FRAGMENT = `#graphql\n  fragment Image on Image {\n    altText\n    url\n    width\n    height\n  }\n`;\n\n/**\n * Hydrogen’s Image component is a wrapper around the HTML image element.\n * It supports the same props as the HTML `img` element, but automatically\n * generates the srcSet and sizes attributes for you. For most use cases,\n * you’ll want to set the `aspectRatio` prop to ensure the image is sized\n * correctly.\n *\n * @remarks\n * - `decoding` is set to `async` by default.\n * - `loading` is set to `lazy` by default.\n * - `alt` will automatically be set to the `altText` from the Storefront API if passed in the `data` prop\n * - `src` will automatically be set to the `url` from the Storefront API if passed in the `data` prop\n *\n * @example\n * A responsive image with a 4:5 aspect ratio:\n * ```\n * <Image\n *   data={product.featuredImage}\n *   aspectRatio=\"4/5\"\n *   sizes=\"(min-width: 45em) 40vw, 100vw\"\n * />\n * ```\n * @example\n * A fixed size image:\n * ```\n * <Image\n *   data={product.featuredImage}\n *   width={100}\n *   height={100}\n * />\n * ```\n *\n * {@link https://shopify.dev/docs/api/hydrogen-react/components/image}\n * @publicDocs\n */\nexport const Image = React.forwardRef<HTMLImageElement, HydrogenImageProps>(\n  (\n    {\n      alt,\n      aspectRatio,\n      crop = 'center',\n      data,\n      decoding = 'async',\n      height = 'auto',\n      loader = shopifyLoader,\n      loading = 'lazy',\n      sizes,\n      src,\n      srcSetOptions = {\n        intervals: 15,\n        startingWidth: 200,\n        incrementSize: 200,\n        placeholderWidth: 100,\n      },\n      width = '100%',\n      ...passthroughProps\n    },\n    ref,\n  ) => {\n    /*\n     * Gets normalized values for width, height from data  prop\n     */\n    const normalizedData = React.useMemo(() => {\n      /* Only use data width if height is also set */\n      const dataWidth: number | undefined =\n        data?.width && data?.height ? data?.width : undefined;\n\n      const dataHeight: number | undefined =\n        data?.width && data?.height ? data?.height : undefined;\n\n      return {\n        width: dataWidth,\n        height: dataHeight,\n        unitsMatch: Boolean(unitsMatch(dataWidth, dataHeight)),\n      };\n    }, [data]);\n\n    /*\n     * Gets normalized values for width, height, src, alt, and aspectRatio props\n     * supporting the presence of `data` in addition to flat props.\n     */\n    const normalizedProps = React.useMemo(() => {\n      const nWidthProp: string | number = width || '100%';\n      const widthParts = getUnitValueParts(nWidthProp.toString());\n      const nWidth = `${widthParts.number}${widthParts.unit}`;\n\n      const autoHeight = height === undefined || height === null;\n      const heightParts = autoHeight\n        ? null\n        : getUnitValueParts(height.toString());\n\n      const fixedHeight = heightParts\n        ? `${heightParts.number}${heightParts.unit}`\n        : '';\n\n      const nHeight = autoHeight ? 'auto' : fixedHeight;\n\n      const nSrc: string | undefined = src || data?.url;\n\n      if (__HYDROGEN_DEV__ && !nSrc) {\n        console.warn(\n          `No src or data.url provided to Image component.`,\n          passthroughProps?.key || '',\n        );\n      }\n\n      const nAlt: string = data?.altText && !alt ? data?.altText : alt || '';\n\n      const nAspectRatio: string | undefined = aspectRatio\n        ? aspectRatio\n        : normalizedData.unitsMatch\n          ? [\n              getNormalizedFixedUnit(normalizedData.width),\n              getNormalizedFixedUnit(normalizedData.height),\n            ].join('/')\n          : undefined;\n\n      return {\n        width: nWidth,\n        height: nHeight,\n        src: nSrc,\n        alt: nAlt,\n        aspectRatio: nAspectRatio,\n      };\n    }, [\n      width,\n      height,\n      src,\n      data,\n      alt,\n      aspectRatio,\n      normalizedData,\n      passthroughProps?.key,\n    ]);\n\n    const {intervals, startingWidth, incrementSize, placeholderWidth} =\n      srcSetOptions;\n\n    /*\n     * This function creates an array of widths to be used in srcSet\n     */\n    const imageWidths = React.useMemo(() => {\n      return generateImageWidths(\n        width,\n        intervals,\n        startingWidth,\n        incrementSize,\n      );\n    }, [width, intervals, startingWidth, incrementSize]);\n\n    const fixedWidth = isFixedWidth(normalizedProps.width);\n\n    if (__HYDROGEN_DEV__ && !sizes && !fixedWidth) {\n      console.warn(\n        [\n          'No sizes prop provided to Image component,',\n          'you may be loading unnecessarily large images.',\n          `Image used is ${\n            src || data?.url || passthroughProps?.key || 'unknown'\n          }`,\n        ].join(' '),\n      );\n    }\n\n    /*\n     * We check to see whether the image is fixed width or not,\n     * if fixed, we still provide a srcSet, but only to account for\n     * different pixel densities.\n     */\n    if (fixedWidth) {\n      return (\n        <FixedWidthImage\n          aspectRatio={aspectRatio}\n          crop={crop}\n          decoding={decoding}\n          height={height}\n          imageWidths={imageWidths}\n          loader={loader}\n          loading={loading}\n          normalizedProps={normalizedProps}\n          passthroughProps={passthroughProps}\n          ref={ref}\n          width={width}\n          data={data}\n        />\n      );\n    } else {\n      return (\n        <FluidImage\n          aspectRatio={aspectRatio}\n          crop={crop}\n          decoding={decoding}\n          imageWidths={imageWidths}\n          loader={loader}\n          loading={loading}\n          normalizedProps={normalizedProps}\n          passthroughProps={passthroughProps}\n          placeholderWidth={placeholderWidth}\n          ref={ref}\n          sizes={sizes}\n          data={data}\n        />\n      );\n    }\n  },\n);\n\ntype FixedImageExludedProps =\n  | 'data'\n  | 'loader'\n  | 'loaderOptions'\n  | 'sizes'\n  | 'srcSetOptions'\n  | 'widths';\n\ntype FixedWidthImageProps = Omit<HydrogenImageProps, FixedImageExludedProps> &\n  Pick<HydrogenImageBaseProps, 'data'> & {\n    loader: Loader;\n    passthroughProps: React.ImgHTMLAttributes<HTMLImageElement>;\n    normalizedProps: NormalizedProps;\n    imageWidths: number[];\n    ref: React.Ref<HTMLImageElement>;\n  };\n\nconst FixedWidthImage = React.forwardRef<\n  HTMLImageElement,\n  FixedWidthImageProps\n>(\n  (\n    {\n      aspectRatio,\n      crop,\n      decoding,\n      height,\n      imageWidths,\n      loader = shopifyLoader,\n      loading,\n      normalizedProps,\n      passthroughProps,\n      width,\n      data,\n    },\n    ref,\n  ) => {\n    const fixed = React.useMemo(() => {\n      const intWidth: number | undefined = getNormalizedFixedUnit(width);\n      const intHeight: number | undefined = getNormalizedFixedUnit(height);\n\n      /*\n       * The aspect ratio for fixed width images is taken from the explicitly\n       * set prop, but if that's not present, and both width and height are\n       * set, we calculate the aspect ratio from the width and height—as\n       * long as they share the same unit type (e.g. both are 'px').\n       */\n      const fixedAspectRatio = aspectRatio\n        ? aspectRatio\n        : unitsMatch(normalizedProps.width, normalizedProps.height)\n          ? [intWidth, intHeight].join('/')\n          : normalizedProps.aspectRatio\n            ? normalizedProps.aspectRatio\n            : undefined;\n\n      /*\n       * The Sizes Array generates an array of all the parts\n       * that make up the srcSet, including the width, height, and crop\n       */\n      const sizesArray =\n        imageWidths === undefined\n          ? undefined\n          : generateSizes(imageWidths, fixedAspectRatio, crop, {\n              width: data?.width ?? undefined,\n              height: data?.height ?? undefined,\n            });\n\n      const fixedHeight = intHeight\n        ? intHeight\n        : fixedAspectRatio && intWidth\n          ? intWidth * (parseAspectRatio(fixedAspectRatio) ?? 1)\n          : undefined;\n\n      const srcSet = generateSrcSet(normalizedProps.src, sizesArray, loader);\n      const src = loader({\n        src: normalizedProps.src,\n        width: intWidth,\n        height: fixedHeight,\n        crop: normalizedProps.height === 'auto' ? undefined : crop,\n      });\n\n      return {\n        width: intWidth,\n        aspectRatio: fixedAspectRatio,\n        height: fixedHeight,\n        srcSet,\n        src,\n      };\n    }, [\n      aspectRatio,\n      crop,\n      data,\n      height,\n      imageWidths,\n      loader,\n      normalizedProps,\n      width,\n    ]);\n\n    return (\n      <img\n        ref={ref}\n        alt={normalizedProps.alt}\n        decoding={decoding}\n        height={fixed.height}\n        loading={loading}\n        src={fixed.src}\n        srcSet={fixed.srcSet}\n        width={fixed.width}\n        style={{\n          aspectRatio: fixed.aspectRatio,\n          ...passthroughProps.style,\n        }}\n        {...passthroughProps}\n      />\n    );\n  },\n);\n\ntype FluidImageExcludedProps =\n  | 'data'\n  | 'width'\n  | 'height'\n  | 'loader'\n  | 'loaderOptions'\n  | 'srcSetOptions';\n\ntype FluidImageProps = Omit<HydrogenImageProps, FluidImageExcludedProps> &\n  Pick<HydrogenImageBaseProps, 'data'> & {\n    imageWidths: number[];\n    loader: Loader;\n    normalizedProps: NormalizedProps;\n    passthroughProps: React.ImgHTMLAttributes<HTMLImageElement>;\n    placeholderWidth: number;\n    ref: React.Ref<HTMLImageElement>;\n  };\n\nconst FluidImage = React.forwardRef<HTMLImageElement, FluidImageProps>(\n  (\n    {\n      crop,\n      decoding,\n      imageWidths,\n      loader = shopifyLoader,\n      loading,\n      normalizedProps,\n      passthroughProps,\n      placeholderWidth,\n      sizes,\n      data,\n    },\n    ref,\n  ) => {\n    const fluid = React.useMemo(() => {\n      const sizesArray =\n        imageWidths === undefined\n          ? undefined\n          : generateSizes(imageWidths, normalizedProps.aspectRatio, crop, {\n              width: data?.width ?? undefined,\n              height: data?.height ?? undefined,\n            });\n\n      const placeholderHeight =\n        normalizedProps.aspectRatio && placeholderWidth\n          ? placeholderWidth *\n            (parseAspectRatio(normalizedProps.aspectRatio) ?? 1)\n          : undefined;\n\n      const srcSet = generateSrcSet(normalizedProps.src, sizesArray, loader);\n\n      const src = loader({\n        src: normalizedProps.src,\n        width: placeholderWidth,\n        height: placeholderHeight,\n        crop,\n      });\n\n      return {\n        placeholderHeight,\n        srcSet,\n        src,\n      };\n    }, [crop, data, imageWidths, loader, normalizedProps, placeholderWidth]);\n\n    return (\n      <img\n        ref={ref}\n        alt={normalizedProps.alt}\n        decoding={decoding}\n        height={fluid.placeholderHeight}\n        loading={loading}\n        sizes={sizes}\n        src={fluid.src}\n        srcSet={fluid.srcSet}\n        width={placeholderWidth}\n        {...passthroughProps}\n        style={{\n          width: normalizedProps.width,\n          aspectRatio: normalizedProps.aspectRatio,\n          ...passthroughProps.style,\n        }}\n      />\n    );\n  },\n);\n\n/**\n * The shopifyLoader function is a simple utility function that takes a src, width,\n * height, and crop and returns a string that can be used as the src for an image.\n * It can be used with the Hydrogen Image component or with the next/image component.\n * (or any others that accept equivalent configuration)\n * @param src - The source URL of the image, e.g. `https://cdn.shopify.com/static/sample-images/garnished.jpeg`\n * @param width - The width of the image, e.g. `100`\n * @param height - The height of the image, e.g. `100`\n * @param crop - The crop of the image, e.g. `center`\n * @returns A Shopify image URL with the correct query parameters, e.g. `https://cdn.shopify.com/static/sample-images/garnished.jpeg?width=100&height=100&crop=center`\n *\n * @example\n * ```\n * shopifyLoader({\n *   src: 'https://cdn.shopify.com/static/sample-images/garnished.jpeg',\n *   width: 100,\n *   height: 100,\n *   crop: 'center',\n * })\n * ```\n */\nconst PLACEHOLDER_DOMAIN = 'https://placeholder.shopify.com';\nexport function shopifyLoader({src, width, height, crop}: LoaderParams) {\n  if (!src) {\n    return '';\n  }\n\n  const url = new URL(src, PLACEHOLDER_DOMAIN);\n\n  if (width) {\n    url.searchParams.append('width', Math.round(width).toString());\n  }\n\n  if (height) {\n    url.searchParams.append('height', Math.round(height).toString());\n  }\n\n  if (crop) {\n    url.searchParams.append('crop', crop);\n  }\n  return url.href.replace(PLACEHOLDER_DOMAIN, '');\n}\n\n/**\n * Checks whether the width and height share the same unit type\n * @param width - The width of the image, e.g. 100% | 10px\n * @param height - The height of the image, e.g. auto | 100px\n * @returns Whether the width and height share the same unit type (boolean)\n */\nfunction unitsMatch(\n  width: string | number = '100%',\n  height: string | number = 'auto',\n): boolean {\n  return (\n    getUnitValueParts(width.toString()).unit ===\n    getUnitValueParts(height.toString()).unit\n  );\n}\n\n/**\n * Given a CSS size, returns the unit and number parts of the value\n * @param value - The CSS size, e.g. 100px\n * @returns The unit and number parts of the value, e.g. \\{unit: 'px', number: 100\\}\n */\nfunction getUnitValueParts(value: string): {unit: string; number: number} {\n  const unit = value.replace(/[0-9.]/g, '');\n  const number = parseFloat(value.replace(unit, ''));\n\n  return {\n    unit: unit === '' ? (number === undefined ? 'auto' : 'px') : unit,\n    number,\n  };\n}\n\n/**\n * Given a value, returns the width of the image as an integer in pixels\n * @param value - The width of the image, e.g. 16px | 1rem | 1em | 16\n * @returns The width of the image in pixels, e.g. 16, or undefined if the value is not a fixed unit\n */\nfunction getNormalizedFixedUnit(value?: string | number): number | undefined {\n  if (value === undefined) {\n    return;\n  }\n\n  const {unit, number} = getUnitValueParts(value.toString());\n\n  switch (unit) {\n    case 'em':\n      return number * 16;\n    case 'rem':\n      return number * 16;\n    case 'px':\n      return number;\n    case '':\n      return number;\n    default:\n      return;\n  }\n}\n\n/**\n * This function checks whether a width is fixed or not.\n * @param width - The width of the image, e.g. 100 | '100px' | '100em' | '100rem'\n * @returns Whether the width is fixed or not\n */\nfunction isFixedWidth(width: string | number): boolean {\n  const fixedEndings = /\\d(px|em|rem)$/;\n  return typeof width === 'number' || fixedEndings.test(width);\n}\n\n/**\n * This function generates a srcSet for Shopify images.\n * @param src - The source URL of the image, e.g. https://cdn.shopify.com/static/sample-images/garnished.jpeg\n * @param sizesArray - An array of objects containing the `width`, `height`, and `crop` of the image, e.g. [\\{width: 200, height: 200, crop: 'center'\\}, \\{width: 400, height: 400, crop: 'center'\\}]\n * @param loader - A function that takes a Shopify image URL and returns a Shopify image URL with the correct query parameters\n * @returns A srcSet for Shopify images, e.g. 'https://cdn.shopify.com/static/sample-images/garnished.jpeg?width=200&height=200&crop=center 200w, https://cdn.shopify.com/static/sample-images/garnished.jpeg?width=400&height=400&crop=center 400w'\n */\nexport function generateSrcSet(\n  src?: string,\n  sizesArray?: Array<{width?: number; height?: number; crop?: Crop}>,\n  loader: Loader = shopifyLoader,\n): string {\n  if (!src) {\n    return '';\n  }\n\n  if (sizesArray?.length === 0 || !sizesArray) {\n    return src;\n  }\n\n  return sizesArray\n    .map(\n      (size, i) =>\n        `${loader({\n          src,\n          width: size.width,\n          height: size.height,\n          crop: size.crop,\n        })} ${sizesArray.length === 3 ? `${i + 1}x` : `${size.width ?? 0}w`}`,\n    )\n    .join(`, `);\n}\n\n/**\n * This function generates an array of sizes for Shopify images, for both fixed and responsive images.\n * @param width - The CSS width of the image\n * @param intervals - The number of intervals to generate\n * @param startingWidth - The starting width of the image\n * @param incrementSize - The size of each interval\n * @returns An array of widths\n */\nexport function generateImageWidths(\n  width: string | number = '100%',\n  intervals: number,\n  startingWidth: number,\n  incrementSize: number,\n): number[] {\n  const responsive = Array.from(\n    {length: intervals},\n    (_, i) => i * incrementSize + startingWidth,\n  );\n\n  const fixed = Array.from(\n    {length: 3},\n    (_, i) => (i + 1) * (getNormalizedFixedUnit(width) ?? 0),\n  );\n\n  return isFixedWidth(width) ? fixed : responsive;\n}\n\n/**\n * Simple utility function to convert an aspect ratio CSS string to a decimal, currently only supports values like `1/1`, not `0.5`, or `auto`\n * @param aspectRatio - The aspect ratio of the image, e.g. `1/1`\n * @returns The aspect ratio as a number, e.g. `0.5`\n *\n * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio}\n */\nexport function parseAspectRatio(aspectRatio?: string): number | undefined {\n  if (!aspectRatio) return;\n  const [width, height] = aspectRatio.split('/');\n  return 1 / (Number(width) / Number(height));\n}\n\n// Generate data needed for Imagery loader\nexport function generateSizes(\n  imageWidths?: number[],\n  aspectRatio?: string,\n  crop: Crop = 'center',\n  sourceDimensions?: {width?: number; height?: number},\n):\n  | {\n      width: number;\n      height: number | undefined;\n      crop: Crop;\n    }[]\n  | undefined {\n  if (!imageWidths) return;\n  return imageWidths\n    .map((width: number) => {\n      return {\n        width,\n        height: aspectRatio\n          ? width * (parseAspectRatio(aspectRatio) ?? 1)\n          : undefined,\n        crop,\n      };\n    })\n    .filter(({width, height}) => {\n      if (sourceDimensions?.width && width > sourceDimensions.width) {\n        return false;\n      }\n\n      if (\n        sourceDimensions?.height &&\n        height &&\n        height > sourceDimensions.height\n      ) {\n        return false;\n      }\n\n      return true;\n    });\n  /*\n    Given:\n      ([100, 200], 1/1, 'center')\n    Returns:\n      [{width: 100, height: 100, crop: 'center'},\n      {width: 200, height: 200, crop: 'center'}]\n  */\n}\n"],"mappings":"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"}