feat(assets): Add a Picture component
This commit is contained in:
parent
77f7774010
commit
cccd165d75
2 changed files with 47 additions and 8 deletions
11
packages/astro/client.d.ts
vendored
11
packages/astro/client.d.ts
vendored
|
@ -53,6 +53,7 @@ declare module 'astro:assets' {
|
||||||
imageConfig: import('./dist/@types/astro.js').AstroConfig['image'];
|
imageConfig: import('./dist/@types/astro.js').AstroConfig['image'];
|
||||||
getConfiguredImageService: typeof import('./dist/assets/index.js').getConfiguredImageService;
|
getConfiguredImageService: typeof import('./dist/assets/index.js').getConfiguredImageService;
|
||||||
Image: typeof import('./components/Image.astro').default;
|
Image: typeof import('./components/Image.astro').default;
|
||||||
|
Picture: typeof import('./components/Picture.astro').default;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ImgAttributes = import('./dist/type-utils.js').WithRequired<
|
type ImgAttributes = import('./dist/type-utils.js').WithRequired<
|
||||||
|
@ -66,17 +67,11 @@ declare module 'astro:assets' {
|
||||||
export type RemoteImageProps = import('./dist/type-utils.js').Simplify<
|
export type RemoteImageProps = import('./dist/type-utils.js').Simplify<
|
||||||
import('./dist/assets/types.js').RemoteImageProps<ImgAttributes>
|
import('./dist/assets/types.js').RemoteImageProps<ImgAttributes>
|
||||||
>;
|
>;
|
||||||
export const { getImage, getConfiguredImageService, imageConfig, Image }: AstroAssets;
|
export const { getImage, getConfiguredImageService, imageConfig, Image, Picture }: AstroAssets;
|
||||||
}
|
}
|
||||||
|
|
||||||
type InputFormat = import('./dist/assets/types.js').ImageInputFormat;
|
type InputFormat = import('./dist/assets/types.js').ImageInputFormat;
|
||||||
|
type ImageMetadata = import('./dist/assets/types.js').ImageMetadata;
|
||||||
interface ImageMetadata {
|
|
||||||
src: string;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
format: InputFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '*.gif' {
|
declare module '*.gif' {
|
||||||
const metadata: ImageMetadata;
|
const metadata: ImageMetadata;
|
||||||
|
|
44
packages/astro/components/Picture.astro
Normal file
44
packages/astro/components/Picture.astro
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
---
|
||||||
|
import { LocalImageProps, RemoteImageProps, getImage } from 'astro:assets';
|
||||||
|
import { GetImageResult, ImageOutputFormat } from '../dist/@types/astro';
|
||||||
|
import { isESMImportedImage } from '../dist/assets/internal';
|
||||||
|
import { AstroError, AstroErrorData } from '../dist/core/errors/index.js';
|
||||||
|
import { HTMLAttributes } from '../types';
|
||||||
|
|
||||||
|
type Props = (LocalImageProps | RemoteImageProps) & {
|
||||||
|
formats: ImageOutputFormat[];
|
||||||
|
fallbackFormat: ImageOutputFormat;
|
||||||
|
pictureAttributes: HTMLAttributes<'picture'>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = Astro.props;
|
||||||
|
const optimizedImages: Record<
|
||||||
|
ImageOutputFormat,
|
||||||
|
GetImageResult
|
||||||
|
> = await Promise.all(
|
||||||
|
props.formats.map(async (format) => await getImage({ ...props, format: format, widths: props.widths, densities: props.densities }))
|
||||||
|
);
|
||||||
|
|
||||||
|
const fallbackFormat =
|
||||||
|
props.fallbackFormat ?? isESMImportedImage(props.src)
|
||||||
|
? ['svg', 'gif'].includes(props.src.format)
|
||||||
|
? props.src.format
|
||||||
|
: 'png'
|
||||||
|
: 'png';
|
||||||
|
|
||||||
|
const originalImage = await getImage({ ...props, format: fallbackFormat, widths: props.widths, densities: props.densities });
|
||||||
|
|
||||||
|
if (props.alt === undefined || props.alt === null) {
|
||||||
|
throw new AstroError(AstroErrorData.ImageMissingAlt);
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
<picture {...props.pictureAttributes}>
|
||||||
|
{Object.entries(optimizedImages).map(([format, image]) => (
|
||||||
|
<source
|
||||||
|
srcset={image.srcSetValue}
|
||||||
|
type={image.srcSet[0].attributes?.type}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<img src={originalImage.src} {...originalImage.attributes} />
|
||||||
|
</picture>
|
Loading…
Reference in a new issue