mirror of
https://github.com/versia-pub/frontend.git
synced 2025-12-06 08:28:20 +01:00
70 lines
1.8 KiB
TypeScript
70 lines
1.8 KiB
TypeScript
import { createInjectionState } from "@vueuse/core";
|
|
import emblaCarouselVue from "embla-carousel-vue";
|
|
import { onMounted, ref } from "vue";
|
|
import type {
|
|
UnwrapRefCarouselApi as CarouselApi,
|
|
CarouselEmits,
|
|
CarouselProps,
|
|
} from "./interface";
|
|
|
|
const [useProvideCarousel, useInjectCarousel] = createInjectionState(
|
|
({ opts, orientation, plugins }: CarouselProps, emits: CarouselEmits) => {
|
|
const [emblaNode, emblaApi] = emblaCarouselVue(
|
|
{
|
|
...opts,
|
|
axis: orientation === "horizontal" ? "x" : "y",
|
|
},
|
|
plugins,
|
|
);
|
|
|
|
function scrollPrev() {
|
|
emblaApi.value?.scrollPrev();
|
|
}
|
|
function scrollNext() {
|
|
emblaApi.value?.scrollNext();
|
|
}
|
|
|
|
const canScrollNext = ref(false);
|
|
const canScrollPrev = ref(false);
|
|
|
|
function onSelect(api: CarouselApi) {
|
|
canScrollNext.value = !!api?.canScrollNext();
|
|
canScrollPrev.value = !!api?.canScrollPrev();
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (!emblaApi.value) {
|
|
return;
|
|
}
|
|
|
|
emblaApi.value?.on("init", onSelect);
|
|
emblaApi.value?.on("reInit", onSelect);
|
|
emblaApi.value?.on("select", onSelect);
|
|
|
|
emits("init-api", emblaApi.value);
|
|
});
|
|
|
|
return {
|
|
carouselRef: emblaNode,
|
|
carouselApi: emblaApi,
|
|
canScrollPrev,
|
|
canScrollNext,
|
|
scrollPrev,
|
|
scrollNext,
|
|
orientation,
|
|
};
|
|
},
|
|
);
|
|
|
|
function useCarousel() {
|
|
const carouselState = useInjectCarousel();
|
|
|
|
if (!carouselState) {
|
|
throw new Error("useCarousel must be used within a <Carousel />");
|
|
}
|
|
|
|
return carouselState;
|
|
}
|
|
|
|
export { useCarousel, useProvideCarousel };
|