UNPKG

@itwin/itwinui-react

Version:

A react component library for iTwinUI

65 lines (64 loc) 2.2 kB
import * as React from 'react'; import cx from 'classnames'; import { CarouselContext } from './CarouselContext.js'; import { getWindow, useMergedRefs, useLayoutEffect, Box, useMediaQuery, } from '../../utils/index.js'; export const CarouselSlider = React.forwardRef((props, ref) => { let { children, className, ...rest } = props; let context = React.useContext(CarouselContext); if (!context) throw new Error('CarouselSlider must be used within Carousel'); let { setSlideCount, idPrefix, scrollToSlide, isManuallyUpdating } = context; let items = React.useMemo( () => React.Children.map(children, (child, index) => React.isValidElement(child) ? React.cloneElement(child, { id: `${idPrefix}--slide-${index}`, 'aria-labelledby': `${idPrefix}--dot-${index}`, index, }) : child, ) ?? [], [children, idPrefix], ); useLayoutEffect(() => { setSlideCount(items.length); }, [items.length, setSlideCount]); let sliderRef = React.useRef(null); let refs = useMergedRefs(sliderRef, ref); let motionOk = useMediaQuery('(prefers-reduced-motion: no-preference)'); scrollToSlide.current = (slideIndex, { instant } = {}) => { isManuallyUpdating.current = true; let slideToShow = sliderRef.current?.children.item(slideIndex); if (!sliderRef.current || !slideToShow) return; sliderRef.current.scrollTo({ left: slideToShow.offsetLeft - sliderRef.current.offsetLeft, behavior: instant || !motionOk ? 'instant' : 'smooth', }); }; let scrollTimeout = React.useRef(void 0); let handleOnScroll = React.useCallback(() => { if (scrollTimeout.current) getWindow()?.clearTimeout(scrollTimeout.current); scrollTimeout.current = getWindow()?.setTimeout(() => { isManuallyUpdating.current = false; }, 100); }, [isManuallyUpdating]); return React.createElement( Box, { className: cx('iui-carousel-slider', className), ref: refs, onScroll: handleOnScroll, tabIndex: -1, ...rest, }, items, ); }); if ('development' === process.env.NODE_ENV) CarouselSlider.displayName = 'Carousel.Slider';