UNPKG

21.8 kBJavaScriptView Raw
1/**
2 * Swiper Vue 11.1.4
3 * Most modern mobile touch slider and framework with hardware accelerated transitions
4 * https://swiperjs.com
5 *
6 * Copyright 2014-2024 Vladimir Kharlampidi
7 *
8 * Released under the MIT License
9 *
10 * Released on: May 30, 2024
11 */
12
13import { h, ref, onUpdated, provide, watch, nextTick, onMounted, onBeforeUnmount, onBeforeUpdate, computed, inject } from 'vue';
14import { S as Swiper$1 } from './shared/swiper-core.mjs';
15import { g as getParams, a as getChangedParams, u as updateOnVirtualData, m as mountSwiper } from './shared/update-on-virtual-data.mjs';
16import { e as extend, u as updateSwiper, d as uniqueClasses, w as wrapperClass, n as needsNavigation, b as needsScrollbar, a as needsPagination } from './shared/update-swiper.mjs';
17
18function getChildren(originalSlots, slidesRef, oldSlidesRef) {
19 if (originalSlots === void 0) {
20 originalSlots = {};
21 }
22 const slides = [];
23 const slots = {
24 'container-start': [],
25 'container-end': [],
26 'wrapper-start': [],
27 'wrapper-end': []
28 };
29 const getSlidesFromElements = (els, slotName) => {
30 if (!Array.isArray(els)) {
31 return;
32 }
33 els.forEach(vnode => {
34 const isFragment = typeof vnode.type === 'symbol';
35 if (slotName === 'default') slotName = 'container-end';
36 if (isFragment && vnode.children) {
37 getSlidesFromElements(vnode.children, slotName);
38 } else if (vnode.type && (vnode.type.name === 'SwiperSlide' || vnode.type.name === 'AsyncComponentWrapper') || vnode.componentOptions && vnode.componentOptions.tag === 'SwiperSlide') {
39 slides.push(vnode);
40 } else if (slots[slotName]) {
41 slots[slotName].push(vnode);
42 }
43 });
44 };
45 Object.keys(originalSlots).forEach(slotName => {
46 if (typeof originalSlots[slotName] !== 'function') return;
47 const els = originalSlots[slotName]();
48 getSlidesFromElements(els, slotName);
49 });
50 oldSlidesRef.value = slidesRef.value;
51 slidesRef.value = slides;
52 return {
53 slides,
54 slots
55 };
56}
57
58function renderVirtual(swiperRef, slides, virtualData) {
59 if (!virtualData) return null;
60 const getSlideIndex = index => {
61 let slideIndex = index;
62 if (index < 0) {
63 slideIndex = slides.length + index;
64 } else if (slideIndex >= slides.length) {
65 // eslint-disable-next-line
66 slideIndex = slideIndex - slides.length;
67 }
68 return slideIndex;
69 };
70 const style = swiperRef.value.isHorizontal() ? {
71 [swiperRef.value.rtlTranslate ? 'right' : 'left']: `${virtualData.offset}px`
72 } : {
73 top: `${virtualData.offset}px`
74 };
75 const {
76 from,
77 to
78 } = virtualData;
79 const loopFrom = swiperRef.value.params.loop ? -slides.length : 0;
80 const loopTo = swiperRef.value.params.loop ? slides.length * 2 : slides.length;
81 const slidesToRender = [];
82 for (let i = loopFrom; i < loopTo; i += 1) {
83 if (i >= from && i <= to && slidesToRender.length < slides.length) {
84 slidesToRender.push(slides[getSlideIndex(i)]);
85 }
86 }
87 return slidesToRender.map(slide => {
88 if (!slide.props) slide.props = {};
89 if (!slide.props.style) slide.props.style = {};
90 slide.props.swiperRef = swiperRef;
91 slide.props.style = style;
92 if (slide.type) {
93 return h(slide.type, {
94 ...slide.props
95 }, slide.children);
96 } else if (slide.componentOptions) {
97 return h(slide.componentOptions.Ctor, {
98 ...slide.props
99 }, slide.componentOptions.children);
100 }
101 });
102}
103
104const Swiper = {
105 name: 'Swiper',
106 props: {
107 tag: {
108 type: String,
109 default: 'div'
110 },
111 wrapperTag: {
112 type: String,
113 default: 'div'
114 },
115 modules: {
116 type: Array,
117 default: undefined
118 },
119 init: {
120 type: Boolean,
121 default: undefined
122 },
123 direction: {
124 type: String,
125 default: undefined
126 },
127 oneWayMovement: {
128 type: Boolean,
129 default: undefined
130 },
131 swiperElementNodeName: {
132 type: String,
133 default: 'SWIPER-CONTAINER'
134 },
135 touchEventsTarget: {
136 type: String,
137 default: undefined
138 },
139 initialSlide: {
140 type: Number,
141 default: undefined
142 },
143 speed: {
144 type: Number,
145 default: undefined
146 },
147 cssMode: {
148 type: Boolean,
149 default: undefined
150 },
151 updateOnWindowResize: {
152 type: Boolean,
153 default: undefined
154 },
155 resizeObserver: {
156 type: Boolean,
157 default: undefined
158 },
159 nested: {
160 type: Boolean,
161 default: undefined
162 },
163 focusableElements: {
164 type: String,
165 default: undefined
166 },
167 width: {
168 type: Number,
169 default: undefined
170 },
171 height: {
172 type: Number,
173 default: undefined
174 },
175 preventInteractionOnTransition: {
176 type: Boolean,
177 default: undefined
178 },
179 userAgent: {
180 type: String,
181 default: undefined
182 },
183 url: {
184 type: String,
185 default: undefined
186 },
187 edgeSwipeDetection: {
188 type: [Boolean, String],
189 default: undefined
190 },
191 edgeSwipeThreshold: {
192 type: Number,
193 default: undefined
194 },
195 autoHeight: {
196 type: Boolean,
197 default: undefined
198 },
199 setWrapperSize: {
200 type: Boolean,
201 default: undefined
202 },
203 virtualTranslate: {
204 type: Boolean,
205 default: undefined
206 },
207 effect: {
208 type: String,
209 default: undefined
210 },
211 breakpoints: {
212 type: Object,
213 default: undefined
214 },
215 spaceBetween: {
216 type: [Number, String],
217 default: undefined
218 },
219 slidesPerView: {
220 type: [Number, String],
221 default: undefined
222 },
223 maxBackfaceHiddenSlides: {
224 type: Number,
225 default: undefined
226 },
227 slidesPerGroup: {
228 type: Number,
229 default: undefined
230 },
231 slidesPerGroupSkip: {
232 type: Number,
233 default: undefined
234 },
235 slidesPerGroupAuto: {
236 type: Boolean,
237 default: undefined
238 },
239 centeredSlides: {
240 type: Boolean,
241 default: undefined
242 },
243 centeredSlidesBounds: {
244 type: Boolean,
245 default: undefined
246 },
247 slidesOffsetBefore: {
248 type: Number,
249 default: undefined
250 },
251 slidesOffsetAfter: {
252 type: Number,
253 default: undefined
254 },
255 normalizeSlideIndex: {
256 type: Boolean,
257 default: undefined
258 },
259 centerInsufficientSlides: {
260 type: Boolean,
261 default: undefined
262 },
263 watchOverflow: {
264 type: Boolean,
265 default: undefined
266 },
267 roundLengths: {
268 type: Boolean,
269 default: undefined
270 },
271 touchRatio: {
272 type: Number,
273 default: undefined
274 },
275 touchAngle: {
276 type: Number,
277 default: undefined
278 },
279 simulateTouch: {
280 type: Boolean,
281 default: undefined
282 },
283 shortSwipes: {
284 type: Boolean,
285 default: undefined
286 },
287 longSwipes: {
288 type: Boolean,
289 default: undefined
290 },
291 longSwipesRatio: {
292 type: Number,
293 default: undefined
294 },
295 longSwipesMs: {
296 type: Number,
297 default: undefined
298 },
299 followFinger: {
300 type: Boolean,
301 default: undefined
302 },
303 allowTouchMove: {
304 type: Boolean,
305 default: undefined
306 },
307 threshold: {
308 type: Number,
309 default: undefined
310 },
311 touchMoveStopPropagation: {
312 type: Boolean,
313 default: undefined
314 },
315 touchStartPreventDefault: {
316 type: Boolean,
317 default: undefined
318 },
319 touchStartForcePreventDefault: {
320 type: Boolean,
321 default: undefined
322 },
323 touchReleaseOnEdges: {
324 type: Boolean,
325 default: undefined
326 },
327 uniqueNavElements: {
328 type: Boolean,
329 default: undefined
330 },
331 resistance: {
332 type: Boolean,
333 default: undefined
334 },
335 resistanceRatio: {
336 type: Number,
337 default: undefined
338 },
339 watchSlidesProgress: {
340 type: Boolean,
341 default: undefined
342 },
343 grabCursor: {
344 type: Boolean,
345 default: undefined
346 },
347 preventClicks: {
348 type: Boolean,
349 default: undefined
350 },
351 preventClicksPropagation: {
352 type: Boolean,
353 default: undefined
354 },
355 slideToClickedSlide: {
356 type: Boolean,
357 default: undefined
358 },
359 loop: {
360 type: Boolean,
361 default: undefined
362 },
363 loopedSlides: {
364 type: Number,
365 default: undefined
366 },
367 loopPreventsSliding: {
368 type: Boolean,
369 default: undefined
370 },
371 rewind: {
372 type: Boolean,
373 default: undefined
374 },
375 allowSlidePrev: {
376 type: Boolean,
377 default: undefined
378 },
379 allowSlideNext: {
380 type: Boolean,
381 default: undefined
382 },
383 swipeHandler: {
384 type: Boolean,
385 default: undefined
386 },
387 noSwiping: {
388 type: Boolean,
389 default: undefined
390 },
391 noSwipingClass: {
392 type: String,
393 default: undefined
394 },
395 noSwipingSelector: {
396 type: String,
397 default: undefined
398 },
399 passiveListeners: {
400 type: Boolean,
401 default: undefined
402 },
403 containerModifierClass: {
404 type: String,
405 default: undefined
406 },
407 slideClass: {
408 type: String,
409 default: undefined
410 },
411 slideActiveClass: {
412 type: String,
413 default: undefined
414 },
415 slideVisibleClass: {
416 type: String,
417 default: undefined
418 },
419 slideFullyVisibleClass: {
420 type: String,
421 default: undefined
422 },
423 slideBlankClass: {
424 type: String,
425 default: undefined
426 },
427 slideNextClass: {
428 type: String,
429 default: undefined
430 },
431 slidePrevClass: {
432 type: String,
433 default: undefined
434 },
435 wrapperClass: {
436 type: String,
437 default: undefined
438 },
439 lazyPreloaderClass: {
440 type: String,
441 default: undefined
442 },
443 lazyPreloadPrevNext: {
444 type: Number,
445 default: undefined
446 },
447 runCallbacksOnInit: {
448 type: Boolean,
449 default: undefined
450 },
451 observer: {
452 type: Boolean,
453 default: undefined
454 },
455 observeParents: {
456 type: Boolean,
457 default: undefined
458 },
459 observeSlideChildren: {
460 type: Boolean,
461 default: undefined
462 },
463 a11y: {
464 type: [Boolean, Object],
465 default: undefined
466 },
467 autoplay: {
468 type: [Boolean, Object],
469 default: undefined
470 },
471 controller: {
472 type: Object,
473 default: undefined
474 },
475 coverflowEffect: {
476 type: Object,
477 default: undefined
478 },
479 cubeEffect: {
480 type: Object,
481 default: undefined
482 },
483 fadeEffect: {
484 type: Object,
485 default: undefined
486 },
487 flipEffect: {
488 type: Object,
489 default: undefined
490 },
491 creativeEffect: {
492 type: Object,
493 default: undefined
494 },
495 cardsEffect: {
496 type: Object,
497 default: undefined
498 },
499 hashNavigation: {
500 type: [Boolean, Object],
501 default: undefined
502 },
503 history: {
504 type: [Boolean, Object],
505 default: undefined
506 },
507 keyboard: {
508 type: [Boolean, Object],
509 default: undefined
510 },
511 mousewheel: {
512 type: [Boolean, Object],
513 default: undefined
514 },
515 navigation: {
516 type: [Boolean, Object],
517 default: undefined
518 },
519 pagination: {
520 type: [Boolean, Object],
521 default: undefined
522 },
523 parallax: {
524 type: [Boolean, Object],
525 default: undefined
526 },
527 scrollbar: {
528 type: [Boolean, Object],
529 default: undefined
530 },
531 thumbs: {
532 type: Object,
533 default: undefined
534 },
535 virtual: {
536 type: [Boolean, Object],
537 default: undefined
538 },
539 zoom: {
540 type: [Boolean, Object],
541 default: undefined
542 },
543 grid: {
544 type: [Object],
545 default: undefined
546 },
547 freeMode: {
548 type: [Boolean, Object],
549 default: undefined
550 },
551 enabled: {
552 type: Boolean,
553 default: undefined
554 }
555 },
556 emits: ['_beforeBreakpoint', '_containerClasses', '_slideClass', '_slideClasses', '_swiper', '_freeModeNoMomentumRelease', 'activeIndexChange', 'afterInit', 'autoplay', 'autoplayStart', 'autoplayStop', 'autoplayPause', 'autoplayResume', 'autoplayTimeLeft', 'beforeDestroy', 'beforeInit', 'beforeLoopFix', 'beforeResize', 'beforeSlideChangeStart', 'beforeTransitionStart', 'breakpoint', 'breakpointsBase', 'changeDirection', 'click', 'disable', 'doubleTap', 'doubleClick', 'destroy', 'enable', 'fromEdge', 'hashChange', 'hashSet', 'init', 'keyPress', 'lock', 'loopFix', 'momentumBounce', 'navigationHide', 'navigationShow', 'navigationPrev', 'navigationNext', 'observerUpdate', 'orientationchange', 'paginationHide', 'paginationRender', 'paginationShow', 'paginationUpdate', 'progress', 'reachBeginning', 'reachEnd', 'realIndexChange', 'resize', 'scroll', 'scrollbarDragEnd', 'scrollbarDragMove', 'scrollbarDragStart', 'setTransition', 'setTranslate', 'slidesUpdated', 'slideChange', 'slideChangeTransitionEnd', 'slideChangeTransitionStart', 'slideNextTransitionEnd', 'slideNextTransitionStart', 'slidePrevTransitionEnd', 'slidePrevTransitionStart', 'slideResetTransitionStart', 'slideResetTransitionEnd', 'sliderMove', 'sliderFirstMove', 'slidesLengthChange', 'slidesGridLengthChange', 'snapGridLengthChange', 'snapIndexChange', 'swiper', 'tap', 'toEdge', 'touchEnd', 'touchMove', 'touchMoveOpposite', 'touchStart', 'transitionEnd', 'transitionStart', 'unlock', 'update', 'virtualUpdate', 'zoomChange'],
557 setup(props, _ref) {
558 let {
559 slots: originalSlots,
560 emit
561 } = _ref;
562 const {
563 tag: Tag,
564 wrapperTag: WrapperTag
565 } = props;
566 const containerClasses = ref('swiper');
567 const virtualData = ref(null);
568 const breakpointChanged = ref(false);
569 const initializedRef = ref(false);
570 const swiperElRef = ref(null);
571 const swiperRef = ref(null);
572 const oldPassedParamsRef = ref(null);
573 const slidesRef = {
574 value: []
575 };
576 const oldSlidesRef = {
577 value: []
578 };
579 const nextElRef = ref(null);
580 const prevElRef = ref(null);
581 const paginationElRef = ref(null);
582 const scrollbarElRef = ref(null);
583 const {
584 params: swiperParams,
585 passedParams
586 } = getParams(props, false);
587 getChildren(originalSlots, slidesRef, oldSlidesRef);
588 oldPassedParamsRef.value = passedParams;
589 oldSlidesRef.value = slidesRef.value;
590 const onBeforeBreakpoint = () => {
591 getChildren(originalSlots, slidesRef, oldSlidesRef);
592 breakpointChanged.value = true;
593 };
594 swiperParams.onAny = function (event) {
595 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
596 args[_key - 1] = arguments[_key];
597 }
598 emit(event, ...args);
599 };
600 Object.assign(swiperParams.on, {
601 _beforeBreakpoint: onBeforeBreakpoint,
602 _containerClasses(swiper, classes) {
603 containerClasses.value = classes;
604 }
605 });
606
607 // init Swiper
608 const passParams = {
609 ...swiperParams
610 };
611 delete passParams.wrapperClass;
612 swiperRef.value = new Swiper$1(passParams);
613 if (swiperRef.value.virtual && swiperRef.value.params.virtual.enabled) {
614 swiperRef.value.virtual.slides = slidesRef.value;
615 const extendWith = {
616 cache: false,
617 slides: slidesRef.value,
618 renderExternal: data => {
619 virtualData.value = data;
620 },
621 renderExternalUpdate: false
622 };
623 extend(swiperRef.value.params.virtual, extendWith);
624 extend(swiperRef.value.originalParams.virtual, extendWith);
625 }
626 onUpdated(() => {
627 // set initialized flag
628 if (!initializedRef.value && swiperRef.value) {
629 swiperRef.value.emitSlidesClasses();
630 initializedRef.value = true;
631 }
632 // watch for params change
633 const {
634 passedParams: newPassedParams
635 } = getParams(props, false);
636 const changedParams = getChangedParams(newPassedParams, oldPassedParamsRef.value, slidesRef.value, oldSlidesRef.value, c => c.props && c.props.key);
637 oldPassedParamsRef.value = newPassedParams;
638 if ((changedParams.length || breakpointChanged.value) && swiperRef.value && !swiperRef.value.destroyed) {
639 updateSwiper({
640 swiper: swiperRef.value,
641 slides: slidesRef.value,
642 passedParams: newPassedParams,
643 changedParams,
644 nextEl: nextElRef.value,
645 prevEl: prevElRef.value,
646 scrollbarEl: scrollbarElRef.value,
647 paginationEl: paginationElRef.value
648 });
649 }
650 breakpointChanged.value = false;
651 });
652 provide('swiper', swiperRef);
653
654 // update on virtual update
655 watch(virtualData, () => {
656 nextTick(() => {
657 updateOnVirtualData(swiperRef.value);
658 });
659 });
660
661 // mount swiper
662 onMounted(() => {
663 if (!swiperElRef.value) return;
664 mountSwiper({
665 el: swiperElRef.value,
666 nextEl: nextElRef.value,
667 prevEl: prevElRef.value,
668 paginationEl: paginationElRef.value,
669 scrollbarEl: scrollbarElRef.value,
670 swiper: swiperRef.value
671 }, swiperParams);
672 emit('swiper', swiperRef.value);
673 });
674 onBeforeUnmount(() => {
675 if (swiperRef.value && !swiperRef.value.destroyed) {
676 swiperRef.value.destroy(true, false);
677 }
678 });
679
680 // bypass swiper instance to slides
681 function renderSlides(slides) {
682 if (swiperParams.virtual) {
683 return renderVirtual(swiperRef, slides, virtualData.value);
684 }
685 slides.forEach((slide, index) => {
686 if (!slide.props) slide.props = {};
687 slide.props.swiperRef = swiperRef;
688 slide.props.swiperSlideIndex = index;
689 });
690 return slides;
691 }
692 return () => {
693 const {
694 slides,
695 slots
696 } = getChildren(originalSlots, slidesRef, oldSlidesRef);
697 return h(Tag, {
698 ref: swiperElRef,
699 class: uniqueClasses(containerClasses.value)
700 }, [slots['container-start'], h(WrapperTag, {
701 class: wrapperClass(swiperParams.wrapperClass)
702 }, [slots['wrapper-start'], renderSlides(slides), slots['wrapper-end']]), needsNavigation(props) && [h('div', {
703 ref: prevElRef,
704 class: 'swiper-button-prev'
705 }), h('div', {
706 ref: nextElRef,
707 class: 'swiper-button-next'
708 })], needsScrollbar(props) && h('div', {
709 ref: scrollbarElRef,
710 class: 'swiper-scrollbar'
711 }), needsPagination(props) && h('div', {
712 ref: paginationElRef,
713 class: 'swiper-pagination'
714 }), slots['container-end']]);
715 };
716 }
717};
718
719const SwiperSlide = {
720 name: 'SwiperSlide',
721 props: {
722 tag: {
723 type: String,
724 default: 'div'
725 },
726 swiperRef: {
727 type: Object,
728 required: false
729 },
730 swiperSlideIndex: {
731 type: Number,
732 default: undefined,
733 required: false
734 },
735 zoom: {
736 type: Boolean,
737 default: undefined,
738 required: false
739 },
740 lazy: {
741 type: Boolean,
742 default: false,
743 required: false
744 },
745 virtualIndex: {
746 type: [String, Number],
747 default: undefined
748 }
749 },
750 setup(props, _ref) {
751 let {
752 slots
753 } = _ref;
754 let eventAttached = false;
755 const {
756 swiperRef
757 } = props;
758 const slideElRef = ref(null);
759 const slideClasses = ref('swiper-slide');
760 const lazyLoaded = ref(false);
761 function updateClasses(swiper, el, classNames) {
762 if (el === slideElRef.value) {
763 slideClasses.value = classNames;
764 }
765 }
766 onMounted(() => {
767 if (!swiperRef || !swiperRef.value) return;
768 swiperRef.value.on('_slideClass', updateClasses);
769 eventAttached = true;
770 });
771 onBeforeUpdate(() => {
772 if (eventAttached || !swiperRef || !swiperRef.value) return;
773 swiperRef.value.on('_slideClass', updateClasses);
774 eventAttached = true;
775 });
776 onUpdated(() => {
777 if (!slideElRef.value || !swiperRef || !swiperRef.value) return;
778 if (typeof props.swiperSlideIndex !== 'undefined') {
779 slideElRef.value.swiperSlideIndex = props.swiperSlideIndex;
780 }
781 if (swiperRef.value.destroyed) {
782 if (slideClasses.value !== 'swiper-slide') {
783 slideClasses.value = 'swiper-slide';
784 }
785 }
786 });
787 onBeforeUnmount(() => {
788 if (!swiperRef || !swiperRef.value) return;
789 swiperRef.value.off('_slideClass', updateClasses);
790 });
791 const slideData = computed(() => ({
792 isActive: slideClasses.value.indexOf('swiper-slide-active') >= 0,
793 isVisible: slideClasses.value.indexOf('swiper-slide-visible') >= 0,
794 isPrev: slideClasses.value.indexOf('swiper-slide-prev') >= 0,
795 isNext: slideClasses.value.indexOf('swiper-slide-next') >= 0
796 }));
797 provide('swiperSlide', slideData);
798 const onLoad = () => {
799 lazyLoaded.value = true;
800 };
801 return () => {
802 return h(props.tag, {
803 class: uniqueClasses(`${slideClasses.value}`),
804 ref: slideElRef,
805 'data-swiper-slide-index': typeof props.virtualIndex === 'undefined' && swiperRef && swiperRef.value && swiperRef.value.params.loop ? props.swiperSlideIndex : props.virtualIndex,
806 onLoadCapture: onLoad
807 }, props.zoom ? h('div', {
808 class: 'swiper-zoom-container',
809 'data-swiper-zoom': typeof props.zoom === 'number' ? props.zoom : undefined
810 }, [slots.default && slots.default(slideData.value), props.lazy && !lazyLoaded.value && h('div', {
811 class: 'swiper-lazy-preloader'
812 })]) : [slots.default && slots.default(slideData.value), props.lazy && !lazyLoaded.value && h('div', {
813 class: 'swiper-lazy-preloader'
814 })]);
815 };
816 }
817};
818
819const useSwiperSlide = () => {
820 return inject('swiperSlide');
821};
822const useSwiper = () => {
823 return inject('swiper');
824};
825
826export { Swiper, SwiperSlide, useSwiper, useSwiperSlide };