repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | "use client" |
| #2 | |
| #3 | import * as React from "react" |
| #4 | import useEmblaCarousel, { |
| #5 | type UseEmblaCarouselType, |
| #6 | } from "embla-carousel-react" |
| #7 | import { ArrowLeft, ArrowRight } from "lucide-react" |
| #8 | |
| #9 | import { cn } from "@/lib/utils" |
| #10 | import { Button } from "@/components/ui/button" |
| #11 | |
| #12 | type CarouselApi = UseEmblaCarouselType[1] |
| #13 | type UseCarouselParameters = Parameters<typeof useEmblaCarousel> |
| #14 | type CarouselOptions = UseCarouselParameters[0] |
| #15 | type CarouselPlugin = UseCarouselParameters[1] |
| #16 | |
| #17 | type CarouselProps = { |
| #18 | opts?: CarouselOptions |
| #19 | plugins?: CarouselPlugin |
| #20 | orientation?: "horizontal" | "vertical" |
| #21 | setApi?: (api: CarouselApi) => void |
| #22 | } |
| #23 | |
| #24 | type CarouselContextProps = { |
| #25 | carouselRef: ReturnType<typeof useEmblaCarousel>[0] |
| #26 | api: ReturnType<typeof useEmblaCarousel>[1] |
| #27 | scrollPrev: () => void |
| #28 | scrollNext: () => void |
| #29 | canScrollPrev: boolean |
| #30 | canScrollNext: boolean |
| #31 | } & CarouselProps |
| #32 | |
| #33 | const CarouselContext = React.createContext<CarouselContextProps | null>(null) |
| #34 | |
| #35 | function useCarousel() { |
| #36 | const context = React.useContext(CarouselContext) |
| #37 | |
| #38 | if (!context) { |
| #39 | throw new Error("useCarousel must be used within a <Carousel />") |
| #40 | } |
| #41 | |
| #42 | return context |
| #43 | } |
| #44 | |
| #45 | const Carousel = React.forwardRef< |
| #46 | HTMLDivElement, |
| #47 | React.HTMLAttributes<HTMLDivElement> & CarouselProps |
| #48 | >( |
| #49 | ( |
| #50 | { |
| #51 | orientation = "horizontal", |
| #52 | opts, |
| #53 | setApi, |
| #54 | plugins, |
| #55 | className, |
| #56 | children, |
| #57 | ...props |
| #58 | }, |
| #59 | ref |
| #60 | ) => { |
| #61 | const [carouselRef, api] = useEmblaCarousel( |
| #62 | { |
| #63 | ...opts, |
| #64 | axis: orientation === "horizontal" ? "x" : "y", |
| #65 | }, |
| #66 | plugins |
| #67 | ) |
| #68 | const [canScrollPrev, setCanScrollPrev] = React.useState(false) |
| #69 | const [canScrollNext, setCanScrollNext] = React.useState(false) |
| #70 | |
| #71 | const onSelect = React.useCallback((api: CarouselApi) => { |
| #72 | if (!api) { |
| #73 | return |
| #74 | } |
| #75 | |
| #76 | setCanScrollPrev(api.canScrollPrev()) |
| #77 | setCanScrollNext(api.canScrollNext()) |
| #78 | }, []) |
| #79 | |
| #80 | const scrollPrev = React.useCallback(() => { |
| #81 | api?.scrollPrev() |
| #82 | }, [api]) |
| #83 | |
| #84 | const scrollNext = React.useCallback(() => { |
| #85 | api?.scrollNext() |
| #86 | }, [api]) |
| #87 | |
| #88 | const handleKeyDown = React.useCallback( |
| #89 | (event: React.KeyboardEvent<HTMLDivElement>) => { |
| #90 | if (event.key === "ArrowLeft") { |
| #91 | event.preventDefault() |
| #92 | scrollPrev() |
| #93 | } else if (event.key === "ArrowRight") { |
| #94 | event.preventDefault() |
| #95 | scrollNext() |
| #96 | } |
| #97 | }, |
| #98 | [scrollPrev, scrollNext] |
| #99 | ) |
| #100 | |
| #101 | React.useEffect(() => { |
| #102 | if (!api || !setApi) { |
| #103 | return |
| #104 | } |
| #105 | |
| #106 | setApi(api) |
| #107 | }, [api, setApi]) |
| #108 | |
| #109 | React.useEffect(() => { |
| #110 | if (!api) { |
| #111 | return |
| #112 | } |
| #113 | |
| #114 | onSelect(api) |
| #115 | api.on("reInit", onSelect) |
| #116 | api.on("select", onSelect) |
| #117 | |
| #118 | return () => { |
| #119 | api?.off("select", onSelect) |
| #120 | } |
| #121 | }, [api, onSelect]) |
| #122 | |
| #123 | return ( |
| #124 | <CarouselContext.Provider |
| #125 | value={{ |
| #126 | carouselRef, |
| #127 | api: api, |
| #128 | opts, |
| #129 | orientation: |
| #130 | orientation || (opts?.axis === "y" ? "vertical" : "horizontal"), |
| #131 | scrollPrev, |
| #132 | scrollNext, |
| #133 | canScrollPrev, |
| #134 | canScrollNext, |
| #135 | }} |
| #136 | > |
| #137 | <div |
| #138 | ref={ref} |
| #139 | onKeyDownCapture={handleKeyDown} |
| #140 | className={cn("relative", className)} |
| #141 | role="region" |
| #142 | aria-roledescription="carousel" |
| #143 | {...props} |
| #144 | > |
| #145 | {children} |
| #146 | </div> |
| #147 | </CarouselContext.Provider> |
| #148 | ) |
| #149 | } |
| #150 | ) |
| #151 | Carousel.displayName = "Carousel" |
| #152 | |
| #153 | const CarouselContent = React.forwardRef< |
| #154 | HTMLDivElement, |
| #155 | React.HTMLAttributes<HTMLDivElement> |
| #156 | >(({ className, ...props }, ref) => { |
| #157 | const { carouselRef, orientation } = useCarousel() |
| #158 | |
| #159 | return ( |
| #160 | <div ref={carouselRef} className="overflow-hidden"> |
| #161 | <div |
| #162 | ref={ref} |
| #163 | className={cn( |
| #164 | "flex", |
| #165 | orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col", |
| #166 | className |
| #167 | )} |
| #168 | {...props} |
| #169 | /> |
| #170 | </div> |
| #171 | ) |
| #172 | }) |
| #173 | CarouselContent.displayName = "CarouselContent" |
| #174 | |
| #175 | const CarouselItem = React.forwardRef< |
| #176 | HTMLDivElement, |
| #177 | React.HTMLAttributes<HTMLDivElement> |
| #178 | >(({ className, ...props }, ref) => { |
| #179 | const { orientation } = useCarousel() |
| #180 | |
| #181 | return ( |
| #182 | <div |
| #183 | ref={ref} |
| #184 | role="group" |
| #185 | aria-roledescription="slide" |
| #186 | className={cn( |
| #187 | "min-w-0 shrink-0 grow-0 basis-full", |
| #188 | orientation === "horizontal" ? "pl-4" : "pt-4", |
| #189 | className |
| #190 | )} |
| #191 | {...props} |
| #192 | /> |
| #193 | ) |
| #194 | }) |
| #195 | CarouselItem.displayName = "CarouselItem" |
| #196 | |
| #197 | const CarouselPrevious = React.forwardRef< |
| #198 | HTMLButtonElement, |
| #199 | React.ComponentProps<typeof Button> |
| #200 | >(({ className, variant = "outline", size = "icon", ...props }, ref) => { |
| #201 | const { orientation, scrollPrev, canScrollPrev } = useCarousel() |
| #202 | |
| #203 | return ( |
| #204 | <Button |
| #205 | ref={ref} |
| #206 | variant={variant} |
| #207 | size={size} |
| #208 | className={cn( |
| #209 | "absolute h-8 w-8 rounded-full", |
| #210 | orientation === "horizontal" |
| #211 | ? "-left-12 top-1/2 -translate-y-1/2" |
| #212 | : "-top-12 left-1/2 -translate-x-1/2 rotate-90", |
| #213 | className |
| #214 | )} |
| #215 | disabled={!canScrollPrev} |
| #216 | onClick={scrollPrev} |
| #217 | {...props} |
| #218 | > |
| #219 | <ArrowLeft className="h-4 w-4" /> |
| #220 | <span className="sr-only">Previous slide</span> |
| #221 | </Button> |
| #222 | ) |
| #223 | }) |
| #224 | CarouselPrevious.displayName = "CarouselPrevious" |
| #225 | |
| #226 | const CarouselNext = React.forwardRef< |
| #227 | HTMLButtonElement, |
| #228 | React.ComponentProps<typeof Button> |
| #229 | >(({ className, variant = "outline", size = "icon", ...props }, ref) => { |
| #230 | const { orientation, scrollNext, canScrollNext } = useCarousel() |
| #231 | |
| #232 | return ( |
| #233 | <Button |
| #234 | ref={ref} |
| #235 | variant={variant} |
| #236 | size={size} |
| #237 | className={cn( |
| #238 | "absolute h-8 w-8 rounded-full", |
| #239 | orientation === "horizontal" |
| #240 | ? "-right-12 top-1/2 -translate-y-1/2" |
| #241 | : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90", |
| #242 | className |
| #243 | )} |
| #244 | disabled={!canScrollNext} |
| #245 | onClick={scrollNext} |
| #246 | {...props} |
| #247 | > |
| #248 | <ArrowRight className="h-4 w-4" /> |
| #249 | <span className="sr-only">Next slide</span> |
| #250 | </Button> |
| #251 | ) |
| #252 | }) |
| #253 | CarouselNext.displayName = "CarouselNext" |
| #254 | |
| #255 | export { |
| #256 | type CarouselApi, |
| #257 | Carousel, |
| #258 | CarouselContent, |
| #259 | CarouselItem, |
| #260 | CarouselPrevious, |
| #261 | CarouselNext, |
| #262 | } |
| #263 |