'use client';
import React, { useState, useCallback, useMemo } from 'react';
import { twMerge } from 'tailwind-merge';
import clsx from 'clsx';
import { Image } from '@akinon/next/components/image';
import { Link } from '@akinon/next/components/link';
import type {
ListHoverImageProps,
IndicatorProps,
HoverZoneProps
} from '../types';
import { mergeSettings } from '../utils';
function HoverZones({ count, href, onHover, customStyles }: HoverZoneProps) {
return (
{Array.from({ length: count }, (_, index) => (
onHover(index)}
aria-label={`View image ${index + 1}`}
/>
))}
);
}
function Indicators({
count,
activeIndex,
onSelect,
customStyles,
customRenderers
}: IndicatorProps) {
if (count <= 1) return null;
if (customRenderers?.renderIndicator) {
return (
<>
{customRenderers.renderIndicator({
count,
activeIndex,
onSelect
})}
>
);
}
return (
{Array.from({ length: count }, (_, index) => {
if (customRenderers?.renderIndicatorDot) {
return (
-
{customRenderers.renderIndicatorDot({
index,
isActive: activeIndex === index,
onClick: () => onSelect(index)
})}
);
}
return (
- onSelect(index)}
/>
);
})}
);
}
export function ListHoverImage({
images,
href,
alt,
width,
height,
fill,
sizes,
aspectRatio,
maxImages,
fallbackImage,
className,
settings: userSettings
}: ListHoverImageProps) {
const settings = mergeSettings(userSettings);
const resolvedMaxImages = maxImages ?? settings.maxImages;
const resolvedFallback = fallbackImage ?? settings.fallbackImage;
const visibleImages = useMemo(
() => images?.slice(0, resolvedMaxImages) ?? [],
[images, resolvedMaxImages]
);
const initialImageUrl = visibleImages[0]?.image || resolvedFallback;
const [activeIndex, setActiveIndex] = useState(0);
const [currentImageUrl, setCurrentImageUrl] = useState(initialImageUrl);
const handleImageChange = useCallback(
(index: number) => {
setActiveIndex(index);
setCurrentImageUrl(visibleImages[index]?.image || resolvedFallback);
},
[visibleImages, resolvedFallback]
);
const imageElement = settings.customRenderers.renderImage ? (
settings.customRenderers.renderImage({
src: currentImageUrl,
alt,
width,
height,
fill,
sizes,
aspectRatio
})
) : (
);
return (
);
}