diff --git a/docs/02-app/02-api-reference/01-components/image.mdx b/docs/02-app/02-api-reference/01-components/image.mdx index dab26ce310d02..e5404be68a7ec 100644 --- a/docs/02-app/02-api-reference/01-components/image.mdx +++ b/docs/02-app/02-api-reference/01-components/image.mdx @@ -795,6 +795,100 @@ Try it out: - [Demo light/dark mode theme detection](https://image-component.nextjs.gallery/theme) +## getImageProps + +For more advanced use cases, you can call `getImageProps()` to get the props that would be passed to the underlying `` element, and instead pass to them to another component, style, canvas, etc. + +This also avoid calling React `useState()` so it can lead to better performance, but it cannot be used with the [`placeholder`](#placeholder) prop because the placeholder will never be removed. + +### Picture + +The example below uses the [``](https://developer.mozilla.org/docs/Web/HTML/Element/picture) element to display a different image based on the user's [preferred color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme). + +```jsx filename="app/page.js" +import { getImageProps } from 'next/image' + +export default function Page() { + const common = { alt: 'Theme Example', width: 800, height: 400 } + const { props: { srcSet: dark } } = getImageProps({ ...common, src: '/dark.png' }) + const { props: { srcSet: light, ...rest } } = getImageProps({ ...common, src: '/light.png' }) + + return ( + + + + + +) +``` + +### Art Direction + +Similarly, you can implement [Art Direction](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#art_direction) with different `src` images. + +```jsx filename="app/page.js" +import { getImageProps } from 'next/image' + +export default function Home() { + const common = { alt: 'Art Direction Example', sizes: '100vw' } + const { props: desktop } = getImageProps({ + ...common, + width: 1440, + height: 875, + quality: 80, + src: '/desktop.jpg', + }) + const { props: mobile } = getImageProps({ + ...common, + width: 750, + height: 1334, + quality: 70, + src: '/mobile.jpg', + }) + + return ( + + + + + + ) +} +``` + +### Background CSS + +You can even convert the `srcSet` string to the [`image-set()`](https://developer.mozilla.org/en-US/docs/Web/CSS/image/image-set) CSS function to optimize a background image. + +```jsx filename="app/page.js" +import { getImageProps } from 'next/image' + +function getBackgroundImage(srcSet = '') { + const imageSet = srcSet + .split(', ') + .map((str) => { + const [url, dpi] = str.split(' ') + return `url("${url}") ${dpi}` + }) + .join(', ') + return `image-set(${imageSet})` +} + +export default function Home() { + const { + props: { srcSet }, + } = getImageProps({ alt: '', width: 128, height: 128, src: '/img.png' }) + const backgroundImage = getBackgroundImage(srcSet) + const style = { height: '100vh', width: '100vw', backgroundImage } + + return ( +
+

Hello World

+
+ ) +} +``` + ## Known Browser Bugs This `next/image` component uses browser native [lazy loading](https://caniuse.com/loading-lazy-attr), which may fallback to eager loading for older browsers before Safari 15.4. When using the blur-up placeholder, older browsers before Safari 12 will fallback to empty placeholder. When using styles with `width`/`height` of `auto`, it is possible to cause [Layout Shift](https://web.dev/cls/) on older browsers before Safari 15 that don't [preserve the aspect ratio](https://caniuse.com/mdn-html_elements_img_aspect_ratio_computed_from_attributes). For more details, see [this MDN video](https://www.youtube.com/watch?v=4-d_SoCHeWE). @@ -810,6 +904,7 @@ This `next/image` component uses browser native [lazy loading](https://caniuse.c | Version | Changes | | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `v14.1.0` | `getImageProps()` is stable. | | `v14.0.0` | `onLoadingComplete` prop and `domains` config deprecated. | | `v13.4.14` | `placeholder` prop support for `data:/image...` | | `v13.2.0` | `contentDispositionType` configuration added. | diff --git a/packages/next/src/shared/lib/image-external.tsx b/packages/next/src/shared/lib/image-external.tsx index 46ccdb7df8f40..85f716e69faa0 100644 --- a/packages/next/src/shared/lib/image-external.tsx +++ b/packages/next/src/shared/lib/image-external.tsx @@ -2,21 +2,20 @@ import type { ImageConfigComplete, ImageLoaderProps } from './image-config' import type { ImageProps, ImageLoader, StaticImageData } from './get-img-props' import { getImgProps } from './get-img-props' -import { warnOnce } from './utils/warn-once' import { Image } from '../../client/image-component' // @ts-ignore - This is replaced by webpack alias import defaultLoader from 'next/dist/shared/lib/image-loader' -export const unstable_getImgProps = (imgProps: ImageProps) => { - warnOnce( - 'Warning: unstable_getImgProps() is experimental and may change or be removed at any time. Use at your own risk.' - ) +export const getImageProps = (imgProps: ImageProps) => { const { props } = getImgProps(imgProps, { defaultLoader, // This is replaced by webpack define plugin imgConf: process.env.__NEXT_IMAGE_OPTS as any as ImageConfigComplete, }) + // Normally we don't care about undefined props because we pass to JSX, + // but this exported function could be used by the end user for anything + // so we delete undefined props to clean it up a little. for (const [key, value] of Object.entries(props)) { if (value === undefined) { delete props[key as keyof typeof props] diff --git a/test/e2e/app-dir/app-esm-js/app/app/components-ext.js b/test/e2e/app-dir/app-esm-js/app/app/components-ext.js index 0a5fcbeef803b..46544b4bf0783 100644 --- a/test/e2e/app-dir/app-esm-js/app/app/components-ext.js +++ b/test/e2e/app-dir/app-esm-js/app/app/components-ext.js @@ -1,4 +1,4 @@ -import NextImage, { unstable_getImgProps } from 'next/image.js' +import NextImage, { getImageProps } from 'next/image.js' import Link from 'next/link.js' import Script from 'next/script.js' @@ -8,7 +8,7 @@ export function Components() { return ( <> -

{typeof unstable_getImgProps}

+

{typeof getImageProps}

link diff --git a/test/e2e/app-dir/app-esm-js/app/app/components.js b/test/e2e/app-dir/app-esm-js/app/app/components.js index 3f319976d4498..339986ee37149 100644 --- a/test/e2e/app-dir/app-esm-js/app/app/components.js +++ b/test/e2e/app-dir/app-esm-js/app/app/components.js @@ -1,4 +1,4 @@ -import NextImage, { unstable_getImgProps } from 'next/image' +import NextImage, { getImageProps } from 'next/image' import Link from 'next/link' import Script from 'next/script' @@ -8,7 +8,7 @@ export function Components() { return ( <> -

{typeof unstable_getImgProps}

+

{typeof getImageProps}

link diff --git a/test/e2e/app-dir/app-esm-js/index.test.ts b/test/e2e/app-dir/app-esm-js/index.test.ts index 7cb2b8d280e8c..c280c844225cb 100644 --- a/test/e2e/app-dir/app-esm-js/index.test.ts +++ b/test/e2e/app-dir/app-esm-js/index.test.ts @@ -12,7 +12,7 @@ createNextDescribe( async function validateDomNodes(selector: string) { expect(await $(`${selector} .img`).prop('tagName')).toBe('IMG') expect(await $(`${selector} .link`).prop('tagName')).toBe('A') - expect(await $(`${selector} .unstable_getImgProps`).text()).toContain( + expect(await $(`${selector} .typeof-getImageProps`).text()).toContain( 'function' ) } diff --git a/test/integration/next-image-new/app-dir/app/picture/page.js b/test/integration/next-image-new/app-dir/app/picture/page.js index 1f3b60b6e6739..c1c203a25f0e0 100644 --- a/test/integration/next-image-new/app-dir/app/picture/page.js +++ b/test/integration/next-image-new/app-dir/app/picture/page.js @@ -1,13 +1,13 @@ -import { unstable_getImgProps as getImgProps } from 'next/image' +import { getImageProps } from 'next/image' export default function Page() { const common = { alt: 'Hero', width: 400, height: 400, priority: true } const { props: { srcSet: dark }, - } = getImgProps({ ...common, src: '/test.png' }) + } = getImageProps({ ...common, src: '/test.png' }) const { props: { srcSet: light, ...rest }, - } = getImgProps({ ...common, src: '/test_light.png' }) + } = getImageProps({ ...common, src: '/test_light.png' }) return ( diff --git a/test/integration/next-image-new/app-dir/test/index.test.ts b/test/integration/next-image-new/app-dir/test/index.test.ts index d2162f585e971..32b24ba19d37c 100644 --- a/test/integration/next-image-new/app-dir/test/index.test.ts +++ b/test/integration/next-image-new/app-dir/test/index.test.ts @@ -795,7 +795,7 @@ function runTests(mode) { } }) - it('should render picture via getImgProps', async () => { + it('should render picture via getImageProps', async () => { const browser = await webdriver(appPort, '/picture') // Wait for image to load: await check(async () => { diff --git a/test/integration/next-image-new/default/pages/picture.js b/test/integration/next-image-new/default/pages/picture.js index 1f3b60b6e6739..c1c203a25f0e0 100644 --- a/test/integration/next-image-new/default/pages/picture.js +++ b/test/integration/next-image-new/default/pages/picture.js @@ -1,13 +1,13 @@ -import { unstable_getImgProps as getImgProps } from 'next/image' +import { getImageProps } from 'next/image' export default function Page() { const common = { alt: 'Hero', width: 400, height: 400, priority: true } const { props: { srcSet: dark }, - } = getImgProps({ ...common, src: '/test.png' }) + } = getImageProps({ ...common, src: '/test.png' }) const { props: { srcSet: light, ...rest }, - } = getImgProps({ ...common, src: '/test_light.png' }) + } = getImageProps({ ...common, src: '/test_light.png' }) return ( diff --git a/test/integration/next-image-new/default/test/index.test.ts b/test/integration/next-image-new/default/test/index.test.ts index 5cb20c9825792..54e6631e64dd2 100644 --- a/test/integration/next-image-new/default/test/index.test.ts +++ b/test/integration/next-image-new/default/test/index.test.ts @@ -796,7 +796,7 @@ function runTests(mode) { } }) - it('should render picture via getImgProps', async () => { + it('should render picture via getImageProps', async () => { const browser = await webdriver(appPort, '/picture') // Wait for image to load: await check(async () => { diff --git a/test/integration/next-image-new/loader-config-default-loader-with-file/pages/get-img-props.js b/test/integration/next-image-new/loader-config-default-loader-with-file/pages/get-img-props.js index db36ae0c908b7..63b619e4d6df8 100644 --- a/test/integration/next-image-new/loader-config-default-loader-with-file/pages/get-img-props.js +++ b/test/integration/next-image-new/loader-config-default-loader-with-file/pages/get-img-props.js @@ -1,11 +1,11 @@ -import { unstable_getImgProps as getImgProps } from 'next/image' +import { getImageProps } from 'next/image' function loader({ src, width, quality }) { return `${src}?wid=${width}&qual=${quality || 35}` } export default function Page() { - const { props: img1 } = getImgProps({ + const { props: img1 } = getImageProps({ id: 'img1', alt: 'img1', src: '/logo.png', @@ -13,7 +13,7 @@ export default function Page() { height: '400', priority: true, }) - const { props: img2 } = getImgProps({ + const { props: img2 } = getImageProps({ id: 'img2', alt: 'img2', src: '/logo.png', diff --git a/test/integration/next-image-new/loader-config-default-loader-with-file/test/index.test.ts b/test/integration/next-image-new/loader-config-default-loader-with-file/test/index.test.ts index 59d82016394ae..634afb888bee1 100644 --- a/test/integration/next-image-new/loader-config-default-loader-with-file/test/index.test.ts +++ b/test/integration/next-image-new/loader-config-default-loader-with-file/test/index.test.ts @@ -69,7 +69,7 @@ describe('Image Loader Config', () => { runTests('/') } ) - describe('dev mode - getImgProps', () => { + describe('dev mode - getImageProps', () => { beforeAll(async () => { appPort = await findPort() app = await launchApp(appDir, appPort) @@ -80,7 +80,7 @@ describe('Image Loader Config', () => { runTests('/get-img-props') }) ;(process.env.TURBOPACK ? describe.skip : describe)( - 'production mode - getImgProps', + 'production mode - getImageProps', () => { beforeAll(async () => { await nextBuild(appDir) diff --git a/test/integration/next-image-new/loader-config/pages/get-img-props.js b/test/integration/next-image-new/loader-config/pages/get-img-props.js index db36ae0c908b7..63b619e4d6df8 100644 --- a/test/integration/next-image-new/loader-config/pages/get-img-props.js +++ b/test/integration/next-image-new/loader-config/pages/get-img-props.js @@ -1,11 +1,11 @@ -import { unstable_getImgProps as getImgProps } from 'next/image' +import { getImageProps } from 'next/image' function loader({ src, width, quality }) { return `${src}?wid=${width}&qual=${quality || 35}` } export default function Page() { - const { props: img1 } = getImgProps({ + const { props: img1 } = getImageProps({ id: 'img1', alt: 'img1', src: '/logo.png', @@ -13,7 +13,7 @@ export default function Page() { height: '400', priority: true, }) - const { props: img2 } = getImgProps({ + const { props: img2 } = getImageProps({ id: 'img2', alt: 'img2', src: '/logo.png', diff --git a/test/integration/next-image-new/loader-config/test/index.test.ts b/test/integration/next-image-new/loader-config/test/index.test.ts index 842b627d24851..c1b25526f9585 100644 --- a/test/integration/next-image-new/loader-config/test/index.test.ts +++ b/test/integration/next-image-new/loader-config/test/index.test.ts @@ -62,7 +62,7 @@ describe('Image Loader Config new', () => { runTests('/') } ) - describe('dev mode - getImgProps', () => { + describe('dev mode - getImageProps', () => { beforeAll(async () => { appPort = await findPort() app = await launchApp(appDir, appPort) @@ -73,7 +73,7 @@ describe('Image Loader Config new', () => { runTests('/get-img-props') }) ;(process.env.TURBOPACK ? describe.skip : describe)( - 'production mode - getImgProps', + 'production mode - getImageProps', () => { beforeAll(async () => { await nextBuild(appDir) diff --git a/test/integration/next-image-new/unoptimized/pages/get-img-props.js b/test/integration/next-image-new/unoptimized/pages/get-img-props.js index 6c68ea913ab70..0525eabc7dcb7 100644 --- a/test/integration/next-image-new/unoptimized/pages/get-img-props.js +++ b/test/integration/next-image-new/unoptimized/pages/get-img-props.js @@ -1,27 +1,27 @@ import React from 'react' -import { unstable_getImgProps as getImgProps } from 'next/image' +import { getImageProps } from 'next/image' import testJpg from '../public/test.jpg' const Page = () => { - const { props: img1 } = getImgProps({ + const { props: img1 } = getImageProps({ id: 'internal-image', src: '/test.png', width: 400, height: 400, }) - const { props: img2 } = getImgProps({ + const { props: img2 } = getImageProps({ id: 'static-image', src: testJpg, width: 400, height: 400, }) - const { props: img3 } = getImgProps({ + const { props: img3 } = getImageProps({ id: 'external-image', src: 'https://image-optimization-test.vercel.app/test.jpg', width: 400, height: 400, }) - const { props: img4 } = getImgProps({ + const { props: img4 } = getImageProps({ id: 'eager-image', src: '/test.webp', width: 400, diff --git a/test/integration/next-image-new/unoptimized/test/index.test.ts b/test/integration/next-image-new/unoptimized/test/index.test.ts index 9a7cde105648c..5803647999c54 100644 --- a/test/integration/next-image-new/unoptimized/test/index.test.ts +++ b/test/integration/next-image-new/unoptimized/test/index.test.ts @@ -118,7 +118,7 @@ describe('Unoptimized Image Tests', () => { runTests('/') } ) - describe('dev mode - getImgProps', () => { + describe('dev mode - getImageProps', () => { beforeAll(async () => { appPort = await findPort() app = await launchApp(appDir, appPort) @@ -130,7 +130,7 @@ describe('Unoptimized Image Tests', () => { runTests('/get-img-props') }) ;(process.env.TURBOPACK ? describe.skip : describe)( - 'production mode - getImgProps', + 'production mode - getImageProps', () => { beforeAll(async () => { await nextBuild(appDir) diff --git a/test/turbopack-tests-manifest.json b/test/turbopack-tests-manifest.json index 7c9752b19f7e1..1ca47d47e37ee 100644 --- a/test/turbopack-tests-manifest.json +++ b/test/turbopack-tests-manifest.json @@ -13136,7 +13136,7 @@ "Image Component Default Tests dev mode should render correct objectFit when blurDataURL and fill", "Image Component Default Tests dev mode should render correct objectFit when data url placeholder and fill", "Image Component Default Tests dev mode should render no wrappers or sizers", - "Image Component Default Tests dev mode should render picture via getImgProps", + "Image Component Default Tests dev mode should render picture via getImageProps", "Image Component Default Tests dev mode should show empty string src error", "Image Component Default Tests dev mode should show error when CSS position changed on fill image", "Image Component Default Tests dev mode should show error when invalid Infinity width prop", @@ -13195,7 +13195,7 @@ "Image Component Default Tests production mode should render correct objectFit when blurDataURL and fill", "Image Component Default Tests production mode should render correct objectFit when data url placeholder and fill", "Image Component Default Tests production mode should render no wrappers or sizers", - "Image Component Default Tests production mode should render picture via getImgProps", + "Image Component Default Tests production mode should render picture via getImageProps", "Image Component Default Tests production mode should update the image on src change", "Image Component Default Tests production mode should warn when legacy prop layout=fill", "Image Component Default Tests production mode should warn when legacy prop layout=responsive", @@ -13356,7 +13356,7 @@ "Image Component Default Tests dev mode should render correct objectFit when blurDataURL and fill", "Image Component Default Tests dev mode should render correct objectFit when data url placeholder and fill", "Image Component Default Tests dev mode should render no wrappers or sizers", - "Image Component Default Tests dev mode should render picture via getImgProps", + "Image Component Default Tests dev mode should render picture via getImageProps", "Image Component Default Tests dev mode should show empty string src error", "Image Component Default Tests dev mode should show error when CSS position changed on fill image", "Image Component Default Tests dev mode should show error when invalid Infinity width prop", @@ -13416,7 +13416,7 @@ "Image Component Default Tests production mode should render correct objectFit when blurDataURL and fill", "Image Component Default Tests production mode should render correct objectFit when data url placeholder and fill", "Image Component Default Tests production mode should render no wrappers or sizers", - "Image Component Default Tests production mode should render picture via getImgProps", + "Image Component Default Tests production mode should render picture via getImageProps", "Image Component Default Tests production mode should update the image on src change", "Image Component Default Tests production mode should warn when legacy prop layout=fill", "Image Component Default Tests production mode should warn when legacy prop layout=responsive", @@ -13495,17 +13495,17 @@ "test/integration/next-image-new/loader-config-default-loader-with-file/test/index.test.ts": { "passed": [ "Image Loader Config dev mode - component should work with loader prop", - "Image Loader Config dev mode - getImgProps should work with loader prop" + "Image Loader Config dev mode - getImageProps should work with loader prop" ], "failed": [ "Image Loader Config dev mode - component should work with loaderFile config, leaving default image optimization enabled", - "Image Loader Config dev mode - getImgProps should work with loaderFile config, leaving default image optimization enabled" + "Image Loader Config dev mode - getImageProps should work with loaderFile config, leaving default image optimization enabled" ], "pending": [ "Image Loader Config production mode - component should work with loader prop", "Image Loader Config production mode - component should work with loaderFile config, leaving default image optimization enabled", - "Image Loader Config production mode - getImgProps should work with loader prop", - "Image Loader Config production mode - getImgProps should work with loaderFile config, leaving default image optimization enabled" + "Image Loader Config production mode - getImageProps should work with loader prop", + "Image Loader Config production mode - getImageProps should work with loaderFile config, leaving default image optimization enabled" ], "flakey": [], "runtimeError": false @@ -13532,14 +13532,14 @@ "failed": [ "Image Loader Config new dev mode - component should work with loader prop", "Image Loader Config new dev mode - component should work with loaderFile config", - "Image Loader Config new dev mode - getImgProps should work with loader prop", - "Image Loader Config new dev mode - getImgProps should work with loaderFile config" + "Image Loader Config new dev mode - getImageProps should work with loader prop", + "Image Loader Config new dev mode - getImageProps should work with loaderFile config" ], "pending": [ "Image Loader Config new production mode - component should work with loader prop", "Image Loader Config new production mode - component should work with loaderFile config", - "Image Loader Config new production mode - getImgProps should work with loader prop", - "Image Loader Config new production mode - getImgProps should work with loaderFile config" + "Image Loader Config new production mode - getImageProps should work with loader prop", + "Image Loader Config new production mode - getImageProps should work with loaderFile config" ], "flakey": [], "runtimeError": false @@ -13617,12 +13617,12 @@ "test/integration/next-image-new/unoptimized/test/index.test.ts": { "passed": [ "Unoptimized Image Tests dev mode - component should not optimize any image", - "Unoptimized Image Tests dev mode - getImgProps should not optimize any image" + "Unoptimized Image Tests dev mode - getImageProps should not optimize any image" ], "failed": [], "pending": [ "Unoptimized Image Tests production mode - component should not optimize any image", - "Unoptimized Image Tests production mode - getImgProps should not optimize any image" + "Unoptimized Image Tests production mode - getImageProps should not optimize any image" ], "flakey": [], "runtimeError": false diff --git a/test/unit/next-image-get-img-props.test.ts b/test/unit/next-image-get-img-props.test.ts index f33e5c1041f9a..82709ca53b812 100644 --- a/test/unit/next-image-get-img-props.test.ts +++ b/test/unit/next-image-get-img-props.test.ts @@ -1,7 +1,7 @@ /* eslint-env jest */ -import { unstable_getImgProps } from 'next/image' +import { getImageProps } from 'next/image' -describe('getImgProps()', () => { +describe('getImageProps()', () => { let warningMessages: string[] const originalConsoleWarn = console.warn beforeEach(() => { @@ -14,17 +14,14 @@ describe('getImgProps()', () => { afterEach(() => { console.warn = originalConsoleWarn }) - it('should warn on first usage and return props in correct order', async () => { - const { props } = unstable_getImgProps({ + it('should return props in correct order', async () => { + const { props } = getImageProps({ alt: 'a nice desc', id: 'my-image', src: '/test.png', width: 100, height: 200, }) - expect(warningMessages).toStrictEqual([ - 'Warning: unstable_getImgProps() is experimental and may change or be removed at any time. Use at your own risk.', - ]) expect(Object.entries(props)).toStrictEqual([ ['alt', 'a nice desc'], ['id', 'my-image'], @@ -41,7 +38,7 @@ describe('getImgProps()', () => { ]) }) it('should handle priority', async () => { - const { props } = unstable_getImgProps({ + const { props } = getImageProps({ alt: 'a nice desc', id: 'my-image', src: '/test.png', @@ -66,7 +63,7 @@ describe('getImgProps()', () => { ]) }) it('should handle quality', async () => { - const { props } = unstable_getImgProps({ + const { props } = getImageProps({ alt: 'a nice desc', id: 'my-image', src: '/test.png', @@ -91,7 +88,7 @@ describe('getImgProps()', () => { ]) }) it('should handle loading eager', async () => { - const { props } = unstable_getImgProps({ + const { props } = getImageProps({ alt: 'a nice desc', id: 'my-image', src: '/test.png', @@ -116,7 +113,7 @@ describe('getImgProps()', () => { ]) }) it('should handle sizes', async () => { - const { props } = unstable_getImgProps({ + const { props } = getImageProps({ alt: 'a nice desc', id: 'my-image', src: '/test.png', @@ -142,7 +139,7 @@ describe('getImgProps()', () => { ]) }) it('should handle fill', async () => { - const { props } = unstable_getImgProps({ + const { props } = getImageProps({ alt: 'a nice desc', id: 'my-image', src: '/test.png', @@ -178,7 +175,7 @@ describe('getImgProps()', () => { ]) }) it('should handle style', async () => { - const { props } = unstable_getImgProps({ + const { props } = getImageProps({ alt: 'a nice desc', id: 'my-image', src: '/test.png', @@ -203,7 +200,7 @@ describe('getImgProps()', () => { ]) }) it('should handle loader', async () => { - const { props } = unstable_getImgProps({ + const { props } = getImageProps({ alt: 'a nice desc', id: 'my-image', src: '/test.png', @@ -229,7 +226,7 @@ describe('getImgProps()', () => { ]) }) it('should handle arbitrary props', async () => { - const { props } = unstable_getImgProps({ + const { props } = getImageProps({ alt: 'a nice desc', src: '/test.png', width: 100,