library_components/components/Ml/Slider/MlSlider.vue
2024-07-09 11:00:50 +02:00

144 lines
3.9 KiB
Vue

<template>
<div v-show="showSwiper" class="relative" :class="rootClasses">
<swiper
loop-add-blank-slides
:class="sliderClasses"
:direction="direction"
:breakpoints="{
450: { slidesPerView: 1.2, spaceBetween: 20 },
500: { slidesPerView: 1.5, spaceBetween: 20 },
600: { slidesPerView: 1.5, spaceBetween: 20 },
770: { slidesPerView: 1, spaceBetween: 20 },
800: { slidesPerView: 1, spaceBetween: 20 },
1000: { slidesPerView: 1.2, spaceBetween: 20 },
1200: { slidesPerView: 1.5, spaceBetween: 20 },
1600: { slidesPerView: 2, spaceBetween: 40 },
2000: { slidesPerView: 2.5, spaceBetween: 40 },
}"
:space-between="50"
@swiper="onSwiper"
@slide-change="onSlideChange"
>
<swiper-slide
v-for="item in items"
:key="item.title"
class="hover:cursor-pointer"
>
<slot :item="item" />
</swiper-slide>
</swiper>
<div>
<div :class="counterClasses">
<div :class="progressClass" :style="`width: ${progerssBar}%`"></div>
<div class="flex justify-between my-4">
<button
:disabled="isPrevDisabled"
class="px-4 py-2 disabled:text-gray-400 cursor-pointer"
@click="
useRipple($event, true);
goPrev();
"
>
<ArrowLeftIcon class="size-5" />
</button>
<button
:disabled="isNextDisabled"
class="px-4 py-2 disabled:text-gray-400 cursor-pointer"
@click="
useRipple($event, true);
goNext();
"
>
<ArrowRightIcon class="size-5" />
</button>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
// import { useRipple } from "#imports";
import { ref, computed, defineProps, withDefaults } from "vue";
import { Swiper, SwiperSlide } from "swiper/vue";
import type { Swiper as swiper } from "swiper/types";
import "swiper/css";
import { twMerge } from "tailwind-merge";
import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/vue/24/solid";
import type { PTAttribs, SliderProps } from "./types";
const showSwiper = ref(false);
const progerssBar = ref(0);
const prevDisabled = ref(true);
const nextDisabled = ref(true);
let swiperInstance: swiper;
const onSwiper = (swiper: swiper) => {
progerssBar.value = Math.ceil(
((swiper.realIndex + (swiper.params.slidesPerView as number)) /
swiper.el.querySelectorAll(".swiper-slide").length) *
100
);
swiperInstance = swiper;
showSwiper.value = true;
prevDisabled.value = !swiper.params.loop && swiper.realIndex == 0;
nextDisabled.value = swiperInstance.isEnd;
};
const onSlideChange = (swiper: swiper) => {
progerssBar.value = Math.ceil(
((swiper.realIndex + (swiper.params.slidesPerView as number)) /
swiper.slides.length) *
100
);
prevDisabled.value = !swiper.params.loop && swiper.realIndex == 0;
nextDisabled.value = swiper.isEnd;
};
const isPrevDisabled = computed(() => prevDisabled.value);
const isNextDisabled = computed(() => nextDisabled.value);
function goNext() {
swiperInstance.slideNext();
}
function goPrev() {
swiperInstance.slidePrev();
}
const props = withDefaults(defineProps<SliderProps>(), {
items: [],
});
const classes = ref({
root: {
class: ``,
},
slider: {
class: ``,
},
counter: {
class: ``,
},
progress: {
class: "",
},
} as unknown as PTAttribs);
const rootClasses = computed(() =>
twMerge(classes.value.root?.class, props.pt?.root?.class)
);
const sliderClasses = computed(() =>
twMerge(classes.value.slider?.class, props.pt?.slider?.class)
);
const counterClasses = computed(() =>
twMerge(classes.value.counter?.class, props.pt?.counter?.class)
);
const progressClass = computed(() =>
twMerge(classes.value.progress?.class, props.pt?.progress?.class)
);
const items = props.items;
</script>