61 lines
1.3 KiB
TypeScript
61 lines
1.3 KiB
TypeScript
"use client"
|
|
|
|
import NextImage, { ImageProps as NextImageProps } from "next/image"
|
|
|
|
import ImageFallback from "../ImageFallback"
|
|
|
|
import { useState, type CSSProperties, type SyntheticEvent } from "react"
|
|
import { imageLoader } from "./imageLoader"
|
|
|
|
type FocalPoint = {
|
|
x: number
|
|
y: number
|
|
}
|
|
|
|
export type ImageProps = Omit<NextImageProps, "src"> & {
|
|
focalPoint?: FocalPoint
|
|
dimensions?: { width: number; height: number }
|
|
src: NextImageProps["src"] | undefined
|
|
}
|
|
|
|
// Next/Image adds & instead of ? before the params
|
|
export default function Image({
|
|
focalPoint,
|
|
dimensions,
|
|
style,
|
|
src,
|
|
onError,
|
|
...props
|
|
}: ImageProps) {
|
|
const [imageError, setImageError] = useState(false)
|
|
const styles: CSSProperties = focalPoint
|
|
? {
|
|
objectFit: "cover",
|
|
objectPosition: `${focalPoint.x}% ${focalPoint.y}%`,
|
|
...style,
|
|
}
|
|
: { ...style }
|
|
|
|
function handleError(error: SyntheticEvent<HTMLImageElement, Event>) {
|
|
if (onError) {
|
|
onError(error)
|
|
} else {
|
|
setImageError(true)
|
|
}
|
|
}
|
|
|
|
if (!src || imageError) {
|
|
return <ImageFallback fill={props.fill} />
|
|
}
|
|
|
|
return (
|
|
<NextImage
|
|
{...props}
|
|
src={src}
|
|
style={styles}
|
|
onError={handleError}
|
|
loader={imageLoader({ dimensions, focalPoint })}
|
|
/>
|
|
)
|
|
}
|