/** * EventsCarousel Component * Карусель событий с использованием Swiper * Отображает список исторических событий в виде слайдера */ import classNames from 'classnames' import gsap from 'gsap' import { memo, useEffect, useRef, useState } from 'react' import { Swiper, SwiperSlide } from 'swiper/react' import 'swiper/css' import 'swiper/css/navigation' import 'swiper/css/pagination' import ChevronSvg from '@/shared/assets/chevron--left.svg' import { Button } from '@/shared/ui/Button' import { Card } from '@/shared/ui/Card' import { EVENT_CAROUSEL_CONFIG, HIDE_DURATION, SHOW_DELAY, SHOW_DURATION, SHOW_Y_OFFSET, } from './constants' import styles from './EventsCarousel.module.scss' import type { HistoricalEvent } from '@/entities/TimePeriod' import type { Swiper as SwiperType } from 'swiper' export interface EventsCarouselProps { /** * Массив исторических событий для отображения */ readonly events: readonly HistoricalEvent[] /** * Флаг видимости карусели (управляет анимацией появления/исчезновения) */ readonly visible: boolean } /** * Компонент карусели исторических событий * * Использует Swiper для создания слайдера с кастомной навигацией. * Поддерживает адаптивное количество слайдов на разных размерах экрана. * Анимирует появление/исчезновение с помощью GSAP. * * @example * ```tsx * * ``` */ export const EventsCarousel = memo( ({ events, visible }: EventsCarouselProps) => { const containerRef = useRef(null) const [isBeginning, setIsBeginning] = useState(true) const [isEnd, setIsEnd] = useState(false) /** * Эффект для анимации появления/исчезновения карусели * Использует GSAP для плавной анимации opacity и y-позиции */ useEffect(() => { if (!containerRef.current) return const ctx = gsap.context(() => { if (visible) { gsap.fromTo( containerRef.current, { opacity: 0, y: SHOW_Y_OFFSET }, { opacity: 1, y: 0, duration: SHOW_DURATION, delay: SHOW_DELAY, } ) } else { gsap.to(containerRef.current, { opacity: 0, duration: HIDE_DURATION, }) } }, containerRef) return () => ctx.revert() }, [visible]) /** * Обработчик инициализации Swiper * Устанавливает начальное состояние кнопок навигации */ const handleSwiperInit = (swiper: SwiperType) => { setIsBeginning(swiper.isBeginning) setIsEnd(swiper.isEnd) } /** * Обработчик изменения состояния Swiper * Обновляет состояние кнопок навигации */ const handleSlideChange = (swiper: SwiperType) => { setIsBeginning(swiper.isBeginning) setIsEnd(swiper.isEnd) } return (
{events.map((event) => ( ))}
) } ) EventsCarousel.displayName = 'EventsCarousel'