@mantine/carousel
Version:
Embla based carousel
1 lines • 19.9 kB
Source Map (JSON)
{"version":3,"file":"Carousel.mjs","names":["classes"],"sources":["../src/Carousel.tsx"],"sourcesContent":["import { Children, useCallback, useEffect, useState } from 'react';\nimport type { EmblaCarouselType, EmblaOptionsType, EmblaPluginType } from 'embla-carousel';\nimport useEmblaCarousel from 'embla-carousel-react';\nimport {\n AccordionChevron,\n Box,\n BoxProps,\n createVarsResolver,\n DataAttributes,\n ElementProps,\n factory,\n Factory,\n getSpacing,\n MantineSpacing,\n rem,\n StyleProp,\n StylesApiProps,\n UnstyledButton,\n useDirection,\n useProps,\n useRandomClassName,\n useStyles,\n VisuallyHidden,\n} from '@mantine/core';\nimport { clamp, useId } from '@mantine/hooks';\nimport { CarouselProvider, type CarouselContextValue } from './Carousel.context';\nimport { CarouselSlide } from './CarouselSlide/CarouselSlide';\nimport {\n CarouselContainerVariables,\n CarouselVariables,\n} from './CarouselVariables/CarouselVariables';\nimport { getChevronRotation } from './get-chevron-rotation';\nimport classes from './Carousel.module.css';\n\nexport type CarouselStylesNames =\n | 'slide'\n | 'root'\n | 'viewport'\n | 'container'\n | 'controls'\n | 'control'\n | 'indicators'\n | 'indicator';\n\nexport type CarouselCssVariables = {\n root: '--carousel-height' | '--carousel-control-size' | '--carousel-controls-offset';\n};\n\nexport interface CarouselProps\n extends BoxProps, StylesApiProps<CarouselFactory>, ElementProps<'div'> {\n /** Options passed down to embla carousel */\n emblaOptions?: EmblaOptionsType;\n\n /** `Carousel.Slide` components */\n children?: React.ReactNode;\n\n /** Called when next slide is shown */\n onNextSlide?: () => void;\n\n /** Called when previous slider is shown */\n onPreviousSlide?: () => void;\n\n /** Called with slide index when slide changes */\n onSlideChange?: (index: number) => void;\n\n /** Get embla API as ref */\n getEmblaApi?: (embla: EmblaCarouselType) => void;\n\n /** Props passed down to next control */\n nextControlProps?: React.ComponentProps<'button'>;\n\n /** Props passed down to previous control */\n previousControlProps?: React.ComponentProps<'button'>;\n\n /** Controls size of the next and previous controls @default 26 */\n controlSize?: React.CSSProperties['width'];\n\n /** Controls position of the next and previous controls, key of `theme.spacing` or any valid CSS value @default 'sm' */\n controlsOffset?: MantineSpacing;\n\n /** Controls slide width based on viewport width @default '100%' */\n slideSize?: StyleProp<string | number>;\n\n /** Key of theme.spacing or number to set gap between slides */\n slideGap?: StyleProp<MantineSpacing>;\n\n /** Carousel orientation @default 'horizontal' */\n orientation?: 'horizontal' | 'vertical';\n\n /** Determines type of queries used for responsive styles @default 'media' */\n type?: 'media' | 'container';\n\n /** Slides container `height`, required for vertical orientation */\n height?: React.CSSProperties['height'];\n\n /** Determines whether gap between slides should be treated as part of the slide size @default true */\n includeGapInSize?: boolean;\n\n /** Index of initial slide */\n initialSlide?: number;\n\n /** Determines whether next/previous controls should be displayed @default true */\n withControls?: boolean;\n\n /** Determines whether indicators should be displayed @default false */\n withIndicators?: boolean;\n\n /** A list of embla plugins */\n plugins?: EmblaPluginType[];\n\n /** Icon of the next control */\n nextControlIcon?: React.ReactNode;\n\n /** Icon of the previous control */\n previousControlIcon?: React.ReactNode;\n\n /** Determines whether arrow key should switch slides @default true */\n withKeyboardEvents?: boolean;\n\n /** Function to get props for indicator button */\n getIndicatorProps?: (index: number) => ElementProps<'button'> & DataAttributes;\n}\n\nexport type CarouselFactory = Factory<{\n props: CarouselProps;\n ref: HTMLDivElement;\n stylesNames: CarouselStylesNames;\n vars: CarouselCssVariables;\n staticComponents: {\n Slide: typeof CarouselSlide;\n };\n}>;\n\nconst defaultProps = {\n controlSize: 26,\n controlsOffset: 'sm',\n slideSize: '100%',\n slideGap: 0,\n orientation: 'horizontal',\n includeGapInSize: true,\n initialSlide: 0,\n withControls: true,\n withIndicators: false,\n withKeyboardEvents: true,\n type: 'media',\n} satisfies Partial<CarouselProps>;\n\nconst defaultEmblaOptions: EmblaOptionsType = {\n align: 'center',\n loop: false,\n slidesToScroll: 1,\n dragFree: false,\n inViewThreshold: 0,\n skipSnaps: false,\n containScroll: 'trimSnaps',\n};\n\nconst varsResolver = createVarsResolver<CarouselFactory>(\n (_, { height, controlSize, controlsOffset }) => ({\n root: {\n '--carousel-height': rem(height),\n '--carousel-control-size': rem(controlSize),\n '--carousel-controls-offset': getSpacing(controlsOffset),\n },\n })\n);\n\nexport const Carousel = factory<CarouselFactory>((_props) => {\n const props = useProps('Carousel', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n children,\n getEmblaApi,\n onNextSlide,\n onPreviousSlide,\n onSlideChange,\n nextControlProps,\n previousControlProps,\n controlSize,\n controlsOffset,\n slideSize,\n slideGap,\n orientation,\n height,\n includeGapInSize,\n draggable,\n initialSlide,\n withControls,\n withIndicators,\n plugins,\n nextControlIcon,\n previousControlIcon,\n withKeyboardEvents,\n mod,\n type,\n emblaOptions,\n attributes,\n getIndicatorProps,\n id,\n ...others\n } = props;\n\n const getStyles = useStyles<CarouselFactory>({\n name: 'Carousel',\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n attributes,\n vars,\n varsResolver,\n });\n\n const _id = useId(id);\n\n const responsiveClassName = useRandomClassName();\n const { dir } = useDirection();\n\n const [emblaRefElement, embla] = useEmblaCarousel(\n {\n axis: orientation === 'horizontal' ? 'x' : 'y',\n direction: orientation === 'horizontal' ? dir : undefined,\n startIndex: initialSlide,\n ...defaultEmblaOptions,\n ...emblaOptions,\n },\n plugins\n );\n\n const [selected, setSelected] = useState(0);\n const [slidesCount, setSlidesCount] = useState(0);\n\n const handleScroll = useCallback((index: number) => embla && embla.scrollTo(index), [embla]);\n\n const handleSelect = useCallback(() => {\n if (!embla) {\n return;\n }\n const slide = embla.selectedScrollSnap();\n setSelected(slide);\n slide !== selected && onSlideChange?.(slide);\n }, [embla, setSelected, onSlideChange, selected]);\n\n const handlePrevious = useCallback(() => {\n embla?.scrollPrev();\n onPreviousSlide?.();\n }, [embla]);\n\n const handleNext = useCallback(() => {\n embla?.scrollNext();\n onNextSlide?.();\n }, [embla]);\n\n const handleKeydown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (withKeyboardEvents) {\n if (event.key === 'ArrowRight') {\n event.preventDefault();\n handleNext();\n }\n\n if (event.key === 'ArrowLeft') {\n event.preventDefault();\n handlePrevious();\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n embla?.scrollTo(0);\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n embla?.scrollTo(embla.scrollSnapList().length - 1);\n }\n }\n },\n [embla, handleNext, handlePrevious]\n );\n\n useEffect(() => {\n if (embla) {\n getEmblaApi?.(embla);\n handleSelect();\n setSlidesCount(embla.scrollSnapList().length);\n embla.on('select', handleSelect);\n\n return () => {\n embla.off('select', handleSelect);\n };\n }\n\n return undefined;\n }, [embla, emblaOptions?.slidesToScroll, handleSelect]);\n\n useEffect(() => {\n if (embla) {\n embla.reInit();\n setSlidesCount(embla.scrollSnapList().length);\n setSelected((currentSelected) =>\n clamp(currentSelected, 0, Children.toArray(children).length - 1)\n );\n }\n }, [Children.toArray(children).length, emblaOptions?.slidesToScroll]);\n\n const canScrollPrev = embla?.canScrollPrev() || false;\n const canScrollNext = embla?.canScrollNext() || false;\n\n const handleIndicatorKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLButtonElement>, index: number) => {\n const isHorizontal = orientation === 'horizontal';\n const nextKey = isHorizontal ? 'ArrowRight' : 'ArrowDown';\n const prevKey = isHorizontal ? 'ArrowLeft' : 'ArrowUp';\n\n if (event.key === nextKey) {\n event.preventDefault();\n const nextIndex = index < slidesCount - 1 ? index + 1 : 0;\n handleScroll(nextIndex);\n const nextIndicator = event.currentTarget.parentElement?.children[nextIndex] as HTMLElement;\n nextIndicator?.focus();\n }\n\n if (event.key === prevKey) {\n event.preventDefault();\n const prevIndex = index > 0 ? index - 1 : slidesCount - 1;\n handleScroll(prevIndex);\n const prevIndicator = event.currentTarget.parentElement?.children[prevIndex] as HTMLElement;\n prevIndicator?.focus();\n }\n\n if (event.key === 'Home') {\n event.preventDefault();\n handleScroll(0);\n const firstIndicator = event.currentTarget.parentElement?.children[0] as HTMLElement;\n firstIndicator?.focus();\n }\n\n if (event.key === 'End') {\n event.preventDefault();\n handleScroll(slidesCount - 1);\n const lastIndicator = event.currentTarget.parentElement?.children[\n slidesCount - 1\n ] as HTMLElement;\n lastIndicator?.focus();\n }\n },\n [orientation, slidesCount, handleScroll]\n );\n\n const indicators = Array(slidesCount)\n .fill(0)\n .map((_, index) => (\n <UnstyledButton\n {...getStyles('indicator')}\n key={index}\n role=\"tab\"\n aria-label={`Go to slide ${index + 1}`}\n aria-selected={index === selected}\n tabIndex={index === selected ? 0 : -1}\n data-active={index === selected || undefined}\n onClick={() => handleScroll(index)}\n onKeyDown={(event) => handleIndicatorKeyDown(event, index)}\n data-orientation={orientation}\n onMouseDown={(event) => event.preventDefault()}\n {...getIndicatorProps?.(index)}\n />\n ));\n\n return (\n <CarouselProvider value={{ getStyles, orientation }}>\n {type === 'container' ? (\n <CarouselContainerVariables {...props} selector={`.${responsiveClassName}`} />\n ) : (\n <CarouselVariables {...props} selector={`.${responsiveClassName}`} />\n )}\n\n <Box\n role=\"region\"\n aria-roledescription=\"carousel\"\n {...getStyles('root', { className: responsiveClassName })}\n {...others}\n id={_id}\n mod={[{ orientation, 'include-gap-in-size': includeGapInSize }, mod]}\n onKeyDownCapture={handleKeydown}\n >\n <VisuallyHidden role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {slidesCount > 0 && `Slide ${selected + 1} of ${slidesCount}`}\n </VisuallyHidden>\n\n {withControls && (\n <div {...getStyles('controls')} data-orientation={orientation}>\n <UnstyledButton\n aria-controls={_id}\n aria-label=\"Previous slide\"\n aria-disabled={!canScrollPrev}\n data-inactive={!canScrollPrev || undefined}\n data-type=\"previous\"\n tabIndex={canScrollPrev ? 0 : -1}\n {...previousControlProps}\n {...getStyles('control', {\n className: previousControlProps?.className,\n style: previousControlProps?.style,\n })}\n onClick={(event) => {\n handlePrevious();\n previousControlProps?.onClick?.(event);\n }}\n >\n {typeof previousControlIcon !== 'undefined' ? (\n previousControlIcon\n ) : (\n <AccordionChevron\n style={{\n transform: `rotate(${getChevronRotation({\n dir,\n orientation,\n direction: 'previous',\n })}deg)`,\n }}\n />\n )}\n </UnstyledButton>\n\n <UnstyledButton\n aria-controls={_id}\n aria-label=\"Next slide\"\n aria-disabled={!canScrollNext}\n data-inactive={!canScrollNext || undefined}\n data-type=\"next\"\n tabIndex={canScrollNext ? 0 : -1}\n {...getStyles('control', {\n className: nextControlProps?.className,\n style: nextControlProps?.style,\n })}\n {...nextControlProps}\n onClick={(event) => {\n handleNext();\n nextControlProps?.onClick?.(event);\n }}\n >\n {typeof nextControlIcon !== 'undefined' ? (\n nextControlIcon\n ) : (\n <AccordionChevron\n style={{\n transform: `rotate(${getChevronRotation({\n dir,\n orientation,\n direction: 'next',\n })}deg)`,\n }}\n />\n )}\n </UnstyledButton>\n </div>\n )}\n\n <div {...getStyles('viewport')} ref={emblaRefElement} data-type={type}>\n <div\n {...getStyles('container', { className: responsiveClassName })}\n data-orientation={orientation}\n >\n {children}\n </div>\n </div>\n\n {withIndicators && (\n <div\n {...getStyles('indicators')}\n role=\"tablist\"\n aria-label=\"Slides\"\n data-orientation={orientation}\n >\n {indicators}\n </div>\n )}\n </Box>\n </CarouselProvider>\n );\n});\n\nCarousel.classes = classes;\nCarousel.varsResolver = varsResolver;\nCarousel.displayName = '@mantine/carousel/Carousel';\nCarousel.Slide = CarouselSlide;\n\nexport namespace Carousel {\n export type Props = CarouselProps;\n export type CssVariables = CarouselCssVariables;\n export type Factory = CarouselFactory;\n export type StylesNames = CarouselStylesNames;\n export type ContextValue = CarouselContextValue;\n}\n"],"mappings":"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"}