Skip to content

Instantly share code, notes, and snippets.

@julrich
Last active May 9, 2024 16:15
Show Gist options
  • Save julrich/0cce036390a30a45061de0179ce16190 to your computer and use it in GitHub Desktop.
Save julrich/0cce036390a30a45061de0179ce16190 to your computer and use it in GitHub Desktop.
Unpic blurhash handling with React
function isStoryblokAsset(object: unknown): object is AssetStoryblok {
return (object as AssetStoryblok)?.filename !== undefined;
}
const Picture = forwardRef<
HTMLImageElement,
PictureProps & ImgHTMLAttributes<HTMLImageElement>
>(({ src, lazy, ...props }, ref) => {
const internalRef = useRef<HTMLImageElement>(null);
const blurHashes = useBlurHashes();
const priority = useImagePriority();
useImperativeHandle<HTMLImageElement | null, HTMLImageElement | null>(
ref,
() => internalRef.current
);
useEffect(() => {
if (internalRef.current) resetBackgroundBlurHash(internalRef.current);
}, []);
if (!src || (isStoryblokAsset(src) && !src.filename)) return;
const source = isStoryblokAsset(src) ? src.filename : src;
const fileUrl = !source.startsWith("http") ? `https:${source}` : source;
const [width, height] = fileUrl.match(/\/(\d+)x(\d+)\//)?.slice(1) || [];
return (
<Image
ref={internalRef}
{...props}
alt={isStoryblokAsset(src) ? src.alt || "" : props.alt || ""}
src={priority ? `${fileUrl}/m/filters:quality(50)` : fileUrl}
width={parseInt(width, 10)}
height={parseInt(height, 10)}
priority={lazy === false || priority}
onLoad={(event) => {
if (event.target instanceof HTMLImageElement) {
resetBackgroundBlurHash(event.target);
}
}}
background={
blurHashes[fileUrl]
? blurhashToCssGradientString(blurHashes[fileUrl])
: undefined
}
/>
);
});
const PictureProvider: FC<PropsWithChildren> = (props) => (
<PictureContext.Provider {...props} value={Picture} />
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment