summaryrefslogtreecommitdiff
path: root/apps/web/src/components/ui/carousel.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/components/ui/carousel.tsx')
-rw-r--r--apps/web/src/components/ui/carousel.tsx384
1 files changed, 192 insertions, 192 deletions
diff --git a/apps/web/src/components/ui/carousel.tsx b/apps/web/src/components/ui/carousel.tsx
index 9ab74471..3c0efdc6 100644
--- a/apps/web/src/components/ui/carousel.tsx
+++ b/apps/web/src/components/ui/carousel.tsx
@@ -2,7 +2,7 @@
import * as React from "react";
import useEmblaCarousel, {
- type UseEmblaCarouselType,
+ type UseEmblaCarouselType,
} from "embla-carousel-react";
import { ArrowLeft, ArrowRight } from "lucide-react";
@@ -15,248 +15,248 @@ type CarouselOptions = UseCarouselParameters[0];
type CarouselPlugin = UseCarouselParameters[1];
type CarouselProps = {
- opts?: CarouselOptions;
- plugins?: CarouselPlugin;
- orientation?: "horizontal" | "vertical";
- setApi?: (api: CarouselApi) => void;
+ opts?: CarouselOptions;
+ plugins?: CarouselPlugin;
+ orientation?: "horizontal" | "vertical";
+ setApi?: (api: CarouselApi) => void;
};
type CarouselContextProps = {
- carouselRef: ReturnType<typeof useEmblaCarousel>[0];
- api: ReturnType<typeof useEmblaCarousel>[1];
- scrollPrev: () => void;
- scrollNext: () => void;
- canScrollPrev: boolean;
- canScrollNext: boolean;
+ carouselRef: ReturnType<typeof useEmblaCarousel>[0];
+ api: ReturnType<typeof useEmblaCarousel>[1];
+ scrollPrev: () => void;
+ scrollNext: () => void;
+ canScrollPrev: boolean;
+ canScrollNext: boolean;
} & CarouselProps;
const CarouselContext = React.createContext<CarouselContextProps | null>(null);
function useCarousel() {
- const context = React.useContext(CarouselContext);
+ const context = React.useContext(CarouselContext);
- if (!context) {
- throw new Error("useCarousel must be used within a <Carousel />");
- }
+ if (!context) {
+ throw new Error("useCarousel must be used within a <Carousel />");
+ }
- return context;
+ return context;
}
const Carousel = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes<HTMLDivElement> & CarouselProps
+ HTMLDivElement,
+ React.HTMLAttributes<HTMLDivElement> & CarouselProps
>(
- (
- {
- orientation = "horizontal",
- opts,
- setApi,
- plugins,
- className,
- children,
- ...props
- },
- ref,
- ) => {
- const [carouselRef, api] = useEmblaCarousel(
- {
- ...opts,
- axis: orientation === "horizontal" ? "x" : "y",
- },
- plugins,
- );
- const [canScrollPrev, setCanScrollPrev] = React.useState(false);
- const [canScrollNext, setCanScrollNext] = React.useState(false);
+ (
+ {
+ orientation = "horizontal",
+ opts,
+ setApi,
+ plugins,
+ className,
+ children,
+ ...props
+ },
+ ref
+ ) => {
+ const [carouselRef, api] = useEmblaCarousel(
+ {
+ ...opts,
+ axis: orientation === "horizontal" ? "x" : "y",
+ },
+ plugins
+ );
+ const [canScrollPrev, setCanScrollPrev] = React.useState(false);
+ const [canScrollNext, setCanScrollNext] = React.useState(false);
- const onSelect = React.useCallback((api: CarouselApi) => {
- if (!api) {
- return;
- }
+ const onSelect = React.useCallback((api: CarouselApi) => {
+ if (!api) {
+ return;
+ }
- setCanScrollPrev(api.canScrollPrev());
- setCanScrollNext(api.canScrollNext());
- }, []);
+ setCanScrollPrev(api.canScrollPrev());
+ setCanScrollNext(api.canScrollNext());
+ }, []);
- const scrollPrev = React.useCallback(() => {
- api?.scrollPrev();
- }, [api]);
+ const scrollPrev = React.useCallback(() => {
+ api?.scrollPrev();
+ }, [api]);
- const scrollNext = React.useCallback(() => {
- api?.scrollNext();
- }, [api]);
+ const scrollNext = React.useCallback(() => {
+ api?.scrollNext();
+ }, [api]);
- const handleKeyDown = React.useCallback(
- (event: React.KeyboardEvent<HTMLDivElement>) => {
- if (event.key === "ArrowLeft") {
- event.preventDefault();
- scrollPrev();
- } else if (event.key === "ArrowRight") {
- event.preventDefault();
- scrollNext();
- }
- },
- [scrollPrev, scrollNext],
- );
+ const handleKeyDown = React.useCallback(
+ (event: React.KeyboardEvent<HTMLDivElement>) => {
+ if (event.key === "ArrowLeft") {
+ event.preventDefault();
+ scrollPrev();
+ } else if (event.key === "ArrowRight") {
+ event.preventDefault();
+ scrollNext();
+ }
+ },
+ [scrollPrev, scrollNext]
+ );
- React.useEffect(() => {
- if (!api || !setApi) {
- return;
- }
+ React.useEffect(() => {
+ if (!api || !setApi) {
+ return;
+ }
- setApi(api);
- }, [api, setApi]);
+ setApi(api);
+ }, [api, setApi]);
- React.useEffect(() => {
- if (!api) {
- return;
- }
+ React.useEffect(() => {
+ if (!api) {
+ return;
+ }
- onSelect(api);
- api.on("reInit", onSelect);
- api.on("select", onSelect);
+ onSelect(api);
+ api.on("reInit", onSelect);
+ api.on("select", onSelect);
- return () => {
- api?.off("select", onSelect);
- };
- }, [api, onSelect]);
+ return () => {
+ api?.off("select", onSelect);
+ };
+ }, [api, onSelect]);
- return (
- <CarouselContext.Provider
- value={{
- carouselRef,
- api: api,
- opts,
- orientation:
- orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
- scrollPrev,
- scrollNext,
- canScrollPrev,
- canScrollNext,
- }}
- >
- <div
- ref={ref}
- onKeyDownCapture={handleKeyDown}
- className={cn("relative", className)}
- role="region"
- aria-roledescription="carousel"
- {...props}
- >
- {children}
- </div>
- </CarouselContext.Provider>
- );
- },
+ return (
+ <CarouselContext.Provider
+ value={{
+ carouselRef,
+ api: api,
+ opts,
+ orientation:
+ orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
+ scrollPrev,
+ scrollNext,
+ canScrollPrev,
+ canScrollNext,
+ }}
+ >
+ <div
+ ref={ref}
+ onKeyDownCapture={handleKeyDown}
+ className={cn("relative", className)}
+ role="region"
+ aria-roledescription="carousel"
+ {...props}
+ >
+ {children}
+ </div>
+ </CarouselContext.Provider>
+ );
+ }
);
Carousel.displayName = "Carousel";
const CarouselContent = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes<HTMLDivElement>
+ HTMLDivElement,
+ React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
- const { carouselRef, orientation } = useCarousel();
+ const { carouselRef, orientation } = useCarousel();
- return (
- <div ref={carouselRef} className="overflow-hidden">
- <div
- ref={ref}
- className={cn(
- "flex",
- orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
- className,
- )}
- {...props}
- />
- </div>
- );
+ return (
+ <div ref={carouselRef} className="overflow-hidden">
+ <div
+ ref={ref}
+ className={cn(
+ "flex",
+ orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
+ className
+ )}
+ {...props}
+ />
+ </div>
+ );
});
CarouselContent.displayName = "CarouselContent";
const CarouselItem = React.forwardRef<
- HTMLDivElement,
- React.HTMLAttributes<HTMLDivElement>
+ HTMLDivElement,
+ React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => {
- const { orientation } = useCarousel();
+ const { orientation } = useCarousel();
- return (
- <div
- ref={ref}
- role="group"
- aria-roledescription="slide"
- className={cn(
- "min-w-0 shrink-0 grow-0 basis-full",
- orientation === "horizontal" ? "pl-4" : "pt-4",
- className,
- )}
- {...props}
- />
- );
+ return (
+ <div
+ ref={ref}
+ role="group"
+ aria-roledescription="slide"
+ className={cn(
+ "min-w-0 shrink-0 grow-0 basis-full",
+ orientation === "horizontal" ? "pl-4" : "pt-4",
+ className
+ )}
+ {...props}
+ />
+ );
});
CarouselItem.displayName = "CarouselItem";
const CarouselPrevious = React.forwardRef<
- HTMLButtonElement,
- React.ComponentProps<typeof Button>
+ HTMLButtonElement,
+ React.ComponentProps<typeof Button>
>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
- const { orientation, scrollPrev, canScrollPrev } = useCarousel();
+ const { orientation, scrollPrev, canScrollPrev } = useCarousel();
- return (
- <Button
- ref={ref}
- variant={variant}
- size={size}
- className={cn(
- "absolute h-8 w-8 rounded-full",
- orientation === "horizontal"
- ? "-left-12 top-1/2 -translate-y-1/2"
- : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
- className,
- )}
- disabled={!canScrollPrev}
- onClick={scrollPrev}
- {...props}
- >
- <ArrowLeft className="h-4 w-4" />
- <span className="sr-only">Previous slide</span>
- </Button>
- );
+ return (
+ <Button
+ ref={ref}
+ variant={variant}
+ size={size}
+ className={cn(
+ "absolute h-8 w-8 rounded-full",
+ orientation === "horizontal"
+ ? "-left-12 top-1/2 -translate-y-1/2"
+ : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
+ className
+ )}
+ disabled={!canScrollPrev}
+ onClick={scrollPrev}
+ {...props}
+ >
+ <ArrowLeft className="h-4 w-4" />
+ <span className="sr-only">Previous slide</span>
+ </Button>
+ );
});
CarouselPrevious.displayName = "CarouselPrevious";
const CarouselNext = React.forwardRef<
- HTMLButtonElement,
- React.ComponentProps<typeof Button>
+ HTMLButtonElement,
+ React.ComponentProps<typeof Button>
>(({ className, variant = "outline", size = "icon", ...props }, ref) => {
- const { orientation, scrollNext, canScrollNext } = useCarousel();
+ const { orientation, scrollNext, canScrollNext } = useCarousel();
- return (
- <Button
- ref={ref}
- variant={variant}
- size={size}
- className={cn(
- "absolute h-8 w-8 rounded-full",
- orientation === "horizontal"
- ? "-right-12 top-1/2 -translate-y-1/2"
- : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
- className,
- )}
- disabled={!canScrollNext}
- onClick={scrollNext}
- {...props}
- >
- <ArrowRight className="h-4 w-4" />
- <span className="sr-only">Next slide</span>
- </Button>
- );
+ return (
+ <Button
+ ref={ref}
+ variant={variant}
+ size={size}
+ className={cn(
+ "absolute h-8 w-8 rounded-full",
+ orientation === "horizontal"
+ ? "-right-12 top-1/2 -translate-y-1/2"
+ : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
+ className
+ )}
+ disabled={!canScrollNext}
+ onClick={scrollNext}
+ {...props}
+ >
+ <ArrowRight className="h-4 w-4" />
+ <span className="sr-only">Next slide</span>
+ </Button>
+ );
});
CarouselNext.displayName = "CarouselNext";
export {
- type CarouselApi,
- Carousel,
- CarouselContent,
- CarouselItem,
- CarouselPrevious,
- CarouselNext,
+ type CarouselApi,
+ Carousel,
+ CarouselContent,
+ CarouselItem,
+ CarouselPrevious,
+ CarouselNext,
};