Skip to content

Commit

Permalink
feat(gatsby-plugin-image): Add useArtDirection hook (#29231)
Browse files Browse the repository at this point in the history
  • Loading branch information
ascorbic committed Jan 28, 2021
1 parent e1c899f commit c2f0298
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 2 deletions.
79 changes: 79 additions & 0 deletions packages/gatsby-plugin-image/src/components/hooks.ts
@@ -1,3 +1,4 @@
/* eslint-disable no-unused-expressions */
import {
useState,
CSSProperties,
Expand Down Expand Up @@ -283,3 +284,81 @@ export function useImageLoaded(
toggleLoaded,
}
}

export interface IArtDirectedImage {
media: string
image: IGatsbyImageData
}

/**
* Generate a Gatsby image data object with multiple, art-directed images that display at different
* resolutions.
*
* @param defaultImage The image displayed when no media query matches.
* It is also used for all other settings applied to the image, such as width, height and layout.
* You should pass a className to the component with media queries to adjust the size of the container,
* as this cannot be adjusted automatically.
* @param artDirected Array of objects which each contains a `media` string which is a media query
* such as `(min-width: 320px)`, and the image object to use when that query matches.
*/
export function useArtDirection(
defaultImage: IGatsbyImageData,
artDirected: Array<IArtDirectedImage>
): IGatsbyImageData {
const { images, placeholder, ...props } = defaultImage
const output: IGatsbyImageData = {
...props,
images: {
...images,
sources: [],
},
placeholder: placeholder && {
...placeholder,
sources: [],
},
}

artDirected.forEach(({ media, image }) => {
if (!media) {
if (process.env.NODE_ENV === `development`) {
console.warn(
"[gatsby-plugin-image] All art-directed images passed to must have a value set for `media`. Skipping."
)
}
return
}

if (
image.layout !== defaultImage.layout &&
process.env.NODE_ENV === `development`
) {
console.warn(
`[gatsby-plugin-image] Mismatched image layout: expected "${defaultImage.layout}" but received "${image.layout}". All art-directed images use the same layout as the default image`
)
}

output.images.sources.push(
...image.images.sources.map(source => {
return { ...source, media }
}),
{
media,
srcSet: image.images.fallback.srcSet,
}
)

if (!output.placeholder) {
return
}

output.placeholder.sources.push({
media,
srcSet: image.placeholder.fallback,
})
})
output.images.sources.push(...images.sources)
if (placeholder?.sources) {
output.placeholder?.sources.push(...placeholder.sources)
}
return output
}
8 changes: 7 additions & 1 deletion packages/gatsby-plugin-image/src/index.browser.ts
Expand Up @@ -7,7 +7,13 @@ export { Placeholder } from "./components/placeholder"
export { MainImage } from "./components/main-image"
export { StaticImage } from "./components/static-image"
export { LaterHydrator } from "./components/later-hydrator"
export { getImage, getSrc, useGatsbyImage } from "./components/hooks"
export {
getImage,
getSrc,
useGatsbyImage,
useArtDirection,
IArtDirectedImage,
} from "./components/hooks"
export {
generateImageData,
IGatsbyImageHelperArgs,
Expand Down
8 changes: 7 additions & 1 deletion packages/gatsby-plugin-image/src/index.ts
Expand Up @@ -6,7 +6,13 @@ export {
export { Placeholder } from "./components/placeholder"
export { MainImage } from "./components/main-image"
export { StaticImage } from "./components/static-image.server"
export { getImage, getSrc, useGatsbyImage } from "./components/hooks"
export {
getImage,
getSrc,
useGatsbyImage,
useArtDirection,
IArtDirectedImage,
} from "./components/hooks"
export {
generateImageData,
IGatsbyImageHelperArgs,
Expand Down

0 comments on commit c2f0298

Please sign in to comment.