import type { MouseEvent } from 'react'; import { useState } from 'react'; import { Group, Image, Stack } from '@mantine/core'; import type { Variants } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion'; import { useTranslation } from 'react-i18next'; import { RiArrowLeftSLine, RiArrowRightSLine } from 'react-icons/ri'; import { Link, generatePath } from 'react-router-dom'; import styled from 'styled-components'; import { Album, LibraryItem } from '/@/renderer/api/types'; import { Button } from '/@/renderer/components/button'; import { TextTitle } from '/@/renderer/components/text-title'; import { Badge } from '/@/renderer/components/badge'; import { AppRoute } from '/@/renderer/router/routes'; import { usePlayQueueAdd } from '/@/renderer/features/player/hooks/use-playqueue-add'; import { Play } from '/@/renderer/types'; import { usePlayButtonBehavior } from '/@/renderer/store'; const Carousel = styled(motion.div)` position: relative; height: 35vh; min-height: 250px; padding: 2rem; overflow: hidden; background: linear-gradient(180deg, var(--main-bg), rgb(25 26 28 / 60%)); border-radius: 1rem; `; const Grid = styled.div` display: grid; grid-template-areas: 'image info'; grid-template-rows: 1fr; grid-template-columns: 200px minmax(0, 1fr); grid-auto-columns: 1fr; width: 100%; max-width: 100%; height: 100%; `; const ImageColumn = styled.div` z-index: 15; display: flex; grid-area: image; align-items: flex-end; `; const InfoColumn = styled.div` z-index: 15; display: flex; grid-area: info; align-items: flex-end; width: 100%; max-width: 100%; padding-left: 1rem; `; const BackgroundImage = styled.img` position: absolute; top: 0; left: 0; z-index: 0; width: 150%; height: 150%; user-select: none; filter: blur(24px); object-fit: var(--image-fit); object-position: 0 30%; `; const BackgroundImageOverlay = styled.div` position: absolute; top: 0; left: 0; z-index: 10; width: 100%; height: 100%; background: linear-gradient(180deg, rgb(25 26 28 / 30%), var(--main-bg)); `; const Wrapper = styled(Link)` position: relative; width: 100%; height: 100%; overflow: hidden; `; const TitleWrapper = styled.div` /* stylelint-disable-next-line value-no-vendor-prefix */ display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; `; const variants: Variants = { animate: { opacity: 1, transition: { opacity: { duration: 0.5 } }, }, exit: { opacity: 0, transition: { opacity: { duration: 0.5 } }, }, initial: { opacity: 0, }, }; interface FeatureCarouselProps { data: Album[] | undefined; } export const FeatureCarousel = ({ data }: FeatureCarouselProps) => { const { t } = useTranslation(); const handlePlayQueueAdd = usePlayQueueAdd(); const [itemIndex, setItemIndex] = useState(0); const [direction, setDirection] = useState(0); const playType = usePlayButtonBehavior(); const currentItem = data?.[itemIndex]; const handleNext = (e: MouseEvent) => { e.preventDefault(); setDirection(1); if (itemIndex === (data?.length || 0) - 1 || 0) { setItemIndex(0); return; } setItemIndex((prev) => prev + 1); }; const handlePrevious = (e: MouseEvent) => { e.preventDefault(); setDirection(-1); if (itemIndex === 0) { setItemIndex((data?.length || 0) - 1); return; } setItemIndex((prev) => prev - 1); }; return ( {data && ( {currentItem?.name} {currentItem?.albumArtists.slice(0, 1).map((artist) => ( {artist.name} ))} {currentItem?.genres?.slice(0, 1).map((genre) => ( {genre.name} ))} {currentItem?.releaseYear} {t('entity.trackWithCount', { count: currentItem?.songCount || 0, })} )} ); };