Skip to content

Commit

Permalink
Update carousel.tsx with Dots api integration
Browse files Browse the repository at this point in the history
I need help to complete this dots integratio with the API of embla carousel and shadcnui carousel in order to upload the Dot functionalitity to the main docuemntation of shadch.
  • Loading branch information
luizarnoldch committed Apr 22, 2024
1 parent 816b654 commit d2204c0
Showing 1 changed file with 81 additions and 2 deletions.
83 changes: 81 additions & 2 deletions apps/www/registry/default/ui/carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import useEmblaCarousel, {
import { ArrowLeft, ArrowRight } from "lucide-react"

import { cn } from "@/lib/utils"
import { Button } from "@/registry/default/ui/button"
import { Button } from "@/components/ui/button"

type CarouselApi = UseEmblaCarouselType[1]
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
Expand All @@ -24,10 +24,18 @@ type CarouselProps = {
type CarouselContextProps = {
carouselRef: ReturnType<typeof useEmblaCarousel>[0]
api: ReturnType<typeof useEmblaCarousel>[1]

// Arrow Props
scrollPrev: () => void
scrollNext: () => void
canScrollPrev: boolean
canScrollNext: boolean

// Dot Props
selectedIndex: number
scrollSnaps: number[]
onDotButtonClick: (index: number) => void

} & CarouselProps

const CarouselContext = React.createContext<CarouselContextProps | null>(null)
Expand Down Expand Up @@ -65,18 +73,33 @@ const Carousel = React.forwardRef<
},
plugins
)
//Arrow States
const [canScrollPrev, setCanScrollPrev] = React.useState(false)
const [canScrollNext, setCanScrollNext] = React.useState(false)

//Dot States
const [selectedIndex, setSelectedIndex] = React.useState(0)
const [scrollSnaps, setScrollSnaps] = React.useState<number[]>([])

const onSelect = React.useCallback((api: CarouselApi) => {
if (!api) {
return
}

//On Select for Arrows
setCanScrollPrev(api.canScrollPrev())
setCanScrollNext(api.canScrollNext())

//On Select for Dot
setSelectedIndex(api.selectedScrollSnap())
}, [])

//On init for Dots
const onInit = React.useCallback((api: CarouselApi) => {
setScrollSnaps(api?.scrollSnapList || [])
}, [])

// Arrow Actions
const scrollPrev = React.useCallback(() => {
api?.scrollPrev()
}, [api])
Expand All @@ -85,6 +108,11 @@ const Carousel = React.forwardRef<
api?.scrollNext()
}, [api])

// Dot Actions
const onDotButtonClick = (index: number) => {
api?.scrollTo(index);
};

const handleKeyDown = React.useCallback(
(event: React.KeyboardEvent<HTMLDivElement>) => {
if (event.key === "ArrowLeft") {
Expand All @@ -111,14 +139,16 @@ const Carousel = React.forwardRef<
return
}

onInit(api)
onSelect(api)
api.on("reInit", onInit)
api.on("reInit", onSelect)
api.on("select", onSelect)

return () => {
api?.off("select", onSelect)
}
}, [api, onSelect])
}, [api, onInit, onSelect])

return (
<CarouselContext.Provider
Expand All @@ -132,6 +162,10 @@ const Carousel = React.forwardRef<
scrollNext,
canScrollPrev,
canScrollNext,

selectedIndex,
scrollSnaps,
onDotButtonClick,
}}
>
<div
Expand Down Expand Up @@ -252,11 +286,56 @@ const CarouselNext = React.forwardRef<
})
CarouselNext.displayName = "CarouselNext"

const CarouselDot = React.forwardRef<
HTMLButtonElement,
React.ComponentProps<typeof Button>
>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
const { orientation } = useCarousel()
return (
<Button
ref={ref}
variant={variant}
size={size}
className={cn(
"h-6 w-6 rounded-full",
orientation === "horizontal"
? ""
: "",
className
)}
{...props}
>
</Button>
)
})
CarouselDot.displayName = "CarouselDot"

const CarouselDots = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => {
const { scrollSnaps, selectedIndex, onDotButtonClick } = useCarousel();

return (
<div ref={ref} className={`flex justify-center space-x-2 p-2 ${className}`} {...props}>
{scrollSnaps.map((_, index) => (
<CarouselDot
key={index}
className={`${index === selectedIndex && 'border-white'}`}
onClick={() => onDotButtonClick(index)}
/>
))}
</div>
);
}
);
CarouselDots.displayName = "CarouselDots"

export {
type CarouselApi,
Carousel,
CarouselContent,
CarouselItem,
CarouselPrevious,
CarouselNext,
CarouselDot,
CarouselDots,
}

0 comments on commit d2204c0

Please sign in to comment.