94 lines
2.4 KiB
TypeScript
94 lines
2.4 KiB
TypeScript
import { ReactElement, useEffect, useState } from 'react';
|
|
|
|
import { As, Box, BoxProps, Flex, StyleProps } from '@chakra-ui/react';
|
|
import { Image } from '@chakra-ui/react';
|
|
|
|
import { DataUrlAccess } from '@/utils/data-url-access';
|
|
import { Icon } from './Icon';
|
|
import { ObjectId } from '@/back-api';
|
|
|
|
export type CoversProps = BoxProps & {
|
|
data?: ObjectId[];
|
|
size?: StyleProps["width"];
|
|
iconEmpty?: As;
|
|
slideshow?: boolean;
|
|
};
|
|
|
|
export const Covers = ({
|
|
data,
|
|
iconEmpty,
|
|
size = '100px',
|
|
slideshow = false,
|
|
...rest
|
|
}: CoversProps) => {
|
|
const [currentImageIndex, setCurrentImageIndex] = useState(0);
|
|
const [previousImageIndex, setPreviousImageIndex] = useState(0);
|
|
const [topOpacity, setTopOpacity] = useState(0.0);
|
|
|
|
useEffect(() => {
|
|
if (!slideshow) {
|
|
return;
|
|
}
|
|
const interval = setInterval(() => {
|
|
setPreviousImageIndex(currentImageIndex);
|
|
setTopOpacity(0.0);
|
|
setTimeout(() => {
|
|
setCurrentImageIndex((prevIndex) => (prevIndex + 1) % (data?.length ?? 1));
|
|
setTopOpacity(1.0);
|
|
}, 1500);
|
|
}, 3000);
|
|
return () => clearInterval(interval);
|
|
}, [slideshow, data]);
|
|
|
|
if (!data || data.length < 1) {
|
|
if (iconEmpty) {
|
|
return <Icon icon={iconEmpty} sizeIcon={size} />;
|
|
} else {
|
|
return (
|
|
<Box
|
|
width={size}
|
|
height={size}
|
|
minHeight={size}
|
|
minWidth={size}
|
|
borderColor="blue"
|
|
borderWidth="1px"
|
|
margin="auto"
|
|
{...rest}
|
|
></Box>
|
|
);
|
|
}
|
|
}
|
|
if (slideshow === false || data.length === 1) {
|
|
const url = DataUrlAccess.getThumbnailUrl(data[0]);
|
|
return <Image loading="lazy" src={url} maxWidth={size} boxSize={size} {...rest} />;
|
|
}
|
|
const urlCurrent = DataUrlAccess.getThumbnailUrl(data[currentImageIndex]);
|
|
const urlPrevious = DataUrlAccess.getThumbnailUrl(data[previousImageIndex]);
|
|
return <Flex position="relative" {...rest} maxWidth={size} width={size} height={size} overflow="hidden">
|
|
<Image
|
|
src={urlPrevious}
|
|
loading="lazy"
|
|
position="absolute"
|
|
top="0"
|
|
left="0"
|
|
width="100%"
|
|
height="100%"
|
|
zIndex={1}
|
|
boxSize={size}
|
|
/>
|
|
<Image
|
|
src={urlCurrent}
|
|
loading="lazy"
|
|
position="absolute"
|
|
top="0"
|
|
left="0"
|
|
width="100%"
|
|
height="100%"
|
|
boxSize={size}
|
|
transition="opacity 0.5s ease-in-out"
|
|
opacity={topOpacity}
|
|
zIndex={2}
|
|
/>
|
|
</Flex>
|
|
};
|