import type { Vue } from 'vue-facing-decorator'; import SwiperCore from 'swiper'; import { Navigation, Pagination, Autoplay, FreeMode } from 'swiper/modules'; import { AutoplayOptions } from 'swiper/types'; import { Prop, toNative } from 'vue-facing-decorator'; import TsxComponent, { Component } from '../../app/vuetsx'; import 'swiper/css'; import 'swiper/css/navigation'; import 'swiper/css/pagination'; import './css/swiper.css'; type VueType = typeof Vue.prototype; interface IVue extends VueType { } SwiperCore.use([ Navigation, Pagination, Autoplay, FreeMode, ]); interface SwiperArgs { hasPagination?: boolean; direction?: 'horizontal' | 'vertical'; slidesPerView?: 'auto' | number; slidesPerGroup?: number; spaceBetween?: number; freeMode?: boolean; clickable?: boolean; grabCursor?: boolean; speed?: number; autoplay?: AutoplayOptions; preventClicks?: boolean; navigation?: { nextEl: () => HTMLElement | string | IVue; prevEl: () => HTMLElement | string | IVue }; slideChanged?: (e?: SwiperSlideChangedArgs) => void; zoomChanged?: (scale: number) => void; zoom?: boolean | SwiperZoomArgs; } export interface SwiperSlideChangedArgs { activeIndex: number; previousIndex: number; swiper: any; } export interface SwiperZoomArgs { enabled: boolean; maxRatio?: number; minRatio?: number; } @Component class SwiperComponent extends TsxComponent implements SwiperArgs { @Prop() hasPagination?: boolean; @Prop() direction?: 'horizontal' | 'vertical'; @Prop() slidesPerView?: 'auto' | number; @Prop() slidesPerGroup?: number; @Prop() spaceBetween?: number; @Prop() freeMode?: boolean; @Prop() clickable?: boolean; @Prop() grabCursor?: boolean; @Prop() speed: number; @Prop() autoplay: AutoplayOptions; @Prop() preventClicks: boolean; @Prop() navigation?: { nextEl: () => HTMLElement | string | IVue; prevEl: () => HTMLElement | string | IVue }; @Prop() zoom?: boolean | SwiperZoomArgs; @Prop() slideChanged?: (e?: SwiperSlideChangedArgs) => void; @Prop() zoomChanged?: (scale: number) => void; zoomed: boolean = false; mounted() { const rootElem = this.$el; if (rootElem != null) { const existingInstance = (rootElem as any).swiper; if (existingInstance == null) { const args: any = { zoom: this.getZoomArgs(), direction: this.direction || 'horizontal', spaceBetween: this.spaceBetween > 0 ? this.spaceBetween : 0, pagination: this.shouldRenderPagination() ? { el: this.$refs.swiperPagination, type: 'bullets', clickable: this.clickable } : { el: null, }, }; if (this.slidesPerView != null) { args.slidesPerView = this.slidesPerView; } if (this.slidesPerGroup != null) { args.slidesPerGroup = this.slidesPerGroup; } if (this.freeMode != null) { args.freeMode = this.freeMode; } if (this.grabCursor != null) { args.grabCursor = this.grabCursor; } if (this.speed != null) { args.speed = this.speed; } if (this.autoplay != null) { args.autoplay = this.autoplay; } if (this.preventClicks != null) { args.preventClicks = this.preventClicks; } if (this.navigation != null) { const getForProp = (prop) => { if (prop == null) { return null; } const propVal = prop(); if (propVal == null) { return null; } return propVal.$el ?? propVal; }; args.navigation = { prevEl: getForProp(this.navigation.prevEl), nextEl: getForProp(this.navigation.nextEl), }; } if (this.slideChanged != null) { args.on = { slideChange: (swiper: any) => { this.slideChanged({ activeIndex: swiper.activeIndex, previousIndex: swiper.previousIndex, swiper, }); }, }; } if (this.zoomChanged != null) { args.on = { ...args.on, zoomChange: (swiperEvent: any, scale: number) => { this.zoomed = scale > 1; this.zoomChanged(scale); }, }; } new SwiperCore(rootElem as any, args); } } } getSwiperInstance() { const rootElem = this.$el; if (rootElem != null) { return (rootElem as any).swiper; } return null; } getZoomArgs(): SwiperZoomArgs { if (this.zoom == true) { return { enabled: true, }; } return this.zoom as SwiperZoomArgs; } shouldRenderPagination(): boolean { return this.hasPagination != false; } render(h) { const zoomEnabled = (this.zoom == true || (this.zoom as SwiperZoomArgs)?.enabled == true); return (
{this.shouldRenderPagination() && (
)}
{this.$slots?.default()}
); } } const Swiper = toNative(SwiperComponent); export default Swiper;