@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
JavaScript
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';