diff --git a/packages/peregrine/lib/talons/Image/__tests__/useImage.spec.js b/packages/peregrine/lib/talons/Image/__tests__/useImage.spec.js index 513c088553..7ceead2570 100644 --- a/packages/peregrine/lib/talons/Image/__tests__/useImage.spec.js +++ b/packages/peregrine/lib/talons/Image/__tests__/useImage.spec.js @@ -36,6 +36,24 @@ test('it returns the proper shape', () => { }); describe('resourceWidth', () => { + test('uses width if present', () => { + // Arrange. + const myProps = { + ...props, + width: 75 + }; + + // Act. + createTestInstance(); + + // Assert. + expect(log).toHaveBeenCalledWith( + expect.objectContaining({ + resourceWidth: myProps.width + }) + ); + }); + test('falls back to the default entry in widths', () => { // Act. createTestInstance(); @@ -49,10 +67,11 @@ describe('resourceWidth', () => { ); }); - test('returns undefined if widths is not present', () => { + test('returns undefined if width and widths are not present', () => { // Arrange. const myProps = { ...props, + width: undefined, widths: undefined }; diff --git a/packages/peregrine/lib/talons/Image/useImage.js b/packages/peregrine/lib/talons/Image/useImage.js index 0ea78d5413..5a061f02d7 100644 --- a/packages/peregrine/lib/talons/Image/useImage.js +++ b/packages/peregrine/lib/talons/Image/useImage.js @@ -6,10 +6,11 @@ import { useCallback, useMemo, useState } from 'react'; * @param {function} props.onError callback for error of loading image * @param {function} props.onLoad callback for load of image * @param {string} props.unconstrainedSizeKey the key in props.widths for the unconstrained / default width. + * @param {number} props.width the intrinsic width of the image & the width to request for the fallback image for browsers that don't support srcset / sizes. * @param {Map} props.widths a map of breakpoints to possible widths used to create the img's sizes attribute. */ export const useImage = props => { - const { onError, onLoad, unconstrainedSizeKey, widths } = props; + const { onError, onLoad, unconstrainedSizeKey, width, widths } = props; const [isLoaded, setIsLoaded] = useState(false); const [hasError, setHasError] = useState(false); @@ -31,12 +32,18 @@ export const useImage = props => { // Use the unconstrained / default entry in widths. const resourceWidth = useMemo(() => { + if (width) { + return width; + } + + // We don't have an explicit width. + // Attempt to use the unconstrained entry in widths. if (!widths) { return undefined; } return widths.get(unconstrainedSizeKey); - }, [unconstrainedSizeKey, widths]); + }, [unconstrainedSizeKey, width, widths]); return { handleError, diff --git a/packages/venia-ui/lib/components/Image/image.js b/packages/venia-ui/lib/components/Image/image.js index b21a747fdf..fae67b6c1f 100644 --- a/packages/venia-ui/lib/components/Image/image.js +++ b/packages/venia-ui/lib/components/Image/image.js @@ -30,6 +30,7 @@ export const UNCONSTRAINED_SIZE_KEY = 'default'; * @param {string} props.resource the Magento path to the image ex: /v/d/vd12-rn_main_2.jpg * @param {string} props.src the source of the image, ready to use in an img element * @param {string} props.type the Magento image type ("image-category" / "image-product"). Used to build the resource URL. + * @param {number} props.width the intrinsic width of the image & the width to request for the fallback image for browsers that don't support srcset / sizes. * @param {Map} props.widths a map of breakpoints to possible widths used to create the img's sizes attribute. */ const Image = props => { @@ -44,6 +45,7 @@ const Image = props => { resource, src, type, + width, widths, ...rest } = props; @@ -52,6 +54,7 @@ const Image = props => { onError, onLoad, unconstrainedSizeKey: UNCONSTRAINED_SIZE_KEY, + width, widths }); @@ -148,6 +151,7 @@ Image.propTypes = { resource: conditionallyRequiredString, src: conditionallyRequiredString, type: string, + width: oneOfType([number, string]), widths: instanceOf(Map) };