components/snap-carousel/snap-carousel.tsx (49 lines of code) (raw):

import React, { useMemo, ReactNode } from 'react'; import cn from 'classnames'; import { useSnapCarousel } from 'react-snap-carousel'; import styles from './snap-carousel.module.css'; import { useTextStyles } from '@rescui/typography'; import { Button } from '@rescui/button'; import { ArrowLeftIcon, ArrowRightIcon } from '@rescui/icons'; interface SnapCarouselProps { children: ReactNode; } export const SnapCarousel = ({ children }: SnapCarouselProps) => { const { scrollRef, activePageIndex, prev, next, pages } = useSnapCarousel(); const textCn = useTextStyles(); const childrenWithProps = useMemo( () => React.Children.map(children, (child, index) => { if (React.isValidElement(child)) { const isChildFunction = typeof child.type === 'function'; return React.cloneElement(child, { ...(isChildFunction && { isActive: activePageIndex === index }), className: cn(styles.slide, child.props.className) }); } return child; }), [children, activePageIndex] ); return ( <div> <div className={cn( styles.block )} > <div className={cn(styles.carousel)}> <div ref={scrollRef} className={styles.wrapper} > {childrenWithProps} </div> </div> </div> <div className={styles.navigation}> <Button onClick={() => prev()} mode={'outline'} icon={<ArrowLeftIcon />} /> <p className={textCn('rs-text-2')}>{activePageIndex + 1}/{pages.length}</p> <Button onClick={() => next()} mode={'outline'} icon={<ArrowRightIcon />} /> </div> </div> ); };