UNPKG

@amsterdam/design-system-react

Version:

All React components from the Amsterdam Design System. Use it to compose pages in your website or application.

39 lines (38 loc) 3.12 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { ChevronBackwardIcon, ChevronForwardIcon } from '@amsterdam/design-system-react-icons'; import { clsx } from 'clsx'; import { forwardRef, useEffect, useRef, useState } from 'react'; import { Button } from '../Button'; import { ImageSliderSlide } from './ImageSliderSlide'; import { ImageSliderThumbnails } from './ImageSliderThumbnails'; import { debounce, scrollToCurrentSlideOnResize, scrollToSlide, setCurrentSlideIdToVisibleSlide } from './utils'; /** * @see {@link https://designsystem.amsterdam/?path=/docs/components-media-image-slider--docs Image Slider docs at Amsterdam Design System} */ export const ImageSlider = forwardRef(({ className, controls, imageLabel = 'Afbeelding', images, nextLabel = 'Volgende', previousLabel = 'Vorige', ...restProps }, ref) => { if (images.length === 0) return null; const [currentSlideId, setCurrentSlideId] = useState(0); const scrollerRef = useRef(null); const isAtStart = currentSlideId === 0; const isAtEnd = currentSlideId === images.length - 1; useEffect(() => { if (!scrollerRef.current) return undefined; const observerOptions = { root: scrollerRef.current, threshold: 0.6, }; const observer = new IntersectionObserver((observations) => setCurrentSlideIdToVisibleSlide({ observations, ref: scrollerRef, setCurrentSlideId }), observerOptions); const slides = Array.from(scrollerRef.current.children); slides.forEach((slide) => observer.observe(slide)); return () => observer.disconnect(); }, []); useEffect(() => { const handleResize = debounce(() => scrollToCurrentSlideOnResize({ currentSlideId, ref: scrollerRef }), 100); window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, [currentSlideId]); return (_jsxs("div", { ...restProps, "aria-roledescription": "carousel", className: clsx('ams-image-slider', className), ref: ref, children: [controls && (_jsxs("div", { className: "ams-image-slider__controls", children: [_jsx(Button, { className: "ams-image-slider__control", color: "inverse", disabled: isAtStart, icon: ChevronBackwardIcon, iconOnly: true, onClick: () => scrollToSlide(currentSlideId - 1, scrollerRef), children: previousLabel }), _jsx(Button, { className: "ams-image-slider__control", color: "inverse", disabled: isAtEnd, icon: ChevronForwardIcon, iconOnly: true, onClick: () => scrollToSlide(currentSlideId + 1, scrollerRef), children: nextLabel })] })), _jsx("div", { "aria-live": "polite", className: "ams-image-slider__scroller", ref: scrollerRef, role: "group", tabIndex: 0, children: images.map((image, index) => (_jsx(ImageSliderSlide, { ...image, currentSlideId: currentSlideId, index: index }, `${index}-${image.src}`))) }), _jsx(ImageSliderThumbnails, { currentSlideId: currentSlideId, imageLabel: imageLabel, scrollToSlide: (id) => scrollToSlide(id, scrollerRef), thumbnails: images })] })); }); ImageSlider.displayName = 'ImageSlider';