UNPKG

15.6 kBJavaScriptView Raw
1import { h, ref, onMounted, onUpdated, onBeforeUnmount, watch, nextTick } from 'vue';
2import { getParams } from './get-params.js';
3import { initSwiper, mountSwiper } from './init-swiper.js';
4import { needsScrollbar, needsNavigation, needsPagination, uniqueClasses, extend } from './utils.js';
5import { renderLoop, calcLoopedSlides } from './loop.js';
6import { getChangedParams } from './get-changed-params.js';
7import { getChildren } from './get-children.js';
8import { updateSwiper } from './update-swiper.js';
9import { renderVirtual, updateOnVirtualData } from './virtual.js';
10const Swiper = {
11 name: 'Swiper',
12 props: {
13 tag: {
14 type: String,
15 default: 'div'
16 },
17 wrapperTag: {
18 type: String,
19 default: 'div'
20 },
21 modules: {
22 type: Array,
23 default: undefined
24 },
25 init: {
26 type: Boolean,
27 default: undefined
28 },
29 direction: {
30 type: String,
31 default: undefined
32 },
33 touchEventsTarget: {
34 type: String,
35 default: undefined
36 },
37 initialSlide: {
38 type: Number,
39 default: undefined
40 },
41 speed: {
42 type: Number,
43 default: undefined
44 },
45 cssMode: {
46 type: Boolean,
47 default: undefined
48 },
49 updateOnWindowResize: {
50 type: Boolean,
51 default: undefined
52 },
53 resizeObserver: {
54 type: Boolean,
55 default: undefined
56 },
57 nested: {
58 type: Boolean,
59 default: undefined
60 },
61 focusableElements: {
62 type: String,
63 default: undefined
64 },
65 width: {
66 type: Number,
67 default: undefined
68 },
69 height: {
70 type: Number,
71 default: undefined
72 },
73 preventInteractionOnTransition: {
74 type: Boolean,
75 default: undefined
76 },
77 userAgent: {
78 type: String,
79 default: undefined
80 },
81 url: {
82 type: String,
83 default: undefined
84 },
85 edgeSwipeDetection: {
86 type: [Boolean, String],
87 default: undefined
88 },
89 edgeSwipeThreshold: {
90 type: Number,
91 default: undefined
92 },
93 autoHeight: {
94 type: Boolean,
95 default: undefined
96 },
97 setWrapperSize: {
98 type: Boolean,
99 default: undefined
100 },
101 virtualTranslate: {
102 type: Boolean,
103 default: undefined
104 },
105 effect: {
106 type: String,
107 default: undefined
108 },
109 breakpoints: {
110 type: Object,
111 default: undefined
112 },
113 spaceBetween: {
114 type: Number,
115 default: undefined
116 },
117 slidesPerView: {
118 type: [Number, String],
119 default: undefined
120 },
121 slidesPerGroup: {
122 type: Number,
123 default: undefined
124 },
125 slidesPerGroupSkip: {
126 type: Number,
127 default: undefined
128 },
129 slidesPerGroupAuto: {
130 type: Boolean,
131 default: undefined
132 },
133 centeredSlides: {
134 type: Boolean,
135 default: undefined
136 },
137 centeredSlidesBounds: {
138 type: Boolean,
139 default: undefined
140 },
141 slidesOffsetBefore: {
142 type: Number,
143 default: undefined
144 },
145 slidesOffsetAfter: {
146 type: Number,
147 default: undefined
148 },
149 normalizeSlideIndex: {
150 type: Boolean,
151 default: undefined
152 },
153 centerInsufficientSlides: {
154 type: Boolean,
155 default: undefined
156 },
157 watchOverflow: {
158 type: Boolean,
159 default: undefined
160 },
161 roundLengths: {
162 type: Boolean,
163 default: undefined
164 },
165 touchRatio: {
166 type: Number,
167 default: undefined
168 },
169 touchAngle: {
170 type: Number,
171 default: undefined
172 },
173 simulateTouch: {
174 type: Boolean,
175 default: undefined
176 },
177 shortSwipes: {
178 type: Boolean,
179 default: undefined
180 },
181 longSwipes: {
182 type: Boolean,
183 default: undefined
184 },
185 longSwipesRatio: {
186 type: Number,
187 default: undefined
188 },
189 longSwipesMs: {
190 type: Number,
191 default: undefined
192 },
193 followFinger: {
194 type: Boolean,
195 default: undefined
196 },
197 allowTouchMove: {
198 type: Boolean,
199 default: undefined
200 },
201 threshold: {
202 type: Number,
203 default: undefined
204 },
205 touchMoveStopPropagation: {
206 type: Boolean,
207 default: undefined
208 },
209 touchStartPreventDefault: {
210 type: Boolean,
211 default: undefined
212 },
213 touchStartForcePreventDefault: {
214 type: Boolean,
215 default: undefined
216 },
217 touchReleaseOnEdges: {
218 type: Boolean,
219 default: undefined
220 },
221 uniqueNavElements: {
222 type: Boolean,
223 default: undefined
224 },
225 resistance: {
226 type: Boolean,
227 default: undefined
228 },
229 resistanceRatio: {
230 type: Number,
231 default: undefined
232 },
233 watchSlidesProgress: {
234 type: Boolean,
235 default: undefined
236 },
237 grabCursor: {
238 type: Boolean,
239 default: undefined
240 },
241 preventClicks: {
242 type: Boolean,
243 default: undefined
244 },
245 preventClicksPropagation: {
246 type: Boolean,
247 default: undefined
248 },
249 slideToClickedSlide: {
250 type: Boolean,
251 default: undefined
252 },
253 preloadImages: {
254 type: Boolean,
255 default: undefined
256 },
257 updateOnImagesReady: {
258 type: Boolean,
259 default: undefined
260 },
261 loop: {
262 type: Boolean,
263 default: undefined
264 },
265 loopAdditionalSlides: {
266 type: Number,
267 default: undefined
268 },
269 loopedSlides: {
270 type: Number,
271 default: undefined
272 },
273 loopFillGroupWithBlank: {
274 type: Boolean,
275 default: undefined
276 },
277 loopPreventsSlide: {
278 type: Boolean,
279 default: undefined
280 },
281 allowSlidePrev: {
282 type: Boolean,
283 default: undefined
284 },
285 allowSlideNext: {
286 type: Boolean,
287 default: undefined
288 },
289 swipeHandler: {
290 type: Boolean,
291 default: undefined
292 },
293 noSwiping: {
294 type: Boolean,
295 default: undefined
296 },
297 noSwipingClass: {
298 type: String,
299 default: undefined
300 },
301 noSwipingSelector: {
302 type: String,
303 default: undefined
304 },
305 passiveListeners: {
306 type: Boolean,
307 default: undefined
308 },
309 containerModifierClass: {
310 type: String,
311 default: undefined
312 },
313 slideClass: {
314 type: String,
315 default: undefined
316 },
317 slideBlankClass: {
318 type: String,
319 default: undefined
320 },
321 slideActiveClass: {
322 type: String,
323 default: undefined
324 },
325 slideDuplicateActiveClass: {
326 type: String,
327 default: undefined
328 },
329 slideVisibleClass: {
330 type: String,
331 default: undefined
332 },
333 slideDuplicateClass: {
334 type: String,
335 default: undefined
336 },
337 slideNextClass: {
338 type: String,
339 default: undefined
340 },
341 slideDuplicateNextClass: {
342 type: String,
343 default: undefined
344 },
345 slidePrevClass: {
346 type: String,
347 default: undefined
348 },
349 slideDuplicatePrevClass: {
350 type: String,
351 default: undefined
352 },
353 wrapperClass: {
354 type: String,
355 default: undefined
356 },
357 runCallbacksOnInit: {
358 type: Boolean,
359 default: undefined
360 },
361 observer: {
362 type: Boolean,
363 default: undefined
364 },
365 observeParents: {
366 type: Boolean,
367 default: undefined
368 },
369 observeSlideChildren: {
370 type: Boolean,
371 default: undefined
372 },
373 a11y: {
374 type: [Boolean, Object],
375 default: undefined
376 },
377 autoplay: {
378 type: [Boolean, Object],
379 default: undefined
380 },
381 controller: {
382 type: Object,
383 default: undefined
384 },
385 coverflowEffect: {
386 type: Object,
387 default: undefined
388 },
389 cubeEffect: {
390 type: Object,
391 default: undefined
392 },
393 fadeEffect: {
394 type: Object,
395 default: undefined
396 },
397 flipEffect: {
398 type: Object,
399 default: undefined
400 },
401 creativeEffect: {
402 type: Object,
403 default: undefined
404 },
405 cardsEffect: {
406 type: Object,
407 default: undefined
408 },
409 hashNavigation: {
410 type: [Boolean, Object],
411 default: undefined
412 },
413 history: {
414 type: [Boolean, Object],
415 default: undefined
416 },
417 keyboard: {
418 type: [Boolean, Object],
419 default: undefined
420 },
421 lazy: {
422 type: [Boolean, Object],
423 default: undefined
424 },
425 mousewheel: {
426 type: [Boolean, Object],
427 default: undefined
428 },
429 navigation: {
430 type: [Boolean, Object],
431 default: undefined
432 },
433 pagination: {
434 type: [Boolean, Object],
435 default: undefined
436 },
437 parallax: {
438 type: [Boolean, Object],
439 default: undefined
440 },
441 scrollbar: {
442 type: [Boolean, Object],
443 default: undefined
444 },
445 thumbs: {
446 type: Object,
447 default: undefined
448 },
449 virtual: {
450 type: [Boolean, Object],
451 default: undefined
452 },
453 zoom: {
454 type: [Boolean, Object],
455 default: undefined
456 },
457 grid: {
458 type: [Object],
459 default: undefined
460 },
461 freeMode: {
462 type: [Boolean, Object],
463 default: undefined
464 }
465 },
466 emits: ['_beforeBreakpoint', '_containerClasses', '_slideClass', '_slideClasses', '_swiper', 'activeIndexChange', 'afterInit', 'autoplay', 'autoplayStart', 'autoplayStop', 'beforeDestroy', 'beforeInit', 'beforeLoopFix', 'beforeResize', 'beforeSlideChangeStart', 'beforeTransitionStart', 'breakpoint', 'changeDirection', 'click', 'disable', 'doubleTap', 'doubleClick', 'destroy', 'enable', 'fromEdge', 'hashChange', 'hashSet', 'imagesReady', 'init', 'keyPress', 'lazyImageLoad', 'lazyImageReady', 'lock', 'loopFix', 'momentumBounce', 'navigationHide', 'navigationShow', 'observerUpdate', 'orientationchange', 'paginationHide', 'paginationRender', 'paginationShow', 'paginationUpdate', 'progress', 'reachBeginning', 'reachEnd', 'realIndexChange', 'resize', 'scroll', 'scrollbarDragEnd', 'scrollbarDragMove', 'scrollbarDragStart', 'setTransition', 'setTranslate', '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', 'zoomChange'],
467
468 setup(props, {
469 slots: originalSlots,
470 emit
471 }) {
472 const {
473 tag: Tag,
474 wrapperTag: WrapperTag
475 } = props;
476 const containerClasses = ref('swiper');
477 const virtualData = ref(null);
478 const breakpointChanged = ref(false);
479 const initializedRef = ref(false);
480 const swiperElRef = ref(null);
481 const swiperRef = ref(null);
482 const oldPassedParamsRef = ref(null);
483 const slidesRef = {
484 value: []
485 };
486 const oldSlidesRef = {
487 value: []
488 };
489 const nextElRef = ref(null);
490 const prevElRef = ref(null);
491 const paginationElRef = ref(null);
492 const scrollbarElRef = ref(null);
493 const {
494 params: swiperParams,
495 passedParams
496 } = getParams(props);
497 getChildren(originalSlots, slidesRef, oldSlidesRef);
498 oldPassedParamsRef.value = passedParams;
499 oldSlidesRef.value = slidesRef.value;
500
501 const onBeforeBreakpoint = () => {
502 getChildren(originalSlots, slidesRef, oldSlidesRef);
503 breakpointChanged.value = true;
504 };
505
506 swiperParams.onAny = (event, ...args) => {
507 emit(event, ...args);
508 };
509
510 Object.assign(swiperParams.on, {
511 _beforeBreakpoint: onBeforeBreakpoint,
512
513 _containerClasses(swiper, classes) {
514 containerClasses.value = classes;
515 }
516
517 }); // init Swiper
518
519 swiperRef.value = initSwiper(swiperParams);
520
521 swiperRef.value.loopCreate = () => {};
522
523 swiperRef.value.loopDestroy = () => {};
524
525 if (swiperParams.loop) {
526 swiperRef.value.loopedSlides = calcLoopedSlides(slidesRef.value, swiperParams);
527 }
528
529 if (swiperRef.value.virtual && swiperRef.value.params.virtual.enabled) {
530 swiperRef.value.virtual.slides = slidesRef.value;
531 const extendWith = {
532 cache: false,
533 slides: slidesRef.value,
534 renderExternal: data => {
535 virtualData.value = data;
536 },
537 renderExternalUpdate: false
538 };
539 extend(swiperRef.value.params.virtual, extendWith);
540 extend(swiperRef.value.originalParams.virtual, extendWith);
541 }
542
543 onUpdated(() => {
544 // set initialized flag
545 if (!initializedRef.value && swiperRef.value) {
546 swiperRef.value.emitSlidesClasses();
547 initializedRef.value = true;
548 } // watch for params change
549
550
551 const {
552 passedParams: newPassedParams
553 } = getParams(props);
554 const changedParams = getChangedParams(newPassedParams, oldPassedParamsRef.value, slidesRef.value, oldSlidesRef.value);
555 oldPassedParamsRef.value = newPassedParams;
556
557 if ((changedParams.length || breakpointChanged.value) && swiperRef.value && !swiperRef.value.destroyed) {
558 updateSwiper({
559 swiper: swiperRef.value,
560 slides: slidesRef.value,
561 passedParams: newPassedParams,
562 changedParams,
563 nextEl: nextElRef.value,
564 prevEl: prevElRef.value,
565 scrollbarEl: scrollbarElRef.value,
566 paginationEl: paginationElRef.value
567 });
568 }
569
570 breakpointChanged.value = false;
571 }); // update on virtual update
572
573 watch(virtualData, () => {
574 nextTick(() => {
575 updateOnVirtualData(swiperRef.value);
576 });
577 }); // mount swiper
578
579 onMounted(() => {
580 if (!swiperElRef.value) return;
581 mountSwiper({
582 el: swiperElRef.value,
583 nextEl: nextElRef.value,
584 prevEl: prevElRef.value,
585 paginationEl: paginationElRef.value,
586 scrollbarEl: scrollbarElRef.value,
587 swiper: swiperRef.value
588 }, swiperParams);
589 emit('swiper', swiperRef.value);
590 });
591 onBeforeUnmount(() => {
592 if (swiperRef.value && !swiperRef.value.destroyed) {
593 swiperRef.value.destroy(true, false);
594 }
595 }); // bypass swiper instance to slides
596
597 function renderSlides(slides) {
598 if (swiperParams.virtual) {
599 return renderVirtual(swiperRef, slides, virtualData.value);
600 }
601
602 if (!swiperParams.loop || swiperRef.value && swiperRef.value.destroyed) {
603 slides.forEach(slide => {
604 if (!slide.props) slide.props = {};
605 slide.props.swiperRef = swiperRef;
606 });
607 return slides;
608 }
609
610 return renderLoop(swiperRef, slides, swiperParams);
611 }
612
613 return () => {
614 const {
615 slides,
616 slots
617 } = getChildren(originalSlots, slidesRef, oldSlidesRef);
618 return h(Tag, {
619 ref: swiperElRef,
620 class: uniqueClasses(containerClasses.value)
621 }, [slots['container-start'], needsNavigation(props) && [h('div', {
622 ref: prevElRef,
623 class: 'swiper-button-prev'
624 }), h('div', {
625 ref: nextElRef,
626 class: 'swiper-button-next'
627 })], needsScrollbar(props) && h('div', {
628 ref: scrollbarElRef,
629 class: 'swiper-scrollbar'
630 }), needsPagination(props) && h('div', {
631 ref: paginationElRef,
632 class: 'swiper-pagination'
633 }), h(WrapperTag, {
634 class: 'swiper-wrapper'
635 }, [slots['wrapper-start'], renderSlides(slides), slots['wrapper-end']]), slots['container-end']]);
636 };
637 }
638
639};
640export { Swiper };
\No newline at end of file