{"version":3,"file":"Image.mjs","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\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-01/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 */\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"],"names":[],"mappings":"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"}