feat(assets): Add a Picture component

This commit is contained in:
Princesseuh 2023-09-21 19:05:45 +02:00
parent 77f7774010
commit cccd165d75
No known key found for this signature in database
GPG key ID: 105BBD6D57F2B0C0
2 changed files with 47 additions and 8 deletions

View file

@ -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;

View 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>