import { clsx } from 'clsx'
import Link from 'next/link'
import { Paragraph } from '@/components/paragraph'
import type { ComponentProps } from 'react'
import { getStudioImage } from '@/utils/studio-helpers'
export interface ImageProps extends Omit<
ComponentProps<'img'>,
'alt' | 'title'
> {
src: string
alt?: string
title?: string
caption?: string
wrap?: boolean
className?: string | undefined
width?: number | undefined
height?: number | undefined
href?: string
size?: 'small' | 'medium' | 'large' | 'full'
rounded?: string
aspect?: string
mediaLink?: boolean
lazy?: boolean
}
export function Image({
src,
alt = '',
title,
caption,
wrap = false,
className = '',
width,
height,
href,
size,
rounded,
aspect,
mediaLink = false,
lazy = true,
}: ImageProps) {
const defaultRounded = 'rounded-lg'
const hasExplicitWidth = width !== undefined
const hasExplicitHeight = height !== undefined
const effectiveSize = size || 'large'
const studioImage = getStudioImage(src, effectiveSize)
const resolvedSrc = studioImage?.url || src
let resolvedWidth: number | 'auto' | undefined = width
let resolvedHeight: number | 'auto' | undefined = height
if (!hasExplicitWidth && !hasExplicitHeight && studioImage) {
resolvedWidth = studioImage.width
resolvedHeight = studioImage.height
}
if (hasExplicitWidth && !hasExplicitHeight) {
resolvedHeight = 'auto'
} else if (hasExplicitHeight && !hasExplicitWidth) {
resolvedWidth = 'auto'
}
let mediaLinkHref: string | null = null
let isMediaLink = false
if (href && /\.(jpg|jpeg|png|gif|webp|svg)$/i.test(href)) {
mediaLinkHref = href
isMediaLink = true
}
else if (!href && mediaLink) {
const fullImage = getStudioImage(src, 'full')
mediaLinkHref = fullImage?.url || src
isMediaLink = true
}
const aspectRatioStyle =
!aspect && resolvedWidth && resolvedHeight
? { aspectRatio: `${resolvedWidth} / ${resolvedHeight}` }
: undefined
const imgClasses = clsx(
rounded || defaultRounded,
aspect,
!resolvedWidth && !resolvedHeight ? 'w-full h-auto' : '',
className
)
const imgTag = (
<img
src={resolvedSrc}
alt={alt}
title={title}
width={resolvedWidth}
height={resolvedHeight}
loading={lazy ? 'lazy' : 'eager'}
style={aspectRatioStyle}
className={imgClasses}
/>
)
let imageElement = imgTag
if (isMediaLink && mediaLinkHref) {
imageElement = (
<figure
className={clsx(
'rounded-none',
!resolvedWidth && !resolvedHeight ? 'w-full h-auto' : ''
)}
>
<Link
href={mediaLinkHref}
prefetch={false}
scroll={true}
className="lightbox-item cursor-pointer"
>
{imgTag}
</Link>
</figure>
)
} else if (href) {
const isExternal = href.startsWith('http://') || href.startsWith('https://')
if (isExternal) {
imageElement = (
<a
href={href}
target="_blank"
rel="noopener noreferrer"
className="cursor-pointer"
>
{imgTag}
</a>
)
} else {
imageElement = (
<Link
href={href}
prefetch={false}
scroll={true}
className="cursor-pointer"
>
{imgTag}
</Link>
)
}
}
if (caption) {
let figureElement = (
<figure className="space-y-2">
{imgTag}
<figcaption
className="text-sm text-contrast-light text-center italic"
dangerouslySetInnerHTML={{ __html: caption }}
/>
</figure>
)
if (isMediaLink && mediaLinkHref) {
figureElement = (
<figure
className={clsx(
'rounded-none',
!resolvedWidth && !resolvedHeight ? 'w-full h-auto space-y-2' : '',
className
)}
>
<Link
href={mediaLinkHref}
prefetch={false}
scroll={true}
className="lightbox-item"
>
{imgTag}
</Link>
<figcaption
className="text-sm text-contrast-light text-center italic"
dangerouslySetInnerHTML={{ __html: caption }}
/>
</figure>
)
}
return wrap ? <Paragraph>{figureElement}</Paragraph> : figureElement
}
return wrap ? <Paragraph>{imageElement}</Paragraph> : imageElement
}