Adding a <Picture /> component

This commit is contained in:
Tony Sullivan 2022-07-06 23:12:40 -05:00
parent 4ec0b2d9ff
commit 621fb8fcce
3 changed files with 54 additions and 1 deletions

View file

@ -4,7 +4,7 @@ import loader from 'virtual:image-loader';
import { getImage } from '../src/index.js';
import type { ImageAttributes, ImageMetadata, TransformOptions, OutputFormat } from '../src/types.js';
export interface LocalImageProps extends Omit<TransformOptions, 'src'>, Omit<ImageAttributes, 'src'> {
export interface LocalImageProps extends Omit<TransformOptions, 'src'> {
src: ImageMetadata | Promise<{ default: ImageMetadata }>;
}
@ -23,3 +23,9 @@ const attrs = await getImage(loader, props);
---
<img {...attrs} />
<style>
img {
content-visibility: auto;
}
</style>

View file

@ -0,0 +1,46 @@
---
import Image from './Image.astro';
// @ts-ignore
import loader from 'virtual:image-loader';
import { lookup } from 'mrmime';
import { getImage } from '../src/index.js';
import type { ImageMetadata, OutputFormat } from '../src/types.js';
export interface Props extends Partial<HTMLPictureElement> {
src: ImageMetadata;
sizes: HTMLImageElement['sizes'];
widths: number[];
formats?: OutputFormat[];
}
const { src, sizes, widths, formats = ['avif', 'webp', 'jpeg'] } = Astro.props as Props;
if (widths.length <= 0) {
throw new Error('At least one width must be provided for the <Picture>');
}
const aspectRatio = src.width / src.height;
async function getSource(format: OutputFormat) {
const imgs = await Promise.all(widths.map(async (width) => {
const img = await getImage(loader, { src: src.src, format, width, height: Math.round(width / aspectRatio) });
return `${img.src} ${width}w`;
}))
return {
type: lookup(format) || format,
srcset: imgs.join(',')
};
}
const sources = await Promise.all(formats.map(format => getSource(format)));
const width = widths.sort().shift()!;
const height = Math.round(width / aspectRatio);
---
<picture>
{sources.map(attrs => (
<source {...attrs} {sizes}>))}
<Image {sizes} {src} {width} {height} />
</picture>

View file

@ -1 +1,2 @@
export { default as Image } from './Image.astro';
export { default as Picture } from './Picture.astro';