33 lines
1.2 KiB
TypeScript
33 lines
1.2 KiB
TypeScript
"use client";
|
|
|
|
import { forwardRef, type ImgHTMLAttributes, useState } from "react";
|
|
|
|
type Props = Omit<ImgHTMLAttributes<HTMLImageElement>, "src"> & { src: string; sourceKey: string };
|
|
|
|
export const CanvasPreviewImage = forwardRef<HTMLImageElement, Props>(function CanvasPreviewImage(
|
|
{ src, sourceKey, onLoad, style, ...props }, ref,
|
|
) {
|
|
const [displayed, setDisplayed] = useState({ sourceKey, src });
|
|
const visibleSrc = displayed.sourceKey === sourceKey ? displayed.src : src;
|
|
const sources = visibleSrc === src ? [src] : [visibleSrc, src];
|
|
return <>{sources.map(candidate => {
|
|
const visible = candidate === visibleSrc;
|
|
return <img
|
|
{...props}
|
|
key={candidate}
|
|
ref={visible ? ref : undefined}
|
|
src={candidate}
|
|
alt={visible ? props.alt : ""}
|
|
aria-hidden={visible ? props["aria-hidden"] : true}
|
|
style={visible ? style : { ...style, position: "absolute", inset: 0, opacity: 0, pointerEvents: "none" }}
|
|
onLoad={event => {
|
|
const image = event.currentTarget;
|
|
onLoad?.(event);
|
|
void image.decode().then(() => {
|
|
if (image.isConnected && candidate === src) setDisplayed({ sourceKey, src: candidate });
|
|
}).catch(() => undefined);
|
|
}}
|
|
/>;
|
|
})}</>;
|
|
});
|