UNPKG

@amsterdam/design-system-react

Version:

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

43 lines (42 loc) 3.54 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 { Image } from '../Image/Image'; import { ImageSliderControl } from './ImageSliderControl'; 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', // The 'ams-image-slider--controls' class is @deprecated and will be removed in a future release. controls && 'ams-image-slider--controls', className), ref: ref, children: [controls && (_jsxs("div", { className: "ams-image-slider__controls", children: [_jsx(ImageSliderControl, { disabled: isAtStart, icon: ChevronBackwardIcon, iconOnly: true, onClick: () => scrollToSlide(currentSlideId - 1, scrollerRef), children: previousLabel }), _jsx(ImageSliderControl, { 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(({ alt, aspectRatio, sizes, src, srcSet }, index) => (_jsx(Image, { alt: alt, "aria-hidden": index !== currentSlideId ? true : undefined, aspectRatio: aspectRatio, className: clsx('ams-image-slider__item', // The 'ams-image-slider__item--in-view' class is @deprecated and will be removed in a future release. index === currentSlideId && 'ams-image-slider__item--in-view'), sizes: sizes, src: src, srcSet: srcSet }, `${index}-${src}`))) }), _jsx(ImageSliderThumbnails, { currentSlideId: currentSlideId, imageLabel: imageLabel, scrollToSlide: (id) => scrollToSlide(id, scrollerRef), thumbnails: images })] })); }); ImageSlider.displayName = 'ImageSlider';