| 55 | }; |
| 56 | |
| 57 | export const Carousel = (props: ComponentProps<"div"> & CarouselProps) => { |
| 58 | const merge = mergeProps< |
| 59 | ParentProps<ComponentProps<"div"> & CarouselProps>[] |
| 60 | >({ orientation: "horizontal" }, props); |
| 61 | |
| 62 | const [local, rest] = splitProps(merge, [ |
| 63 | "orientation", |
| 64 | "opts", |
| 65 | "setApi", |
| 66 | "plugins", |
| 67 | "class", |
| 68 | "children", |
| 69 | ]); |
| 70 | |
| 71 | const [carouselRef, api] = createEmblaCarousel( |
| 72 | () => ({ |
| 73 | ...local.opts, |
| 74 | axis: local.orientation === "horizontal" ? "x" : "y", |
| 75 | }), |
| 76 | () => (local.plugins === undefined ? [] : local.plugins), |
| 77 | ); |
| 78 | const [canScrollPrev, setCanScrollPrev] = createSignal(false); |
| 79 | const [canScrollNext, setCanScrollNext] = createSignal(false); |
| 80 | |
| 81 | const onSelect = (api: NonNullable<ReturnType<CarouselApi>>) => { |
| 82 | setCanScrollPrev(api.canScrollPrev()); |
| 83 | setCanScrollNext(api.canScrollNext()); |
| 84 | }; |
| 85 | |
| 86 | const scrollPrev = () => api()?.scrollPrev(); |
| 87 | |
| 88 | const scrollNext = () => api()?.scrollNext(); |
| 89 | |
| 90 | const handleKeyDown = (event: KeyboardEvent) => { |
| 91 | if (event.key === "ArrowLeft") { |
| 92 | event.preventDefault(); |
| 93 | scrollPrev(); |
| 94 | } else if (event.key === "ArrowRight") { |
| 95 | event.preventDefault(); |
| 96 | scrollNext(); |
| 97 | } |
| 98 | }; |
| 99 | |
| 100 | createEffect(() => { |
| 101 | if (!api() || !local.setApi) return; |
| 102 | |
| 103 | local.setApi(api); |
| 104 | }); |
| 105 | |
| 106 | createEffect(() => { |
| 107 | const _api = api(); |
| 108 | if (_api === undefined) return; |
| 109 | |
| 110 | onSelect(_api); |
| 111 | _api.on("reInit", onSelect); |
| 112 | _api.on("select", onSelect); |
| 113 | |
| 114 | onCleanup(() => { |