Skip to content

Instantly share code, notes, and snippets.

@geff21st
Created November 8, 2023 09:30
Show Gist options
  • Save geff21st/2413cdbce75fb53a47c51e0c96da0452 to your computer and use it in GitHub Desktop.
Save geff21st/2413cdbce75fb53a47c51e0c96da0452 to your computer and use it in GitHub Desktop.
/**
* @typedef {import('vue').Ref} Ref
* @typedef {import('vue').ComputedRef} ComputedRef
* @typedef {import('swiper').Swiper} SwiperType
* @typedef {import('swiper/types').SwiperEvents} SwiperEvents
* @typedef {import('swiper/types').CSSSelector} CSSSelector
* @typedef {import('swiper/types').SwiperOptions} SwiperOptions
* @typedef {{ [event in keyof SwiperEvents]?: SwiperEvents[event] }} SwiperEventsList
*/
import { computed, onMounted, ref } from 'vue';
import { Swiper } from 'swiper/bundle';
import { Navigation, Pagination } from 'swiper';
import 'swiper/swiper-bundle.min.css';
/**
* @param sliderContainer
* @param {ComputedRef<SwiperOptions> | null} options
* @param {boolean} initOnMount
* @returns {{ swiper: Ref<SwiperType>, slideIndex: Ref<number>, init: () => void }}
*/
export function useSwiperSlider(
sliderContainer,
options = null,
initOnMount = false,
) {
const swiper = ref(undefined);
const isInitialized = ref(false);
const slideIndex = ref(0);
const inputEvents = computed(() => {
const optionsValue =
/** @type SwiperOptions */
options?.value;
const optionsEvents =
/** @type {SwiperEventsList | undefined} */
optionsValue?.on;
return /** @type {SwiperEventsList} */ (optionsEvents || {});
});
const setSlideIndex = (swiper) => {
slideIndex.value = swiper.realIndex;
};
const handleInitialized = (swiper) => {
setSlideIndex(swiper);
const inputHandler = inputEvents.value.init;
if (inputHandler && typeof inputHandler === 'function') {
inputHandler(swiper);
}
};
const handleSlideChanged = (swiper) => {
setSlideIndex(swiper);
const inputHandler = inputEvents.value.slideChange;
if (inputHandler && typeof inputHandler === 'function') {
inputHandler(swiper, slideIndex.value);
}
};
const swiperOptions = computed(() => (
/** @type SwiperOptions */ {
modules: [Navigation, Pagination],
navigation: {
nextEl: /** @type CSSSelector */ '.swiper-button-next',
prevEl: /** @type CSSSelector */ '.swiper-button-prev',
},
pagination: {
el: /** @type CSSSelector */ '.swiper-pagination',
dynamicBullets: true,
},
grabCursor: true,
...(options ? options.value : null),
on: /** @type {SwiperEventsList} */ {
...inputEvents.value,
init: handleInitialized,
slideChange: handleSlideChanged,
},
}
));
const init = () => {
if (isInitialized.value) {
return;
}
isInitialized.value = true;
setTimeout(() => {
swiper.value = new Swiper(sliderContainer.value, swiperOptions.value);
});
};
const destroy = () => {
isInitialized.value = false;
if (!swiper.value) {
return;
}
setTimeout(() => {
swiper.value.destroy();
});
};
if (initOnMount) {
onMounted(init);
}
return {
swiper,
slideIndex,
isInitialized,
init,
destroy,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment