chore: Cleanup scandic-web * Remove unused files * Remove unused and add missing packages * Remove unused exports Approved-by: Linus Flood
122 lines
2.7 KiB
TypeScript
122 lines
2.7 KiB
TypeScript
"use client"
|
|
|
|
import { cx } from "class-variance-authority"
|
|
import useEmblaCarousel from "embla-carousel-react"
|
|
import { useCallback, useEffect, useState } from "react"
|
|
|
|
import { CarouselContent } from "./CarouselContent"
|
|
import { CarouselContext } from "./CarouselContext"
|
|
import { CarouselDots } from "./CarouselDots"
|
|
import { CarouselItem } from "./CarouselItem"
|
|
import { CarouselNext, CarouselPrevious } from "./CarouselNavigation"
|
|
|
|
import styles from "./carousel.module.css"
|
|
|
|
import type { CarouselApi, CarouselProps } from "./types"
|
|
|
|
function Carousel({
|
|
opts,
|
|
setApi,
|
|
plugins,
|
|
className,
|
|
children,
|
|
scrollToIdx = 0,
|
|
align = "start",
|
|
onScrollSelect,
|
|
}: CarouselProps) {
|
|
const [carouselRef, api] = useEmblaCarousel(
|
|
{
|
|
containScroll: "trimSnaps",
|
|
align,
|
|
axis: "x",
|
|
...opts,
|
|
},
|
|
plugins
|
|
)
|
|
const [selectedIndex, setSelectedIndex] = useState(scrollToIdx)
|
|
|
|
const onSelect = useCallback(
|
|
(api: CarouselApi) => {
|
|
if (!api) return
|
|
setSelectedIndex(api.selectedScrollSnap())
|
|
onScrollSelect?.(api.selectedScrollSnap())
|
|
},
|
|
[onScrollSelect]
|
|
)
|
|
|
|
function scrollPrev() {
|
|
api?.scrollPrev()
|
|
}
|
|
|
|
function scrollNext() {
|
|
api?.scrollNext()
|
|
}
|
|
|
|
function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {
|
|
if (event.key === "ArrowLeft") {
|
|
event.preventDefault()
|
|
scrollPrev()
|
|
} else if (event.key === "ArrowRight") {
|
|
event.preventDefault()
|
|
scrollNext()
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (!api || !setApi) return
|
|
setApi(api)
|
|
}, [api, setApi])
|
|
|
|
useEffect(() => {
|
|
if (!api) return
|
|
onSelect(api)
|
|
api.on("reInit", onSelect)
|
|
api.on("select", onSelect)
|
|
|
|
return () => {
|
|
api.off("select", onSelect)
|
|
}
|
|
}, [api, onSelect])
|
|
|
|
useEffect(() => {
|
|
if (!api || scrollToIdx === -1) return
|
|
api.reInit()
|
|
api.scrollTo(scrollToIdx)
|
|
}, [api, scrollToIdx])
|
|
|
|
return (
|
|
<CarouselContext.Provider
|
|
value={{
|
|
carouselRef,
|
|
api,
|
|
opts,
|
|
plugins,
|
|
setApi,
|
|
children,
|
|
scrollPrev,
|
|
scrollNext,
|
|
canScrollPrev: api?.canScrollPrev.bind(api) ?? (() => false),
|
|
canScrollNext: api?.canScrollNext.bind(api) ?? (() => false),
|
|
selectedIndex,
|
|
}}
|
|
>
|
|
<div
|
|
onKeyDownCapture={handleKeyDown}
|
|
className={cx(styles.root, className)}
|
|
role="region"
|
|
aria-roledescription="carousel"
|
|
>
|
|
{children}
|
|
</div>
|
|
</CarouselContext.Provider>
|
|
)
|
|
}
|
|
|
|
Carousel.Content = CarouselContent
|
|
Carousel.Item = CarouselItem
|
|
Carousel.Next = CarouselNext
|
|
Carousel.Previous = CarouselPrevious
|
|
Carousel.Dots = CarouselDots
|
|
|
|
export { Carousel }
|